@alepha/ui 0.10.6 → 0.10.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["e","segmentedControlProps: Partial<SegmentedControlProps>"],"sources":["../src/components/Action.tsx","../src/components/AlephaMantineProvider.tsx","../src/components/Control.tsx","../src/index.ts"],"sourcesContent":["import {\n\ttype RouterGoOptions,\n\ttype UseActiveOptions,\n\tuseActive,\n\tuseAlepha,\n\tuseRouter,\n} from \"@alepha/react\";\nimport { type FormModel, useFormState } from \"@alepha/react-form\";\nimport { Button, type ButtonProps, Flex } from \"@mantine/core\";\nimport { type ReactNode, useState } from \"react\";\n\nexport interface ActionCommonProps extends ButtonProps {\n\tchildren?: ReactNode;\n\ttextVisibleFrom?: \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\n\t// TODO\n\n\t/**\n\t * If set, a confirmation dialog will be shown before performing the action.\n\t * If `true`, a default title and message will be used.\n\t * If a string, it will be used as the message with a default title.\n\t * If an object, it can contain `title` and `message` properties to customize the dialog.\n\t */\n\tconfirm?: boolean | string | { title?: string; message: string };\n}\n\nexport type ActionProps = ActionCommonProps &\n\t(ActiveHrefProps | ActionClickProps | ActionSubmitProps | {});\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nconst Action = (_props: ActionProps) => {\n\tconst props = { variant: \"subtle\", ..._props };\n\n\tif (props.leftSection && !props.children) {\n\t\tprops.className ??= \"mantine-Action-iconOnly\";\n\t\tprops.p ??= \"xs\";\n\t}\n\n\tif (props.textVisibleFrom) {\n\t\tconst { children, textVisibleFrom, leftSection, ...rest } = props;\n\t\treturn (\n\t\t\t<>\n\t\t\t\t<Flex w={\"100%\"} visibleFrom={textVisibleFrom}>\n\t\t\t\t\t<Action flex={1} {...rest} leftSection={leftSection}>\n\t\t\t\t\t\t{children}\n\t\t\t\t\t</Action>\n\t\t\t\t</Flex>\n\t\t\t\t<Flex w={\"100%\"} hiddenFrom={textVisibleFrom}>\n\t\t\t\t\t<Action px={\"xs\"} {...rest}>\n\t\t\t\t\t\t{leftSection}\n\t\t\t\t\t</Action>\n\t\t\t\t</Flex>\n\t\t\t</>\n\t\t);\n\t}\n\n\tconst renderAction = () => {\n\t\tif (\"href\" in props && props.href) {\n\t\t\treturn (\n\t\t\t\t<ActionHref {...props} href={props.href}>\n\t\t\t\t\t{props.children}\n\t\t\t\t</ActionHref>\n\t\t\t);\n\t\t}\n\n\t\tif (\"onClick\" in props && props.onClick) {\n\t\t\treturn (\n\t\t\t\t<ActionClick {...props} onClick={props.onClick}>\n\t\t\t\t\t{props.children}\n\t\t\t\t</ActionClick>\n\t\t\t);\n\t\t}\n\n\t\tif (\"form\" in props && props.form) {\n\t\t\treturn (\n\t\t\t\t<ActionSubmit {...props} form={props.form}>\n\t\t\t\t\t{props.children}\n\t\t\t\t</ActionSubmit>\n\t\t\t);\n\t\t}\n\n\t\treturn <Button {...(props as any)}>{props.children}</Button>;\n\t};\n\n\treturn renderAction();\n};\n\nexport default Action;\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface ActionSubmitProps extends ButtonProps {\n\tform: FormModel<any>;\n}\n\n/**\n * Action button that submits a form with loading and disabled state handling.\n */\nconst ActionSubmit = (props: ActionSubmitProps) => {\n\tconst { form, ...buttonProps } = props;\n\tconst state = useFormState(form);\n\treturn (\n\t\t<Button\n\t\t\t{...buttonProps}\n\t\t\tloading={state.loading}\n\t\t\tdisabled={state.loading || !state.dirty}\n\t\t\ttype={\"submit\"}\n\t\t>\n\t\t\t{props.children}\n\t\t</Button>\n\t);\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface ActionClickProps extends ButtonProps {\n\tonClick: (e: any) => any;\n}\n\n/**\n * Basic action button that handles click events with loading and error handling.\n */\nconst ActionClick = (props: ActionClickProps) => {\n\tconst [pending, setPending] = useState(false);\n\tconst alepha = useAlepha();\n\n\tconst onClick = async (e: any) => {\n\t\tsetPending(true);\n\t\ttry {\n\t\t\tawait props.onClick(e);\n\t\t} catch (e) {\n\t\t\tconsole.error(e);\n\t\t\tawait alepha.events.emit(\"form:submit:error\", {\n\t\t\t\tid: \"action\",\n\t\t\t\terror: e as Error,\n\t\t\t});\n\t\t} finally {\n\t\t\tsetPending(false);\n\t\t}\n\t};\n\n\treturn (\n\t\t<Button\n\t\t\t{...props}\n\t\t\tdisabled={pending || props.disabled}\n\t\t\tloading={pending}\n\t\t\tonClick={onClick}\n\t\t>\n\t\t\t{props.children}\n\t\t</Button>\n\t);\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface ActiveHrefProps extends ButtonProps {\n\thref: string;\n\tactive?: Partial<UseActiveOptions> | false;\n\trouterGoOptions?: RouterGoOptions;\n}\n\n/**\n * Action for navigation with active state support.\n */\nconst ActionHref = (props: ActiveHrefProps) => {\n\tconst { active: options, routerGoOptions, ...buttonProps } = props;\n\tconst router = useRouter();\n\tconst { isPending, isActive } = useActive(\n\t\toptions ? { href: props.href, ...options } : { href: props.href },\n\t);\n\tconst anchorProps = router.anchor(props.href, routerGoOptions);\n\n\treturn (\n\t\t<Button\n\t\t\tcomponent={\"a\"}\n\t\t\tloading={isPending}\n\t\t\t{...anchorProps}\n\t\t\t{...buttonProps}\n\t\t\tvariant={isActive && options !== false ? \"filled\" : \"subtle\"}\n\t\t>\n\t\t\t{props.children}\n\t\t</Button>\n\t);\n};\n","import { NestedView, useRouterEvents } from \"@alepha/react\";\nimport type {\n\tColorSchemeScriptProps,\n\tMantineProviderProps,\n} from \"@mantine/core\";\nimport { ColorSchemeScript, MantineProvider } from \"@mantine/core\";\nimport { ModalsProvider, type ModalsProviderProps } from \"@mantine/modals\";\nimport { Notifications, type NotificationsProps } from \"@mantine/notifications\";\nimport type { NavigationProgressProps } from \"@mantine/nprogress\";\nimport { NavigationProgress, nprogress } from \"@mantine/nprogress\";\nimport type { ReactNode } from \"react\";\n\nexport interface AlephaMantineProviderProps {\n\tchildren?: ReactNode;\n\tmantine?: MantineProviderProps;\n\tcolorSchemeScript?: ColorSchemeScriptProps;\n\tnavigationProgress?: NavigationProgressProps;\n\tnotifications?: NotificationsProps;\n\tmodals?: ModalsProviderProps;\n}\n\nconst AlephaMantineProvider = (props: AlephaMantineProviderProps) => {\n\tuseRouterEvents({\n\t\tonBegin: () => {\n\t\t\tnprogress.start();\n\t\t},\n\t\tonEnd: () => {\n\t\t\tnprogress.complete();\n\t\t},\n\t});\n\n\treturn (\n\t\t<>\n\t\t\t<ColorSchemeScript\n\t\t\t\tdefaultColorScheme={props.mantine?.defaultColorScheme}\n\t\t\t\t{...props.colorSchemeScript}\n\t\t\t/>\n\t\t\t<MantineProvider {...props.mantine}>\n\t\t\t\t<Notifications {...props.notifications} />\n\t\t\t\t<NavigationProgress {...props.navigationProgress} />\n\t\t\t\t<ModalsProvider {...props.modals}>\n\t\t\t\t\t{props.children ?? <NestedView />}\n\t\t\t\t</ModalsProvider>\n\t\t\t</MantineProvider>\n\t\t</>\n\t);\n};\n\nexport default AlephaMantineProvider;\n","import { TypeBoxError } from \"@alepha/core\";\nimport { type InputField, useFormState } from \"@alepha/react-form\";\nimport {\n\tAutocomplete,\n\ttype AutocompleteProps,\n\tFlex,\n\tInput,\n\tPasswordInput,\n\ttype PasswordInputProps,\n\tSegmentedControl,\n\ttype SegmentedControlProps,\n\tSelect,\n\ttype SelectProps,\n\tSwitch,\n\ttype SwitchProps,\n\tTextarea,\n\ttype TextareaProps,\n\tTextInput,\n\ttype TextInputProps,\n} from \"@mantine/core\";\nimport type { ComponentType, ReactNode } from \"react\";\n\nexport interface ControlProps {\n\tinput: InputField;\n\n\ttitle?: string;\n\tdescription?: string;\n\n\ticon?: ReactNode;\n\n\ttext?: TextInputProps;\n\tarea?: boolean | TextareaProps;\n\tselect?: boolean | SelectProps;\n\tautocomplete?: boolean | AutocompleteProps;\n\tpassword?: boolean | PasswordInputProps;\n\tswitch?: boolean | SwitchProps;\n\tsegmented?: boolean | Partial<SegmentedControlProps>;\n\n\tcustom?: ComponentType<CustomControlProps>;\n}\n\n/**\n * Generic form control that renders the appropriate input based on the schema and props.\n *\n * Supports:\n * - TextInput\n * - Textarea\n * - Select (for enum types)\n * - Autocomplete\n * - PasswordInput\n * - Switch (for boolean types)\n * - SegmentedControl (for enum types)\n * - Custom component\n *\n * Automatically handles labels, descriptions, error messages, and required state.\n */\nconst Control = (props: ControlProps) => {\n\tconst form = useFormState(props.input);\n\tif (!props.input?.props) {\n\t\treturn null;\n\t}\n\n\t// shared props\n\n\tconst disabled = false; // form.loading;\n\tconst id = props.input.props.id;\n\tconst label =\n\t\tprops.title ??\n\t\t(\"title\" in props.input.schema &&\n\t\ttypeof props.input.schema.title === \"string\"\n\t\t\t? props.input.schema.title\n\t\t\t: undefined) ??\n\t\tprettyName(props.input.path);\n\tconst description =\n\t\tprops.description ??\n\t\t(\"description\" in props.input.schema &&\n\t\ttypeof props.input.schema.description === \"string\"\n\t\t\t? props.input.schema.description\n\t\t\t: undefined);\n\tconst error =\n\t\tform.error && form.error instanceof TypeBoxError\n\t\t\t? form.error.value.message\n\t\t\t: undefined;\n\tconst icon = props.icon;\n\tconst required = props.input.required;\n\n\tconst inputProps = {\n\t\tlabel,\n\t\tdescription,\n\t\terror,\n\t\trequired,\n\t\tdisabled,\n\t};\n\n\t// -------------------------------------------------------------------------------------------------------------------\n\n\tif (props.custom) {\n\t\tconst Custom = props.custom;\n\t\treturn (\n\t\t\t<Input.Wrapper {...inputProps}>\n\t\t\t\t<Flex flex={1} mt={\"calc(var(--mantine-spacing-xs) / 2)\"}>\n\t\t\t\t\t<Custom\n\t\t\t\t\t\tdefaultValue={props.input.props.defaultValue}\n\t\t\t\t\t\tonChange={(value) => {\n\t\t\t\t\t\t\tprops.input.set(value);\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\t\t\t\t</Flex>\n\t\t\t</Input.Wrapper>\n\t\t);\n\t}\n\n\t// region <SegmentedControl/>\n\tif (props.segmented) {\n\t\tconst segmentedControlProps: Partial<SegmentedControlProps> =\n\t\t\ttypeof props.segmented === \"object\" ? props.segmented : {};\n\t\tconst data =\n\t\t\tsegmentedControlProps.data ??\n\t\t\t(props.input.schema &&\n\t\t\t\"enum\" in props.input.schema &&\n\t\t\tArray.isArray(props.input.schema.enum)\n\t\t\t\t? props.input.schema.enum?.map((value: string) => ({\n\t\t\t\t\t\tvalue,\n\t\t\t\t\t\tlabel: value,\n\t\t\t\t\t}))\n\t\t\t\t: []);\n\t\treturn (\n\t\t\t<Input.Wrapper {...inputProps}>\n\t\t\t\t<Flex mt={\"calc(var(--mantine-spacing-xs) / 2)\"}>\n\t\t\t\t\t<SegmentedControl\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\tdefaultValue={String(props.input.props.defaultValue)}\n\t\t\t\t\t\t{...segmentedControlProps}\n\t\t\t\t\t\tonChange={(value) => {\n\t\t\t\t\t\t\tprops.input.set(value);\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tdata={data}\n\t\t\t\t\t/>\n\t\t\t\t</Flex>\n\t\t\t</Input.Wrapper>\n\t\t);\n\t}\n\t// endregion\n\n\t// region <Autocomplete/>\n\tif (props.autocomplete) {\n\t\tconst autocompleteProps =\n\t\t\ttypeof props.autocomplete === \"object\" ? props.autocomplete : {};\n\n\t\treturn (\n\t\t\t<Autocomplete\n\t\t\t\t{...inputProps}\n\t\t\t\tid={id}\n\t\t\t\tleftSection={icon}\n\t\t\t\t{...props.input.props}\n\t\t\t\t{...autocompleteProps}\n\t\t\t/>\n\t\t);\n\t}\n\t// endregion\n\n\t// region <Select/>\n\tif (\n\t\t(props.input.schema &&\n\t\t\t\"enum\" in props.input.schema &&\n\t\t\tprops.input.schema.enum) ||\n\t\tprops.select\n\t) {\n\t\tconst data =\n\t\t\tprops.input.schema &&\n\t\t\t\"enum\" in props.input.schema &&\n\t\t\tArray.isArray(props.input.schema.enum)\n\t\t\t\t? props.input.schema.enum?.map((value: string) => ({\n\t\t\t\t\t\tvalue,\n\t\t\t\t\t\tlabel: value,\n\t\t\t\t\t}))\n\t\t\t\t: [];\n\n\t\tconst selectProps = typeof props.select === \"object\" ? props.select : {};\n\n\t\treturn (\n\t\t\t<Select\n\t\t\t\t{...inputProps}\n\t\t\t\tid={id}\n\t\t\t\tleftSection={icon}\n\t\t\t\tdata={data}\n\t\t\t\t{...props.input.props}\n\t\t\t\t{...selectProps}\n\t\t\t/>\n\t\t);\n\t}\n\t// endregion\n\n\t// region <Switch/>\n\n\tif (\n\t\t(props.input.schema &&\n\t\t\t\"type\" in props.input.schema &&\n\t\t\tprops.input.schema.type === \"boolean\") ||\n\t\tprops.switch\n\t) {\n\t\tconst switchProps = typeof props.switch === \"object\" ? props.switch : {};\n\n\t\treturn (\n\t\t\t<Switch\n\t\t\t\t{...inputProps}\n\t\t\t\tid={id}\n\t\t\t\tcolor={\"blue\"}\n\t\t\t\tdefaultChecked={props.input.props.defaultValue}\n\t\t\t\t{...props.input.props}\n\t\t\t\t{...switchProps}\n\t\t\t/>\n\t\t);\n\t}\n\t// endregion\n\n\t// region <PasswordInput/>\n\tif (props.password) {\n\t\tconst passwordInputProps =\n\t\t\ttypeof props.password === \"object\" ? props.password : {};\n\t\treturn (\n\t\t\t<PasswordInput\n\t\t\t\t{...inputProps}\n\t\t\t\tid={id}\n\t\t\t\tleftSection={icon}\n\t\t\t\t{...props.input.props}\n\t\t\t\t{...passwordInputProps}\n\t\t\t/>\n\t\t);\n\t}\n\t//endregion\n\n\t//region <Textarea/>\n\tif (props.area) {\n\t\tconst textAreaProps = typeof props.area === \"object\" ? props.area : {};\n\t\treturn (\n\t\t\t<Textarea\n\t\t\t\t{...inputProps}\n\t\t\t\tid={id}\n\t\t\t\tleftSection={icon}\n\t\t\t\t{...props.input.props}\n\t\t\t\t{...textAreaProps}\n\t\t\t/>\n\t\t);\n\t}\n\t//endregion\n\n\t// region <TextInput/>\n\tconst textInputProps = typeof props.text === \"object\" ? props.text : {};\n\treturn (\n\t\t<TextInput\n\t\t\t{...inputProps}\n\t\t\tid={id}\n\t\t\tleftSection={icon}\n\t\t\t{...props.input.props}\n\t\t\t{...textInputProps}\n\t\t/>\n\t);\n\t//endregion\n};\n\nexport default Control;\n\nconst prettyName = (name: string) => {\n\treturn capitalize(name.replaceAll(\"/\", \"\"));\n};\n\nconst capitalize = (str: string) => {\n\treturn str.charAt(0).toUpperCase() + str.slice(1);\n};\n\nexport type CustomControlProps = {\n\tdefaultValue: any;\n\tonChange: (value: any) => void;\n};\n","import { $module } from \"@alepha/core\";\nimport { AlephaReact } from \"@alepha/react\";\n\n// ---------------------------------------------------------------------------------------------------------------------\nimport \"@mantine/core/styles.css\";\nimport \"@mantine/nprogress/styles.css\";\nimport \"@mantine/spotlight/styles.css\";\nimport \"@mantine/notifications/styles.css\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport { default as Action } from \"./components/Action\";\nexport { default as AlephaMantineProvider } from \"./components/AlephaMantineProvider.tsx\";\nexport { default as Control } from \"./components/Control\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n *\n *\n * @module alepha.ui\n */\nexport const AlephaUI = $module({\n\tname: \"alepha.ui\",\n\tservices: [AlephaReact],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["Flex","e","itemsEnum: string[] | undefined","items: any","data","Flex","segmentedControlProps: Partial<SegmentedControlProps>","ControlSelect","ControlDate","Flex","schema: any","Control","Action"],"sources":["../src/RootRouter.ts","../src/services/ToastService.tsx","../src/components/Action.tsx","../src/utils/icons.tsx","../src/utils/string.ts","../src/components/ControlDate.tsx","../src/components/ControlSelect.tsx","../src/components/Control.tsx","../src/components/DarkModeButton.tsx","../src/components/TypeForm.tsx","../src/hooks/useToast.ts","../src/index.ts"],"sourcesContent":["import { $page } from \"@alepha/react\";\n\nexport class RootRouter {\n public readonly root = $page({\n path: \"/\",\n lazy: () => import(\"./components/AlephaMantineProvider.tsx\"),\n });\n}\n","import type { NotificationData } from \"@mantine/notifications\";\nimport { notifications } from \"@mantine/notifications\";\nimport {\n IconAlertTriangle,\n IconCheck,\n IconInfoCircle,\n IconX,\n} from \"@tabler/icons-react\";\n\nexport interface ToastServiceOptions {\n default?: Partial<NotificationData>;\n}\n\nexport class ToastService {\n protected readonly raw = notifications;\n\n public readonly options: ToastServiceOptions = {\n default: {\n autoClose: 5000,\n withCloseButton: true,\n position: \"top-center\",\n },\n };\n\n public show(options: NotificationData) {\n notifications.show({\n ...this.options.default,\n ...options,\n });\n }\n\n public info(options: Partial<NotificationData>) {\n this.show({\n color: \"blue\",\n icon: <IconInfoCircle size={20} />,\n title: \"Info\",\n message: \"Information notification\",\n ...options,\n });\n }\n\n public success(options: Partial<NotificationData>) {\n this.show({\n color: \"green\",\n icon: <IconCheck size={16} />,\n title: \"Success\",\n message: \"Operation completed successfully\",\n ...options,\n });\n }\n\n public warning(options: Partial<NotificationData>) {\n this.show({\n color: \"yellow\",\n icon: <IconAlertTriangle size={20} />,\n title: \"Warning\",\n message: \"Please review this warning\",\n ...options,\n });\n }\n\n public danger(options: Partial<NotificationData>) {\n this.show({\n color: \"red\",\n icon: <IconX size={20} />,\n title: \"Error\",\n message: \"An error occurred\",\n ...options,\n });\n }\n}\n","import {\n type RouterGoOptions,\n type UseActiveOptions,\n useActive,\n useAlepha,\n useRouter,\n} from \"@alepha/react\";\nimport { type FormModel, useFormState } from \"@alepha/react-form\";\nimport { Button, type ButtonProps, Flex } from \"@mantine/core\";\nimport { type ReactNode, useState } from \"react\";\n\nexport interface ActionCommonProps extends ButtonProps {\n children?: ReactNode;\n textVisibleFrom?: \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\n // TODO\n\n /**\n * If set, a confirmation dialog will be shown before performing the action.\n * If `true`, a default title and message will be used.\n * If a string, it will be used as the message with a default title.\n * If an object, it can contain `title` and `message` properties to customize the dialog.\n */\n confirm?: boolean | string | { title?: string; message: string };\n}\n\nexport type ActionProps = ActionCommonProps &\n (ActiveHrefProps | ActionClickProps | ActionSubmitProps | {});\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nconst Action = (_props: ActionProps) => {\n const props = { variant: \"subtle\", ..._props };\n\n if (props.leftSection && !props.children) {\n props.className ??= \"mantine-Action-iconOnly\";\n props.p ??= \"xs\";\n }\n\n if (props.textVisibleFrom) {\n const { children, textVisibleFrom, leftSection, ...rest } = props;\n return (\n <>\n <Flex w={\"100%\"} visibleFrom={textVisibleFrom}>\n <Action flex={1} {...rest} leftSection={leftSection}>\n {children}\n </Action>\n </Flex>\n <Flex w={\"100%\"} hiddenFrom={textVisibleFrom}>\n <Action px={\"xs\"} {...rest}>\n {leftSection}\n </Action>\n </Flex>\n </>\n );\n }\n\n const renderAction = () => {\n if (\"href\" in props && props.href) {\n return (\n <ActionHref {...props} href={props.href}>\n {props.children}\n </ActionHref>\n );\n }\n\n if (\"onClick\" in props && props.onClick) {\n return (\n <ActionClick {...props} onClick={props.onClick}>\n {props.children}\n </ActionClick>\n );\n }\n\n if (\"form\" in props && props.form) {\n return (\n <ActionSubmit {...props} form={props.form}>\n {props.children}\n </ActionSubmit>\n );\n }\n\n return <Button {...(props as any)}>{props.children}</Button>;\n };\n\n return renderAction();\n};\n\nexport default Action;\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface ActionSubmitProps extends ButtonProps {\n form: FormModel<any>;\n}\n\n/**\n * Action button that submits a form with loading and disabled state handling.\n */\nconst ActionSubmit = (props: ActionSubmitProps) => {\n const { form, ...buttonProps } = props;\n const state = useFormState(form);\n return (\n <Button\n {...buttonProps}\n loading={state.loading}\n disabled={state.loading}\n type={\"submit\"}\n >\n {props.children}\n </Button>\n );\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface ActionClickProps extends ButtonProps {\n onClick: (e: any) => any;\n}\n\n/**\n * Basic action button that handles click events with loading and error handling.\n */\nconst ActionClick = (props: ActionClickProps) => {\n const [pending, setPending] = useState(false);\n const alepha = useAlepha();\n\n const onClick = async (e: any) => {\n setPending(true);\n try {\n await props.onClick(e);\n } catch (e) {\n console.error(e);\n await alepha.events.emit(\"form:submit:error\", {\n id: \"action\",\n error: e as Error,\n });\n } finally {\n setPending(false);\n }\n };\n\n return (\n <Button\n {...props}\n disabled={pending || props.disabled}\n loading={pending}\n onClick={onClick}\n >\n {props.children}\n </Button>\n );\n};\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport interface ActiveHrefProps extends ButtonProps {\n href: string;\n active?: Partial<UseActiveOptions> | false;\n routerGoOptions?: RouterGoOptions;\n}\n\n/**\n * Action for navigation with active state support.\n */\nconst ActionHref = (props: ActiveHrefProps) => {\n const { active: options, routerGoOptions, ...buttonProps } = props;\n const router = useRouter();\n const { isPending, isActive } = useActive(\n options ? { href: props.href, ...options } : { href: props.href },\n );\n const anchorProps = router.anchor(props.href, routerGoOptions);\n\n return (\n <Button\n component={\"a\"}\n loading={isPending}\n {...anchorProps}\n {...buttonProps}\n variant={isActive && options !== false ? \"filled\" : \"subtle\"}\n >\n {props.children}\n </Button>\n );\n};\n","import {\n IconAt,\n IconCalendar,\n IconClock,\n IconColorPicker,\n IconFile,\n IconHash,\n IconKey,\n IconLetterCase,\n IconLink,\n IconList,\n IconMail,\n IconPalette,\n IconPhone,\n IconSelector,\n IconToggleLeft,\n} from \"@tabler/icons-react\";\nimport type { ReactNode } from \"react\";\n\n/**\n * Icon size presets following Mantine's size conventions\n */\nexport const ICON_SIZES = {\n xs: 12,\n sm: 16,\n md: 20,\n lg: 24,\n xl: 28,\n} as const;\n\nexport type IconSize = keyof typeof ICON_SIZES;\n\n/**\n * Get the default icon for an input based on its type, format, or name.\n */\nexport const getDefaultIcon = (params: {\n type?: string;\n format?: string;\n name?: string;\n isEnum?: boolean;\n isArray?: boolean;\n size?: IconSize;\n}): ReactNode => {\n const { type, format, name, isEnum, isArray, size = \"sm\" } = params;\n const iconSize = ICON_SIZES[size];\n\n // Format-based icons (highest priority)\n if (format) {\n switch (format) {\n case \"email\":\n return <IconMail size={iconSize} />;\n case \"url\":\n case \"uri\":\n return <IconLink size={iconSize} />;\n case \"tel\":\n case \"phone\":\n return <IconPhone size={iconSize} />;\n case \"date\":\n return <IconCalendar size={iconSize} />;\n case \"date-time\":\n return <IconCalendar size={iconSize} />;\n case \"time\":\n return <IconClock size={iconSize} />;\n case \"color\":\n return <IconColorPicker size={iconSize} />;\n case \"uuid\":\n return <IconKey size={iconSize} />;\n }\n }\n\n // Name-based icons (medium priority)\n if (name) {\n const nameLower = name.toLowerCase();\n if (nameLower.includes(\"password\") || nameLower.includes(\"secret\")) {\n return <IconKey size={iconSize} />;\n }\n if (nameLower.includes(\"email\") || nameLower.includes(\"mail\")) {\n return <IconMail size={iconSize} />;\n }\n if (nameLower.includes(\"url\") || nameLower.includes(\"link\")) {\n return <IconLink size={iconSize} />;\n }\n if (nameLower.includes(\"phone\") || nameLower.includes(\"tel\")) {\n return <IconPhone size={iconSize} />;\n }\n if (nameLower.includes(\"color\")) {\n return <IconPalette size={iconSize} />;\n }\n if (nameLower.includes(\"file\") || nameLower.includes(\"upload\")) {\n return <IconFile size={iconSize} />;\n }\n if (nameLower.includes(\"date\")) {\n return <IconCalendar size={iconSize} />;\n }\n if (nameLower.includes(\"time\")) {\n return <IconClock size={iconSize} />;\n }\n }\n\n // Type-based icons (lowest priority)\n if (isEnum || isArray) {\n return <IconSelector size={iconSize} />;\n }\n\n if (type) {\n switch (type) {\n case \"boolean\":\n return <IconToggleLeft size={iconSize} />;\n case \"number\":\n case \"integer\":\n return <IconHash size={iconSize} />;\n case \"array\":\n return <IconList size={iconSize} />;\n case \"string\":\n return <IconLetterCase size={iconSize} />;\n }\n }\n\n // Default icon\n return <IconAt size={iconSize} />;\n};\n","/**\n * Capitalizes the first letter of a string.\n *\n * @example\n * capitalize(\"hello\") // \"Hello\"\n */\nexport const capitalize = (str: string): string => {\n return str.charAt(0).toUpperCase() + str.slice(1);\n};\n\n/**\n * Converts a path or identifier string into a pretty display name.\n * Removes slashes and capitalizes the first letter.\n *\n * @example\n * prettyName(\"/userName\") // \"UserName\"\n * prettyName(\"email\") // \"Email\"\n */\nexport const prettyName = (name: string): string => {\n return capitalize(name.replaceAll(\"/\", \"\"));\n};\n","import { useFormState } from \"@alepha/react-form\";\nimport {\n DateInput,\n type DateInputProps,\n DateTimePicker,\n type DateTimePickerProps,\n TimeInput,\n type TimeInputProps,\n} from \"@mantine/dates\";\nimport { type GenericControlProps, parseInput } from \"./Control.tsx\";\n\nexport interface ControlDateProps extends GenericControlProps {\n date?: boolean | DateInputProps;\n datetime?: boolean | DateTimePickerProps;\n time?: boolean | TimeInputProps;\n}\n\n/**\n * ControlDate component for handling date, datetime, and time inputs.\n *\n * Features:\n * - DateInput for date format\n * - DateTimePicker for date-time format\n * - TimeInput for time format\n *\n * Automatically detects date formats from schema and renders appropriate picker.\n */\nconst ControlDate = (props: ControlDateProps) => {\n const form = useFormState(props.input);\n const { inputProps, id, icon } = parseInput(props, form);\n if (!props.input?.props) {\n return null;\n }\n\n // Detect format from schema\n const format =\n props.input.schema &&\n \"format\" in props.input.schema &&\n typeof props.input.schema.format === \"string\"\n ? props.input.schema.format\n : undefined;\n\n // region <DateTimePicker/>\n if (props.datetime || format === \"date-time\") {\n const dateTimePickerProps =\n typeof props.datetime === \"object\" ? props.datetime : {};\n return (\n <DateTimePicker\n {...inputProps}\n id={id}\n leftSection={icon}\n defaultValue={\n props.input.props.defaultValue\n ? new Date(props.input.props.defaultValue)\n : undefined\n }\n onChange={(value) => {\n props.input.set(value ? new Date(value).toISOString() : undefined);\n }}\n {...dateTimePickerProps}\n />\n );\n }\n //endregion\n\n // region <DateInput/>\n if (props.date || format === \"date\") {\n const dateInputProps = typeof props.date === \"object\" ? props.date : {};\n return (\n <DateInput\n {...inputProps}\n id={id}\n leftSection={icon}\n defaultValue={\n props.input.props.defaultValue\n ? new Date(props.input.props.defaultValue)\n : undefined\n }\n onChange={(value) => {\n props.input.set(\n value ? new Date(value).toISOString().slice(0, 10) : undefined,\n );\n }}\n {...dateInputProps}\n />\n );\n }\n //endregion\n\n // region <TimeInput/>\n if (props.time || format === \"time\") {\n const timeInputProps = typeof props.time === \"object\" ? props.time : {};\n return (\n <TimeInput\n {...inputProps}\n id={id}\n leftSection={icon}\n defaultValue={props.input.props.defaultValue}\n onChange={(event) => {\n props.input.set(event.currentTarget.value);\n }}\n {...timeInputProps}\n />\n );\n }\n //endregion\n\n // Fallback - shouldn't happen\n return null;\n};\n\nexport default ControlDate;\n","import { useFormState } from \"@alepha/react-form\";\nimport {\n MultiSelect,\n type MultiSelectProps,\n Select,\n type SelectProps,\n TagsInput,\n type TagsInputProps,\n} from \"@mantine/core\";\nimport { type GenericControlProps, parseInput } from \"./Control.tsx\";\n\nexport interface ControlSelectProps extends GenericControlProps {\n select?: boolean | SelectProps;\n multi?: boolean | MultiSelectProps;\n tags?: boolean | TagsInputProps;\n}\n\n/**\n * ControlSelect component for handling Select, MultiSelect, and TagsInput.\n *\n * Features:\n * - Basic Select with enum support\n * - MultiSelect for array of enums\n * - TagsInput for array of strings (no enum)\n * - Future: Lazy loading\n * - Future: Searchable/filterable options\n * - Future: Custom option rendering\n *\n * Automatically detects enum values and array types from schema.\n */\nconst ControlSelect = (props: ControlSelectProps) => {\n const form = useFormState(props.input);\n const { inputProps, id, icon } = parseInput(props, form);\n if (!props.input?.props) {\n return null;\n }\n\n // Detect if schema is an array type\n const isArray =\n props.input.schema &&\n \"type\" in props.input.schema &&\n props.input.schema.type === \"array\";\n\n // For arrays, check if items have enum (MultiSelect) or not (TagsInput)\n let itemsEnum: string[] | undefined;\n if (isArray && \"items\" in props.input.schema && props.input.schema.items) {\n const items: any = props.input.schema.items;\n if (\"enum\" in items && Array.isArray(items.enum)) {\n itemsEnum = items.enum;\n }\n }\n\n // Extract enum values from schema (for non-array select)\n const enumValues =\n props.input.schema &&\n \"enum\" in props.input.schema &&\n Array.isArray(props.input.schema.enum)\n ? props.input.schema.enum\n : [];\n\n // region <TagsInput/> - for array of strings without enum\n if ((isArray && !itemsEnum) || props.tags) {\n const tagsInputProps = typeof props.tags === \"object\" ? props.tags : {};\n return (\n <TagsInput\n {...inputProps}\n id={id}\n leftSection={icon}\n defaultValue={\n Array.isArray(props.input.props.defaultValue)\n ? props.input.props.defaultValue\n : []\n }\n onChange={(value) => {\n props.input.set(value);\n }}\n {...tagsInputProps}\n />\n );\n }\n // endregion\n\n // region <MultiSelect/> - for array of enums\n if ((isArray && itemsEnum) || props.multi) {\n const data =\n itemsEnum?.map((value: string) => ({\n value,\n label: value,\n })) || [];\n\n const multiSelectProps = typeof props.multi === \"object\" ? props.multi : {};\n\n return (\n <MultiSelect\n {...inputProps}\n id={id}\n leftSection={icon}\n data={data}\n defaultValue={\n Array.isArray(props.input.props.defaultValue)\n ? props.input.props.defaultValue\n : []\n }\n onChange={(value) => {\n props.input.set(value);\n }}\n {...multiSelectProps}\n />\n );\n }\n // endregion\n\n // region <Select/> - for single enum value\n const data = enumValues.map((value: string) => ({\n value,\n label: value,\n }));\n\n const selectProps = typeof props.select === \"object\" ? props.select : {};\n\n return (\n <Select\n {...inputProps}\n id={id}\n leftSection={icon}\n data={data}\n {...props.input.props}\n {...selectProps}\n />\n );\n // endregion\n};\n\nexport default ControlSelect;\n","import { type TObject, TypeBoxError } from \"@alepha/core\";\nimport {\n type InputField,\n type UseFormStateReturn,\n useFormState,\n} from \"@alepha/react-form\";\nimport {\n Autocomplete,\n type AutocompleteProps,\n ColorInput,\n type ColorInputProps,\n FileInput,\n type FileInputProps,\n Flex,\n Input,\n NumberInput,\n type NumberInputProps,\n PasswordInput,\n type PasswordInputProps,\n SegmentedControl,\n type SegmentedControlProps,\n type SelectProps,\n Switch,\n type SwitchProps,\n Textarea,\n type TextareaProps,\n TextInput,\n type TextInputProps,\n} from \"@mantine/core\";\nimport type {\n DateInputProps,\n DateTimePickerProps,\n TimeInputProps,\n} from \"@mantine/dates\";\nimport type { ComponentType, ReactNode } from \"react\";\nimport { getDefaultIcon } from \"../utils/icons.tsx\";\nimport { prettyName } from \"../utils/string.ts\";\nimport ControlDate from \"./ControlDate\";\nimport ControlSelect from \"./ControlSelect\";\n\nexport interface ControlProps extends GenericControlProps {\n text?: TextInputProps;\n area?: boolean | TextareaProps;\n select?: boolean | SelectProps;\n autocomplete?: boolean | AutocompleteProps;\n password?: boolean | PasswordInputProps;\n switch?: boolean | SwitchProps;\n segmented?: boolean | Partial<SegmentedControlProps>;\n number?: boolean | NumberInputProps;\n file?: boolean | FileInputProps;\n color?: boolean | ColorInputProps;\n date?: boolean | DateInputProps;\n datetime?: boolean | DateTimePickerProps;\n time?: boolean | TimeInputProps;\n custom?: ComponentType<CustomControlProps>;\n}\n\n/**\n * Generic form control that renders the appropriate input based on the schema and props.\n *\n * Supports:\n * - TextInput (with format detection: email, url, tel)\n * - Textarea\n * - NumberInput (for number/integer types)\n * - FileInput\n * - ColorInput (for color format)\n * - Select (for enum types)\n * - Autocomplete\n * - PasswordInput\n * - Switch (for boolean types)\n * - SegmentedControl (for enum types)\n * - DateInput (for date format)\n * - DateTimePicker (for date-time format)\n * - TimeInput (for time format)\n * - Custom component\n *\n * Automatically handles labels, descriptions, error messages, required state, and default icons.\n */\nconst Control = (props: ControlProps) => {\n const form = useFormState(props.input);\n const { inputProps, id, icon } = parseInput(props, form);\n if (!props.input?.props) {\n return null;\n }\n\n // Extract format once to avoid redeclaration\n const format =\n props.input.schema &&\n \"format\" in props.input.schema &&\n typeof props.input.schema.format === \"string\"\n ? props.input.schema.format\n : undefined;\n\n //region <Custom/>\n if (props.custom) {\n const Custom = props.custom;\n return (\n <Input.Wrapper {...inputProps}>\n <Flex flex={1} mt={\"calc(var(--mantine-spacing-xs) / 2)\"}>\n <Custom\n defaultValue={props.input.props.defaultValue}\n onChange={(value) => {\n props.input.set(value);\n }}\n />\n </Flex>\n </Input.Wrapper>\n );\n }\n //endregion\n\n //region <NumberInput/>\n if (\n props.number ||\n (props.input.schema &&\n \"type\" in props.input.schema &&\n (props.input.schema.type === \"number\" ||\n props.input.schema.type === \"integer\"))\n ) {\n const numberInputProps =\n typeof props.number === \"object\" ? props.number : {};\n const { type, ...inputPropsWithoutType } = props.input.props;\n return (\n <NumberInput\n {...inputProps}\n id={id}\n leftSection={icon}\n {...inputPropsWithoutType}\n {...numberInputProps}\n />\n );\n }\n //endregion\n\n //region <FileInput/>\n if (props.file) {\n const fileInputProps = typeof props.file === \"object\" ? props.file : {};\n return (\n <FileInput\n {...inputProps}\n id={id}\n leftSection={icon}\n onChange={(file) => {\n props.input.set(file);\n }}\n {...fileInputProps}\n />\n );\n }\n //endregion\n\n //region <ColorInput/>\n if (props.color || format === \"color\") {\n const colorInputProps = typeof props.color === \"object\" ? props.color : {};\n return (\n <ColorInput\n {...inputProps}\n id={id}\n leftSection={icon}\n {...props.input.props}\n {...colorInputProps}\n />\n );\n }\n //endregion\n\n //region <SegmentedControl/>\n if (props.segmented) {\n const segmentedControlProps: Partial<SegmentedControlProps> =\n typeof props.segmented === \"object\" ? props.segmented : {};\n const data =\n segmentedControlProps.data ??\n (props.input.schema &&\n \"enum\" in props.input.schema &&\n Array.isArray(props.input.schema.enum)\n ? props.input.schema.enum?.map((value: string) => ({\n value,\n label: value,\n }))\n : []);\n return (\n <Input.Wrapper {...inputProps}>\n <Flex mt={\"calc(var(--mantine-spacing-xs) / 2)\"}>\n <SegmentedControl\n disabled={inputProps.disabled}\n defaultValue={String(props.input.props.defaultValue)}\n {...segmentedControlProps}\n onChange={(value) => {\n props.input.set(value);\n }}\n data={data}\n />\n </Flex>\n </Input.Wrapper>\n );\n }\n //endregion\n\n //region <Autocomplete/>\n if (props.autocomplete) {\n const autocompleteProps =\n typeof props.autocomplete === \"object\" ? props.autocomplete : {};\n\n return (\n <Autocomplete\n {...inputProps}\n id={id}\n leftSection={icon}\n {...props.input.props}\n {...autocompleteProps}\n />\n );\n }\n //endregion\n\n //region <ControlSelect/>\n // Handle: single enum, array of enum, array of strings, or explicit select/multi/tags props\n const isEnum =\n props.input.schema &&\n \"enum\" in props.input.schema &&\n props.input.schema.enum;\n const isArray =\n props.input.schema &&\n \"type\" in props.input.schema &&\n props.input.schema.type === \"array\";\n\n if (isEnum || isArray || props.select) {\n return (\n <ControlSelect\n input={props.input}\n title={props.title}\n description={props.description}\n icon={icon}\n select={props.select}\n />\n );\n }\n //endregion\n\n //region <Switch/>\n if (\n (props.input.schema &&\n \"type\" in props.input.schema &&\n props.input.schema.type === \"boolean\") ||\n props.switch\n ) {\n const switchProps = typeof props.switch === \"object\" ? props.switch : {};\n\n return (\n <Switch\n {...inputProps}\n id={id}\n color={\"blue\"}\n defaultChecked={props.input.props.defaultValue}\n {...props.input.props}\n {...switchProps}\n />\n );\n }\n //endregion\n\n //region <PasswordInput/>\n if (props.password || props.input.props.name?.includes(\"password\")) {\n const passwordInputProps =\n typeof props.password === \"object\" ? props.password : {};\n return (\n <PasswordInput\n {...inputProps}\n id={id}\n leftSection={icon}\n {...props.input.props}\n {...passwordInputProps}\n />\n );\n }\n //endregion\n\n //region <Textarea/>\n if (props.area) {\n const textAreaProps = typeof props.area === \"object\" ? props.area : {};\n return (\n <Textarea\n {...inputProps}\n id={id}\n leftSection={icon}\n {...props.input.props}\n {...textAreaProps}\n />\n );\n }\n //endregion\n\n //region <ControlDate/>\n // Handle: date, date-time, and time formats\n if (\n props.date ||\n props.datetime ||\n props.time ||\n format === \"date\" ||\n format === \"date-time\" ||\n format === \"time\"\n ) {\n return (\n <ControlDate\n input={props.input}\n title={props.title}\n description={props.description}\n icon={icon}\n date={props.date}\n datetime={props.datetime}\n time={props.time}\n />\n );\n }\n //endregion\n\n //region <TextInput/> with format detection\n const textInputProps = typeof props.text === \"object\" ? props.text : {};\n\n // Detect HTML5 input type from format\n const getInputType = (): string | undefined => {\n switch (format) {\n case \"email\":\n return \"email\";\n case \"url\":\n case \"uri\":\n return \"url\";\n case \"tel\":\n case \"phone\":\n return \"tel\";\n default:\n return undefined;\n }\n };\n\n return (\n <TextInput\n {...inputProps}\n id={id}\n leftSection={icon}\n type={getInputType()}\n {...props.input.props}\n {...textInputProps}\n />\n );\n //endregion\n};\n\nexport default Control;\n\n// =============================================================================\n// Helper Types and Functions\n// =============================================================================\n\nexport interface GenericControlProps {\n input: InputField;\n title?: string;\n description?: string;\n icon?: ReactNode;\n}\n\nexport const parseInput = (\n props: GenericControlProps,\n form: UseFormStateReturn<TObject>,\n) => {\n const disabled = false; // form.loading;\n const id = props.input.props.id;\n const label =\n props.title ??\n (\"title\" in props.input.schema &&\n typeof props.input.schema.title === \"string\"\n ? props.input.schema.title\n : undefined) ??\n prettyName(props.input.path);\n const description =\n props.description ??\n (\"description\" in props.input.schema &&\n typeof props.input.schema.description === \"string\"\n ? props.input.schema.description\n : undefined);\n const error =\n form.error && form.error instanceof TypeBoxError\n ? form.error.value.message\n : undefined;\n\n // Auto-generate icon if not provided\n const icon =\n props.icon ??\n getDefaultIcon({\n type:\n props.input.schema && \"type\" in props.input.schema\n ? String(props.input.schema.type)\n : undefined,\n format:\n props.input.schema &&\n \"format\" in props.input.schema &&\n typeof props.input.schema.format === \"string\"\n ? props.input.schema.format\n : undefined,\n name: props.input.props.name,\n isEnum:\n props.input.schema &&\n \"enum\" in props.input.schema &&\n Boolean(props.input.schema.enum),\n isArray:\n props.input.schema &&\n \"type\" in props.input.schema &&\n props.input.schema.type === \"array\",\n });\n\n const required = props.input.required;\n\n return {\n id,\n icon,\n inputProps: {\n label,\n description,\n error,\n required,\n disabled,\n },\n };\n};\n\nexport type CustomControlProps = {\n defaultValue: any;\n onChange: (value: any) => void;\n};\n","import {\n ActionIcon,\n Flex,\n SegmentedControl,\n useComputedColorScheme,\n useMantineColorScheme,\n} from \"@mantine/core\";\nimport { IconMoon, IconSun } from \"@tabler/icons-react\";\nimport { useEffect, useState } from \"react\";\n\nexport interface DarkModeButtonProps {\n mode?: \"minimal\" | \"segmented\";\n size?: string | number;\n variant?:\n | \"filled\"\n | \"light\"\n | \"outline\"\n | \"default\"\n | \"subtle\"\n | \"transparent\";\n}\n\nconst DarkModeButton = (props: DarkModeButtonProps) => {\n const { setColorScheme } = useMantineColorScheme();\n const computedColorScheme = useComputedColorScheme(\"light\");\n const [colorScheme, setColorScheme2] = useState(\"default\");\n useEffect(() => {\n setColorScheme2(computedColorScheme);\n }, [computedColorScheme]);\n const mode = props.mode ?? \"minimal\";\n\n const toggleColorScheme = () => {\n setColorScheme(computedColorScheme === \"dark\" ? \"light\" : \"dark\");\n };\n\n if (mode === \"segmented\") {\n return (\n <SegmentedControl\n value={colorScheme}\n onChange={(value) => setColorScheme(value as \"light\" | \"dark\")}\n data={[\n {\n value: \"light\",\n label: (\n <Flex h={20} align=\"center\" justify=\"center\">\n <IconSun size={16} />\n </Flex>\n ),\n },\n {\n value: \"dark\",\n label: (\n <Flex h={20} align=\"center\" justify=\"center\">\n <IconMoon size={16} />\n </Flex>\n ),\n },\n ]}\n />\n );\n }\n\n return (\n <ActionIcon\n onClick={toggleColorScheme}\n variant={props.variant ?? \"default\"}\n size={props.size ?? \"lg\"}\n aria-label=\"Toggle color scheme\"\n >\n {colorScheme === \"dark\" ? <IconSun size={20} /> : <IconMoon size={20} />}\n </ActionIcon>\n );\n};\n\nexport default DarkModeButton;\n","import type { TObject } from \"@alepha/core\";\nimport type { FormModel } from \"@alepha/react-form\";\nimport { Grid, Stack } from \"@mantine/core\";\nimport type { ReactNode } from \"react\";\nimport Action, { type ActionSubmitProps } from \"./Action\";\nimport Control, { type ControlProps } from \"./Control\";\n\nexport interface TypeFormProps<T extends TObject> {\n form: FormModel<T>;\n columns?:\n | number\n | {\n base?: number;\n xs?: number;\n sm?: number;\n md?: number;\n lg?: number;\n xl?: number;\n };\n children?: (input: FormModel<T>[\"input\"]) => ReactNode;\n controlProps?: Partial<Omit<ControlProps, \"input\">>;\n skipFormElement?: boolean;\n skipSubmitButton?: boolean;\n submitButtonProps?: Partial<Omit<ActionSubmitProps, \"form\">>;\n}\n\n/**\n * TypeForm component that automatically renders all form inputs based on schema.\n * Uses the Control component to render individual fields and Mantine Grid for responsive layout.\n *\n * @example\n * ```tsx\n * import { t } from \"alepha\";\n * import { useForm } from \"@alepha/react-form\";\n * import { TypeForm } from \"@alepha/ui\";\n *\n * const form = useForm({\n * schema: t.object({\n * username: t.text(),\n * email: t.text(),\n * age: t.integer(),\n * subscribe: t.boolean(),\n * }),\n * handler: (values) => {\n * console.log(values);\n * },\n * });\n *\n * return <TypeForm form={form} columns={2} />;\n * ```\n */\nconst TypeForm = <T extends TObject>(props: TypeFormProps<T>) => {\n const {\n form,\n columns = 1,\n children,\n controlProps,\n skipFormElement = false,\n skipSubmitButton = false,\n submitButtonProps,\n } = props;\n\n if (!form.options?.schema?.properties) {\n return null;\n }\n\n const fieldNames = Object.keys(form.options.schema.properties);\n\n // Filter out unsupported field types (objects only, arrays are now supported)\n const supportedFields = fieldNames.filter((fieldName) => {\n const field = form.input[fieldName as keyof typeof form.input];\n if (!field || typeof field !== \"object\" || !(\"schema\" in field)) {\n return false;\n }\n\n const schema: any = field.schema;\n\n // Skip if it's an object (not supported by Control)\n // Arrays are now supported via ControlSelect (MultiSelect/TagsInput)\n if (\"type\" in schema) {\n if (schema.type === \"object\") {\n return false;\n }\n }\n\n // Check if it has properties (nested object)\n if (\"properties\" in schema && schema.properties) {\n return false;\n }\n\n return true;\n });\n\n // Handle column configuration with defaults: xs=1, sm=2, lg=3\n const colSpan =\n typeof columns === \"number\"\n ? {\n xs: 12,\n sm: 6,\n lg: 12 / 3,\n }\n : {\n base: columns.base ? 12 / columns.base : undefined,\n xs: columns.xs ? 12 / columns.xs : 12,\n sm: columns.sm ? 12 / columns.sm : 6,\n md: columns.md ? 12 / columns.md : undefined,\n lg: columns.lg ? 12 / columns.lg : 4,\n xl: columns.xl ? 12 / columns.xl : undefined,\n };\n\n const renderFields = () => {\n if (children) {\n return <>{children(form.input)}</>;\n }\n\n return (\n <Grid>\n {supportedFields.map((fieldName) => {\n const field = form.input[fieldName as keyof typeof form.input];\n\n // Type guard to ensure field has the expected structure\n if (!field || typeof field !== \"object\" || !(\"schema\" in field)) {\n return null;\n }\n\n return (\n <Grid.Col key={fieldName} span={colSpan}>\n <Control input={field as any} {...controlProps} />\n </Grid.Col>\n );\n })}\n </Grid>\n );\n };\n\n const content = (\n <Stack>\n {renderFields()}\n {!skipSubmitButton && (\n <Action form={form} {...submitButtonProps}>\n {submitButtonProps?.children ?? \"Submit\"}\n </Action>\n )}\n </Stack>\n );\n\n if (skipFormElement) {\n return content;\n }\n\n return (\n <form onSubmit={form.onSubmit} noValidate>\n {content}\n </form>\n );\n};\n\nexport default TypeForm;\n","import { useInject } from \"@alepha/react\";\nimport { ToastService } from \"../services/ToastService.tsx\";\n\n/**\n * Use this hook to access the Toast Service for showing notifications.\n *\n * @example\n * const toast = useToast();\n * toast.success({ message: \"Operation completed successfully!\" });\n * toast.error({ title: \"Error\", message: \"Something went wrong\" });\n */\nexport const useToast = (): ToastService => {\n return useInject(ToastService);\n};\n","import { $module } from \"@alepha/core\";\nimport { AlephaReact } from \"@alepha/react\";\nimport type { ControlProps } from \"./components/Control.tsx\";\nimport { RootRouter } from \"./RootRouter.ts\";\nimport { ToastService } from \"./services/ToastService.tsx\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport { Flex } from \"@mantine/core\";\nexport { default as Action } from \"./components/Action.tsx\";\nexport { default as AlephaMantineProvider } from \"./components/AlephaMantineProvider.tsx\";\nexport { default as Control } from \"./components/Control.tsx\";\nexport { default as ControlDate } from \"./components/ControlDate.tsx\";\nexport { default as ControlSelect } from \"./components/ControlSelect.tsx\";\nexport { default as DarkModeButton } from \"./components/DarkModeButton.tsx\";\nexport { default as Omnibar } from \"./components/Omnibar.tsx\";\nexport { default as TypeForm } from \"./components/TypeForm.tsx\";\nexport { useToast } from \"./hooks/useToast.ts\";\nexport * from \"./RootRouter.ts\";\nexport { ToastService } from \"./services/ToastService.tsx\";\nexport * from \"./utils/icons.tsx\";\nexport * from \"./utils/string.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\ndeclare module \"typebox\" {\n interface TSchemaOptions {\n $control?: Omit<ControlProps, \"input\">;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n *\n *\n * @module alepha.ui\n */\nexport const AlephaUI = $module({\n name: \"alepha.ui\",\n services: [AlephaReact, ToastService, RootRouter],\n});\n"],"mappings":"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"}
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "mantine"
7
7
  ],
8
8
  "author": "Feunard",
9
- "version": "0.10.6",
9
+ "version": "0.10.7",
10
10
  "type": "module",
11
11
  "engines": {
12
12
  "node": ">=22.0.0"
@@ -19,22 +19,26 @@
19
19
  "src"
20
20
  ],
21
21
  "dependencies": {
22
- "@alepha/core": "0.10.6",
23
- "@alepha/react": "0.10.6",
24
- "@alepha/react-form": "0.10.6",
22
+ "@alepha/core": "0.10.7",
23
+ "@alepha/react": "0.10.7",
24
+ "@alepha/react-form": "0.10.7",
25
25
  "@mantine/core": "^8.3.5",
26
+ "@mantine/dates": "^8.3.5",
26
27
  "@mantine/hooks": "^8.3.5",
27
28
  "@mantine/modals": "^8.3.5",
28
29
  "@mantine/notifications": "^8.3.5",
29
30
  "@mantine/nprogress": "^8.3.5",
30
- "@mantine/spotlight": "^8.3.5"
31
+ "@mantine/spotlight": "^8.3.5",
32
+ "@tabler/icons-react": "^3.35.0"
31
33
  },
32
34
  "devDependencies": {
35
+ "@alepha/vite": "0.10.7",
33
36
  "@biomejs/biome": "^2.2.6",
34
37
  "react": "^19.2.0",
35
38
  "react-dom": "^19.2.0",
36
- "tsdown": "^0.15.7",
39
+ "tsdown": "^0.15.9",
37
40
  "typescript": "^5.9.3",
41
+ "vite": "^7.1.11",
38
42
  "vitest": "^3.2.4"
39
43
  },
40
44
  "peerDependencies": {
@@ -42,6 +46,7 @@
42
46
  "react-dom": "*"
43
47
  },
44
48
  "scripts": {
49
+ "dev": "vite dev",
45
50
  "test": "vitest run",
46
51
  "lint": "biome check --write --unsafe",
47
52
  "build": "tsdown -c ../../tsdown.config.ts",
@@ -0,0 +1,8 @@
1
+ import { $page } from "@alepha/react";
2
+
3
+ export class RootRouter {
4
+ public readonly root = $page({
5
+ path: "/",
6
+ lazy: () => import("./components/AlephaMantineProvider.tsx"),
7
+ });
8
+ }
@@ -1,88 +1,88 @@
1
1
  import {
2
- type RouterGoOptions,
3
- type UseActiveOptions,
4
- useActive,
5
- useAlepha,
6
- useRouter,
2
+ type RouterGoOptions,
3
+ type UseActiveOptions,
4
+ useActive,
5
+ useAlepha,
6
+ useRouter,
7
7
  } from "@alepha/react";
8
8
  import { type FormModel, useFormState } from "@alepha/react-form";
9
9
  import { Button, type ButtonProps, Flex } from "@mantine/core";
10
10
  import { type ReactNode, useState } from "react";
11
11
 
12
12
  export interface ActionCommonProps extends ButtonProps {
13
- children?: ReactNode;
14
- textVisibleFrom?: "xs" | "sm" | "md" | "lg" | "xl";
15
- // TODO
16
-
17
- /**
18
- * If set, a confirmation dialog will be shown before performing the action.
19
- * If `true`, a default title and message will be used.
20
- * If a string, it will be used as the message with a default title.
21
- * If an object, it can contain `title` and `message` properties to customize the dialog.
22
- */
23
- confirm?: boolean | string | { title?: string; message: string };
13
+ children?: ReactNode;
14
+ textVisibleFrom?: "xs" | "sm" | "md" | "lg" | "xl";
15
+ // TODO
16
+
17
+ /**
18
+ * If set, a confirmation dialog will be shown before performing the action.
19
+ * If `true`, a default title and message will be used.
20
+ * If a string, it will be used as the message with a default title.
21
+ * If an object, it can contain `title` and `message` properties to customize the dialog.
22
+ */
23
+ confirm?: boolean | string | { title?: string; message: string };
24
24
  }
25
25
 
26
26
  export type ActionProps = ActionCommonProps &
27
- (ActiveHrefProps | ActionClickProps | ActionSubmitProps | {});
27
+ (ActiveHrefProps | ActionClickProps | ActionSubmitProps | {});
28
28
 
29
29
  // ---------------------------------------------------------------------------------------------------------------------
30
30
 
31
31
  const Action = (_props: ActionProps) => {
32
- const props = { variant: "subtle", ..._props };
33
-
34
- if (props.leftSection && !props.children) {
35
- props.className ??= "mantine-Action-iconOnly";
36
- props.p ??= "xs";
37
- }
38
-
39
- if (props.textVisibleFrom) {
40
- const { children, textVisibleFrom, leftSection, ...rest } = props;
41
- return (
42
- <>
43
- <Flex w={"100%"} visibleFrom={textVisibleFrom}>
44
- <Action flex={1} {...rest} leftSection={leftSection}>
45
- {children}
46
- </Action>
47
- </Flex>
48
- <Flex w={"100%"} hiddenFrom={textVisibleFrom}>
49
- <Action px={"xs"} {...rest}>
50
- {leftSection}
51
- </Action>
52
- </Flex>
53
- </>
54
- );
55
- }
56
-
57
- const renderAction = () => {
58
- if ("href" in props && props.href) {
59
- return (
60
- <ActionHref {...props} href={props.href}>
61
- {props.children}
62
- </ActionHref>
63
- );
64
- }
65
-
66
- if ("onClick" in props && props.onClick) {
67
- return (
68
- <ActionClick {...props} onClick={props.onClick}>
69
- {props.children}
70
- </ActionClick>
71
- );
72
- }
73
-
74
- if ("form" in props && props.form) {
75
- return (
76
- <ActionSubmit {...props} form={props.form}>
77
- {props.children}
78
- </ActionSubmit>
79
- );
80
- }
81
-
82
- return <Button {...(props as any)}>{props.children}</Button>;
83
- };
84
-
85
- return renderAction();
32
+ const props = { variant: "subtle", ..._props };
33
+
34
+ if (props.leftSection && !props.children) {
35
+ props.className ??= "mantine-Action-iconOnly";
36
+ props.p ??= "xs";
37
+ }
38
+
39
+ if (props.textVisibleFrom) {
40
+ const { children, textVisibleFrom, leftSection, ...rest } = props;
41
+ return (
42
+ <>
43
+ <Flex w={"100%"} visibleFrom={textVisibleFrom}>
44
+ <Action flex={1} {...rest} leftSection={leftSection}>
45
+ {children}
46
+ </Action>
47
+ </Flex>
48
+ <Flex w={"100%"} hiddenFrom={textVisibleFrom}>
49
+ <Action px={"xs"} {...rest}>
50
+ {leftSection}
51
+ </Action>
52
+ </Flex>
53
+ </>
54
+ );
55
+ }
56
+
57
+ const renderAction = () => {
58
+ if ("href" in props && props.href) {
59
+ return (
60
+ <ActionHref {...props} href={props.href}>
61
+ {props.children}
62
+ </ActionHref>
63
+ );
64
+ }
65
+
66
+ if ("onClick" in props && props.onClick) {
67
+ return (
68
+ <ActionClick {...props} onClick={props.onClick}>
69
+ {props.children}
70
+ </ActionClick>
71
+ );
72
+ }
73
+
74
+ if ("form" in props && props.form) {
75
+ return (
76
+ <ActionSubmit {...props} form={props.form}>
77
+ {props.children}
78
+ </ActionSubmit>
79
+ );
80
+ }
81
+
82
+ return <Button {...(props as any)}>{props.children}</Button>;
83
+ };
84
+
85
+ return renderAction();
86
86
  };
87
87
 
88
88
  export default Action;
@@ -90,95 +90,95 @@ export default Action;
90
90
  // ---------------------------------------------------------------------------------------------------------------------
91
91
 
92
92
  export interface ActionSubmitProps extends ButtonProps {
93
- form: FormModel<any>;
93
+ form: FormModel<any>;
94
94
  }
95
95
 
96
96
  /**
97
97
  * Action button that submits a form with loading and disabled state handling.
98
98
  */
99
99
  const ActionSubmit = (props: ActionSubmitProps) => {
100
- const { form, ...buttonProps } = props;
101
- const state = useFormState(form);
102
- return (
103
- <Button
104
- {...buttonProps}
105
- loading={state.loading}
106
- disabled={state.loading || !state.dirty}
107
- type={"submit"}
108
- >
109
- {props.children}
110
- </Button>
111
- );
100
+ const { form, ...buttonProps } = props;
101
+ const state = useFormState(form);
102
+ return (
103
+ <Button
104
+ {...buttonProps}
105
+ loading={state.loading}
106
+ disabled={state.loading}
107
+ type={"submit"}
108
+ >
109
+ {props.children}
110
+ </Button>
111
+ );
112
112
  };
113
113
 
114
114
  // ---------------------------------------------------------------------------------------------------------------------
115
115
 
116
116
  export interface ActionClickProps extends ButtonProps {
117
- onClick: (e: any) => any;
117
+ onClick: (e: any) => any;
118
118
  }
119
119
 
120
120
  /**
121
121
  * Basic action button that handles click events with loading and error handling.
122
122
  */
123
123
  const ActionClick = (props: ActionClickProps) => {
124
- const [pending, setPending] = useState(false);
125
- const alepha = useAlepha();
126
-
127
- const onClick = async (e: any) => {
128
- setPending(true);
129
- try {
130
- await props.onClick(e);
131
- } catch (e) {
132
- console.error(e);
133
- await alepha.events.emit("form:submit:error", {
134
- id: "action",
135
- error: e as Error,
136
- });
137
- } finally {
138
- setPending(false);
139
- }
140
- };
141
-
142
- return (
143
- <Button
144
- {...props}
145
- disabled={pending || props.disabled}
146
- loading={pending}
147
- onClick={onClick}
148
- >
149
- {props.children}
150
- </Button>
151
- );
124
+ const [pending, setPending] = useState(false);
125
+ const alepha = useAlepha();
126
+
127
+ const onClick = async (e: any) => {
128
+ setPending(true);
129
+ try {
130
+ await props.onClick(e);
131
+ } catch (e) {
132
+ console.error(e);
133
+ await alepha.events.emit("form:submit:error", {
134
+ id: "action",
135
+ error: e as Error,
136
+ });
137
+ } finally {
138
+ setPending(false);
139
+ }
140
+ };
141
+
142
+ return (
143
+ <Button
144
+ {...props}
145
+ disabled={pending || props.disabled}
146
+ loading={pending}
147
+ onClick={onClick}
148
+ >
149
+ {props.children}
150
+ </Button>
151
+ );
152
152
  };
153
153
 
154
154
  // ---------------------------------------------------------------------------------------------------------------------
155
155
 
156
156
  export interface ActiveHrefProps extends ButtonProps {
157
- href: string;
158
- active?: Partial<UseActiveOptions> | false;
159
- routerGoOptions?: RouterGoOptions;
157
+ href: string;
158
+ active?: Partial<UseActiveOptions> | false;
159
+ routerGoOptions?: RouterGoOptions;
160
160
  }
161
161
 
162
162
  /**
163
163
  * Action for navigation with active state support.
164
164
  */
165
165
  const ActionHref = (props: ActiveHrefProps) => {
166
- const { active: options, routerGoOptions, ...buttonProps } = props;
167
- const router = useRouter();
168
- const { isPending, isActive } = useActive(
169
- options ? { href: props.href, ...options } : { href: props.href },
170
- );
171
- const anchorProps = router.anchor(props.href, routerGoOptions);
172
-
173
- return (
174
- <Button
175
- component={"a"}
176
- loading={isPending}
177
- {...anchorProps}
178
- {...buttonProps}
179
- variant={isActive && options !== false ? "filled" : "subtle"}
180
- >
181
- {props.children}
182
- </Button>
183
- );
166
+ const { active: options, routerGoOptions, ...buttonProps } = props;
167
+ const router = useRouter();
168
+ const { isPending, isActive } = useActive(
169
+ options ? { href: props.href, ...options } : { href: props.href },
170
+ );
171
+ const anchorProps = router.anchor(props.href, routerGoOptions);
172
+
173
+ return (
174
+ <Button
175
+ component={"a"}
176
+ loading={isPending}
177
+ {...anchorProps}
178
+ {...buttonProps}
179
+ variant={isActive && options !== false ? "filled" : "subtle"}
180
+ >
181
+ {props.children}
182
+ </Button>
183
+ );
184
184
  };
@@ -1,7 +1,7 @@
1
1
  import { NestedView, useRouterEvents } from "@alepha/react";
2
2
  import type {
3
- ColorSchemeScriptProps,
4
- MantineProviderProps,
3
+ ColorSchemeScriptProps,
4
+ MantineProviderProps,
5
5
  } from "@mantine/core";
6
6
  import { ColorSchemeScript, MantineProvider } from "@mantine/core";
7
7
  import { ModalsProvider, type ModalsProviderProps } from "@mantine/modals";
@@ -9,41 +9,44 @@ import { Notifications, type NotificationsProps } from "@mantine/notifications";
9
9
  import type { NavigationProgressProps } from "@mantine/nprogress";
10
10
  import { NavigationProgress, nprogress } from "@mantine/nprogress";
11
11
  import type { ReactNode } from "react";
12
+ import Omnibar, { type OmnibarProps } from "./Omnibar";
12
13
 
13
14
  export interface AlephaMantineProviderProps {
14
- children?: ReactNode;
15
- mantine?: MantineProviderProps;
16
- colorSchemeScript?: ColorSchemeScriptProps;
17
- navigationProgress?: NavigationProgressProps;
18
- notifications?: NotificationsProps;
19
- modals?: ModalsProviderProps;
15
+ children?: ReactNode;
16
+ mantine?: MantineProviderProps;
17
+ colorSchemeScript?: ColorSchemeScriptProps;
18
+ navigationProgress?: NavigationProgressProps;
19
+ notifications?: NotificationsProps;
20
+ modals?: ModalsProviderProps;
21
+ omnibar?: OmnibarProps;
20
22
  }
21
23
 
22
24
  const AlephaMantineProvider = (props: AlephaMantineProviderProps) => {
23
- useRouterEvents({
24
- onBegin: () => {
25
- nprogress.start();
26
- },
27
- onEnd: () => {
28
- nprogress.complete();
29
- },
30
- });
25
+ useRouterEvents({
26
+ onBegin: () => {
27
+ nprogress.start();
28
+ },
29
+ onEnd: () => {
30
+ nprogress.complete();
31
+ },
32
+ });
31
33
 
32
- return (
33
- <>
34
- <ColorSchemeScript
35
- defaultColorScheme={props.mantine?.defaultColorScheme}
36
- {...props.colorSchemeScript}
37
- />
38
- <MantineProvider {...props.mantine}>
39
- <Notifications {...props.notifications} />
40
- <NavigationProgress {...props.navigationProgress} />
41
- <ModalsProvider {...props.modals}>
42
- {props.children ?? <NestedView />}
43
- </ModalsProvider>
44
- </MantineProvider>
45
- </>
46
- );
34
+ return (
35
+ <>
36
+ <ColorSchemeScript
37
+ defaultColorScheme={props.mantine?.defaultColorScheme}
38
+ {...props.colorSchemeScript}
39
+ />
40
+ <MantineProvider {...props.mantine}>
41
+ <Notifications {...props.notifications} />
42
+ <NavigationProgress {...props.navigationProgress} />
43
+ <ModalsProvider {...props.modals}>
44
+ <Omnibar {...props.omnibar} />
45
+ {props.children ?? <NestedView />}
46
+ </ModalsProvider>
47
+ </MantineProvider>
48
+ </>
49
+ );
47
50
  };
48
51
 
49
52
  export default AlephaMantineProvider;