diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/domains/page-client.tsx b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/domains/page-client.tsx index d5ff4ba08..a38b05e97 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/domains/page-client.tsx +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/domains/page-client.tsx @@ -1,9 +1,10 @@ "use client"; -import { SmartFormDialog } from "@/components/form-dialog"; +import { FormDialog } from "@/components/form-dialog"; +import { InputField, SwitchField } from "@/components/form-fields"; import { SettingCard, SettingSwitch } from "@/components/settings"; import { AdminDomainConfig, AdminProject } from "@stackframe/stack"; import { urlSchema } from "@stackframe/stack-shared/dist/schema-fields"; -import { ActionCell, ActionDialog, Alert, Button, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Typography } from "@stackframe/stack-ui"; +import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, ActionCell, ActionDialog, Alert, Button, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Typography } from "@stackframe/stack-ui"; import React from "react"; import * as yup from "yup"; import { PageLayout } from "../page-layout"; @@ -28,48 +29,29 @@ function EditDialog(props: { } )) { const domainFormSchema = yup.object({ - makeSureAlert: yup.mixed().meta({ - stackFormFieldRender: () => ( - - Make sure this is a trusted domain or a URL that you control. - - ), - }), domain: urlSchema - .matches(/^https:\/\//, "Origin must start with https://") - .url("Domain must be a valid URL") + .url("Invalid URL") + .transform((value) => 'https://' + value) .notOneOf( props.domains .filter((_, i) => (props.type === 'update' && i !== props.editIndex) || props.type === 'create') .map(({ domain }) => domain), "Domain already exists" ) - .required() - .label("Origin (starts with https://)") - .meta({ - stackFormFieldPlaceholder: "https://example.com", - }).default(props.type === 'update' ? props.defaultDomain : ""), + .required(), handlerPath: yup.string() .matches(/^\//, "Handler path must start with /") - .required() - .label("Handler path (default: /handler)") - .default(props.type === 'update' ? props.defaultHandlerPath : "/handler"), - description: yup.mixed().meta({ - stackFormFieldRender: () => ( - <> - - Note that sub-domains are not automatically added. Create two domains like www.example.com and example.com if you want to allow both. - - - {"You don't need to change the handler path unless you updated the path to the StackHandler."} - - - ), - }), + .required(), + addWww: yup.boolean(), }); - return ( + <> + + Please ensure you own or have control over this domain. Note that each subdomain (e.g. blog.example.com, app.example.com) is treated as a distinct domain. + + + + {props.type === 'create' && + urlSchema.url().required().isValidSync('https://' + form.watch('domain')) && + !((form.watch('domain') as any)?.startsWith('www.')) && ( + + )} + + + + Advanced + + + + only modify this if you changed the default handler path in your app + + + + + + )} />; } @@ -200,7 +230,6 @@ export default function PageClient() { Domain - Handler @@ -208,7 +237,6 @@ export default function PageClient() { {domains.map(({ domain, handlerPath }, i) => ( {domain} - {handlerPath} (props: { required?: boolean, type?: string, disabled?: boolean, + prefixItem?: React.ReactNode, }) { return ( (props: { className="max-w-lg" disabled={props.disabled} type={props.type} + prefixItem={props.prefixItem} /> diff --git a/packages/stack-ui/src/components/ui/accordion.tsx b/packages/stack-ui/src/components/ui/accordion.tsx index 42ffbfa86..b560f656b 100644 --- a/packages/stack-ui/src/components/ui/accordion.tsx +++ b/packages/stack-ui/src/components/ui/accordion.tsx @@ -47,7 +47,7 @@ const AccordionContent = forwardRefIfNeeded< >(({ className, children, ...props }, ref) => (
{children}
diff --git a/packages/stack-ui/src/components/ui/input.tsx b/packages/stack-ui/src/components/ui/input.tsx index 1c930ded9..93bc5d821 100644 --- a/packages/stack-ui/src/components/ui/input.tsx +++ b/packages/stack-ui/src/components/ui/input.tsx @@ -3,28 +3,42 @@ import { forwardRefIfNeeded } from "@stackframe/stack-shared/dist/utils/react"; import { cn } from "../../lib/utils"; -export interface InputProps - extends React.InputHTMLAttributes {} +export interface InputProps extends React.InputHTMLAttributes { + prefixItem?: React.ReactNode, +} -const Input = forwardRefIfNeeded( - ({ className, type, ...props }, ref) => { - return ( - - ); +export const Input = forwardRefIfNeeded( + ({ className, type, prefixItem, ...props }, ref) => { + const baseClasses = "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"; + + if (prefixItem) { + return ( +
+
+ {prefixItem} +
+ +
+ ); + } else { + return ( + + ); + } } ); Input.displayName = "Input"; -export { Input }; - export interface DelayedInputProps extends InputProps { delay?: number,