@craftzbay/ui 0.10.0 → 0.11.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.
- package/README.md +18 -12
- package/dist-lib/__tests__/helpers/color.d.ts +9 -0
- package/dist-lib/__tests__/helpers/theme.d.ts +18 -0
- package/dist-lib/components/ui/Accordion.js +18 -7
- package/dist-lib/components/ui/Accordion.js.map +1 -1
- package/dist-lib/components/ui/Alert.d.ts +16 -0
- package/dist-lib/components/ui/Alert.js +47 -34
- package/dist-lib/components/ui/Alert.js.map +1 -1
- package/dist-lib/components/ui/Avatar.d.ts +1 -1
- package/dist-lib/components/ui/Avatar.js +45 -47
- package/dist-lib/components/ui/Avatar.js.map +1 -1
- package/dist-lib/components/ui/Badge.d.ts +3 -1
- package/dist-lib/components/ui/Badge.js +24 -15
- package/dist-lib/components/ui/Badge.js.map +1 -1
- package/dist-lib/components/ui/Breadcrumbs.d.ts +2 -0
- package/dist-lib/components/ui/Breadcrumbs.js +46 -28
- package/dist-lib/components/ui/Breadcrumbs.js.map +1 -1
- package/dist-lib/components/ui/Button.d.ts +5 -3
- package/dist-lib/components/ui/Button.js +59 -45
- package/dist-lib/components/ui/Button.js.map +1 -1
- package/dist-lib/components/ui/Calendar.d.ts +1 -1
- package/dist-lib/components/ui/Calendar.js +87 -59
- package/dist-lib/components/ui/Calendar.js.map +1 -1
- package/dist-lib/components/ui/Card.d.ts +2 -0
- package/dist-lib/components/ui/Card.js +48 -67
- package/dist-lib/components/ui/Card.js.map +1 -1
- package/dist-lib/components/ui/Carousel.d.ts +6 -6
- package/dist-lib/components/ui/Carousel.js +133 -102
- package/dist-lib/components/ui/Carousel.js.map +1 -1
- package/dist-lib/components/ui/Chart.d.ts +49 -10
- package/dist-lib/components/ui/Chart.js +415 -181
- package/dist-lib/components/ui/Chart.js.map +1 -1
- package/dist-lib/components/ui/Checkbox.js +42 -28
- package/dist-lib/components/ui/Checkbox.js.map +1 -1
- package/dist-lib/components/ui/Combobox.d.ts +2 -0
- package/dist-lib/components/ui/Combobox.js +142 -111
- package/dist-lib/components/ui/Combobox.js.map +1 -1
- package/dist-lib/components/ui/CommandPalette.d.ts +6 -3
- package/dist-lib/components/ui/CommandPalette.js +92 -87
- package/dist-lib/components/ui/CommandPalette.js.map +1 -1
- package/dist-lib/components/ui/ContextMenu.d.ts +7 -2
- package/dist-lib/components/ui/ContextMenu.js +77 -62
- package/dist-lib/components/ui/ContextMenu.js.map +1 -1
- package/dist-lib/components/ui/DataGrid.d.ts +17 -4
- package/dist-lib/components/ui/DataGrid.js +65 -50
- package/dist-lib/components/ui/DataGrid.js.map +1 -1
- package/dist-lib/components/ui/DatePicker.js +118 -99
- package/dist-lib/components/ui/DatePicker.js.map +1 -1
- package/dist-lib/components/ui/DesignSystemProvider.d.ts +94 -40
- package/dist-lib/components/ui/DesignSystemProvider.js +111 -55
- package/dist-lib/components/ui/DesignSystemProvider.js.map +1 -1
- package/dist-lib/components/ui/Dialog.d.ts +18 -3
- package/dist-lib/components/ui/Dialog.js +105 -80
- package/dist-lib/components/ui/Dialog.js.map +1 -1
- package/dist-lib/components/ui/Drawer.d.ts +17 -2
- package/dist-lib/components/ui/Drawer.js +89 -55
- package/dist-lib/components/ui/Drawer.js.map +1 -1
- package/dist-lib/components/ui/DropdownMenu.js +14 -9
- package/dist-lib/components/ui/DropdownMenu.js.map +1 -1
- package/dist-lib/components/ui/EmptyState.d.ts +2 -0
- package/dist-lib/components/ui/EmptyState.js +30 -16
- package/dist-lib/components/ui/EmptyState.js.map +1 -1
- package/dist-lib/components/ui/ErrorState.d.ts +13 -2
- package/dist-lib/components/ui/ErrorState.js +44 -23
- package/dist-lib/components/ui/ErrorState.js.map +1 -1
- package/dist-lib/components/ui/FileUpload.js +59 -56
- package/dist-lib/components/ui/FileUpload.js.map +1 -1
- package/dist-lib/components/ui/Form.d.ts +15 -2
- package/dist-lib/components/ui/Form.js +97 -71
- package/dist-lib/components/ui/Form.js.map +1 -1
- package/dist-lib/components/ui/Icon.d.ts +1 -1
- package/dist-lib/components/ui/Icon.js +20 -14
- package/dist-lib/components/ui/Icon.js.map +1 -1
- package/dist-lib/components/ui/IconButton.d.ts +2 -2
- package/dist-lib/components/ui/IconButton.js +28 -20
- package/dist-lib/components/ui/IconButton.js.map +1 -1
- package/dist-lib/components/ui/Input.d.ts +3 -1
- package/dist-lib/components/ui/Input.js +102 -79
- package/dist-lib/components/ui/Input.js.map +1 -1
- package/dist-lib/components/ui/Kbd.js +1 -1
- package/dist-lib/components/ui/Kbd.js.map +1 -1
- package/dist-lib/components/ui/MultiSelect.js +121 -107
- package/dist-lib/components/ui/MultiSelect.js.map +1 -1
- package/dist-lib/components/ui/Pagination.js +67 -62
- package/dist-lib/components/ui/Pagination.js.map +1 -1
- package/dist-lib/components/ui/Popover.js +14 -14
- package/dist-lib/components/ui/Popover.js.map +1 -1
- package/dist-lib/components/ui/Progress.d.ts +3 -3
- package/dist-lib/components/ui/Progress.js +77 -72
- package/dist-lib/components/ui/Progress.js.map +1 -1
- package/dist-lib/components/ui/RadioGroup.d.ts +1 -1
- package/dist-lib/components/ui/RadioGroup.js +69 -52
- package/dist-lib/components/ui/RadioGroup.js.map +1 -1
- package/dist-lib/components/ui/RelativeTime.d.ts +19 -0
- package/dist-lib/components/ui/RelativeTime.js +31 -0
- package/dist-lib/components/ui/RelativeTime.js.map +1 -0
- package/dist-lib/components/ui/ScrollArea.d.ts +9 -1
- package/dist-lib/components/ui/ScrollArea.js +43 -27
- package/dist-lib/components/ui/ScrollArea.js.map +1 -1
- package/dist-lib/components/ui/Select.d.ts +6 -1
- package/dist-lib/components/ui/Select.js +79 -71
- package/dist-lib/components/ui/Select.js.map +1 -1
- package/dist-lib/components/ui/Separator.js +1 -1
- package/dist-lib/components/ui/Separator.js.map +1 -1
- package/dist-lib/components/ui/Sheet.d.ts +9 -0
- package/dist-lib/components/ui/Sheet.js +69 -46
- package/dist-lib/components/ui/Sheet.js.map +1 -1
- package/dist-lib/components/ui/Sidebar.d.ts +12 -9
- package/dist-lib/components/ui/Sidebar.js +152 -109
- package/dist-lib/components/ui/Sidebar.js.map +1 -1
- package/dist-lib/components/ui/Skeleton.d.ts +13 -2
- package/dist-lib/components/ui/Skeleton.js +15 -14
- package/dist-lib/components/ui/Skeleton.js.map +1 -1
- package/dist-lib/components/ui/Slider.js +41 -29
- package/dist-lib/components/ui/Slider.js.map +1 -1
- package/dist-lib/components/ui/Snackbar.js +23 -22
- package/dist-lib/components/ui/Snackbar.js.map +1 -1
- package/dist-lib/components/ui/Spinner.js +18 -6
- package/dist-lib/components/ui/Spinner.js.map +1 -1
- package/dist-lib/components/ui/Stepper.d.ts +6 -0
- package/dist-lib/components/ui/Stepper.js +71 -48
- package/dist-lib/components/ui/Stepper.js.map +1 -1
- package/dist-lib/components/ui/Switch.js +46 -43
- package/dist-lib/components/ui/Switch.js.map +1 -1
- package/dist-lib/components/ui/Table.d.ts +33 -5
- package/dist-lib/components/ui/Table.js +141 -119
- package/dist-lib/components/ui/Table.js.map +1 -1
- package/dist-lib/components/ui/Tabs.js +50 -48
- package/dist-lib/components/ui/Tabs.js.map +1 -1
- package/dist-lib/components/ui/TagInput.js +45 -45
- package/dist-lib/components/ui/TagInput.js.map +1 -1
- package/dist-lib/components/ui/Textarea.js +65 -54
- package/dist-lib/components/ui/Textarea.js.map +1 -1
- package/dist-lib/components/ui/Timeline.js +39 -35
- package/dist-lib/components/ui/Timeline.js.map +1 -1
- package/dist-lib/components/ui/Toast.js +44 -57
- package/dist-lib/components/ui/Toast.js.map +1 -1
- package/dist-lib/components/ui/Tooltip.d.ts +4 -1
- package/dist-lib/components/ui/Tooltip.js +24 -22
- package/dist-lib/components/ui/Tooltip.js.map +1 -1
- package/dist-lib/components/ui/TopNav.d.ts +7 -3
- package/dist-lib/components/ui/TopNav.js +39 -22
- package/dist-lib/components/ui/TopNav.js.map +1 -1
- package/dist-lib/components/ui/Tree.d.ts +15 -10
- package/dist-lib/components/ui/Tree.js +82 -79
- package/dist-lib/components/ui/Tree.js.map +1 -1
- package/dist-lib/hooks/use-debounce.d.ts +19 -0
- package/dist-lib/hooks/use-debounce.js +36 -0
- package/dist-lib/hooks/use-debounce.js.map +1 -0
- package/dist-lib/hooks/use-delayed-loading.d.ts +21 -0
- package/dist-lib/hooks/use-delayed-loading.js +20 -0
- package/dist-lib/hooks/use-delayed-loading.js.map +1 -0
- package/dist-lib/hooks/use-field-ids.d.ts +2 -1
- package/dist-lib/hooks/use-field-ids.js +9 -9
- package/dist-lib/hooks/use-field-ids.js.map +1 -1
- package/dist-lib/hooks/use-media-query.d.ts +3 -1
- package/dist-lib/hooks/use-media-query.js +16 -12
- package/dist-lib/hooks/use-media-query.js.map +1 -1
- package/dist-lib/hooks/use-modifier-key.d.ts +13 -0
- package/dist-lib/hooks/use-modifier-key.js +19 -0
- package/dist-lib/hooks/use-modifier-key.js.map +1 -0
- package/dist-lib/hooks/use-toast.d.ts +7 -2
- package/dist-lib/hooks/use-toast.js +61 -30
- package/dist-lib/hooks/use-toast.js.map +1 -1
- package/dist-lib/icons/index.d.ts +9 -0
- package/dist-lib/icons/index.js +148 -130
- package/dist-lib/icons/index.js.map +1 -1
- package/dist-lib/illustrations/index.d.ts +1 -0
- package/dist-lib/illustrations/index.js +15 -6
- package/dist-lib/illustrations/index.js.map +1 -1
- package/dist-lib/index.d.ts +6 -0
- package/dist-lib/index.js +280 -260
- package/dist-lib/index.js.map +1 -1
- package/dist-lib/lib/format.d.ts +65 -0
- package/dist-lib/lib/format.js +95 -0
- package/dist-lib/lib/format.js.map +1 -0
- package/dist-lib/lib/return-focus.d.ts +11 -0
- package/dist-lib/lib/return-focus.js +12 -0
- package/dist-lib/lib/return-focus.js.map +1 -0
- package/dist-lib/lib/strings.d.ts +62 -1
- package/dist-lib/lib/strings.js +75 -19
- package/dist-lib/lib/strings.js.map +1 -1
- package/dist-lib/lib/strings.mn.js +50 -5
- package/dist-lib/lib/strings.mn.js.map +1 -1
- package/dist-lib/styles.css +1 -1
- package/dist-lib/theme.css +141 -78
- package/package.json +11 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DatePicker.js","sources":["../../../src/components/ui/DatePicker.tsx"],"sourcesContent":["'use client';\n\nimport { forwardRef, useId, useMemo, useState, type ReactNode } from 'react';\nimport * as PopoverPrimitive from '@radix-ui/react-popover';\nimport type { DateRange, DayPickerProps, Matcher } from 'react-day-picker';\nimport { Calendar as CalendarIcon } from '@/icons';\nimport { Calendar } from './Calendar';\nimport { cn } from '@/lib/utils';\nimport { useStrings } from '@/hooks/use-strings';\n\n/* -----------------------------------------------------------------------------\n * Two related components share the same trigger shell:\n *\n * <DatePicker value={date} onChange={setDate} /> // single date\n * <DateRangePicker value={range} onChange={setRange} /> // {from,to}\n * --------------------------------------------------------------------------- */\n\ntype CalendarLocale = DayPickerProps['locale'];\n\nfunction defaultFormatDate(d: Date): string {\n return d.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' });\n}\n\n/** Merge the fromDate/toDate bounds with any consumer-supplied RDP matcher. */\nfunction useBounds(fromDate?: Date, toDate?: Date, disabled?: Matcher | Matcher[]) {\n return useMemo<Matcher[] | undefined>(() => {\n const list: Matcher[] = [];\n if (fromDate) list.push({ before: fromDate });\n if (toDate) list.push({ after: toDate });\n if (disabled) list.push(...(Array.isArray(disabled) ? disabled : [disabled]));\n return list.length ? list : undefined;\n }, [fromDate, toDate, disabled]);\n}\n\nfunction PickerTrigger({\n label,\n placeholder,\n hasValue,\n children,\n error,\n fieldId,\n disabled,\n open,\n}: {\n label?: ReactNode;\n placeholder: string;\n hasValue: boolean;\n children: ReactNode;\n error?: ReactNode;\n fieldId: string;\n disabled?: boolean;\n open: boolean;\n}) {\n const errorId = `${fieldId}-error`;\n const calendarId = `${fieldId}-calendar`;\n const text = hasValue ? children : placeholder;\n return (\n <div className=\"flex flex-col gap-1.5\">\n {label && (\n <label htmlFor={fieldId} className=\"text-foreground text-sm font-medium\">\n {label}\n </label>\n )}\n <PopoverPrimitive.Trigger asChild>\n <button\n id={fieldId}\n type=\"button\"\n // combobox-with-dialog pattern: lets the field carry aria-invalid like other inputs.\n role=\"combobox\"\n aria-expanded={open}\n aria-controls={calendarId}\n disabled={disabled}\n aria-invalid={Boolean(error) || undefined}\n aria-describedby={error ? errorId : undefined}\n className={cn(\n 'bg-card inline-flex h-9 w-full items-center justify-start gap-2 rounded-md border px-3 text-left text-sm',\n 'transition-colors duration-[var(--duration-fast)] ease-[var(--ease-out)]',\n 'focus-visible:ring-offset-background outline-none focus-visible:ring-2 focus-visible:ring-offset-2',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n error\n ? 'border-danger focus-visible:border-danger focus-visible:ring-danger'\n : 'border-border focus-visible:border-accent focus-visible:ring-ring',\n !hasValue && 'text-foreground-subtle',\n )}\n >\n <CalendarIcon className=\"text-foreground-subtle size-4\" aria-hidden />\n <span className=\"truncate\" title={typeof text === 'string' ? text : undefined}>\n {text}\n </span>\n </button>\n </PopoverPrimitive.Trigger>\n {error && (\n <p id={errorId} role=\"alert\" className=\"text-danger-text text-xs\">\n {error}\n </p>\n )}\n </div>\n );\n}\n\ninterface PickerCommonProps {\n label?: ReactNode;\n placeholder?: string;\n error?: ReactNode;\n disabled?: boolean;\n /** Restrict to a date range. Days outside are not selectable. */\n fromDate?: Date;\n toDate?: Date;\n /** Extra RDP matcher(s) for disabled days, merged with `fromDate`/`toDate`. */\n disabledDays?: Matcher | Matcher[];\n /** Custom display formatter for the trigger text. */\n formatDate?: (d: Date) => string;\n /** date-fns locale object passed through to react-day-picker. */\n locale?: CalendarLocale;\n className?: string;\n}\n\nexport interface DatePickerProps extends PickerCommonProps {\n value?: Date;\n onChange: (date: Date | undefined) => void;\n}\n\n/**\n * Single-date picker.\n *\n * @example\n * <DatePicker label=\"Date of birth\" value={dob} onChange={setDob} />\n *\n * @do Use locale-aware formatting via `formatDate` / `locale`.\n * @dont Roll a custom calendar — Radix Popover + react-day-picker handles a11y.\n */\nexport const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>(function DatePicker(\n {\n value,\n onChange,\n label,\n placeholder: placeholderProp,\n error,\n disabled,\n fromDate,\n toDate,\n disabledDays,\n formatDate = defaultFormatDate,\n locale,\n className,\n },\n ref,\n) {\n const strings = useStrings();\n const placeholder = placeholderProp ?? strings.datePicker.pickDate;\n const fieldId = useId();\n const [open, setOpen] = useState(false);\n const bounds = useBounds(fromDate, toDate, disabledDays);\n\n return (\n <div ref={ref} className={cn(className)}>\n <PopoverPrimitive.Root open={open} onOpenChange={setOpen}>\n <PickerTrigger\n label={label}\n placeholder={placeholder}\n hasValue={Boolean(value)}\n error={error}\n fieldId={fieldId}\n disabled={disabled}\n open={open}\n >\n {value ? formatDate(value) : ''}\n </PickerTrigger>\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n id={`${fieldId}-calendar`}\n align=\"start\"\n sideOffset={4}\n className=\"text-popover-foreground z-[var(--z-popover)] rounded-lg shadow-lg\"\n >\n <Calendar\n mode=\"single\"\n selected={value}\n onSelect={(d) => {\n onChange(d ?? undefined);\n if (d) setOpen(false);\n }}\n startMonth={fromDate}\n endMonth={toDate}\n disabled={bounds}\n locale={locale}\n />\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n </PopoverPrimitive.Root>\n </div>\n );\n});\nDatePicker.displayName = 'DatePicker';\n\nexport interface DateRangePickerProps extends PickerCommonProps {\n value?: DateRange;\n onChange: (range: DateRange | undefined) => void;\n}\n\n/**\n * Two-date range picker. `value` is `{from, to}`.\n *\n * @example\n * <DateRangePicker label=\"Reporting period\" value={range} onChange={setRange} />\n */\nexport const DateRangePicker = forwardRef<HTMLDivElement, DateRangePickerProps>(\n function DateRangePicker(\n {\n value,\n onChange,\n label,\n placeholder: placeholderProp,\n error,\n disabled,\n fromDate,\n toDate,\n disabledDays,\n formatDate = defaultFormatDate,\n locale,\n className,\n },\n ref,\n ) {\n const strings = useStrings();\n const placeholder = placeholderProp ?? strings.datePicker.pickRange;\n const fieldId = useId();\n const [open, setOpen] = useState(false);\n const hasValue = Boolean(value?.from);\n const bounds = useBounds(fromDate, toDate, disabledDays);\n\n return (\n <div ref={ref} className={cn(className)}>\n <PopoverPrimitive.Root open={open} onOpenChange={setOpen}>\n <PickerTrigger\n label={label}\n placeholder={placeholder}\n hasValue={hasValue}\n error={error}\n fieldId={fieldId}\n disabled={disabled}\n open={open}\n >\n {value?.from && value.to\n ? `${formatDate(value.from)} – ${formatDate(value.to)}`\n : value?.from\n ? formatDate(value.from)\n : ''}\n </PickerTrigger>\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n id={`${fieldId}-calendar`}\n align=\"start\"\n sideOffset={4}\n className=\"text-popover-foreground z-[var(--z-popover)] rounded-lg shadow-lg\"\n >\n <Calendar\n mode=\"range\"\n selected={value}\n onSelect={onChange}\n numberOfMonths={2}\n startMonth={fromDate}\n endMonth={toDate}\n disabled={bounds}\n locale={locale}\n />\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n </PopoverPrimitive.Root>\n </div>\n );\n },\n);\nDateRangePicker.displayName = 'DateRangePicker';\n"],"names":["defaultFormatDate","d","useBounds","fromDate","toDate","disabled","useMemo","list","PickerTrigger","label","placeholder","hasValue","children","error","fieldId","open","errorId","calendarId","text","jsxs","jsx","PopoverPrimitive","cn","CalendarIcon","DatePicker","forwardRef","value","onChange","placeholderProp","disabledDays","formatDate","locale","className","ref","strings","useStrings","useId","setOpen","useState","bounds","Calendar","DateRangePicker"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DatePicker.js","sources":["../../../src/components/ui/DatePicker.tsx"],"sourcesContent":["'use client';\n\nimport { forwardRef, useId, useMemo, useState, type ReactNode } from 'react';\nimport * as PopoverPrimitive from '@radix-ui/react-popover';\nimport type { DateRange, DayPickerProps, Matcher } from 'react-day-picker';\nimport { Calendar as CalendarIcon } from '@/icons';\nimport { Calendar } from './Calendar';\nimport { cn } from '@/lib/utils';\nimport { useStrings } from '@/hooks/use-strings';\n\n/* -----------------------------------------------------------------------------\n * Two related components share the same trigger shell:\n *\n * <DatePicker value={date} onChange={setDate} /> // single date\n * <DateRangePicker value={range} onChange={setRange} /> // {from,to}\n * --------------------------------------------------------------------------- */\n\ntype CalendarLocale = DayPickerProps['locale'];\n\n/**\n * Default trigger text. With a date-fns `locale` the date is rendered in that\n * locale; without one it is the canonical `yyyy-MM-dd` — deterministic on\n * server and client, so SSR output never depends on the host's locale.\n */\nfunction defaultFormatDate(d: Date, locale?: CalendarLocale): string {\n if (locale?.code) {\n return d.toLocaleDateString(locale.code, { year: 'numeric', month: 'short', day: 'numeric' });\n }\n const pad = (n: number) => String(n).padStart(2, '0');\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;\n}\n\n/** Merge the fromDate/toDate bounds with any consumer-supplied RDP matcher. */\nfunction useBounds(fromDate?: Date, toDate?: Date, disabled?: Matcher | Matcher[]) {\n return useMemo<Matcher[] | undefined>(() => {\n const list: Matcher[] = [];\n if (fromDate) list.push({ before: fromDate });\n if (toDate) list.push({ after: toDate });\n if (disabled) list.push(...(Array.isArray(disabled) ? disabled : [disabled]));\n return list.length ? list : undefined;\n }, [fromDate, toDate, disabled]);\n}\n\nfunction PickerTrigger({\n label,\n placeholder,\n hasValue,\n children,\n error,\n fieldId,\n disabled,\n open,\n}: {\n label?: ReactNode;\n placeholder: string;\n hasValue: boolean;\n children: ReactNode;\n error?: ReactNode;\n fieldId: string;\n disabled?: boolean;\n open: boolean;\n}) {\n const errorId = `${fieldId}-error`;\n const calendarId = `${fieldId}-calendar`;\n const text = hasValue ? children : placeholder;\n return (\n <div className=\"flex flex-col gap-1.5\">\n {label && (\n <label\n id={`${fieldId}-label`}\n htmlFor={fieldId}\n className=\"text-foreground text-sm font-medium\"\n >\n {label}\n </label>\n )}\n <PopoverPrimitive.Trigger asChild>\n <button\n id={fieldId}\n type=\"button\"\n // combobox-with-dialog pattern: lets the field carry aria-invalid like other inputs.\n role=\"combobox\"\n aria-expanded={open}\n aria-controls={calendarId}\n // role=combobox takes no name from content; expose the placeholder.\n aria-labelledby={label ? `${fieldId}-label` : undefined}\n aria-label={label ? undefined : placeholder}\n disabled={disabled}\n aria-invalid={Boolean(error) || undefined}\n aria-describedby={error ? errorId : undefined}\n className={cn(\n 'bg-card inline-flex h-9 w-full items-center justify-start gap-2 rounded-md border px-3 text-left text-lg md:text-sm',\n 'transition-colors duration-[var(--duration-fast)] ease-[var(--ease-out)]',\n 'focus-visible:ring-offset-background outline-none focus-visible:ring-2 focus-visible:ring-offset-2',\n 'disabled:cursor-not-allowed disabled:opacity-50',\n error\n ? 'border-danger focus-visible:border-danger focus-visible:ring-danger'\n : 'border-border-input focus-visible:border-accent focus-visible:ring-ring',\n !hasValue && 'text-foreground-subtle',\n )}\n >\n <CalendarIcon className=\"text-foreground-subtle size-4\" aria-hidden />\n <span className=\"truncate\" title={typeof text === 'string' ? text : undefined}>\n {text}\n </span>\n </button>\n </PopoverPrimitive.Trigger>\n {error && (\n <p id={errorId} className=\"text-danger-text text-xs\">\n {error}\n </p>\n )}\n </div>\n );\n}\n\ninterface PickerCommonProps {\n label?: ReactNode;\n placeholder?: string;\n error?: ReactNode;\n disabled?: boolean;\n /** Restrict to a date range. Days outside are not selectable. */\n fromDate?: Date;\n toDate?: Date;\n /** Extra RDP matcher(s) for disabled days, merged with `fromDate`/`toDate`. */\n disabledDays?: Matcher | Matcher[];\n /** Custom display formatter for the trigger text. */\n formatDate?: (d: Date) => string;\n /** date-fns locale object passed through to react-day-picker. */\n locale?: CalendarLocale;\n className?: string;\n}\n\nexport interface DatePickerProps extends PickerCommonProps {\n value?: Date;\n onChange: (date: Date | undefined) => void;\n}\n\n/**\n * Single-date picker.\n *\n * @example\n * <DatePicker label=\"Date of birth\" value={dob} onChange={setDob} />\n *\n * @do Use locale-aware formatting via `formatDate` / `locale`.\n * @dont Roll a custom calendar — Radix Popover + react-day-picker handles a11y.\n */\nexport const DatePicker = forwardRef<HTMLDivElement, DatePickerProps>(function DatePicker(\n {\n value,\n onChange,\n label,\n placeholder: placeholderProp,\n error,\n disabled,\n fromDate,\n toDate,\n disabledDays,\n formatDate: formatDateProp,\n locale,\n className,\n },\n ref,\n) {\n const strings = useStrings();\n const formatDate = formatDateProp ?? ((d: Date) => defaultFormatDate(d, locale));\n const placeholder = placeholderProp ?? strings.datePicker.pickDate;\n const fieldId = useId();\n const [open, setOpen] = useState(false);\n const bounds = useBounds(fromDate, toDate, disabledDays);\n\n return (\n <div ref={ref} className={cn(className)}>\n <PopoverPrimitive.Root open={open} onOpenChange={setOpen}>\n <PickerTrigger\n label={label}\n placeholder={placeholder}\n hasValue={Boolean(value)}\n error={error}\n fieldId={fieldId}\n disabled={disabled}\n open={open}\n >\n {value ? formatDate(value) : ''}\n </PickerTrigger>\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n id={`${fieldId}-calendar`}\n // Radix gives the popover role=\"dialog\"; name it after the field.\n aria-labelledby={label ? `${fieldId}-label` : undefined}\n aria-label={label ? undefined : placeholder}\n align=\"start\"\n sideOffset={4}\n className=\"text-popover-foreground z-[var(--z-popover)] rounded-lg shadow-md\"\n >\n <Calendar\n mode=\"single\"\n selected={value}\n // RDP 9 ignores `selected` for the initial month; open on the value.\n defaultMonth={value}\n onSelect={(d) => {\n onChange(d ?? undefined);\n if (d) setOpen(false);\n }}\n startMonth={fromDate}\n endMonth={toDate}\n disabled={bounds}\n locale={locale}\n />\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n </PopoverPrimitive.Root>\n </div>\n );\n});\nDatePicker.displayName = 'DatePicker';\n\nexport interface DateRangePickerProps extends PickerCommonProps {\n value?: DateRange;\n onChange: (range: DateRange | undefined) => void;\n}\n\n/**\n * Two-date range picker. `value` is `{from, to}`.\n *\n * @example\n * <DateRangePicker label=\"Reporting period\" value={range} onChange={setRange} />\n */\nexport const DateRangePicker = forwardRef<HTMLDivElement, DateRangePickerProps>(\n function DateRangePicker(\n {\n value,\n onChange,\n label,\n placeholder: placeholderProp,\n error,\n disabled,\n fromDate,\n toDate,\n disabledDays,\n formatDate: formatDateProp,\n locale,\n className,\n },\n ref,\n ) {\n const strings = useStrings();\n const formatDate = formatDateProp ?? ((d: Date) => defaultFormatDate(d, locale));\n const placeholder = placeholderProp ?? strings.datePicker.pickRange;\n const fieldId = useId();\n const [open, setOpen] = useState(false);\n const hasValue = Boolean(value?.from);\n const bounds = useBounds(fromDate, toDate, disabledDays);\n\n return (\n <div ref={ref} className={cn(className)}>\n <PopoverPrimitive.Root open={open} onOpenChange={setOpen}>\n <PickerTrigger\n label={label}\n placeholder={placeholder}\n hasValue={hasValue}\n error={error}\n fieldId={fieldId}\n disabled={disabled}\n open={open}\n >\n {value?.from && value.to\n ? `${formatDate(value.from)} – ${formatDate(value.to)}`\n : value?.from\n ? formatDate(value.from)\n : ''}\n </PickerTrigger>\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n id={`${fieldId}-calendar`}\n aria-labelledby={label ? `${fieldId}-label` : undefined}\n aria-label={label ? undefined : placeholder}\n align=\"start\"\n sideOffset={4}\n className=\"text-popover-foreground z-[var(--z-popover)] rounded-lg shadow-md\"\n >\n <Calendar\n mode=\"range\"\n selected={value}\n defaultMonth={value?.from}\n onSelect={onChange}\n numberOfMonths={2}\n startMonth={fromDate}\n endMonth={toDate}\n disabled={bounds}\n locale={locale}\n />\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n </PopoverPrimitive.Root>\n </div>\n );\n },\n);\nDateRangePicker.displayName = 'DateRangePicker';\n"],"names":["defaultFormatDate","d","locale","pad","n","useBounds","fromDate","toDate","disabled","useMemo","list","PickerTrigger","label","placeholder","hasValue","children","error","fieldId","open","errorId","calendarId","text","jsxs","jsx","PopoverPrimitive","cn","CalendarIcon","DatePicker","forwardRef","value","onChange","placeholderProp","disabledDays","formatDateProp","className","ref","strings","useStrings","formatDate","useId","setOpen","useState","bounds","Calendar","DateRangePicker"],"mappings":"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"}
|
|
@@ -16,9 +16,21 @@ import { DeepPartial, UiStrings } from '../../lib/strings.js';
|
|
|
16
16
|
* </DesignSystemProvider>
|
|
17
17
|
*/
|
|
18
18
|
export type BrandTokens = Record<string, string>;
|
|
19
|
+
/**
|
|
20
|
+
* Mode-aware token overrides: `light` applies always, `dark` wins under the
|
|
21
|
+
* `.dark` class (on `<html>` or any ancestor). Use this for anything with a
|
|
22
|
+
* different value per mode — accent, subtle surfaces, ring.
|
|
23
|
+
*/
|
|
24
|
+
export interface BrandTokenPair {
|
|
25
|
+
light: BrandTokens;
|
|
26
|
+
dark?: BrandTokens;
|
|
27
|
+
}
|
|
19
28
|
export interface DesignSystemProviderProps extends HTMLAttributes<HTMLDivElement> {
|
|
20
|
-
/**
|
|
21
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Token overrides (CSS variable name → value). A flat record applies in both
|
|
31
|
+
* modes; a `{ light, dark }` pair applies `dark` under `.dark`.
|
|
32
|
+
*/
|
|
33
|
+
tokens?: BrandTokens | BrandTokenPair;
|
|
22
34
|
/**
|
|
23
35
|
* Override any of the library's built-in UI strings (aria-labels,
|
|
24
36
|
* placeholders, empty states). Partial — merged over the parent provider /
|
|
@@ -33,61 +45,103 @@ export declare function DesignSystemProvider({ tokens, strings, className, child
|
|
|
33
45
|
* Built-in accent presets — swap the system's single accent colour without
|
|
34
46
|
* touching anything else.
|
|
35
47
|
*
|
|
36
|
-
* These override the *semantic* tokens the utilities resolve to.
|
|
48
|
+
* These override the *semantic* tokens the utilities resolve to. theme.css
|
|
37
49
|
* maps the accent utilities with `@theme inline` (e.g. `bg-accent` →
|
|
38
50
|
* `var(--accent)`, `bg-accent-soft` → `var(--accent-subtle)`), so the override
|
|
39
51
|
* must target `--accent` / `--accent-subtle` / `--accent-subtle-foreground` /
|
|
40
52
|
* `--ring` — NOT `--color-accent` (which `inline` never emits). The hover/
|
|
41
53
|
* active steps (`--color-accent-700/800`) come from the raw palette and are
|
|
42
|
-
*
|
|
54
|
+
* mode-agnostic. Values mirror the `[data-accent]` presets in theme.css: the
|
|
55
|
+
* dark half lifts the accent to the 400 step (readable as text on neutral-950)
|
|
56
|
+
* and darkens the subtle surface. `default` is the built-in graphite-indigo.
|
|
43
57
|
*/
|
|
44
58
|
export declare const brandPresets: {
|
|
45
59
|
/** The library default — graphite indigo. */
|
|
46
|
-
|
|
60
|
+
default: BrandTokenPair;
|
|
47
61
|
/** Blue. */
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
62
|
+
blue: {
|
|
63
|
+
light: {
|
|
64
|
+
accent: string;
|
|
65
|
+
'color-accent-700': string;
|
|
66
|
+
'color-accent-800': string;
|
|
67
|
+
'accent-subtle': string;
|
|
68
|
+
'accent-subtle-foreground': string;
|
|
69
|
+
ring: string;
|
|
70
|
+
};
|
|
71
|
+
dark: {
|
|
72
|
+
accent: string;
|
|
73
|
+
'accent-subtle': string;
|
|
74
|
+
'accent-subtle-foreground': string;
|
|
75
|
+
ring: string;
|
|
76
|
+
};
|
|
55
77
|
};
|
|
56
78
|
/** Violet. */
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
79
|
+
violet: {
|
|
80
|
+
light: {
|
|
81
|
+
accent: string;
|
|
82
|
+
'color-accent-700': string;
|
|
83
|
+
'color-accent-800': string;
|
|
84
|
+
'accent-subtle': string;
|
|
85
|
+
'accent-subtle-foreground': string;
|
|
86
|
+
ring: string;
|
|
87
|
+
};
|
|
88
|
+
dark: {
|
|
89
|
+
accent: string;
|
|
90
|
+
'accent-subtle': string;
|
|
91
|
+
'accent-subtle-foreground': string;
|
|
92
|
+
ring: string;
|
|
93
|
+
};
|
|
64
94
|
};
|
|
65
95
|
/** Emerald. */
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
96
|
+
emerald: {
|
|
97
|
+
light: {
|
|
98
|
+
accent: string;
|
|
99
|
+
'color-accent-700': string;
|
|
100
|
+
'color-accent-800': string;
|
|
101
|
+
'accent-subtle': string;
|
|
102
|
+
'accent-subtle-foreground': string;
|
|
103
|
+
ring: string;
|
|
104
|
+
};
|
|
105
|
+
dark: {
|
|
106
|
+
accent: string;
|
|
107
|
+
'accent-subtle': string;
|
|
108
|
+
'accent-subtle-foreground': string;
|
|
109
|
+
ring: string;
|
|
110
|
+
};
|
|
73
111
|
};
|
|
74
112
|
/** Rose. */
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
113
|
+
rose: {
|
|
114
|
+
light: {
|
|
115
|
+
accent: string;
|
|
116
|
+
'color-accent-700': string;
|
|
117
|
+
'color-accent-800': string;
|
|
118
|
+
'accent-subtle': string;
|
|
119
|
+
'accent-subtle-foreground': string;
|
|
120
|
+
ring: string;
|
|
121
|
+
};
|
|
122
|
+
dark: {
|
|
123
|
+
accent: string;
|
|
124
|
+
'accent-subtle': string;
|
|
125
|
+
'accent-subtle-foreground': string;
|
|
126
|
+
ring: string;
|
|
127
|
+
};
|
|
82
128
|
};
|
|
83
129
|
/** Amber. */
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
130
|
+
amber: {
|
|
131
|
+
light: {
|
|
132
|
+
accent: string;
|
|
133
|
+
'color-accent-700': string;
|
|
134
|
+
'color-accent-800': string;
|
|
135
|
+
'accent-subtle': string;
|
|
136
|
+
'accent-subtle-foreground': string;
|
|
137
|
+
ring: string;
|
|
138
|
+
};
|
|
139
|
+
dark: {
|
|
140
|
+
accent: string;
|
|
141
|
+
'accent-subtle': string;
|
|
142
|
+
'accent-subtle-foreground': string;
|
|
143
|
+
ring: string;
|
|
144
|
+
};
|
|
91
145
|
};
|
|
92
146
|
};
|
|
93
147
|
export type BrandName = keyof typeof brandPresets;
|
|
@@ -1,79 +1,135 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx as
|
|
3
|
-
import { useMemo as
|
|
4
|
-
import { cn as
|
|
5
|
-
import { useStrings as
|
|
6
|
-
import { mergeStrings as
|
|
7
|
-
function
|
|
8
|
-
|
|
2
|
+
import { jsxs as f, jsx as h } from "react/jsx-runtime";
|
|
3
|
+
import { useMemo as m, useId as p } from "react";
|
|
4
|
+
import { cn as $ } from "../../lib/utils.js";
|
|
5
|
+
import { useStrings as v, StringsContext as j } from "../../hooks/use-strings.js";
|
|
6
|
+
import { mergeStrings as y } from "../../lib/strings.js";
|
|
7
|
+
function S(c) {
|
|
8
|
+
return "light" in c && typeof c.light == "object";
|
|
9
|
+
}
|
|
10
|
+
function s(c) {
|
|
11
|
+
return Object.entries(c).map(([e, l]) => `${e.startsWith("--") ? e : `--${e}`}:${l}`).join(";");
|
|
12
|
+
}
|
|
13
|
+
function W({
|
|
14
|
+
tokens: c,
|
|
9
15
|
strings: e,
|
|
10
|
-
className:
|
|
11
|
-
children:
|
|
12
|
-
style:
|
|
13
|
-
...
|
|
16
|
+
className: l,
|
|
17
|
+
children: k,
|
|
18
|
+
style: i,
|
|
19
|
+
...u
|
|
14
20
|
}) {
|
|
15
|
-
const
|
|
16
|
-
() =>
|
|
17
|
-
[
|
|
18
|
-
),
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
const r = v(), d = m(
|
|
22
|
+
() => y(r, e),
|
|
23
|
+
[r, e]
|
|
24
|
+
), n = p(), a = { ...i };
|
|
25
|
+
let t = null;
|
|
26
|
+
if (c)
|
|
27
|
+
if (S(c)) {
|
|
28
|
+
const o = `[data-brand-scope="${n}"]`;
|
|
29
|
+
t = `${o}{${s(c.light)}}`, c.dark && (t += `.dark ${o},.dark${o}{${s(c.dark)}}`);
|
|
30
|
+
} else
|
|
31
|
+
for (const [o, g] of Object.entries(c)) {
|
|
32
|
+
const b = o.startsWith("--") ? o : `--${o}`;
|
|
33
|
+
a[b] = g;
|
|
34
|
+
}
|
|
35
|
+
return /* @__PURE__ */ f(j.Provider, { value: d, children: [
|
|
36
|
+
t && /* @__PURE__ */ h("style", { "data-brand-scope-style": n, children: t }),
|
|
37
|
+
/* @__PURE__ */ h("div", { "data-brand-scope": n, className: $("contents", l), style: a, ...u, children: k })
|
|
38
|
+
] });
|
|
25
39
|
}
|
|
26
|
-
const
|
|
40
|
+
const C = {
|
|
27
41
|
/** The library default — graphite indigo. */
|
|
28
|
-
default: {},
|
|
42
|
+
default: { light: {} },
|
|
29
43
|
/** Blue. */
|
|
30
44
|
blue: {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
45
|
+
light: {
|
|
46
|
+
accent: "oklch(0.55 0.16 250)",
|
|
47
|
+
"color-accent-700": "oklch(0.47 0.16 250)",
|
|
48
|
+
"color-accent-800": "oklch(0.39 0.14 250)",
|
|
49
|
+
"accent-subtle": "oklch(0.96 0.03 250)",
|
|
50
|
+
"accent-subtle-foreground": "oklch(0.45 0.15 250)",
|
|
51
|
+
ring: "oklch(0.62 0.16 250)"
|
|
52
|
+
},
|
|
53
|
+
dark: {
|
|
54
|
+
accent: "oklch(0.64 0.15 250)",
|
|
55
|
+
"accent-subtle": "oklch(0.24 0.06 250)",
|
|
56
|
+
"accent-subtle-foreground": "oklch(0.82 0.1 250)",
|
|
57
|
+
ring: "oklch(0.68 0.15 250)"
|
|
58
|
+
}
|
|
37
59
|
},
|
|
38
60
|
/** Violet. */
|
|
39
61
|
violet: {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
62
|
+
light: {
|
|
63
|
+
accent: "oklch(0.53 0.20 295)",
|
|
64
|
+
"color-accent-700": "oklch(0.45 0.18 295)",
|
|
65
|
+
"color-accent-800": "oklch(0.38 0.16 295)",
|
|
66
|
+
"accent-subtle": "oklch(0.96 0.03 295)",
|
|
67
|
+
"accent-subtle-foreground": "oklch(0.46 0.18 295)",
|
|
68
|
+
ring: "oklch(0.60 0.20 295)"
|
|
69
|
+
},
|
|
70
|
+
dark: {
|
|
71
|
+
accent: "oklch(0.64 0.18 295)",
|
|
72
|
+
"accent-subtle": "oklch(0.25 0.07 295)",
|
|
73
|
+
"accent-subtle-foreground": "oklch(0.83 0.12 295)",
|
|
74
|
+
ring: "oklch(0.68 0.18 295)"
|
|
75
|
+
}
|
|
46
76
|
},
|
|
47
77
|
/** Emerald. */
|
|
48
78
|
emerald: {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
79
|
+
light: {
|
|
80
|
+
accent: "oklch(0.55 0.13 160)",
|
|
81
|
+
"color-accent-700": "oklch(0.47 0.13 160)",
|
|
82
|
+
"color-accent-800": "oklch(0.39 0.12 160)",
|
|
83
|
+
"accent-subtle": "oklch(0.96 0.03 160)",
|
|
84
|
+
"accent-subtle-foreground": "oklch(0.42 0.12 160)",
|
|
85
|
+
ring: "oklch(0.60 0.13 160)"
|
|
86
|
+
},
|
|
87
|
+
dark: {
|
|
88
|
+
accent: "oklch(0.64 0.14 160)",
|
|
89
|
+
"accent-subtle": "oklch(0.23 0.05 160)",
|
|
90
|
+
"accent-subtle-foreground": "oklch(0.8 0.12 160)",
|
|
91
|
+
ring: "oklch(0.68 0.14 160)"
|
|
92
|
+
}
|
|
55
93
|
},
|
|
56
94
|
/** Rose. */
|
|
57
95
|
rose: {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
96
|
+
light: {
|
|
97
|
+
accent: "oklch(0.57 0.19 12)",
|
|
98
|
+
"color-accent-700": "oklch(0.49 0.18 12)",
|
|
99
|
+
"color-accent-800": "oklch(0.41 0.16 12)",
|
|
100
|
+
"accent-subtle": "oklch(0.96 0.03 12)",
|
|
101
|
+
"accent-subtle-foreground": "oklch(0.48 0.18 12)",
|
|
102
|
+
ring: "oklch(0.62 0.19 12)"
|
|
103
|
+
},
|
|
104
|
+
dark: {
|
|
105
|
+
accent: "oklch(0.65 0.18 12)",
|
|
106
|
+
"accent-subtle": "oklch(0.25 0.07 12)",
|
|
107
|
+
"accent-subtle-foreground": "oklch(0.83 0.12 12)",
|
|
108
|
+
ring: "oklch(0.7 0.18 12)"
|
|
109
|
+
}
|
|
64
110
|
},
|
|
65
111
|
/** Amber. */
|
|
66
112
|
amber: {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
113
|
+
light: {
|
|
114
|
+
// 0.56 keeps white text at 4.8:1 (0.62 was 3.8:1).
|
|
115
|
+
accent: "oklch(0.56 0.14 65)",
|
|
116
|
+
"color-accent-700": "oklch(0.54 0.13 65)",
|
|
117
|
+
"color-accent-800": "oklch(0.46 0.12 65)",
|
|
118
|
+
"accent-subtle": "oklch(0.96 0.04 75)",
|
|
119
|
+
"accent-subtle-foreground": "oklch(0.48 0.12 65)",
|
|
120
|
+
ring: "oklch(0.64 0.14 65)"
|
|
121
|
+
// 3.17:1 on background-muted (0.66 was 2.93)
|
|
122
|
+
},
|
|
123
|
+
dark: {
|
|
124
|
+
accent: "oklch(0.66 0.14 65)",
|
|
125
|
+
"accent-subtle": "oklch(0.26 0.05 70)",
|
|
126
|
+
"accent-subtle-foreground": "oklch(0.85 0.12 80)",
|
|
127
|
+
ring: "oklch(0.72 0.14 65)"
|
|
128
|
+
}
|
|
73
129
|
}
|
|
74
130
|
};
|
|
75
131
|
export {
|
|
76
|
-
|
|
77
|
-
|
|
132
|
+
W as DesignSystemProvider,
|
|
133
|
+
C as brandPresets
|
|
78
134
|
};
|
|
79
135
|
//# sourceMappingURL=DesignSystemProvider.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DesignSystemProvider.js","sources":["../../../src/components/ui/DesignSystemProvider.tsx"],"sourcesContent":["'use client';\n\nimport { useMemo, type CSSProperties, type HTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '@/lib/utils';\nimport { StringsContext, useStrings } from '@/hooks/use-strings';\nimport { mergeStrings, type DeepPartial, type UiStrings } from '@/lib/strings';\n\n/**\n * Per-brand token overrides. Keys are CSS variable names (without the `--`\n * prefix); values are CSS values. Any unspecified token falls back to the\n * design system default.\n *\n * @example\n * <DesignSystemProvider tokens={{ accent: '#ff5555', 'radius-md': '10px' }}>\n * <App />\n * </DesignSystemProvider>\n *\n * @example Swap in one of the built-in accent presets\n * <DesignSystemProvider tokens={brandPresets.violet}>\n * <Card>...</Card>\n * </DesignSystemProvider>\n */\nexport type BrandTokens = Record<string, string>;\n\nexport interface DesignSystemProviderProps extends HTMLAttributes<HTMLDivElement> {\n /** Token overrides (CSS variable name → value). */\n tokens?: BrandTokens;\n /**\n * Override any of the library's built-in UI strings (aria-labels,\n * placeholders, empty states). Partial — merged over the parent provider /\n * English defaults. Pass `mnStrings` for Mongolian.\n */\n strings?: DeepPartial<UiStrings>;\n /** Children to scope this brand to. */\n children: ReactNode;\n}\n\nexport function DesignSystemProvider({\n tokens,\n strings,\n className,\n children,\n style,\n ...props\n}: DesignSystemProviderProps) {\n // Build the inline style from tokens — wrapping every key with `--` so\n // consumers can pass either `accent` or `color-accent` without remembering\n // the prefix dance.\n const parentStrings = useStrings();\n const resolvedStrings = useMemo(\n () => mergeStrings(parentStrings, strings),\n [parentStrings, strings],\n );\n const css: CSSProperties = { ...style };\n if (tokens) {\n for (const [k, v] of Object.entries(tokens)) {\n const key = k.startsWith('--') ? k : `--${k}`;\n (css as Record<string, string>)[key] = v;\n }\n }\n\n return (\n <StringsContext.Provider value={resolvedStrings}>\n <div data-brand-scope className={cn('contents', className)} style={css} {...props}>\n {children}\n </div>\n </StringsContext.Provider>\n );\n}\n\n/**\n * Built-in accent presets — swap the system's single accent colour without\n * touching anything else.\n *\n * These override the *semantic* tokens the utilities resolve to. globals.css\n * maps the accent utilities with `@theme inline` (e.g. `bg-accent` →\n * `var(--accent)`, `bg-accent-soft` → `var(--accent-subtle)`), so the override\n * must target `--accent` / `--accent-subtle` / `--accent-subtle-foreground` /\n * `--ring` — NOT `--color-accent` (which `inline` never emits). The hover/\n * active steps (`--color-accent-700/800`) come from the raw palette and are\n * overridden directly. `default` is the built-in graphite-indigo.\n */\nexport const brandPresets = {\n /** The library default — graphite indigo. */\n default: {} as BrandTokens,\n /** Blue. */\n blue: {\n accent: 'oklch(0.55 0.16 250)',\n 'color-accent-700': 'oklch(0.47 0.16 250)',\n 'color-accent-800': 'oklch(0.39 0.14 250)',\n 'accent-subtle': 'oklch(0.95 0.04 250)',\n 'accent-subtle-foreground': 'oklch(0.45 0.15 250)',\n ring: 'oklch(0.62 0.16 250)',\n },\n /** Violet. */\n violet: {\n accent: 'oklch(0.53 0.20 295)',\n 'color-accent-700': 'oklch(0.45 0.18 295)',\n 'color-accent-800': 'oklch(0.38 0.16 295)',\n 'accent-subtle': 'oklch(0.95 0.04 295)',\n 'accent-subtle-foreground': 'oklch(0.45 0.18 295)',\n ring: 'oklch(0.60 0.20 295)',\n },\n /** Emerald. */\n emerald: {\n accent: 'oklch(0.55 0.13 160)',\n 'color-accent-700': 'oklch(0.47 0.13 160)',\n 'color-accent-800': 'oklch(0.39 0.12 160)',\n 'accent-subtle': 'oklch(0.95 0.04 160)',\n 'accent-subtle-foreground': 'oklch(0.42 0.12 160)',\n ring: 'oklch(0.60 0.13 160)',\n },\n /** Rose. */\n rose: {\n accent: 'oklch(0.57 0.19 12)',\n 'color-accent-700': 'oklch(0.49 0.18 12)',\n 'color-accent-800': 'oklch(0.41 0.16 12)',\n 'accent-subtle': 'oklch(0.95 0.035 12)',\n 'accent-subtle-foreground': 'oklch(0.48 0.18 12)',\n ring: 'oklch(0.62 0.19 12)',\n },\n /** Amber. */\n amber: {\n accent: 'oklch(0.62 0.14 65)',\n 'color-accent-700': 'oklch(0.54 0.13 65)',\n 'color-accent-800': 'oklch(0.46 0.12 65)',\n 'accent-subtle': 'oklch(0.95 0.05 75)',\n 'accent-subtle-foreground': 'oklch(0.48 0.12 65)',\n ring: 'oklch(0.66 0.14 65)',\n },\n} as const;\n\nexport type BrandName = keyof typeof brandPresets;\n"],"names":["DesignSystemProvider","tokens","strings","className","children","style","props","parentStrings","useStrings","resolvedStrings","useMemo","mergeStrings","css","k","v","key","jsx","StringsContext","cn","brandPresets"],"mappings":";;;;;;AAqCO,SAASA,EAAqB;AAAA,EACnC,QAAAC;AAAA,EACA,SAAAC;AAAA,EACA,WAAAC;AAAA,EACA,UAAAC;AAAA,EACA,OAAAC;AAAA,EACA,GAAGC;AACL,GAA8B;AAI5B,QAAMC,IAAgBC,EAAA,GAChBC,IAAkBC;AAAA,IACtB,MAAMC,EAAaJ,GAAeL,CAAO;AAAA,IACzC,CAACK,GAAeL,CAAO;AAAA,EAAA,GAEnBU,IAAqB,EAAE,GAAGP,EAAA;AAChC,MAAIJ;AACF,eAAW,CAACY,GAAGC,CAAC,KAAK,OAAO,QAAQb,CAAM,GAAG;AAC3C,YAAMc,IAAMF,EAAE,WAAW,IAAI,IAAIA,IAAI,KAAKA,CAAC;AAC1C,MAAAD,EAA+BG,CAAG,IAAID;AAAA,IACzC;AAGF,SACE,gBAAAE,EAACC,EAAe,UAAf,EAAwB,OAAOR,GAC9B,UAAA,gBAAAO,EAAC,SAAI,oBAAgB,IAAC,WAAWE,EAAG,YAAYf,CAAS,GAAG,OAAOS,GAAM,GAAGN,GACzE,UAAAF,GACH,GACF;AAEJ;AAcO,MAAMe,IAAe;AAAA;AAAA,EAE1B,SAAS,CAAA;AAAA;AAAA,EAET,MAAM;AAAA,IACJ,QAAQ;AAAA,IACR,oBAAoB;AAAA,IACpB,oBAAoB;AAAA,IACpB,iBAAiB;AAAA,IACjB,4BAA4B;AAAA,IAC5B,MAAM;AAAA,EAAA;AAAA;AAAA,EAGR,QAAQ;AAAA,IACN,QAAQ;AAAA,IACR,oBAAoB;AAAA,IACpB,oBAAoB;AAAA,IACpB,iBAAiB;AAAA,IACjB,4BAA4B;AAAA,IAC5B,MAAM;AAAA,EAAA;AAAA;AAAA,EAGR,SAAS;AAAA,IACP,QAAQ;AAAA,IACR,oBAAoB;AAAA,IACpB,oBAAoB;AAAA,IACpB,iBAAiB;AAAA,IACjB,4BAA4B;AAAA,IAC5B,MAAM;AAAA,EAAA;AAAA;AAAA,EAGR,MAAM;AAAA,IACJ,QAAQ;AAAA,IACR,oBAAoB;AAAA,IACpB,oBAAoB;AAAA,IACpB,iBAAiB;AAAA,IACjB,4BAA4B;AAAA,IAC5B,MAAM;AAAA,EAAA;AAAA;AAAA,EAGR,OAAO;AAAA,IACL,QAAQ;AAAA,IACR,oBAAoB;AAAA,IACpB,oBAAoB;AAAA,IACpB,iBAAiB;AAAA,IACjB,4BAA4B;AAAA,IAC5B,MAAM;AAAA,EAAA;AAEV;"}
|
|
1
|
+
{"version":3,"file":"DesignSystemProvider.js","sources":["../../../src/components/ui/DesignSystemProvider.tsx"],"sourcesContent":["'use client';\n\nimport { useId, useMemo, type CSSProperties, type HTMLAttributes, type ReactNode } from 'react';\nimport { cn } from '@/lib/utils';\nimport { StringsContext, useStrings } from '@/hooks/use-strings';\nimport { mergeStrings, type DeepPartial, type UiStrings } from '@/lib/strings';\n\n/**\n * Per-brand token overrides. Keys are CSS variable names (without the `--`\n * prefix); values are CSS values. Any unspecified token falls back to the\n * design system default.\n *\n * @example\n * <DesignSystemProvider tokens={{ accent: '#ff5555', 'radius-md': '10px' }}>\n * <App />\n * </DesignSystemProvider>\n *\n * @example Swap in one of the built-in accent presets\n * <DesignSystemProvider tokens={brandPresets.violet}>\n * <Card>...</Card>\n * </DesignSystemProvider>\n */\nexport type BrandTokens = Record<string, string>;\n\n/**\n * Mode-aware token overrides: `light` applies always, `dark` wins under the\n * `.dark` class (on `<html>` or any ancestor). Use this for anything with a\n * different value per mode — accent, subtle surfaces, ring.\n */\nexport interface BrandTokenPair {\n light: BrandTokens;\n dark?: BrandTokens;\n}\n\nfunction isPair(t: BrandTokens | BrandTokenPair): t is BrandTokenPair {\n return 'light' in t && typeof t.light === 'object';\n}\n\nfunction toDeclarations(tokens: BrandTokens): string {\n return Object.entries(tokens)\n .map(([k, v]) => `${k.startsWith('--') ? k : `--${k}`}:${v}`)\n .join(';');\n}\n\nexport interface DesignSystemProviderProps extends HTMLAttributes<HTMLDivElement> {\n /**\n * Token overrides (CSS variable name → value). A flat record applies in both\n * modes; a `{ light, dark }` pair applies `dark` under `.dark`.\n */\n tokens?: BrandTokens | BrandTokenPair;\n /**\n * Override any of the library's built-in UI strings (aria-labels,\n * placeholders, empty states). Partial — merged over the parent provider /\n * English defaults. Pass `mnStrings` for Mongolian.\n */\n strings?: DeepPartial<UiStrings>;\n /** Children to scope this brand to. */\n children: ReactNode;\n}\n\nexport function DesignSystemProvider({\n tokens,\n strings,\n className,\n children,\n style,\n ...props\n}: DesignSystemProviderProps) {\n // Build the inline style from tokens — wrapping every key with `--` so\n // consumers can pass either `accent` or `color-accent` without remembering\n // the prefix dance.\n const parentStrings = useStrings();\n const resolvedStrings = useMemo(\n () => mergeStrings(parentStrings, strings),\n [parentStrings, strings],\n );\n const scopeId = useId();\n const css: CSSProperties = { ...style };\n let sheet: string | null = null;\n if (tokens) {\n if (isPair(tokens)) {\n // Mode-aware tokens cannot be inline (inline beats `.dark` rules), so\n // they go through a scoped <style>: light on the scope, dark under .dark.\n const scope = `[data-brand-scope=\"${scopeId}\"]`;\n sheet = `${scope}{${toDeclarations(tokens.light)}}`;\n if (tokens.dark) {\n sheet += `.dark ${scope},.dark${scope}{${toDeclarations(tokens.dark)}}`;\n }\n } else {\n for (const [k, v] of Object.entries(tokens)) {\n const key = k.startsWith('--') ? k : `--${k}`;\n (css as Record<string, string>)[key] = v;\n }\n }\n }\n\n return (\n <StringsContext.Provider value={resolvedStrings}>\n {sheet && <style data-brand-scope-style={scopeId}>{sheet}</style>}\n <div data-brand-scope={scopeId} className={cn('contents', className)} style={css} {...props}>\n {children}\n </div>\n </StringsContext.Provider>\n );\n}\n\n/**\n * Built-in accent presets — swap the system's single accent colour without\n * touching anything else.\n *\n * These override the *semantic* tokens the utilities resolve to. theme.css\n * maps the accent utilities with `@theme inline` (e.g. `bg-accent` →\n * `var(--accent)`, `bg-accent-soft` → `var(--accent-subtle)`), so the override\n * must target `--accent` / `--accent-subtle` / `--accent-subtle-foreground` /\n * `--ring` — NOT `--color-accent` (which `inline` never emits). The hover/\n * active steps (`--color-accent-700/800`) come from the raw palette and are\n * mode-agnostic. Values mirror the `[data-accent]` presets in theme.css: the\n * dark half lifts the accent to the 400 step (readable as text on neutral-950)\n * and darkens the subtle surface. `default` is the built-in graphite-indigo.\n */\nexport const brandPresets = {\n /** The library default — graphite indigo. */\n default: { light: {} } as BrandTokenPair,\n /** Blue. */\n blue: {\n light: {\n accent: 'oklch(0.55 0.16 250)',\n 'color-accent-700': 'oklch(0.47 0.16 250)',\n 'color-accent-800': 'oklch(0.39 0.14 250)',\n 'accent-subtle': 'oklch(0.96 0.03 250)',\n 'accent-subtle-foreground': 'oklch(0.45 0.15 250)',\n ring: 'oklch(0.62 0.16 250)',\n },\n dark: {\n accent: 'oklch(0.64 0.15 250)',\n 'accent-subtle': 'oklch(0.24 0.06 250)',\n 'accent-subtle-foreground': 'oklch(0.82 0.1 250)',\n ring: 'oklch(0.68 0.15 250)',\n },\n },\n /** Violet. */\n violet: {\n light: {\n accent: 'oklch(0.53 0.20 295)',\n 'color-accent-700': 'oklch(0.45 0.18 295)',\n 'color-accent-800': 'oklch(0.38 0.16 295)',\n 'accent-subtle': 'oklch(0.96 0.03 295)',\n 'accent-subtle-foreground': 'oklch(0.46 0.18 295)',\n ring: 'oklch(0.60 0.20 295)',\n },\n dark: {\n accent: 'oklch(0.64 0.18 295)',\n 'accent-subtle': 'oklch(0.25 0.07 295)',\n 'accent-subtle-foreground': 'oklch(0.83 0.12 295)',\n ring: 'oklch(0.68 0.18 295)',\n },\n },\n /** Emerald. */\n emerald: {\n light: {\n accent: 'oklch(0.55 0.13 160)',\n 'color-accent-700': 'oklch(0.47 0.13 160)',\n 'color-accent-800': 'oklch(0.39 0.12 160)',\n 'accent-subtle': 'oklch(0.96 0.03 160)',\n 'accent-subtle-foreground': 'oklch(0.42 0.12 160)',\n ring: 'oklch(0.60 0.13 160)',\n },\n dark: {\n accent: 'oklch(0.64 0.14 160)',\n 'accent-subtle': 'oklch(0.23 0.05 160)',\n 'accent-subtle-foreground': 'oklch(0.8 0.12 160)',\n ring: 'oklch(0.68 0.14 160)',\n },\n },\n /** Rose. */\n rose: {\n light: {\n accent: 'oklch(0.57 0.19 12)',\n 'color-accent-700': 'oklch(0.49 0.18 12)',\n 'color-accent-800': 'oklch(0.41 0.16 12)',\n 'accent-subtle': 'oklch(0.96 0.03 12)',\n 'accent-subtle-foreground': 'oklch(0.48 0.18 12)',\n ring: 'oklch(0.62 0.19 12)',\n },\n dark: {\n accent: 'oklch(0.65 0.18 12)',\n 'accent-subtle': 'oklch(0.25 0.07 12)',\n 'accent-subtle-foreground': 'oklch(0.83 0.12 12)',\n ring: 'oklch(0.7 0.18 12)',\n },\n },\n /** Amber. */\n amber: {\n light: {\n // 0.56 keeps white text at 4.8:1 (0.62 was 3.8:1).\n accent: 'oklch(0.56 0.14 65)',\n 'color-accent-700': 'oklch(0.54 0.13 65)',\n 'color-accent-800': 'oklch(0.46 0.12 65)',\n 'accent-subtle': 'oklch(0.96 0.04 75)',\n 'accent-subtle-foreground': 'oklch(0.48 0.12 65)',\n ring: 'oklch(0.64 0.14 65)', // 3.17:1 on background-muted (0.66 was 2.93)\n },\n dark: {\n accent: 'oklch(0.66 0.14 65)',\n 'accent-subtle': 'oklch(0.26 0.05 70)',\n 'accent-subtle-foreground': 'oklch(0.85 0.12 80)',\n ring: 'oklch(0.72 0.14 65)',\n },\n },\n} satisfies Record<string, BrandTokenPair>;\n\nexport type BrandName = keyof typeof brandPresets;\n"],"names":["isPair","t","toDeclarations","tokens","k","v","DesignSystemProvider","strings","className","children","style","props","parentStrings","useStrings","resolvedStrings","useMemo","mergeStrings","scopeId","useId","css","sheet","scope","key","jsxs","StringsContext","jsx","cn","brandPresets"],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ComponentPropsWithoutRef, HTMLAttributes, ReactNode } from 'react';
|
|
2
2
|
import { ButtonProps } from './Button.js';
|
|
3
|
+
import { ReturnFocusRef } from '../../lib/return-focus.js';
|
|
3
4
|
import * as DialogPrimitive from '@radix-ui/react-dialog';
|
|
4
5
|
export declare const Dialog: import('react').FC<DialogPrimitive.DialogProps>;
|
|
5
6
|
export declare const DialogTrigger: import('react').ForwardRefExoticComponent<DialogPrimitive.DialogTriggerProps & import('react').RefAttributes<HTMLButtonElement>>;
|
|
@@ -11,6 +12,14 @@ export interface DialogContentProps extends ComponentPropsWithoutRef<typeof Dial
|
|
|
11
12
|
showClose?: boolean;
|
|
12
13
|
/** Dialog width — `sm` 400 / `md` 520 / `lg` 720. */
|
|
13
14
|
size?: 'sm' | 'md' | 'lg';
|
|
15
|
+
/**
|
|
16
|
+
* Element to focus when the overlay closes. Overrides Radix's default
|
|
17
|
+
* (the element focused when the content mounted), which is `<body>` for
|
|
18
|
+
* controlled overlays opened from a pointer click on a non-focusable /
|
|
19
|
+
* tooltip-wrapped trigger. A consumer `onCloseAutoFocus` runs first and
|
|
20
|
+
* wins if it calls `preventDefault()`.
|
|
21
|
+
*/
|
|
22
|
+
returnFocusTo?: ReturnFocusRef;
|
|
14
23
|
}
|
|
15
24
|
export declare const DialogContent: import('react').ForwardRefExoticComponent<DialogContentProps & import('react').RefAttributes<HTMLDivElement>>;
|
|
16
25
|
export declare function DialogHeader({ className, ...props }: HTMLAttributes<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -34,10 +43,16 @@ export interface ConfirmationDialogProps {
|
|
|
34
43
|
cancelLabel?: string;
|
|
35
44
|
/** Variant of the confirm button — typically `primary` or `destructive`. */
|
|
36
45
|
confirmVariant?: ButtonProps['variant'];
|
|
37
|
-
/**
|
|
46
|
+
/**
|
|
47
|
+
* Called when the user confirms. Awaited — the confirm button shows a
|
|
48
|
+
* spinner while pending and a rejection is rendered inline (the dialog stays
|
|
49
|
+
* open so the user can retry or cancel).
|
|
50
|
+
*/
|
|
38
51
|
onConfirm: () => void | Promise<void>;
|
|
39
|
-
/**
|
|
52
|
+
/** Force the submitting state from outside (in addition to the awaited `onConfirm`). */
|
|
40
53
|
loading?: boolean;
|
|
54
|
+
/** Map a rejected `onConfirm` to the message shown. Defaults to `Error.message`. */
|
|
55
|
+
formatError?: (err: unknown) => ReactNode;
|
|
41
56
|
}
|
|
42
57
|
/**
|
|
43
58
|
* Confirmation dialog with title, description, cancel + confirm buttons.
|
|
@@ -56,7 +71,7 @@ export interface ConfirmationDialogProps {
|
|
|
56
71
|
* State consequences in the description.
|
|
57
72
|
* @dont Use for low-risk reversible actions — those don't need a dialog.
|
|
58
73
|
*/
|
|
59
|
-
export declare function ConfirmationDialog({ open, onOpenChange, title, description, confirmLabel, cancelLabel, confirmVariant, onConfirm, loading, }: ConfirmationDialogProps): import("react/jsx-runtime").JSX.Element;
|
|
74
|
+
export declare function ConfirmationDialog({ open, onOpenChange, title, description, confirmLabel, cancelLabel, confirmVariant, onConfirm, loading, formatError, }: ConfirmationDialogProps): import("react/jsx-runtime").JSX.Element;
|
|
60
75
|
export declare namespace ConfirmationDialog {
|
|
61
76
|
var displayName: string;
|
|
62
77
|
}
|