@jameskabz/nextcraft-ui 0.5.0 → 0.6.1

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.
Files changed (59) hide show
  1. package/README.md +94 -0
  2. package/dist/chunk-6F7FN2ZF.js +671 -0
  3. package/dist/chunk-6F7FN2ZF.js.map +1 -0
  4. package/dist/chunk-7Q4Z47HT.js +657 -0
  5. package/dist/chunk-7Q4Z47HT.js.map +1 -0
  6. package/dist/chunk-7SKDTIEK.js +49 -0
  7. package/dist/chunk-7SKDTIEK.js.map +1 -0
  8. package/dist/chunk-FEFH5O5K.js +49 -0
  9. package/dist/chunk-FEFH5O5K.js.map +1 -0
  10. package/dist/chunk-M2EKVXB6.js +127 -0
  11. package/dist/chunk-M2EKVXB6.js.map +1 -0
  12. package/dist/chunk-SBLIF6UU.js +1029 -0
  13. package/dist/chunk-SBLIF6UU.js.map +1 -0
  14. package/dist/chunk-VQ6T3HIX.js +9 -0
  15. package/dist/chunk-VQ6T3HIX.js.map +1 -0
  16. package/dist/chunk-YVZL4GET.js +328 -0
  17. package/dist/chunk-YVZL4GET.js.map +1 -0
  18. package/dist/chunk-ZRV4Y374.js +582 -0
  19. package/dist/chunk-ZRV4Y374.js.map +1 -0
  20. package/dist/craft/components.cjs +1838 -0
  21. package/dist/craft/components.cjs.map +1 -0
  22. package/dist/craft/components.d.cts +369 -0
  23. package/dist/craft/components.d.ts +369 -0
  24. package/dist/craft/components.js +78 -0
  25. package/dist/craft/components.js.map +1 -0
  26. package/dist/craft/forms.cjs +1376 -0
  27. package/dist/craft/forms.cjs.map +1 -0
  28. package/dist/craft/forms.d.cts +101 -0
  29. package/dist/craft/forms.d.ts +101 -0
  30. package/dist/craft/forms.js +14 -0
  31. package/dist/craft/forms.js.map +1 -0
  32. package/dist/craft/layout.cjs +410 -0
  33. package/dist/craft/layout.cjs.map +1 -0
  34. package/dist/craft/layout.d.cts +170 -0
  35. package/dist/craft/layout.d.ts +170 -0
  36. package/dist/craft/layout.js +27 -0
  37. package/dist/craft/layout.js.map +1 -0
  38. package/dist/craft/table.cjs +662 -0
  39. package/dist/craft/table.cjs.map +1 -0
  40. package/dist/craft/table.d.cts +99 -0
  41. package/dist/craft/table.d.ts +99 -0
  42. package/dist/craft/table.js +15 -0
  43. package/dist/craft/table.js.map +1 -0
  44. package/dist/craft/theme.cjs +166 -0
  45. package/dist/craft/theme.cjs.map +1 -0
  46. package/dist/craft/theme.d.cts +10 -0
  47. package/dist/craft/theme.d.ts +10 -0
  48. package/dist/craft/theme.js +12 -0
  49. package/dist/craft/theme.js.map +1 -0
  50. package/dist/index.cjs +1000 -299
  51. package/dist/index.cjs.map +1 -1
  52. package/dist/index.d.cts +10 -499
  53. package/dist/index.d.ts +10 -499
  54. package/dist/index.js +81 -2689
  55. package/dist/index.js.map +1 -1
  56. package/dist/styles.css +124 -0
  57. package/dist/theme-context-EVI9PfKv.d.cts +22 -0
  58. package/dist/theme-context-EVI9PfKv.d.ts +22 -0
  59. package/package.json +28 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/craft-form.tsx","../src/components/craft-form-field.tsx","../src/components/craft-form-builder.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { FormProvider, type FieldValues, type UseFormReturn } from \"react-hook-form\";\n\nimport { cn } from \"@/utils/cn\";\nimport type { ThemeName } from \"@/theme/theme-context\";\nimport { CraftModal } from \"@/components/craft-modal\";\nimport { CraftButton } from \"@/components/craft-button\";\nimport { CraftSubmitButton } from \"@/components/craft-submit-button\";\n\nexport type CraftFormProps<TValues extends FieldValues> = {\n form: UseFormReturn<TValues>;\n onSubmit: (values: TValues) => void | Promise<void>;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n trigger?: React.ReactNode;\n title?: React.ReactNode;\n description?: React.ReactNode;\n submitLabel?: React.ReactNode;\n cancelLabel?: React.ReactNode;\n tone?: ThemeName;\n className?: string;\n children?: React.ReactNode;\n footer?: React.ReactNode;\n disableSubmitWhenInvalid?: boolean;\n closeOnSubmit?: boolean;\n formClassName?: string;\n};\n\nexport function CraftForm<TValues extends FieldValues>({\n form,\n onSubmit,\n open,\n defaultOpen = false,\n onOpenChange,\n trigger,\n title,\n description,\n submitLabel = \"Save\",\n cancelLabel = \"Cancel\",\n tone,\n className,\n children,\n footer,\n disableSubmitWhenInvalid = true,\n closeOnSubmit = true,\n formClassName,\n}: CraftFormProps<TValues>) {\n const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen);\n const isControlled = typeof open === \"boolean\";\n const isOpen = isControlled ? open : uncontrolledOpen;\n\n const setOpen = React.useCallback(\n (next: boolean) => {\n if (!isControlled) setUncontrolledOpen(next);\n onOpenChange?.(next);\n },\n [isControlled, onOpenChange]\n );\n\n const formId = React.useId();\n\n const handleSubmit = form.handleSubmit(async (values) => {\n await onSubmit(values);\n if (closeOnSubmit) setOpen(false);\n });\n\n const footerContent = footer ?? (\n <div className=\"flex flex-wrap items-center justify-end gap-3\">\n <CraftButton type=\"button\" variant=\"ghost\" onClick={() => setOpen(false)}>\n {cancelLabel}\n </CraftButton>\n <CraftSubmitButton\n form={formId}\n disableWhenInvalid={disableSubmitWhenInvalid}\n >\n {submitLabel}\n </CraftSubmitButton>\n </div>\n );\n\n return (\n <FormProvider {...form}>\n <CraftModal\n open={isOpen}\n onOpenChange={setOpen}\n trigger={trigger}\n title={title}\n description={description}\n tone={tone}\n className={className}\n footer={footerContent}\n >\n <form\n id={formId}\n onSubmit={handleSubmit}\n className={cn(\"space-y-5\", formClassName)}\n >\n {children}\n </form>\n </CraftModal>\n </FormProvider>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport {\n Controller,\n type FieldValues,\n type Path,\n type RegisterOptions,\n useFormContext,\n} from \"react-hook-form\";\n\nimport { cn } from \"@/utils/cn\";\nimport type { ThemeName } from \"@/theme/theme-context\";\nimport { CraftInput } from \"@/components/craft-input\";\nimport { CraftTextarea } from \"@/components/craft-textarea\";\nimport { CraftSelect } from \"@/components/craft-select\";\nimport { CraftCheckbox } from \"@/components/craft-checkbox\";\nimport { CraftSwitch } from \"@/components/craft-switch\";\nimport { CraftDatePicker } from \"@/components/craft-date-picker\";\nimport { CraftNumberInput } from \"@/components/craft-number-input\";\nimport { CraftCurrencyInput } from \"@/components/craft-currency-input\";\n\nexport type CraftFormFieldOption = {\n label: React.ReactNode;\n value: string;\n disabled?: boolean;\n};\n\nexport type CraftFormFieldType =\n | \"text\"\n | \"number\"\n | \"password\"\n | \"textarea\"\n | \"select\"\n | \"checkbox\"\n | \"slider\"\n | \"date\"\n | \"color\"\n | \"email\"\n | \"tel\"\n | \"url\"\n | \"time\"\n | \"datetime-local\"\n | \"month\"\n | \"week\"\n | \"file\"\n | \"multifile\"\n | \"radio\"\n | \"switch\"\n | \"range\"\n | \"search\"\n | \"hidden\"\n | \"multiselect\"\n | \"currency\";\n\nexport type CraftFormFieldProps<TValues extends FieldValues = FieldValues> = {\n name: Path<TValues>;\n label?: React.ReactNode;\n description?: React.ReactNode;\n type?: CraftFormFieldType;\n options?: CraftFormFieldOption[];\n placeholder?: string;\n tone?: ThemeName;\n className?: string;\n inputClassName?: string;\n labelClassName?: string;\n descriptionClassName?: string;\n rules?: RegisterOptions<TValues>;\n disabled?: boolean;\n fieldProps?: Record<string, unknown>;\n};\n\nfunction getFieldError(errors: unknown, name: string) {\n if (!errors || typeof errors !== \"object\") return undefined;\n const segments = name.split(\".\");\n let current: unknown = errors;\n for (const segment of segments) {\n if (!current || typeof current !== \"object\") return undefined;\n current = (current as Record<string, unknown>)[segment];\n }\n return current;\n}\n\nconst baseInputClass =\n \"w-full rounded-2xl border-2 bg-[rgb(var(--nc-surface)/0.08)] text-[rgb(var(--nc-fg))] backdrop-blur-xl shadow-[inset_0_2px_8px_rgba(0,0,0,0.3)] focus:outline-none focus:ring-4 transition-all duration-300 disabled:opacity-50 disabled:cursor-not-allowed border-[rgb(var(--nc-border)/0.35)] focus:border-[rgb(var(--nc-accent-1)/0.8)] focus:ring-[rgb(var(--nc-accent-1)/0.3)] px-5 py-3 text-base placeholder:text-[rgb(var(--nc-fg-soft))]\";\n\nexport function CraftFormField<TValues extends FieldValues = FieldValues>({\n name,\n label,\n description,\n type = \"text\",\n options = [],\n placeholder,\n tone,\n className,\n inputClassName,\n labelClassName,\n descriptionClassName,\n rules,\n disabled,\n fieldProps,\n}: CraftFormFieldProps<TValues>) {\n const { register, control, formState } = useFormContext<TValues>();\n const error = getFieldError(formState.errors, name);\n const errorMessage =\n typeof (error as { message?: unknown })?.message === \"string\"\n ? (error as { message: string }).message\n : undefined;\n\n if (type === \"hidden\") {\n return <input type=\"hidden\" {...register(name, rules)} />;\n }\n\n const labelNode = label ? (\n <label\n htmlFor={name}\n className={cn(\n \"text-sm font-semibold text-[rgb(var(--nc-fg))]\",\n labelClassName\n )}\n >\n {label}\n </label>\n ) : null;\n\n const descriptionNode = description ? (\n <p\n className={cn(\n \"text-xs text-[rgb(var(--nc-fg-muted))]\",\n descriptionClassName\n )}\n >\n {description}\n </p>\n ) : null;\n\n const errorNode = errorMessage ? (\n <p className=\"text-xs text-[rgb(var(--nc-accent-3))]\">{errorMessage}</p>\n ) : null;\n\n const renderInput = () => {\n if (type === \"textarea\") {\n return (\n <CraftTextarea\n id={name}\n placeholder={placeholder}\n tone={tone}\n className={inputClassName}\n disabled={disabled}\n {...(fieldProps as Record<string, unknown>)}\n {...register(name, rules)}\n />\n );\n }\n\n if (type === \"select\" || type === \"multiselect\") {\n return (\n <CraftSelect\n id={name}\n tone={tone}\n className={inputClassName}\n multiple={type === \"multiselect\"}\n disabled={disabled}\n {...(fieldProps as Record<string, unknown>)}\n {...register(name, rules)}\n >\n {placeholder && (\n <option value=\"\" disabled>\n {placeholder}\n </option>\n )}\n {options.map((option) => (\n <option\n key={option.value}\n value={option.value}\n disabled={option.disabled}\n >\n {option.label}\n </option>\n ))}\n </CraftSelect>\n );\n }\n\n if (type === \"checkbox\") {\n return (\n <CraftCheckbox\n tone={tone}\n label={label}\n description={description}\n disabled={disabled}\n {...(fieldProps as Record<string, unknown>)}\n {...register(name, rules)}\n />\n );\n }\n\n if (type === \"switch\") {\n return (\n <CraftSwitch\n tone={tone}\n label={label}\n disabled={disabled}\n {...(fieldProps as Record<string, unknown>)}\n {...register(name, rules)}\n />\n );\n }\n\n if (type === \"date\") {\n return (\n <Controller\n control={control}\n name={name}\n rules={rules}\n render={({ field }) => (\n <CraftDatePicker\n value={field.value ?? \"\"}\n onChange={field.onChange}\n tone={tone}\n placeholder={placeholder}\n {...(fieldProps as Record<string, unknown>)}\n />\n )}\n />\n );\n }\n\n if (type === \"number\") {\n return (\n <CraftNumberInput\n id={name}\n tone={tone}\n placeholder={placeholder}\n className={inputClassName}\n disabled={disabled}\n {...(fieldProps as Record<string, unknown>)}\n {...register(name, rules)}\n />\n );\n }\n\n if (type === \"currency\") {\n return (\n <CraftCurrencyInput\n id={name}\n tone={tone}\n placeholder={placeholder}\n className={inputClassName}\n disabled={disabled}\n {...(fieldProps as Record<string, unknown>)}\n {...register(name, rules)}\n />\n );\n }\n\n if (type === \"radio\") {\n return (\n <div className=\"grid gap-3\">\n {options.map((option) => (\n <label\n key={option.value}\n className={cn(\n \"flex items-center gap-3 rounded-2xl border border-[rgb(var(--nc-border)/0.35)] bg-[rgb(var(--nc-surface)/0.08)] px-4 py-3 text-sm text-[rgb(var(--nc-fg))]\",\n \"transition-all duration-200\",\n \"focus-within:ring-2 focus-within:ring-[rgb(var(--nc-accent-1)/0.5)]\",\n option.disabled ? \"opacity-60\" : \"cursor-pointer\"\n )}\n data-nc-theme={tone}\n >\n <input\n type=\"radio\"\n value={option.value}\n disabled={option.disabled || disabled}\n className=\"h-4 w-4 accent-[rgb(var(--nc-accent-1))]\"\n {...(fieldProps as Record<string, unknown>)}\n {...register(name, rules)}\n />\n <span>{option.label}</span>\n </label>\n ))}\n </div>\n );\n }\n\n if (type === \"range\" || type === \"slider\") {\n return (\n <input\n id={name}\n type=\"range\"\n className={cn(\n \"w-full accent-[rgb(var(--nc-accent-1))]\",\n inputClassName\n )}\n disabled={disabled}\n {...(fieldProps as Record<string, unknown>)}\n {...register(name, rules)}\n />\n );\n }\n\n if (type === \"file\" || type === \"multifile\") {\n return (\n <input\n id={name}\n type=\"file\"\n multiple={type === \"multifile\"}\n className={cn(\n baseInputClass,\n \"file:mr-4 file:rounded-xl file:border-0 file:bg-[rgb(var(--nc-surface)/0.35)] file:px-4 file:py-2 file:text-sm file:font-semibold file:text-[rgb(var(--nc-fg))]\",\n inputClassName\n )}\n disabled={disabled}\n {...(fieldProps as Record<string, unknown>)}\n {...register(name, rules)}\n />\n );\n }\n\n const inputType =\n type === \"search\" ||\n type === \"password\" ||\n type === \"email\" ||\n type === \"tel\" ||\n type === \"url\" ||\n type === \"time\" ||\n type === \"datetime-local\" ||\n type === \"month\" ||\n type === \"week\" ||\n type === \"color\"\n ? type\n : \"text\";\n\n return (\n <CraftInput\n id={name}\n type={inputType}\n placeholder={placeholder}\n tone={tone}\n className={inputClassName}\n disabled={disabled}\n {...(fieldProps as Record<string, unknown>)}\n {...register(name, rules)}\n />\n );\n };\n\n const showLabel = type !== \"checkbox\" && type !== \"switch\";\n const showDescriptionAbove = type !== \"checkbox\" && type !== \"switch\";\n const showDescriptionBelow = type === \"switch\";\n\n return (\n <div className={cn(\"space-y-2\", className)} data-nc-theme={tone}>\n {showLabel ? labelNode : null}\n {showDescriptionAbove ? descriptionNode : null}\n {renderInput()}\n {showDescriptionBelow ? descriptionNode : null}\n {errorNode}\n </div>\n );\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport {\n FormProvider,\n type DefaultValues,\n type FieldValues,\n type Path,\n type RegisterOptions,\n useForm,\n} from \"react-hook-form\";\n\nimport { cn } from \"@/utils/cn\";\nimport type { ThemeName } from \"@/theme/theme-context\";\nimport { CraftModal } from \"@/components/craft-modal\";\nimport { CraftButton } from \"@/components/craft-button\";\nimport { CraftSubmitButton } from \"@/components/craft-submit-button\";\nimport {\n CraftFormField,\n type CraftFormFieldOption,\n type CraftFormFieldType,\n} from \"@/components/craft-form-field\";\n\nexport type CraftFormBuilderField<TValues extends FieldValues> = {\n name: Path<TValues>;\n label?: React.ReactNode;\n description?: React.ReactNode;\n type: CraftFormFieldType;\n placeholder?: string;\n options?: CraftFormFieldOption[];\n required?: boolean;\n disabled?: boolean;\n rules?: RegisterOptions<TValues>;\n defaultValue?: unknown;\n min?: number;\n max?: number;\n step?: number;\n rows?: number;\n accept?: string;\n minFiles?: number;\n maxFiles?: number;\n helpText?: React.ReactNode;\n fieldProps?: Record<string, unknown>;\n validate?: (value: unknown, values: TValues) => string | boolean | undefined;\n};\n\nexport type CraftFormBuilderProps<TValues extends FieldValues> = {\n title?: React.ReactNode;\n description?: React.ReactNode;\n fields: Array<CraftFormBuilderField<TValues>>;\n initialData?: Partial<TValues> | null;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n trigger?: React.ReactNode;\n submitLabel?: React.ReactNode;\n cancelLabel?: React.ReactNode;\n resetLabel?: React.ReactNode;\n showReset?: boolean;\n showCancel?: boolean;\n tone?: ThemeName;\n className?: string;\n formClassName?: string;\n loading?: boolean;\n disableSubmitWhenInvalid?: boolean;\n closeOnSubmit?: boolean;\n closeOnCancel?: boolean;\n onSubmit: (values: TValues) => void | Promise<void>;\n onReset?: () => void;\n onCancel?: () => void;\n customValidation?: (values: TValues) => Partial<Record<Path<TValues>, string>>;\n};\n\nfunction defaultValueForField<TValues extends FieldValues>(\n field: CraftFormBuilderField<TValues>\n) {\n if (field.defaultValue !== undefined) return field.defaultValue;\n switch (field.type) {\n case \"checkbox\":\n case \"switch\":\n return false;\n case \"number\":\n case \"slider\":\n case \"range\":\n return field.min ?? 0;\n case \"multifile\":\n return [];\n case \"file\":\n return null;\n case \"multiselect\":\n return [];\n case \"radio\":\n return field.options?.[0]?.value ?? \"\";\n default:\n return \"\";\n }\n}\n\nfunction buildDefaultValues<TValues extends FieldValues>(\n fields: Array<CraftFormBuilderField<TValues>>,\n initialData?: Partial<TValues> | null\n): DefaultValues<TValues> {\n const values = {} as Record<string, unknown>;\n fields.forEach((field) => {\n const initialValue = initialData?.[field.name as keyof TValues];\n if (initialValue !== undefined && initialValue !== null) {\n values[field.name] = initialValue;\n } else {\n values[field.name] = defaultValueForField(field);\n }\n });\n return values as DefaultValues<TValues>;\n}\n\nfunction buildRules<TValues extends FieldValues>(\n field: CraftFormBuilderField<TValues>,\n getValues: () => TValues\n): RegisterOptions<TValues> {\n const rules: RegisterOptions<TValues> = { ...field.rules };\n const mergeValidate = (\n current: RegisterOptions<TValues>[\"validate\"],\n next: (value: unknown) => string | boolean | undefined\n ) => {\n if (!current) return next;\n if (typeof current === \"function\") {\n return (value: unknown): string | boolean | undefined => {\n const result = (current as (value: unknown, values: TValues) => string | boolean | undefined)(\n value,\n getValues()\n );\n if (result !== true) return result as string | undefined;\n return next(value);\n };\n }\n if (typeof current === \"object\") {\n return (value: unknown): string | boolean | undefined => {\n const entries = Object.entries(current);\n for (const [, validator] of entries) {\n const result = (validator as (value: unknown, values: TValues) => string | boolean | undefined)(\n value,\n getValues()\n );\n if (result !== true) return result as string | undefined;\n }\n return next(value);\n };\n }\n return next;\n };\n\n if (field.required && field.type !== \"hidden\") {\n if (field.type === \"checkbox\" || field.type === \"switch\") {\n rules.validate = mergeValidate(\n rules.validate,\n (value: unknown): string | boolean | undefined =>\n value ? true : `${String(field.label ?? field.name)} is required`\n );\n } else if (field.type === \"multiselect\") {\n rules.validate = mergeValidate(\n rules.validate,\n (value: unknown): string | boolean | undefined =>\n Array.isArray(value) && value.length > 0\n ? true\n : `${String(field.label ?? field.name)} is required`\n );\n } else if (field.type === \"file\") {\n rules.validate = mergeValidate(\n rules.validate,\n (value: unknown): string | boolean | undefined =>\n value instanceof FileList && value.length > 0\n ? true\n : `${String(field.label ?? field.name)} is required`\n );\n } else if (field.type === \"multifile\") {\n rules.validate = mergeValidate(\n rules.validate,\n (value: unknown): string | boolean | undefined =>\n Array.isArray(value) && value.length > 0\n ? true\n : `${String(field.label ?? field.name)} is required`\n );\n } else {\n rules.required = `${String(field.label ?? field.name)} is required`;\n }\n }\n\n if (field.min !== undefined) {\n rules.min = { value: field.min, message: `Min ${field.min}` };\n }\n if (field.max !== undefined) {\n rules.max = { value: field.max, message: `Max ${field.max}` };\n }\n\n if (field.type === \"email\") {\n rules.pattern = {\n value: /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/,\n message: \"Please enter a valid email address\",\n };\n }\n\n if (field.type === \"url\") {\n rules.pattern = {\n value: /^https?:\\/\\/.+/,\n message: \"Please enter a valid URL\",\n };\n }\n\n if (field.validate) {\n rules.validate = mergeValidate(\n rules.validate,\n (value: unknown): string | boolean | undefined =>\n field.validate?.(value, getValues())\n );\n }\n\n return rules;\n}\n\nexport function CraftFormBuilder<TValues extends FieldValues>({\n title = \"Form\",\n description,\n fields,\n initialData = null,\n open,\n defaultOpen = false,\n onOpenChange,\n trigger,\n submitLabel = \"Submit\",\n cancelLabel = \"Cancel\",\n resetLabel = \"Reset\",\n showReset = true,\n showCancel = true,\n tone,\n className,\n formClassName,\n loading = false,\n disableSubmitWhenInvalid = true,\n closeOnSubmit = true,\n closeOnCancel = true,\n onSubmit,\n onReset,\n onCancel,\n customValidation,\n}: CraftFormBuilderProps<TValues>) {\n const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen);\n const isControlled = typeof open === \"boolean\";\n const isOpen = isControlled ? open : uncontrolledOpen;\n\n const setOpen = React.useCallback(\n (next: boolean) => {\n if (!isControlled) setUncontrolledOpen(next);\n onOpenChange?.(next);\n },\n [isControlled, onOpenChange]\n );\n\n const defaultValues = React.useMemo(\n () => buildDefaultValues(fields, initialData),\n [fields, initialData]\n );\n\n const form = useForm<TValues>({\n mode: \"onChange\",\n defaultValues,\n });\n\n const formId = React.useId();\n\n React.useEffect(() => {\n form.reset(defaultValues);\n }, [defaultValues, form]);\n\n const handleSubmit = form.handleSubmit(async (values) => {\n if (customValidation) {\n const customErrors = customValidation(values);\n if (customErrors && Object.keys(customErrors).length > 0) {\n Object.entries(customErrors).forEach(([key, message]) => {\n if (message) {\n form.setError(key as Path<TValues>, {\n type: \"custom\",\n message: String(message),\n });\n }\n });\n return;\n }\n }\n\n await onSubmit(values);\n if (closeOnSubmit) setOpen(false);\n });\n\n const handleReset = () => {\n form.reset(defaultValues);\n onReset?.();\n };\n\n const handleCancel = () => {\n onCancel?.();\n if (closeOnCancel) setOpen(false);\n };\n\n return (\n <FormProvider {...form}>\n <CraftModal\n open={isOpen}\n onOpenChange={setOpen}\n trigger={trigger}\n title={title}\n description={description}\n tone={tone}\n className={className}\n footer={\n <div className=\"flex flex-wrap items-center justify-end gap-3\">\n {showReset && (\n <CraftButton\n type=\"button\"\n variant=\"outline\"\n onClick={handleReset}\n disabled={loading}\n >\n {resetLabel}\n </CraftButton>\n )}\n {showCancel && (\n <CraftButton\n type=\"button\"\n variant=\"ghost\"\n onClick={handleCancel}\n disabled={loading}\n >\n {cancelLabel}\n </CraftButton>\n )}\n <CraftSubmitButton\n loading={loading}\n disableWhenInvalid={disableSubmitWhenInvalid}\n form={formId}\n >\n {submitLabel}\n </CraftSubmitButton>\n </div>\n }\n >\n <form\n id={formId}\n onSubmit={handleSubmit}\n className={cn(\"space-y-5\", formClassName)}\n >\n {fields.map((field) => (\n <div key={field.name} className=\"space-y-2\">\n {field.helpText && (\n <p className=\"text-xs text-[rgb(var(--nc-fg-muted))]\">\n {field.helpText}\n </p>\n )}\n <CraftFormField\n name={field.name}\n label={field.label}\n description={field.description}\n type={field.type}\n placeholder={field.placeholder}\n options={field.options}\n tone={tone}\n disabled={field.disabled || loading}\n rules={buildRules(field, form.getValues)}\n fieldProps={{\n min: field.min,\n max: field.max,\n step: field.step,\n rows: field.rows,\n accept: field.accept,\n multiple: field.type === \"multifile\",\n ...field.fieldProps,\n }}\n />\n </div>\n ))}\n </form>\n </CraftModal>\n </FormProvider>\n );\n}"],"mappings":"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","names":["jsx","jsxs","React","FormProvider","jsx","jsxs","_a","FormProvider"]}
@@ -0,0 +1,49 @@
1
+ import {
2
+ cn
3
+ } from "./chunk-VQ6T3HIX.js";
4
+
5
+ // src/components/craft-input.tsx
6
+ import * as React from "react";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ var inputSizeClasses = {
9
+ sm: "h-10 px-4 text-sm",
10
+ md: "h-12 px-5 text-base",
11
+ lg: "h-14 px-6 text-lg"
12
+ };
13
+ var CraftInput = React.forwardRef(
14
+ ({ className, tone, inputSize = "md", glow = true, icon, ...props }, ref) => {
15
+ return /* @__PURE__ */ jsxs("div", { className: "relative w-full", "data-nc-theme": tone, children: [
16
+ icon && /* @__PURE__ */ jsx("div", { className: "absolute left-4 top-1/2 -translate-y-1/2 text-[rgb(var(--nc-fg-soft))]", children: icon }),
17
+ /* @__PURE__ */ jsx(
18
+ "input",
19
+ {
20
+ ref,
21
+ className: cn(
22
+ "w-full rounded-2xl border-2 bg-[rgb(var(--nc-surface)/0.08)] text-[rgb(var(--nc-fg))] backdrop-blur-xl",
23
+ "shadow-[inset_0_2px_8px_rgba(0,0,0,0.3)]",
24
+ "focus:outline-none focus:ring-4",
25
+ "transition-all duration-300",
26
+ "disabled:opacity-50 disabled:cursor-not-allowed",
27
+ inputSizeClasses[inputSize],
28
+ "border-[rgb(var(--nc-border)/0.35)]",
29
+ "focus:border-[rgb(var(--nc-accent-1)/0.8)] focus:ring-[rgb(var(--nc-accent-1)/0.3)]",
30
+ "placeholder:text-[rgb(var(--nc-fg-soft))]",
31
+ glow ? "focus:shadow-[0_0_30px_-5px_var(--glow-color)]" : "",
32
+ icon ? "pl-12" : "",
33
+ className
34
+ ),
35
+ style: {
36
+ "--glow-color": "rgb(var(--nc-accent-1) / 0.5)"
37
+ },
38
+ ...props
39
+ }
40
+ )
41
+ ] });
42
+ }
43
+ );
44
+ CraftInput.displayName = "CraftInput";
45
+
46
+ export {
47
+ CraftInput
48
+ };
49
+ //# sourceMappingURL=chunk-7SKDTIEK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/craft-input.tsx"],"sourcesContent":["\nimport * as React from \"react\";\n\nimport { cn } from \"@/utils/cn\";\nimport type { ThemeName } from \"@/theme/theme-context\";\n\n// ============================================================================\n// CRAFT INPUT\n// ============================================================================\n\ntype CraftInputSize = \"sm\" | \"md\" | \"lg\";\n\nexport type CraftInputProps = Omit<\n React.InputHTMLAttributes<HTMLInputElement>,\n \"size\"\n> & {\n tone?: ThemeName;\n inputSize?: CraftInputSize;\n glow?: boolean;\n icon?: React.ReactNode;\n};\n\nconst inputSizeClasses: Record<CraftInputSize, string> = {\n sm: \"h-10 px-4 text-sm\",\n md: \"h-12 px-5 text-base\",\n lg: \"h-14 px-6 text-lg\",\n};\n\nexport const CraftInput = React.forwardRef<HTMLInputElement, CraftInputProps>(\n (\n { className, tone, inputSize = \"md\", glow = true, icon, ...props },\n ref\n ) => {\n return (\n <div className=\"relative w-full\" data-nc-theme={tone}>\n {icon && (\n <div className=\"absolute left-4 top-1/2 -translate-y-1/2 text-[rgb(var(--nc-fg-soft))]\">\n {icon}\n </div>\n )}\n <input\n ref={ref}\n className={cn(\n \"w-full rounded-2xl border-2 bg-[rgb(var(--nc-surface)/0.08)] text-[rgb(var(--nc-fg))] backdrop-blur-xl\",\n \"shadow-[inset_0_2px_8px_rgba(0,0,0,0.3)]\",\n \"focus:outline-none focus:ring-4\",\n \"transition-all duration-300\",\n \"disabled:opacity-50 disabled:cursor-not-allowed\",\n inputSizeClasses[inputSize],\n \"border-[rgb(var(--nc-border)/0.35)]\",\n \"focus:border-[rgb(var(--nc-accent-1)/0.8)] focus:ring-[rgb(var(--nc-accent-1)/0.3)]\",\n \"placeholder:text-[rgb(var(--nc-fg-soft))]\",\n glow ? \"focus:shadow-[0_0_30px_-5px_var(--glow-color)]\" : \"\",\n icon ? \"pl-12\" : \"\",\n className\n )}\n style={{\n \"--glow-color\": \"rgb(var(--nc-accent-1) / 0.5)\",\n } as React.CSSProperties}\n {...props}\n />\n </div>\n );\n }\n);\n\nCraftInput.displayName = \"CraftInput\";\n"],"mappings":";;;;;AACA,YAAY,WAAW;AAiCjB,SAEI,KAFJ;AAZN,IAAM,mBAAmD;AAAA,EACvD,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;AAEO,IAAM,aAAmB;AAAA,EAC9B,CACE,EAAE,WAAW,MAAM,YAAY,MAAM,OAAO,MAAM,MAAM,GAAG,MAAM,GACjE,QACG;AACH,WACE,qBAAC,SAAI,WAAU,mBAAkB,iBAAe,MAC7C;AAAA,cACC,oBAAC,SAAI,WAAU,0EACZ,gBACH;AAAA,MAEF;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA,WAAW;AAAA,YACT;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,iBAAiB,SAAS;AAAA,YAC1B;AAAA,YACA;AAAA,YACA;AAAA,YACA,OAAO,mDAAmD;AAAA,YAC1D,OAAO,UAAU;AAAA,YACjB;AAAA,UACF;AAAA,UACA,OAAO;AAAA,YACL,gBAAgB;AAAA,UAClB;AAAA,UACC,GAAG;AAAA;AAAA,MACN;AAAA,OACF;AAAA,EAEJ;AACF;AAEA,WAAW,cAAc;","names":[]}
@@ -0,0 +1,49 @@
1
+ import {
2
+ cn
3
+ } from "./chunk-VQ6T3HIX.js";
4
+
5
+ // src/components/craft-icon.tsx
6
+ import * as React from "react";
7
+ import { DynamicIcon } from "lucide-react/dynamic";
8
+ import { jsx } from "react/jsx-runtime";
9
+ var CraftIconContext = React.createContext(null);
10
+ function CraftIconProvider({ icons, children }) {
11
+ return /* @__PURE__ */ jsx(CraftIconContext.Provider, { value: icons, children });
12
+ }
13
+ function CraftIcon({
14
+ name,
15
+ className,
16
+ "aria-label": ariaLabel,
17
+ icons,
18
+ useLucide = true
19
+ }) {
20
+ const contextRegistry = React.useContext(CraftIconContext);
21
+ const registry = icons != null ? icons : contextRegistry;
22
+ const icon = registry == null ? void 0 : registry[name];
23
+ if (!icon) {
24
+ if (!useLucide) return null;
25
+ return /* @__PURE__ */ jsx(
26
+ DynamicIcon,
27
+ {
28
+ name,
29
+ className,
30
+ "aria-hidden": ariaLabel ? void 0 : true,
31
+ "aria-label": ariaLabel
32
+ }
33
+ );
34
+ }
35
+ if (React.isValidElement(icon)) {
36
+ return React.cloneElement(icon, {
37
+ className: cn(icon.props.className, className),
38
+ "aria-hidden": ariaLabel ? void 0 : true,
39
+ "aria-label": ariaLabel
40
+ });
41
+ }
42
+ return /* @__PURE__ */ jsx("span", { className, "aria-label": ariaLabel, children: icon });
43
+ }
44
+
45
+ export {
46
+ CraftIconProvider,
47
+ CraftIcon
48
+ };
49
+ //# sourceMappingURL=chunk-FEFH5O5K.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/craft-icon.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { DynamicIcon } from \"lucide-react/dynamic\";\n\nimport { cn } from \"@/utils/cn\";\n\nexport type CraftIconRegistry = Record<string, React.ReactNode>;\n\nconst CraftIconContext = React.createContext<CraftIconRegistry | null>(null);\n\nexport type CraftIconProviderProps = {\n icons: CraftIconRegistry;\n children: React.ReactNode;\n};\n\nexport function CraftIconProvider({ icons, children }: CraftIconProviderProps) {\n return <CraftIconContext.Provider value={icons}>{children}</CraftIconContext.Provider>;\n}\n\nexport type CraftIconProps = {\n name: string;\n className?: string;\n \"aria-label\"?: string;\n icons?: CraftIconRegistry;\n useLucide?: boolean;\n};\n\nexport function CraftIcon({\n name,\n className,\n \"aria-label\": ariaLabel,\n icons,\n useLucide = true,\n}: CraftIconProps) {\n const contextRegistry = React.useContext(CraftIconContext);\n const registry = icons ?? contextRegistry;\n const icon = registry?.[name];\n\n if (!icon) {\n if (!useLucide) return null;\n return (\n <DynamicIcon\n name={name as unknown as React.ComponentProps<typeof DynamicIcon>[\"name\"]}\n className={className}\n aria-hidden={ariaLabel ? undefined : true}\n aria-label={ariaLabel}\n />\n );\n }\n\n type IconElementProps = {\n className?: string;\n \"aria-hidden\"?: boolean;\n \"aria-label\"?: string;\n };\n\n if (React.isValidElement<IconElementProps>(icon)) {\n return React.cloneElement(icon, {\n className: cn(icon.props.className, className),\n \"aria-hidden\": ariaLabel ? undefined : true,\n \"aria-label\": ariaLabel,\n });\n }\n\n return (\n <span className={className} aria-label={ariaLabel}>\n {icon}\n </span>\n );\n}\n"],"mappings":";;;;;AAEA,YAAY,WAAW;AACvB,SAAS,mBAAmB;AAcnB;AART,IAAM,mBAAyB,oBAAwC,IAAI;AAOpE,SAAS,kBAAkB,EAAE,OAAO,SAAS,GAA2B;AAC7E,SAAO,oBAAC,iBAAiB,UAAjB,EAA0B,OAAO,OAAQ,UAAS;AAC5D;AAUO,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA,YAAY;AACd,GAAmB;AACjB,QAAM,kBAAwB,iBAAW,gBAAgB;AACzD,QAAM,WAAW,wBAAS;AAC1B,QAAM,OAAO,qCAAW;AAExB,MAAI,CAAC,MAAM;AACT,QAAI,CAAC,UAAW,QAAO;AACvB,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,eAAa,YAAY,SAAY;AAAA,QACrC,cAAY;AAAA;AAAA,IACd;AAAA,EAEJ;AAQA,MAAU,qBAAiC,IAAI,GAAG;AAChD,WAAa,mBAAa,MAAM;AAAA,MAC9B,WAAW,GAAG,KAAK,MAAM,WAAW,SAAS;AAAA,MAC7C,eAAe,YAAY,SAAY;AAAA,MACvC,cAAc;AAAA,IAChB,CAAC;AAAA,EACH;AAEA,SACE,oBAAC,UAAK,WAAsB,cAAY,WACrC,gBACH;AAEJ;","names":[]}
@@ -0,0 +1,127 @@
1
+ import {
2
+ cn
3
+ } from "./chunk-VQ6T3HIX.js";
4
+
5
+ // src/theme/theme-context.tsx
6
+ import * as React from "react";
7
+ import { jsx } from "react/jsx-runtime";
8
+ var THEME_NAMES = [
9
+ "aurora",
10
+ "ember",
11
+ "ocean",
12
+ "midnight",
13
+ "cosmic"
14
+ ];
15
+ var ThemeContext = React.createContext(null);
16
+ var DEFAULT_THEME_KEY = "nextcraft-theme";
17
+ var DEFAULT_MODE_KEY = "nextcraft-mode";
18
+ function ThemeProvider({
19
+ children,
20
+ defaultTheme = "ocean",
21
+ defaultMode = "system",
22
+ storageKeyTheme = DEFAULT_THEME_KEY,
23
+ storageKeyMode = DEFAULT_MODE_KEY
24
+ }) {
25
+ const [theme, setTheme] = React.useState(defaultTheme);
26
+ const [mode, setMode] = React.useState(defaultMode);
27
+ React.useEffect(() => {
28
+ if (typeof window === "undefined") return;
29
+ try {
30
+ const storedTheme = window.localStorage.getItem(storageKeyTheme);
31
+ const storedMode = window.localStorage.getItem(storageKeyMode);
32
+ if (storedTheme) setTheme(storedTheme);
33
+ if (storedMode) setMode(storedMode);
34
+ } catch {
35
+ }
36
+ }, [storageKeyTheme, storageKeyMode]);
37
+ React.useEffect(() => {
38
+ if (typeof window === "undefined") return;
39
+ try {
40
+ window.localStorage.setItem(storageKeyTheme, theme);
41
+ window.localStorage.setItem(storageKeyMode, mode);
42
+ } catch {
43
+ }
44
+ }, [theme, mode, storageKeyTheme, storageKeyMode]);
45
+ React.useEffect(() => {
46
+ if (typeof document === "undefined") return;
47
+ const root = document.documentElement;
48
+ root.dataset.ncTheme = theme;
49
+ if (mode !== "system") {
50
+ root.dataset.ncMode = mode;
51
+ return;
52
+ }
53
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
54
+ const applySystem = () => {
55
+ root.dataset.ncMode = mediaQuery.matches ? "dark" : "light";
56
+ };
57
+ applySystem();
58
+ if (typeof mediaQuery.addEventListener === "function") {
59
+ mediaQuery.addEventListener("change", applySystem);
60
+ return () => mediaQuery.removeEventListener("change", applySystem);
61
+ }
62
+ mediaQuery.addListener(applySystem);
63
+ return () => mediaQuery.removeListener(applySystem);
64
+ }, [theme, mode]);
65
+ const value = React.useMemo(
66
+ () => ({ theme, mode, setTheme, setMode }),
67
+ [theme, mode]
68
+ );
69
+ return /* @__PURE__ */ jsx(ThemeContext.Provider, { value, children });
70
+ }
71
+ function useTheme() {
72
+ const context = React.useContext(ThemeContext);
73
+ if (!context) {
74
+ throw new Error("useTheme must be used within ThemeProvider");
75
+ }
76
+ return context;
77
+ }
78
+
79
+ // src/components/theme-switcher.tsx
80
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
81
+ var MODE_OPTIONS = ["system", "light", "dark"];
82
+ function ThemeSwitcher({ className, showLabels = true, ...props }) {
83
+ const { theme, mode, setTheme, setMode } = useTheme();
84
+ return /* @__PURE__ */ jsxs(
85
+ "div",
86
+ {
87
+ className: cn(
88
+ "flex flex-wrap items-center gap-3 rounded-2xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.08)] px-4 py-3 text-sm text-[rgb(var(--nc-fg))] shadow-[inset_0_1px_0_rgba(255,255,255,0.06)]",
89
+ className
90
+ ),
91
+ ...props,
92
+ children: [
93
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
94
+ showLabels && /* @__PURE__ */ jsx2("span", { className: "text-[rgb(var(--nc-fg-muted))]", children: "Theme" }),
95
+ /* @__PURE__ */ jsx2(
96
+ "select",
97
+ {
98
+ className: "rounded-lg border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] px-3 py-1 text-[rgb(var(--nc-fg))] outline-none focus:ring-2 focus:ring-[rgb(var(--nc-accent-1)/0.5)]",
99
+ value: theme,
100
+ onChange: (event) => setTheme(event.target.value),
101
+ children: THEME_NAMES.map((name) => /* @__PURE__ */ jsx2("option", { value: name, className: "text-slate-900", children: name }, name))
102
+ }
103
+ )
104
+ ] }),
105
+ /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2", children: [
106
+ showLabels && /* @__PURE__ */ jsx2("span", { className: "text-[rgb(var(--nc-fg-muted))]", children: "Mode" }),
107
+ /* @__PURE__ */ jsx2(
108
+ "select",
109
+ {
110
+ className: "rounded-lg border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] px-3 py-1 text-[rgb(var(--nc-fg))] outline-none focus:ring-2 focus:ring-[rgb(var(--nc-accent-1)/0.5)]",
111
+ value: mode,
112
+ onChange: (event) => setMode(event.target.value),
113
+ children: MODE_OPTIONS.map((value) => /* @__PURE__ */ jsx2("option", { value, className: "text-slate-900", children: value }, value))
114
+ }
115
+ )
116
+ ] })
117
+ ]
118
+ }
119
+ );
120
+ }
121
+
122
+ export {
123
+ ThemeProvider,
124
+ useTheme,
125
+ ThemeSwitcher
126
+ };
127
+ //# sourceMappingURL=chunk-M2EKVXB6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/theme/theme-context.tsx","../src/components/theme-switcher.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\n\nexport type ThemeName = \"aurora\" | \"ember\" | \"ocean\" | \"midnight\" | \"cosmic\";\nexport type ThemeMode = \"light\" | \"dark\" | \"system\";\n\nexport const THEME_NAMES: ThemeName[] = [\n \"aurora\",\n \"ember\",\n \"ocean\",\n \"midnight\",\n \"cosmic\",\n];\n\ntype ThemeContextValue = {\n theme: ThemeName;\n mode: ThemeMode;\n setTheme: (theme: ThemeName) => void;\n setMode: (mode: ThemeMode) => void;\n};\n\nconst ThemeContext = React.createContext<ThemeContextValue | null>(null);\n\ntype ThemeProviderProps = {\n children: React.ReactNode;\n defaultTheme?: ThemeName;\n defaultMode?: ThemeMode;\n storageKeyTheme?: string;\n storageKeyMode?: string;\n};\n\nconst DEFAULT_THEME_KEY = \"nextcraft-theme\";\nconst DEFAULT_MODE_KEY = \"nextcraft-mode\";\n\nexport function ThemeProvider({\n children,\n defaultTheme = \"ocean\",\n defaultMode = \"system\",\n storageKeyTheme = DEFAULT_THEME_KEY,\n storageKeyMode = DEFAULT_MODE_KEY,\n}: ThemeProviderProps) {\n const [theme, setTheme] = React.useState<ThemeName>(defaultTheme);\n const [mode, setMode] = React.useState<ThemeMode>(defaultMode);\n\n React.useEffect(() => {\n if (typeof window === \"undefined\") return;\n try {\n const storedTheme = window.localStorage.getItem(storageKeyTheme) as ThemeName | null;\n const storedMode = window.localStorage.getItem(storageKeyMode) as ThemeMode | null;\n if (storedTheme) setTheme(storedTheme);\n if (storedMode) setMode(storedMode);\n } catch {\n // Ignore storage errors.\n }\n }, [storageKeyTheme, storageKeyMode]);\n\n React.useEffect(() => {\n if (typeof window === \"undefined\") return;\n try {\n window.localStorage.setItem(storageKeyTheme, theme);\n window.localStorage.setItem(storageKeyMode, mode);\n } catch {\n // Ignore storage errors.\n }\n }, [theme, mode, storageKeyTheme, storageKeyMode]);\n\n React.useEffect(() => {\n if (typeof document === \"undefined\") return;\n const root = document.documentElement;\n root.dataset.ncTheme = theme;\n\n if (mode !== \"system\") {\n root.dataset.ncMode = mode;\n return;\n }\n\n const mediaQuery = window.matchMedia(\"(prefers-color-scheme: dark)\");\n const applySystem = () => {\n root.dataset.ncMode = mediaQuery.matches ? \"dark\" : \"light\";\n };\n\n applySystem();\n\n if (typeof mediaQuery.addEventListener === \"function\") {\n mediaQuery.addEventListener(\"change\", applySystem);\n return () => mediaQuery.removeEventListener(\"change\", applySystem);\n }\n\n mediaQuery.addListener(applySystem);\n return () => mediaQuery.removeListener(applySystem);\n }, [theme, mode]);\n\n const value = React.useMemo(\n () => ({ theme, mode, setTheme, setMode }),\n [theme, mode]\n );\n\n return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;\n}\n\nexport function useTheme() {\n const context = React.useContext(ThemeContext);\n if (!context) {\n throw new Error(\"useTheme must be used within ThemeProvider\");\n }\n return context;\n}\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport { cn } from \"@/utils/cn\";\nimport { THEME_NAMES, type ThemeMode, type ThemeName, useTheme } from \"@/theme/theme-context\";\n\nconst MODE_OPTIONS: ThemeMode[] = [\"system\", \"light\", \"dark\"];\n\nexport type ThemeSwitcherProps = React.HTMLAttributes<HTMLDivElement> & {\n showLabels?: boolean;\n};\n\nexport function ThemeSwitcher({ className, showLabels = true, ...props }: ThemeSwitcherProps) {\n const { theme, mode, setTheme, setMode } = useTheme();\n\n return (\n <div\n className={cn(\n \"flex flex-wrap items-center gap-3 rounded-2xl border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.08)] px-4 py-3 text-sm text-[rgb(var(--nc-fg))] shadow-[inset_0_1px_0_rgba(255,255,255,0.06)]\",\n className\n )}\n {...props}\n >\n <label className=\"flex items-center gap-2\">\n {showLabels && <span className=\"text-[rgb(var(--nc-fg-muted))]\">Theme</span>}\n <select\n className=\"rounded-lg border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] px-3 py-1 text-[rgb(var(--nc-fg))] outline-none focus:ring-2 focus:ring-[rgb(var(--nc-accent-1)/0.5)]\"\n value={theme}\n onChange={(event) => setTheme(event.target.value as ThemeName)}\n >\n {THEME_NAMES.map((name) => (\n <option key={name} value={name} className=\"text-slate-900\">\n {name}\n </option>\n ))}\n </select>\n </label>\n <label className=\"flex items-center gap-2\">\n {showLabels && <span className=\"text-[rgb(var(--nc-fg-muted))]\">Mode</span>}\n <select\n className=\"rounded-lg border border-[rgb(var(--nc-border)/0.3)] bg-[rgb(var(--nc-surface)/0.12)] px-3 py-1 text-[rgb(var(--nc-fg))] outline-none focus:ring-2 focus:ring-[rgb(var(--nc-accent-1)/0.5)]\"\n value={mode}\n onChange={(event) => setMode(event.target.value as ThemeMode)}\n >\n {MODE_OPTIONS.map((value) => (\n <option key={value} value={value} className=\"text-slate-900\">\n {value}\n </option>\n ))}\n </select>\n </label>\n </div>\n );\n}\n"],"mappings":"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","names":["jsx"]}