@keboola/design 15.0.0 → 15.1.0

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 (108) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/{AIKit-CaAW4GLx.js → AIKit-BR6jfsdI.js} +60 -21
  3. package/dist/AIKit-BR6jfsdI.js.map +1 -0
  4. package/dist/{AlertModal-D4AtpvLS.js → AlertModal-DMsn62JJ.js} +3 -3
  5. package/dist/AlertModal-DMsn62JJ.js.map +1 -0
  6. package/dist/{Badge-5GHIsgRS.js → Badge-CqlOE5A2.js} +10 -10
  7. package/dist/Badge-CqlOE5A2.js.map +1 -0
  8. package/dist/{BrandEditor-CTGtQUFZ.js → BrandEditor-D61pzWRq.js} +3 -3
  9. package/dist/{BrandEditor-CTGtQUFZ.js.map → BrandEditor-D61pzWRq.js.map} +1 -1
  10. package/dist/{Breadcrumb-B2YSNON4.js → Breadcrumb-DbqvDnYl.js} +2 -2
  11. package/dist/{Breadcrumb-B2YSNON4.js.map → Breadcrumb-DbqvDnYl.js.map} +1 -1
  12. package/dist/{ColorModeSwitch-B6UEzG0H.js → ColorModeSwitch-BlrH8jAi.js} +2 -2
  13. package/dist/{ColorModeSwitch-B6UEzG0H.js.map → ColorModeSwitch-BlrH8jAi.js.map} +1 -1
  14. package/dist/{Combobox-CaKqgstG.js → Combobox-BLqX-Tdh.js} +3 -3
  15. package/dist/Combobox-BLqX-Tdh.js.map +1 -0
  16. package/dist/{DateInput-BgbMDJkm.js → DateInput-duinbI9_.js} +2 -2
  17. package/dist/{DateInput-BgbMDJkm.js.map → DateInput-duinbI9_.js.map} +1 -1
  18. package/dist/{DatePicker-BXpDRo-R.js → DatePicker-Cg_aG_N4.js} +2 -2
  19. package/dist/{DatePicker-BXpDRo-R.js.map → DatePicker-Cg_aG_N4.js.map} +1 -1
  20. package/dist/{DateRangeInput-BW0-_jV0.js → DateRangeInput-BYVHf9zo.js} +2 -2
  21. package/dist/{DateRangeInput-BW0-_jV0.js.map → DateRangeInput-BYVHf9zo.js.map} +1 -1
  22. package/dist/{DateRangePicker-C4-DoWac.js → DateRangePicker-m47cSV1r.js} +3 -3
  23. package/dist/{DateRangePicker-C4-DoWac.js.map → DateRangePicker-m47cSV1r.js.map} +1 -1
  24. package/dist/{DropdownMenu-CcVbZ_5u.js → DropdownMenu-Bum99mVf.js} +2 -2
  25. package/dist/DropdownMenu-Bum99mVf.js.map +1 -0
  26. package/dist/{Form-CAofWyMI.js → Form-Dqbt_tIs.js} +2 -2
  27. package/dist/{Form-CAofWyMI.js.map → Form-Dqbt_tIs.js.map} +1 -1
  28. package/dist/HoverCard-Cf9iYyaW.js +26 -0
  29. package/dist/HoverCard-Cf9iYyaW.js.map +1 -0
  30. package/dist/{MermaidDiagram-Te-5gOCU.js → MermaidDiagram-2-EuNu1i.js} +2 -2
  31. package/dist/{MermaidDiagram-Te-5gOCU.js.map → MermaidDiagram-2-EuNu1i.js.map} +1 -1
  32. package/dist/{Modal-CbUz-5YH.js → Modal-DwuvuiUx.js} +3 -3
  33. package/dist/Modal-DwuvuiUx.js.map +1 -0
  34. package/dist/{ModalTitle-cy0Ht9VY.js → ModalTitle-RGWwIMU6.js} +2 -2
  35. package/dist/ModalTitle-RGWwIMU6.js.map +1 -0
  36. package/dist/{PageToolbar-DJ5tdYla.js → PageToolbar-LKP6PiP_.js} +3 -3
  37. package/dist/{PageToolbar-DJ5tdYla.js.map → PageToolbar-LKP6PiP_.js.map} +1 -1
  38. package/dist/{Popconfirm-DwLCYNaF.js → Popconfirm-p72DiagN.js} +2 -2
  39. package/dist/{Popconfirm-DwLCYNaF.js.map → Popconfirm-p72DiagN.js.map} +1 -1
  40. package/dist/{Popover-DtUDwUVO.js → Popover-DnBw5Uay.js} +2 -2
  41. package/dist/Popover-DnBw5Uay.js.map +1 -0
  42. package/dist/{SectionNav-tLK3iF6c.js → SectionNav-6hcIpZLO.js} +3 -3
  43. package/dist/{SectionNav-tLK3iF6c.js.map → SectionNav-6hcIpZLO.js.map} +1 -1
  44. package/dist/{Select-B22hB_-w.js → Select-C6zKeip5.js} +2 -2
  45. package/dist/Select-C6zKeip5.js.map +1 -0
  46. package/dist/{Sheet-0TWKTqid.js → Sheet-DKG20J7W.js} +3 -3
  47. package/dist/Sheet-DKG20J7W.js.map +1 -0
  48. package/dist/{Sidebar-C5hdANBU.js → Sidebar-BlYqasnX.js} +4 -4
  49. package/dist/{Sidebar-C5hdANBU.js.map → Sidebar-BlYqasnX.js.map} +1 -1
  50. package/dist/{TimePicker-CoRpiEM3.js → TimePicker-lk3NGqeK.js} +2 -2
  51. package/dist/{TimePicker-CoRpiEM3.js.map → TimePicker-lk3NGqeK.js.map} +1 -1
  52. package/dist/Workbench-CxgNCs3I.js.map +1 -1
  53. package/dist/{ZoomableSvg-DnFXo2L4.js → ZoomableSvg-CxXKanUR.js} +2 -2
  54. package/dist/{ZoomableSvg-DnFXo2L4.js.map → ZoomableSvg-CxXKanUR.js.map} +1 -1
  55. package/dist/flint.js +1 -1
  56. package/dist/index.d.ts +42 -8
  57. package/dist/index.js +26 -25
  58. package/dist/internal/blocks/AIKit.js +1 -1
  59. package/dist/internal/blocks/BrandEditor.js +1 -1
  60. package/dist/internal/blocks/ChipEditor.js +1 -1
  61. package/dist/internal/blocks/ColorModeSwitch.js +1 -1
  62. package/dist/internal/blocks/DateInput.js +1 -1
  63. package/dist/internal/blocks/DateRangeInput.js +1 -1
  64. package/dist/internal/blocks/ExportMenu.js +1 -1
  65. package/dist/internal/blocks/Form/connectors/ComboboxField.js +1 -1
  66. package/dist/internal/blocks/Form.js +1 -1
  67. package/dist/internal/blocks/MultiCombobox.js +1 -1
  68. package/dist/internal/blocks/PageToolbar.js +1 -1
  69. package/dist/internal/blocks/SectionNav.js +1 -1
  70. package/dist/internal/blocks/SplitButton.js +1 -1
  71. package/dist/internal/blocks/TimeInput.js +1 -1
  72. package/dist/internal/components/AlertModal.js +1 -1
  73. package/dist/internal/components/Badge.js +1 -1
  74. package/dist/internal/components/Breadcrumb.js +1 -1
  75. package/dist/internal/components/Combobox.js +1 -1
  76. package/dist/internal/components/DatePicker.js +1 -1
  77. package/dist/internal/components/DateRangePicker.js +1 -1
  78. package/dist/internal/components/DropdownMenu.js +1 -1
  79. package/dist/internal/components/HoverCard.js +1 -1
  80. package/dist/internal/components/Modal.js +1 -1
  81. package/dist/internal/components/Popconfirm.js +1 -1
  82. package/dist/internal/components/Popover.js +1 -1
  83. package/dist/internal/components/Select.js +1 -1
  84. package/dist/internal/components/Sheet.js +1 -1
  85. package/dist/internal/components/Sidebar.js +1 -1
  86. package/dist/internal/components/TimePicker.js +1 -1
  87. package/dist/internal/components/ZoomableSvg.js +1 -1
  88. package/dist/internal/hooks/useTimeout.js +19 -0
  89. package/dist/internal/hooks/useTimeout.js.map +1 -0
  90. package/dist/markdown-editor.js +3 -3
  91. package/dist/mermaid.js +1 -1
  92. package/dist/rjsf.js +2 -2
  93. package/dist/styles.css +1 -1
  94. package/dist/utils-DwC9u0tM.js.map +1 -1
  95. package/package.json +1 -1
  96. package/src/theme.css +4 -0
  97. package/dist/AIKit-CaAW4GLx.js.map +0 -1
  98. package/dist/AlertModal-D4AtpvLS.js.map +0 -1
  99. package/dist/Badge-5GHIsgRS.js.map +0 -1
  100. package/dist/Combobox-CaKqgstG.js.map +0 -1
  101. package/dist/DropdownMenu-CcVbZ_5u.js.map +0 -1
  102. package/dist/HoverCard-Cv5rmvJq.js +0 -26
  103. package/dist/HoverCard-Cv5rmvJq.js.map +0 -1
  104. package/dist/Modal-CbUz-5YH.js.map +0 -1
  105. package/dist/ModalTitle-cy0Ht9VY.js.map +0 -1
  106. package/dist/Popover-DtUDwUVO.js.map +0 -1
  107. package/dist/Select-B22hB_-w.js.map +0 -1
  108. package/dist/Sheet-0TWKTqid.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"DateInput-BgbMDJkm.js","names":["CalendarIcon"],"sources":["../src/blocks/DateInput/helpers.ts","../src/blocks/DateInput/DateInput.tsx"],"sourcesContent":["export const formatDate = (date: Date | null | undefined, inputValue: string): string => {\n if (!date) {\n return inputValue;\n }\n return date.toLocaleDateString();\n};\n\n// Detect locale day/month/year order once, matching toLocaleDateString() output\nconst datePartOrder = new Intl.DateTimeFormat()\n .formatToParts(new Date(2000, 0, 2))\n .filter(\n (p): p is { type: 'day' | 'month' | 'year'; value: string } =>\n p.type === 'day' || p.type === 'month' || p.type === 'year',\n )\n .map((p) => p.type);\n\nexport const parseDate = (value: string): Date | null => {\n if (!value.trim()) return null;\n\n // Try locale-aware parsing first (matches toLocaleDateString round-trip)\n const nums = value.match(/\\d+/g)?.map(Number);\n if (nums && nums.length >= 3) {\n const parts = Object.fromEntries(datePartOrder.map((type, i) => [type, nums[i]]));\n const year = parts.year;\n const month = parts.month;\n const day = parts.day;\n\n if (\n year != null &&\n month != null &&\n day != null &&\n month >= 1 &&\n month <= 12 &&\n day >= 1 &&\n day <= 31\n ) {\n const date = new Date(year, month - 1, day);\n if (date.getFullYear() === year && date.getMonth() === month - 1 && date.getDate() === day) {\n return date;\n }\n }\n }\n\n // Fallback: detect ISO YYYY-MM-DD and construct as local midnight to avoid UTC offset issues\n const isoMatch = value.match(/^(\\d{4})-(\\d{1,2})-(\\d{1,2})$/);\n if (isoMatch) {\n const y = Number(isoMatch[1]);\n const m = Number(isoMatch[2]) - 1;\n const d = Number(isoMatch[3]);\n const date = new Date(y, m, d);\n if (date.getFullYear() === y && date.getMonth() === m && date.getDate() === d) {\n return date;\n }\n return null;\n }\n\n const fallback = new Date(value);\n return isNaN(fallback.getTime()) ? null : fallback;\n};\n","import { useRef, useState } from 'react';\nimport type {\n ChangeEventHandler,\n ComponentProps,\n ComponentRef,\n FocusEventHandler,\n MouseEventHandler,\n} from 'react';\nimport type { Matcher } from 'react-day-picker';\n\nimport { DatePicker } from '../../components/DatePicker';\nimport { InputGroup } from '../../components/InputGroup';\nimport { useControllableState } from '../../hooks/useControllableState';\nimport { Calendar as CalendarIcon, X } from '../../icons';\nimport { createChangeInputEvent, mergeRefs } from '../../utils';\n\nimport { formatDate, parseDate } from './helpers';\n\ntype InputGroupProps = Pick<ComponentProps<typeof InputGroup>, 'focusVariant' | 'state'>;\n\ntype InputGroupInputProps = Omit<\n ComponentProps<typeof InputGroup.Input>,\n 'value' | 'defaultValue' | 'type'\n>;\n\ntype Props = InputGroupProps &\n InputGroupInputProps & {\n value?: Date | null;\n defaultValue?: Date | null;\n onValueChange?: (value: Date | null) => void;\n onValueBlur?: (value: Date | null) => void;\n allowClear?: boolean;\n disabledDays?: Matcher | Matcher[];\n endMonth?: Date;\n startMonth?: Date;\n };\n\nexport const DateInput = ({\n ref,\n\n // group props\n state,\n focusVariant,\n className,\n\n // own props\n value,\n defaultValue,\n onValueChange,\n onValueBlur,\n onChange,\n onBlur,\n onFocus,\n allowClear = false,\n disabledDays,\n endMonth,\n startMonth,\n\n // input props\n disabled,\n readOnly,\n placeholder = 'Select a date',\n ...restInputProps\n}: Props) => {\n const inputRef = useRef<ComponentRef<'input'>>(null);\n\n const [inputValue, setInputValue] = useState('');\n const [hasFocus, setHasFocus] = useState(false);\n const [isOpen, setIsOpen] = useState(false);\n const [month, setMonth] = useState<Date>(new Date());\n\n // `onValueChange` is fired explicitly per-path below (not through the hook), because commits\n // happen on blur / picker-select rather than on every keystroke.\n const [currentValue, setCurrentValue] = useControllableState<Date | null>({\n prop: value,\n defaultProp: defaultValue ?? null,\n });\n\n const canClear = allowClear && !!currentValue && !disabled && !readOnly;\n const showPicker = !disabled && !readOnly;\n\n const handleChange: ChangeEventHandler<HTMLInputElement> = (event) => {\n const newValue = event.target.value;\n setInputValue(newValue);\n onChange?.(event);\n\n const parsedDate = parseDate(newValue);\n if (parsedDate !== null || !newValue.trim()) {\n onValueChange?.(parsedDate);\n }\n };\n\n const handleFocus: FocusEventHandler<HTMLInputElement> = (event) => {\n const formatted = formatDate(currentValue, '');\n setInputValue(formatted);\n setHasFocus(true);\n onFocus?.(event);\n };\n\n const handleBlur: FocusEventHandler<HTMLInputElement> = (event) => {\n setHasFocus(false);\n onBlur?.(event);\n\n // If the field still shows the formatted current value (focused and blurred\n // without editing), keep it as-is. `formatDate` uses `toLocaleDateString`,\n // whose output is not reliably parseable by `parseDate` in every locale, so\n // round-tripping an untouched value could wrongly null it.\n const text = event.target.value;\n const parsedDate = text === formatDate(currentValue, '') ? currentValue : parseDate(text);\n onValueBlur?.(parsedDate);\n\n setCurrentValue(parsedDate);\n };\n\n const handleDatePickerChange = (newValue?: Date) => {\n const dateValue = newValue ?? null;\n\n setCurrentValue(dateValue);\n onValueChange?.(dateValue);\n\n setHasFocus(false);\n setIsOpen(false);\n };\n\n const handleClear: MouseEventHandler<HTMLButtonElement> = () => {\n if (!inputRef.current) return;\n inputRef.current.value = '';\n setInputValue('');\n setCurrentValue(null);\n onValueChange?.(null);\n onChange?.(createChangeInputEvent(inputRef.current));\n };\n\n const handleOpenChange = (open: boolean) => {\n if (open) {\n setMonth(currentValue ?? new Date());\n }\n setIsOpen(open);\n };\n\n const displayValue = hasFocus ? inputValue : formatDate(currentValue, '');\n\n return (\n <InputGroup state={state} focusVariant={focusVariant} className={className}>\n <InputGroup.Input\n {...restInputProps}\n ref={mergeRefs(ref ?? null, inputRef)}\n type=\"text\"\n value={displayValue}\n placeholder={placeholder}\n onChange={handleChange}\n onFocus={handleFocus}\n onBlur={handleBlur}\n disabled={disabled}\n readOnly={readOnly}\n />\n\n {(canClear || showPicker) && (\n <InputGroup.Addon align=\"inline-end\">\n {canClear && (\n <InputGroup.Button\n aria-label=\"Clear date\"\n onMouseDown={(event) => event.preventDefault()}\n onClick={handleClear}\n >\n <X className=\"tw:size-4\" />\n </InputGroup.Button>\n )}\n {showPicker && (\n <DatePicker\n disabled={disabledDays}\n endMonth={endMonth}\n mode=\"single\"\n month={month}\n onMonthChange={setMonth}\n onOpenChange={handleOpenChange}\n onSelect={handleDatePickerChange}\n open={isOpen}\n selected={currentValue ?? undefined}\n startMonth={startMonth}\n >\n <InputGroup.Button aria-label=\"Select Date\">\n <CalendarIcon className=\"tw:size-4\" />\n </InputGroup.Button>\n </DatePicker>\n )}\n </InputGroup.Addon>\n )}\n </InputGroup>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"DateInput-duinbI9_.js","names":["CalendarIcon"],"sources":["../src/blocks/DateInput/helpers.ts","../src/blocks/DateInput/DateInput.tsx"],"sourcesContent":["export const formatDate = (date: Date | null | undefined, inputValue: string): string => {\n if (!date) {\n return inputValue;\n }\n return date.toLocaleDateString();\n};\n\n// Detect locale day/month/year order once, matching toLocaleDateString() output\nconst datePartOrder = new Intl.DateTimeFormat()\n .formatToParts(new Date(2000, 0, 2))\n .filter(\n (p): p is { type: 'day' | 'month' | 'year'; value: string } =>\n p.type === 'day' || p.type === 'month' || p.type === 'year',\n )\n .map((p) => p.type);\n\nexport const parseDate = (value: string): Date | null => {\n if (!value.trim()) return null;\n\n // Try locale-aware parsing first (matches toLocaleDateString round-trip)\n const nums = value.match(/\\d+/g)?.map(Number);\n if (nums && nums.length >= 3) {\n const parts = Object.fromEntries(datePartOrder.map((type, i) => [type, nums[i]]));\n const year = parts.year;\n const month = parts.month;\n const day = parts.day;\n\n if (\n year != null &&\n month != null &&\n day != null &&\n month >= 1 &&\n month <= 12 &&\n day >= 1 &&\n day <= 31\n ) {\n const date = new Date(year, month - 1, day);\n if (date.getFullYear() === year && date.getMonth() === month - 1 && date.getDate() === day) {\n return date;\n }\n }\n }\n\n // Fallback: detect ISO YYYY-MM-DD and construct as local midnight to avoid UTC offset issues\n const isoMatch = value.match(/^(\\d{4})-(\\d{1,2})-(\\d{1,2})$/);\n if (isoMatch) {\n const y = Number(isoMatch[1]);\n const m = Number(isoMatch[2]) - 1;\n const d = Number(isoMatch[3]);\n const date = new Date(y, m, d);\n if (date.getFullYear() === y && date.getMonth() === m && date.getDate() === d) {\n return date;\n }\n return null;\n }\n\n const fallback = new Date(value);\n return isNaN(fallback.getTime()) ? null : fallback;\n};\n","import { useRef, useState } from 'react';\nimport type {\n ChangeEventHandler,\n ComponentProps,\n ComponentRef,\n FocusEventHandler,\n MouseEventHandler,\n} from 'react';\nimport type { Matcher } from 'react-day-picker';\n\nimport { DatePicker } from '../../components/DatePicker';\nimport { InputGroup } from '../../components/InputGroup';\nimport { useControllableState } from '../../hooks/useControllableState';\nimport { Calendar as CalendarIcon, X } from '../../icons';\nimport { createChangeInputEvent, mergeRefs } from '../../utils';\n\nimport { formatDate, parseDate } from './helpers';\n\ntype InputGroupProps = Pick<ComponentProps<typeof InputGroup>, 'focusVariant' | 'state'>;\n\ntype InputGroupInputProps = Omit<\n ComponentProps<typeof InputGroup.Input>,\n 'value' | 'defaultValue' | 'type'\n>;\n\ntype Props = InputGroupProps &\n InputGroupInputProps & {\n value?: Date | null;\n defaultValue?: Date | null;\n onValueChange?: (value: Date | null) => void;\n onValueBlur?: (value: Date | null) => void;\n allowClear?: boolean;\n disabledDays?: Matcher | Matcher[];\n endMonth?: Date;\n startMonth?: Date;\n };\n\nexport const DateInput = ({\n ref,\n\n // group props\n state,\n focusVariant,\n className,\n\n // own props\n value,\n defaultValue,\n onValueChange,\n onValueBlur,\n onChange,\n onBlur,\n onFocus,\n allowClear = false,\n disabledDays,\n endMonth,\n startMonth,\n\n // input props\n disabled,\n readOnly,\n placeholder = 'Select a date',\n ...restInputProps\n}: Props) => {\n const inputRef = useRef<ComponentRef<'input'>>(null);\n\n const [inputValue, setInputValue] = useState('');\n const [hasFocus, setHasFocus] = useState(false);\n const [isOpen, setIsOpen] = useState(false);\n const [month, setMonth] = useState<Date>(new Date());\n\n // `onValueChange` is fired explicitly per-path below (not through the hook), because commits\n // happen on blur / picker-select rather than on every keystroke.\n const [currentValue, setCurrentValue] = useControllableState<Date | null>({\n prop: value,\n defaultProp: defaultValue ?? null,\n });\n\n const canClear = allowClear && !!currentValue && !disabled && !readOnly;\n const showPicker = !disabled && !readOnly;\n\n const handleChange: ChangeEventHandler<HTMLInputElement> = (event) => {\n const newValue = event.target.value;\n setInputValue(newValue);\n onChange?.(event);\n\n const parsedDate = parseDate(newValue);\n if (parsedDate !== null || !newValue.trim()) {\n onValueChange?.(parsedDate);\n }\n };\n\n const handleFocus: FocusEventHandler<HTMLInputElement> = (event) => {\n const formatted = formatDate(currentValue, '');\n setInputValue(formatted);\n setHasFocus(true);\n onFocus?.(event);\n };\n\n const handleBlur: FocusEventHandler<HTMLInputElement> = (event) => {\n setHasFocus(false);\n onBlur?.(event);\n\n // If the field still shows the formatted current value (focused and blurred\n // without editing), keep it as-is. `formatDate` uses `toLocaleDateString`,\n // whose output is not reliably parseable by `parseDate` in every locale, so\n // round-tripping an untouched value could wrongly null it.\n const text = event.target.value;\n const parsedDate = text === formatDate(currentValue, '') ? currentValue : parseDate(text);\n onValueBlur?.(parsedDate);\n\n setCurrentValue(parsedDate);\n };\n\n const handleDatePickerChange = (newValue?: Date) => {\n const dateValue = newValue ?? null;\n\n setCurrentValue(dateValue);\n onValueChange?.(dateValue);\n\n setHasFocus(false);\n setIsOpen(false);\n };\n\n const handleClear: MouseEventHandler<HTMLButtonElement> = () => {\n if (!inputRef.current) return;\n inputRef.current.value = '';\n setInputValue('');\n setCurrentValue(null);\n onValueChange?.(null);\n onChange?.(createChangeInputEvent(inputRef.current));\n };\n\n const handleOpenChange = (open: boolean) => {\n if (open) {\n setMonth(currentValue ?? new Date());\n }\n setIsOpen(open);\n };\n\n const displayValue = hasFocus ? inputValue : formatDate(currentValue, '');\n\n return (\n <InputGroup state={state} focusVariant={focusVariant} className={className}>\n <InputGroup.Input\n {...restInputProps}\n ref={mergeRefs(ref ?? null, inputRef)}\n type=\"text\"\n value={displayValue}\n placeholder={placeholder}\n onChange={handleChange}\n onFocus={handleFocus}\n onBlur={handleBlur}\n disabled={disabled}\n readOnly={readOnly}\n />\n\n {(canClear || showPicker) && (\n <InputGroup.Addon align=\"inline-end\">\n {canClear && (\n <InputGroup.Button\n aria-label=\"Clear date\"\n onMouseDown={(event) => event.preventDefault()}\n onClick={handleClear}\n >\n <X className=\"tw:size-4\" />\n </InputGroup.Button>\n )}\n {showPicker && (\n <DatePicker\n disabled={disabledDays}\n endMonth={endMonth}\n mode=\"single\"\n month={month}\n onMonthChange={setMonth}\n onOpenChange={handleOpenChange}\n onSelect={handleDatePickerChange}\n open={isOpen}\n selected={currentValue ?? undefined}\n startMonth={startMonth}\n >\n <InputGroup.Button aria-label=\"Select Date\">\n <CalendarIcon className=\"tw:size-4\" />\n </InputGroup.Button>\n </DatePicker>\n )}\n </InputGroup.Addon>\n )}\n </InputGroup>\n );\n};\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { Popover } from "./Popover-DtUDwUVO.js";
1
+ import { Popover } from "./Popover-DnBw5Uay.js";
2
2
  import { Calendar } from "./Calendar-BnKi1kPu.js";
3
3
  import { jsx, jsxs } from "react/jsx-runtime";
4
4
  //#region src/components/DatePicker/DatePicker.tsx
@@ -21,4 +21,4 @@ DatePicker.displayName = "DatePicker";
21
21
  //#endregion
22
22
  export { DatePicker };
23
23
 
24
- //# sourceMappingURL=DatePicker-BXpDRo-R.js.map
24
+ //# sourceMappingURL=DatePicker-Cg_aG_N4.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DatePicker-BXpDRo-R.js","names":[],"sources":["../src/components/DatePicker/DatePicker.tsx"],"sourcesContent":["import type { PropsWithChildren } from 'react';\nimport type { PopoverContentProps, PopoverProps } from '@radix-ui/react-popover';\n\nimport type { CalendarProps } from '../Calendar';\nimport { Calendar } from '../Calendar';\nimport { Popover } from '../Popover';\n\ntype OwnPopoverProps = PropsWithChildren &\n Pick<PopoverProps, 'open' | 'onOpenChange' | 'defaultOpen'> &\n Pick<PopoverContentProps, 'align' | 'alignOffset' | 'sideOffset'>;\n\ntype DatePickerProps = OwnPopoverProps & CalendarProps;\n\nexport const DatePicker = ({\n align = 'end',\n alignOffset = -18,\n children,\n defaultOpen,\n onOpenChange,\n open,\n sideOffset = 12,\n ...calendarProps\n}: DatePickerProps) => (\n <Popover defaultOpen={defaultOpen} open={open} onOpenChange={onOpenChange}>\n <Popover.Trigger asChild>{children}</Popover.Trigger>\n <Popover.Content\n align={align}\n alignOffset={alignOffset}\n className=\"tw:w-auto tw:p-0\"\n sideOffset={sideOffset}\n >\n <Calendar {...calendarProps} />\n </Popover.Content>\n </Popover>\n);\n\nDatePicker.displayName = 'DatePicker';\n"],"mappings":";;;;AAaA,MAAa,cAAc,EACzB,QAAQ,OACR,cAAc,KACd,UACA,aACA,cACA,MACA,aAAa,IACb,GAAG,oBAEH,qBAAC,SAAD;CAAsB;CAAmB;CAAoB;CAA7D,UAAA,CACE,oBAAC,QAAQ,SAAT;EAAiB,SAAA;EAAS;CAA0B,CAAA,GACpD,oBAAC,QAAQ,SAAT;EACS;EACM;EACb,WAAU;EACE;EAEZ,UAAA,oBAAC,UAAD,EAAU,GAAI,cAAgB,CAAA;CACf,CAAA,CACV;;AAGX,WAAW,cAAc"}
1
+ {"version":3,"file":"DatePicker-Cg_aG_N4.js","names":[],"sources":["../src/components/DatePicker/DatePicker.tsx"],"sourcesContent":["import type { PropsWithChildren } from 'react';\nimport type { PopoverContentProps, PopoverProps } from '@radix-ui/react-popover';\n\nimport type { CalendarProps } from '../Calendar';\nimport { Calendar } from '../Calendar';\nimport { Popover } from '../Popover';\n\ntype OwnPopoverProps = PropsWithChildren &\n Pick<PopoverProps, 'open' | 'onOpenChange' | 'defaultOpen'> &\n Pick<PopoverContentProps, 'align' | 'alignOffset' | 'sideOffset'>;\n\ntype DatePickerProps = OwnPopoverProps & CalendarProps;\n\nexport const DatePicker = ({\n align = 'end',\n alignOffset = -18,\n children,\n defaultOpen,\n onOpenChange,\n open,\n sideOffset = 12,\n ...calendarProps\n}: DatePickerProps) => (\n <Popover defaultOpen={defaultOpen} open={open} onOpenChange={onOpenChange}>\n <Popover.Trigger asChild>{children}</Popover.Trigger>\n <Popover.Content\n align={align}\n alignOffset={alignOffset}\n className=\"tw:w-auto tw:p-0\"\n sideOffset={sideOffset}\n >\n <Calendar {...calendarProps} />\n </Popover.Content>\n </Popover>\n);\n\nDatePicker.displayName = 'DatePicker';\n"],"mappings":";;;;AAaA,MAAa,cAAc,EACzB,QAAQ,OACR,cAAc,KACd,UACA,aACA,cACA,MACA,aAAa,IACb,GAAG,oBAEH,qBAAC,SAAD;CAAsB;CAAmB;CAAoB;CAA7D,UAAA,CACE,oBAAC,QAAQ,SAAT;EAAiB,SAAA;EAAS;CAA0B,CAAA,GACpD,oBAAC,QAAQ,SAAT;EACS;EACM;EACb,WAAU;EACE;EAEZ,UAAA,oBAAC,UAAD,EAAU,GAAI,cAAgB,CAAA;CACf,CAAA,CACV;;AAGX,WAAW,cAAc"}
@@ -3,7 +3,7 @@ import { mergeRefs } from "./internal/utils/mergeRefs.js";
3
3
  import { Calendar, X } from "./icons-ZIeZXXS7.js";
4
4
  import { InputGroup } from "./InputGroup-CZv_7QlM.js";
5
5
  import { useControllableState } from "./useControllableState-CUYXMsfz.js";
6
- import { DatePicker } from "./DatePicker-BXpDRo-R.js";
6
+ import { DatePicker } from "./DatePicker-Cg_aG_N4.js";
7
7
  import { useRef, useState } from "react";
8
8
  import { jsx, jsxs } from "react/jsx-runtime";
9
9
  //#region src/blocks/DateRangeInput/helpers.ts
@@ -130,4 +130,4 @@ const DateRangeInput = ({ ref, state, focusVariant, className, value: valueProp,
130
130
  //#endregion
131
131
  export { DateRangeInput };
132
132
 
133
- //# sourceMappingURL=DateRangeInput-BW0-_jV0.js.map
133
+ //# sourceMappingURL=DateRangeInput-BYVHf9zo.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DateRangeInput-BW0-_jV0.js","names":["CalendarIcon"],"sources":["../src/blocks/DateRangeInput/helpers.ts","../src/blocks/DateRangeInput/DateRangeInput.tsx"],"sourcesContent":["import type { DateRange } from 'react-day-picker';\n\nexport const formatDateRange = (\n range: DateRange | null | undefined,\n inputValue: string,\n): string => {\n if (!range) {\n return inputValue;\n }\n\n const { from, to } = range;\n const fromStr = from?.toLocaleDateString();\n const toStr = to?.toLocaleDateString();\n return `${fromStr} - ${toStr}`;\n};\n\nconst ISO_DATE_ONLY = /^\\d{4}-\\d{2}-\\d{2}$/;\n\n/**\n * Parses date-only ISO (`2024-01-15`) as local time, not UTC midnight.\n *\n * - UTC midnight reads back as the previous day west of UTC.\n * - Keeps `new Date` validation; `new Date(y, m - 1, d)` would roll `2024-13-45` over.\n * - Other accepted formats already parse as local time.\n */\nconst parseLocalDate = (value: string): Date =>\n ISO_DATE_ONLY.test(value) ? new Date(`${value}T00:00:00`) : new Date(value);\n\nexport const parseDateRange = (value: string): DateRange | null => {\n const parts = value.split(' - ');\n if (parts.length !== 2) {\n return null;\n }\n\n const [fromPart, toPart] = parts;\n if (!fromPart || !toPart) {\n return null;\n }\n\n const from = parseLocalDate(fromPart.trim());\n const to = parseLocalDate(toPart.trim());\n\n if (isNaN(from.getTime()) || isNaN(to.getTime())) {\n return null;\n }\n\n return { from, to };\n};\n","import { useRef, useState } from 'react';\nimport type { ChangeEventHandler, ComponentProps, ComponentRef, FocusEventHandler } from 'react';\nimport type { DateRange } from 'react-day-picker';\n\nimport { DatePicker } from '../../components/DatePicker';\nimport { InputGroup } from '../../components/InputGroup';\nimport { useControllableState } from '../../hooks/useControllableState';\nimport { Calendar as CalendarIcon, X } from '../../icons';\nimport { createChangeInputEvent, mergeRefs } from '../../utils';\n\nimport { formatDateRange, parseDateRange } from './helpers';\n\ntype InputGroupProps = Pick<ComponentProps<typeof InputGroup>, 'focusVariant' | 'state'>;\n\ntype InputGroupInputProps = Omit<\n ComponentProps<typeof InputGroup.Input>,\n 'value' | 'defaultValue' | 'type'\n>;\n\ntype Props = InputGroupProps &\n InputGroupInputProps & {\n value?: DateRange | null;\n defaultValue?: DateRange | null;\n onValueChange?: (value: DateRange | null) => void;\n onValueBlur?: (value: DateRange | null) => void;\n allowClear?: boolean;\n startMonth?: Date;\n endMonth?: Date;\n };\n\nexport const DateRangeInput = ({\n ref,\n\n // group props\n state,\n focusVariant,\n className,\n\n // own props\n value: valueProp,\n defaultValue,\n onValueChange,\n onValueBlur,\n onChange,\n onBlur,\n onFocus,\n allowClear = false,\n startMonth,\n endMonth,\n\n // input props\n disabled,\n readOnly,\n placeholder = 'Select a date range',\n ...restInputProps\n}: Props) => {\n const inputRef = useRef<ComponentRef<'input'>>(null);\n\n const [inputValue, setInputValue] = useState('');\n const [hasFocus, setHasFocus] = useState(false);\n const [isOpen, setIsOpen] = useState(false);\n const [month, setMonth] = useState<Date>(new Date());\n\n // `onValueChange` is fired explicitly per-path below (not through the hook), because commits\n // happen on blur / picker-select rather than on every keystroke.\n const [currentValue, setCurrentValue] = useControllableState<DateRange | null>({\n prop: valueProp,\n defaultProp: defaultValue ?? null,\n });\n\n const canClear = allowClear && !!currentValue && !disabled && !readOnly;\n const showPicker = !disabled && !readOnly;\n\n const handleChange: ChangeEventHandler<HTMLInputElement> = (event) => {\n const newValue = event.target.value;\n setInputValue(newValue);\n onChange?.(event);\n\n const parsedRange = parseDateRange(newValue);\n if (parsedRange !== null || !newValue.trim()) {\n onValueChange?.(parsedRange);\n }\n };\n\n const handleFocus: FocusEventHandler<HTMLInputElement> = (event) => {\n setInputValue(formatDateRange(currentValue, ''));\n setHasFocus(true);\n onFocus?.(event);\n };\n\n const handleBlur: FocusEventHandler<HTMLInputElement> = (event) => {\n setHasFocus(false);\n onBlur?.(event);\n\n // If the field still shows the formatted current value (focused and blurred\n // without editing), keep it as-is. `formatDateRange` uses `toLocaleDateString`,\n // whose output is not reliably parseable by `new Date(...)` in every locale, so\n // round-tripping an untouched value through `parseDateRange` could wrongly null it.\n const text = event.target.value;\n const parsedRange =\n text === formatDateRange(currentValue, '') ? currentValue : parseDateRange(text);\n onValueBlur?.(parsedRange);\n\n setCurrentValue(parsedRange);\n };\n\n const handleDatePickerChange = (newValue: DateRange | undefined) => {\n const rangeValue = newValue ?? null;\n\n setCurrentValue(rangeValue);\n onValueChange?.(rangeValue);\n\n setHasFocus(false);\n };\n\n const handleClear = () => {\n if (!inputRef.current) return;\n inputRef.current.value = '';\n setInputValue('');\n setCurrentValue(null);\n onValueChange?.(null);\n onChange?.(createChangeInputEvent(inputRef.current));\n };\n\n const handleOpenChange = (open: boolean) => {\n if (open) {\n setMonth(currentValue?.from ?? new Date());\n }\n setIsOpen(open);\n };\n\n const displayValue = hasFocus ? inputValue : formatDateRange(currentValue, '');\n\n return (\n <InputGroup state={state} focusVariant={focusVariant} className={className}>\n <InputGroup.Input\n {...restInputProps}\n ref={mergeRefs(ref ?? null, inputRef)}\n type=\"text\"\n value={displayValue}\n placeholder={placeholder}\n onChange={handleChange}\n onFocus={handleFocus}\n onBlur={handleBlur}\n disabled={disabled}\n readOnly={readOnly}\n />\n\n {(canClear || showPicker) && (\n <InputGroup.Addon align=\"inline-end\">\n {canClear && (\n <InputGroup.Button\n aria-label=\"Clear date range\"\n onMouseDown={(event) => event.preventDefault()}\n onClick={handleClear}\n >\n <X className=\"tw:size-4\" />\n </InputGroup.Button>\n )}\n {showPicker && (\n <DatePicker\n endMonth={endMonth}\n mode=\"range\"\n month={month}\n onMonthChange={setMonth}\n onOpenChange={handleOpenChange}\n onSelect={handleDatePickerChange}\n open={isOpen}\n startMonth={startMonth}\n selected={currentValue ?? undefined}\n >\n <InputGroup.Button aria-label=\"Select date range\">\n <CalendarIcon className=\"tw:size-4\" />\n </InputGroup.Button>\n </DatePicker>\n )}\n </InputGroup.Addon>\n )}\n </InputGroup>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"DateRangeInput-BYVHf9zo.js","names":["CalendarIcon"],"sources":["../src/blocks/DateRangeInput/helpers.ts","../src/blocks/DateRangeInput/DateRangeInput.tsx"],"sourcesContent":["import type { DateRange } from 'react-day-picker';\n\nexport const formatDateRange = (\n range: DateRange | null | undefined,\n inputValue: string,\n): string => {\n if (!range) {\n return inputValue;\n }\n\n const { from, to } = range;\n const fromStr = from?.toLocaleDateString();\n const toStr = to?.toLocaleDateString();\n return `${fromStr} - ${toStr}`;\n};\n\nconst ISO_DATE_ONLY = /^\\d{4}-\\d{2}-\\d{2}$/;\n\n/**\n * Parses date-only ISO (`2024-01-15`) as local time, not UTC midnight.\n *\n * - UTC midnight reads back as the previous day west of UTC.\n * - Keeps `new Date` validation; `new Date(y, m - 1, d)` would roll `2024-13-45` over.\n * - Other accepted formats already parse as local time.\n */\nconst parseLocalDate = (value: string): Date =>\n ISO_DATE_ONLY.test(value) ? new Date(`${value}T00:00:00`) : new Date(value);\n\nexport const parseDateRange = (value: string): DateRange | null => {\n const parts = value.split(' - ');\n if (parts.length !== 2) {\n return null;\n }\n\n const [fromPart, toPart] = parts;\n if (!fromPart || !toPart) {\n return null;\n }\n\n const from = parseLocalDate(fromPart.trim());\n const to = parseLocalDate(toPart.trim());\n\n if (isNaN(from.getTime()) || isNaN(to.getTime())) {\n return null;\n }\n\n return { from, to };\n};\n","import { useRef, useState } from 'react';\nimport type { ChangeEventHandler, ComponentProps, ComponentRef, FocusEventHandler } from 'react';\nimport type { DateRange } from 'react-day-picker';\n\nimport { DatePicker } from '../../components/DatePicker';\nimport { InputGroup } from '../../components/InputGroup';\nimport { useControllableState } from '../../hooks/useControllableState';\nimport { Calendar as CalendarIcon, X } from '../../icons';\nimport { createChangeInputEvent, mergeRefs } from '../../utils';\n\nimport { formatDateRange, parseDateRange } from './helpers';\n\ntype InputGroupProps = Pick<ComponentProps<typeof InputGroup>, 'focusVariant' | 'state'>;\n\ntype InputGroupInputProps = Omit<\n ComponentProps<typeof InputGroup.Input>,\n 'value' | 'defaultValue' | 'type'\n>;\n\ntype Props = InputGroupProps &\n InputGroupInputProps & {\n value?: DateRange | null;\n defaultValue?: DateRange | null;\n onValueChange?: (value: DateRange | null) => void;\n onValueBlur?: (value: DateRange | null) => void;\n allowClear?: boolean;\n startMonth?: Date;\n endMonth?: Date;\n };\n\nexport const DateRangeInput = ({\n ref,\n\n // group props\n state,\n focusVariant,\n className,\n\n // own props\n value: valueProp,\n defaultValue,\n onValueChange,\n onValueBlur,\n onChange,\n onBlur,\n onFocus,\n allowClear = false,\n startMonth,\n endMonth,\n\n // input props\n disabled,\n readOnly,\n placeholder = 'Select a date range',\n ...restInputProps\n}: Props) => {\n const inputRef = useRef<ComponentRef<'input'>>(null);\n\n const [inputValue, setInputValue] = useState('');\n const [hasFocus, setHasFocus] = useState(false);\n const [isOpen, setIsOpen] = useState(false);\n const [month, setMonth] = useState<Date>(new Date());\n\n // `onValueChange` is fired explicitly per-path below (not through the hook), because commits\n // happen on blur / picker-select rather than on every keystroke.\n const [currentValue, setCurrentValue] = useControllableState<DateRange | null>({\n prop: valueProp,\n defaultProp: defaultValue ?? null,\n });\n\n const canClear = allowClear && !!currentValue && !disabled && !readOnly;\n const showPicker = !disabled && !readOnly;\n\n const handleChange: ChangeEventHandler<HTMLInputElement> = (event) => {\n const newValue = event.target.value;\n setInputValue(newValue);\n onChange?.(event);\n\n const parsedRange = parseDateRange(newValue);\n if (parsedRange !== null || !newValue.trim()) {\n onValueChange?.(parsedRange);\n }\n };\n\n const handleFocus: FocusEventHandler<HTMLInputElement> = (event) => {\n setInputValue(formatDateRange(currentValue, ''));\n setHasFocus(true);\n onFocus?.(event);\n };\n\n const handleBlur: FocusEventHandler<HTMLInputElement> = (event) => {\n setHasFocus(false);\n onBlur?.(event);\n\n // If the field still shows the formatted current value (focused and blurred\n // without editing), keep it as-is. `formatDateRange` uses `toLocaleDateString`,\n // whose output is not reliably parseable by `new Date(...)` in every locale, so\n // round-tripping an untouched value through `parseDateRange` could wrongly null it.\n const text = event.target.value;\n const parsedRange =\n text === formatDateRange(currentValue, '') ? currentValue : parseDateRange(text);\n onValueBlur?.(parsedRange);\n\n setCurrentValue(parsedRange);\n };\n\n const handleDatePickerChange = (newValue: DateRange | undefined) => {\n const rangeValue = newValue ?? null;\n\n setCurrentValue(rangeValue);\n onValueChange?.(rangeValue);\n\n setHasFocus(false);\n };\n\n const handleClear = () => {\n if (!inputRef.current) return;\n inputRef.current.value = '';\n setInputValue('');\n setCurrentValue(null);\n onValueChange?.(null);\n onChange?.(createChangeInputEvent(inputRef.current));\n };\n\n const handleOpenChange = (open: boolean) => {\n if (open) {\n setMonth(currentValue?.from ?? new Date());\n }\n setIsOpen(open);\n };\n\n const displayValue = hasFocus ? inputValue : formatDateRange(currentValue, '');\n\n return (\n <InputGroup state={state} focusVariant={focusVariant} className={className}>\n <InputGroup.Input\n {...restInputProps}\n ref={mergeRefs(ref ?? null, inputRef)}\n type=\"text\"\n value={displayValue}\n placeholder={placeholder}\n onChange={handleChange}\n onFocus={handleFocus}\n onBlur={handleBlur}\n disabled={disabled}\n readOnly={readOnly}\n />\n\n {(canClear || showPicker) && (\n <InputGroup.Addon align=\"inline-end\">\n {canClear && (\n <InputGroup.Button\n aria-label=\"Clear date range\"\n onMouseDown={(event) => event.preventDefault()}\n onClick={handleClear}\n >\n <X className=\"tw:size-4\" />\n </InputGroup.Button>\n )}\n {showPicker && (\n <DatePicker\n endMonth={endMonth}\n mode=\"range\"\n month={month}\n onMonthChange={setMonth}\n onOpenChange={handleOpenChange}\n onSelect={handleDatePickerChange}\n open={isOpen}\n startMonth={startMonth}\n selected={currentValue ?? undefined}\n >\n <InputGroup.Button aria-label=\"Select date range\">\n <CalendarIcon className=\"tw:size-4\" />\n </InputGroup.Button>\n </DatePicker>\n )}\n </InputGroup.Addon>\n )}\n </InputGroup>\n );\n};\n"],"mappings":"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"}
@@ -1,10 +1,10 @@
1
1
  import { cn } from "./classNames-DcGnTh2N.js";
2
2
  import { ChevronDown } from "./icons-ZIeZXXS7.js";
3
3
  import { Button } from "./Button-BNkyYU8u.js";
4
- import { Popover } from "./Popover-DtUDwUVO.js";
4
+ import { Popover } from "./Popover-DnBw5Uay.js";
5
5
  import { Calendar } from "./Calendar-BnKi1kPu.js";
6
6
  import { overlayTriggerVariants } from "./styles-T8xwr0sR.js";
7
- import { TimePicker, formatTime, pad, parseTime } from "./TimePicker-CoRpiEM3.js";
7
+ import { TimePicker, formatTime, pad, parseTime } from "./TimePicker-lk3NGqeK.js";
8
8
  import { useState } from "react";
9
9
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
10
10
  //#region src/components/DateRangePicker/DateRangePicker.tsx
@@ -147,4 +147,4 @@ DateRangePicker.displayName = "DateRangePicker";
147
147
  //#endregion
148
148
  export { DateRangePicker };
149
149
 
150
- //# sourceMappingURL=DateRangePicker-C4-DoWac.js.map
150
+ //# sourceMappingURL=DateRangePicker-m47cSV1r.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DateRangePicker-C4-DoWac.js","names":[],"sources":["../src/components/DateRangePicker/DateRangePicker.tsx"],"sourcesContent":["import { useState } from 'react';\nimport type { ReactNode } from 'react';\nimport type { DateRange as DayPickerDateRange, Matcher } from 'react-day-picker';\nimport type { PopoverContentProps, PopoverProps } from '@radix-ui/react-popover';\n\nimport { ChevronDown } from '../../icons';\nimport { cn } from '../../utils';\nimport { Button } from '../Button';\nimport { Calendar } from '../Calendar';\nimport { overlayTriggerVariants } from '../OverlayTrigger/styles';\nimport { Popover } from '../Popover';\nimport { TimePicker } from '../TimePicker';\nimport { formatTime, pad, parseTime } from '../TimePicker/utils';\n\nexport type DateRange = {\n from: Date;\n to?: Date;\n};\n\nexport type DateRangePreset = {\n label: string;\n /** Omit for a `value` preset, or for a clear preset (\"All time\") that calls `onChange(undefined)`. */\n range?: DateRange;\n /** Echoed through `onPresetSelect` instead of `range` — e.g. a server-resolved token like `-7 days`. */\n value?: string;\n};\n\ntype DateRangePickerProps = {\n value: DateRange | undefined;\n onChange: (range: DateRange | undefined) => void;\n /** Replaces the trigger's whole range text, e.g. the active preset name; to restyle dates use `formatDate`. */\n label?: ReactNode;\n /** Formats each end of the range on the trigger in place of ISO; the from → to join stays. */\n formatDate?: (date: Date) => string;\n placeholder?: string;\n presets?: readonly DateRangePreset[];\n /** Called instead of `onChange` when a preset is picked, with the preset itself. */\n onPresetSelect?: (preset: DateRangePreset) => void;\n /** Adds a start/end time-of-day row; the emitted `from` / `to` then carry hours and minutes. */\n withTime?: boolean;\n /** Hold edits in a draft and emit only on Apply, so one range costs one `onChange`. */\n requireApply?: boolean;\n /** Days that cannot be picked, as a react-day-picker matcher — e.g. `{ after: new Date() }`. */\n disabledDays?: Matcher | Matcher[];\n disabled?: boolean;\n className?: string;\n} & Pick<PopoverProps, 'open' | 'onOpenChange' | 'defaultOpen'> &\n Pick<PopoverContentProps, 'align' | 'alignOffset' | 'sideOffset'>;\n\nconst timeOf = (date: Date) => formatTime(date.getHours(), date.getMinutes());\n\nconst isoDate = (date: Date) =>\n `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;\n\nconst formatRange = (\n range: DateRange | undefined,\n format: (date: Date) => string,\n): string | null => {\n if (!range?.from) return null;\n return range.to ? `${format(range.from)} → ${format(range.to)}` : format(range.from);\n};\n\nconst withHoursMinutes = (target: Date, hour: number, minute: number) => {\n const next = new Date(target);\n next.setHours(hour, minute, 0, 0);\n return next;\n};\n\nconst withTimeOf = (target: Date, source: Date) =>\n withHoursMinutes(target, source.getHours(), source.getMinutes());\n\n/** Returns `target` at `time` (\"HH:mm\"); unparseable input leaves it alone. */\nconst atTime = (target: Date, time: string) => {\n const { hour, minute } = parseTime(time);\n return hour === null || minute === null ? target : withHoursMinutes(target, hour, minute);\n};\n\ntype TimeFieldProps = {\n label: string;\n date: Date | undefined;\n onChange: (time: string) => void;\n};\n\n/** Time-of-day for one end of the range, on the same `TimePicker` the rest of the app uses. */\nconst TimeField = ({ label, date, onChange }: TimeFieldProps) => (\n <div className=\"tw:flex tw:items-center tw:gap-2 tw:text-sm\">\n <span className=\"tw:text-muted-foreground\">{label}</span>\n <TimePicker selected={date ? timeOf(date) : null} onSelect={onChange}>\n <Button variant=\"outline\" size=\"small\" disabled={!date} aria-label={`${label} time`}>\n {date ? timeOf(date) : '--:--'}\n </Button>\n </TimePicker>\n </div>\n);\n\n/** Picks a `{ from, to }` range, with optional presets, time row and Apply step; single date: `DatePicker`. */\nexport const DateRangePicker = ({\n align = 'start',\n alignOffset,\n className,\n defaultOpen,\n disabled = false,\n disabledDays,\n formatDate,\n label,\n onChange,\n onOpenChange,\n onPresetSelect,\n open,\n placeholder = 'Pick a date range',\n presets,\n requireApply = false,\n sideOffset,\n value,\n withTime = false,\n}: DateRangePickerProps) => {\n const [draft, setDraft] = useState<DateRange | undefined>(value);\n\n const handleOpenChange = (nextOpen: boolean) => {\n // Reopening discards a cancelled draft.\n if (nextOpen) setDraft(value);\n onOpenChange?.(nextOpen);\n };\n\n const current = requireApply ? draft : value;\n\n const edit = (range: DateRange | undefined) => {\n if (requireApply) setDraft(range);\n else onChange(range);\n };\n\n const handleSelect = (range: DayPickerDateRange | undefined) => {\n if (!range?.from) {\n edit(undefined);\n return;\n }\n\n // Keeps the set time-of-day; otherwise a day click resets it to midnight.\n edit({\n from: current?.from ? withTimeOf(range.from, current.from) : range.from,\n to: range.to && current?.to ? withTimeOf(range.to, current.to) : range.to,\n });\n };\n\n const format =\n formatDate ?? ((date: Date) => (withTime ? `${isoDate(date)} ${timeOf(date)}` : isoDate(date)));\n const triggerLabel = label ?? formatRange(value, format);\n\n return (\n <Popover open={open} defaultOpen={defaultOpen} onOpenChange={handleOpenChange}>\n <Popover.Trigger disabled={disabled} className={cn(overlayTriggerVariants(), className)}>\n <span className={cn('tw:truncate', !triggerLabel && 'tw:text-muted-foreground')}>\n {triggerLabel ?? placeholder}\n </span>\n <ChevronDown className=\"tw:size-4 tw:text-muted-foreground\" />\n </Popover.Trigger>\n <Popover.Content\n align={align}\n alignOffset={alignOffset}\n sideOffset={sideOffset}\n className=\"tw:w-auto tw:p-0\"\n >\n <div className=\"tw:flex\">\n {presets && presets.length > 0 ? (\n <div className=\"tw:flex tw:flex-col tw:gap-1 tw:border-r tw:border-solid tw:border-border tw:p-2\">\n {presets.map((preset) => (\n <Popover.Close asChild key={preset.label}>\n <Button\n variant=\"invisible\"\n size=\"small\"\n className=\"tw:justify-start\"\n onClick={() =>\n onPresetSelect ? onPresetSelect(preset) : onChange(preset.range)\n }\n >\n {preset.label}\n </Button>\n </Popover.Close>\n ))}\n </div>\n ) : null}\n <Calendar\n mode=\"range\"\n selected={current}\n onSelect={handleSelect}\n numberOfMonths={2}\n defaultMonth={current?.from}\n disabled={disabledDays}\n />\n </div>\n {(withTime || requireApply) && (\n <div className=\"tw:flex tw:items-center tw:gap-3 tw:border-t tw:border-solid tw:border-border tw:p-3\">\n {withTime && (\n <>\n <TimeField\n label=\"From\"\n date={current?.from}\n onChange={(time) =>\n current?.from && edit({ ...current, from: atTime(current.from, time) })\n }\n />\n <TimeField\n label=\"To\"\n date={current?.to}\n onChange={(time) =>\n current?.to && edit({ ...current, to: atTime(current.to, time) })\n }\n />\n </>\n )}\n {requireApply && (\n <div className=\"tw:ml-auto tw:flex tw:gap-2\">\n <Popover.Close asChild>\n <Button variant=\"outline\" size=\"small\">\n Cancel\n </Button>\n </Popover.Close>\n <Popover.Close asChild>\n <Button size=\"small\" disabled={!draft?.from} onClick={() => onChange(draft)}>\n Apply\n </Button>\n </Popover.Close>\n </div>\n )}\n </div>\n )}\n </Popover.Content>\n </Popover>\n );\n};\n\nDateRangePicker.displayName = 'DateRangePicker';\n"],"mappings":"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"}
1
+ {"version":3,"file":"DateRangePicker-m47cSV1r.js","names":[],"sources":["../src/components/DateRangePicker/DateRangePicker.tsx"],"sourcesContent":["import { useState } from 'react';\nimport type { ReactNode } from 'react';\nimport type { DateRange as DayPickerDateRange, Matcher } from 'react-day-picker';\nimport type { PopoverContentProps, PopoverProps } from '@radix-ui/react-popover';\n\nimport { ChevronDown } from '../../icons';\nimport { cn } from '../../utils';\nimport { Button } from '../Button';\nimport { Calendar } from '../Calendar';\nimport { overlayTriggerVariants } from '../OverlayTrigger/styles';\nimport { Popover } from '../Popover';\nimport { TimePicker } from '../TimePicker';\nimport { formatTime, pad, parseTime } from '../TimePicker/utils';\n\nexport type DateRange = {\n from: Date;\n to?: Date;\n};\n\nexport type DateRangePreset = {\n label: string;\n /** Omit for a `value` preset, or for a clear preset (\"All time\") that calls `onChange(undefined)`. */\n range?: DateRange;\n /** Echoed through `onPresetSelect` instead of `range` — e.g. a server-resolved token like `-7 days`. */\n value?: string;\n};\n\ntype DateRangePickerProps = {\n value: DateRange | undefined;\n onChange: (range: DateRange | undefined) => void;\n /** Replaces the trigger's whole range text, e.g. the active preset name; to restyle dates use `formatDate`. */\n label?: ReactNode;\n /** Formats each end of the range on the trigger in place of ISO; the from → to join stays. */\n formatDate?: (date: Date) => string;\n placeholder?: string;\n presets?: readonly DateRangePreset[];\n /** Called instead of `onChange` when a preset is picked, with the preset itself. */\n onPresetSelect?: (preset: DateRangePreset) => void;\n /** Adds a start/end time-of-day row; the emitted `from` / `to` then carry hours and minutes. */\n withTime?: boolean;\n /** Hold edits in a draft and emit only on Apply, so one range costs one `onChange`. */\n requireApply?: boolean;\n /** Days that cannot be picked, as a react-day-picker matcher — e.g. `{ after: new Date() }`. */\n disabledDays?: Matcher | Matcher[];\n disabled?: boolean;\n className?: string;\n} & Pick<PopoverProps, 'open' | 'onOpenChange' | 'defaultOpen'> &\n Pick<PopoverContentProps, 'align' | 'alignOffset' | 'sideOffset'>;\n\nconst timeOf = (date: Date) => formatTime(date.getHours(), date.getMinutes());\n\nconst isoDate = (date: Date) =>\n `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;\n\nconst formatRange = (\n range: DateRange | undefined,\n format: (date: Date) => string,\n): string | null => {\n if (!range?.from) return null;\n return range.to ? `${format(range.from)} → ${format(range.to)}` : format(range.from);\n};\n\nconst withHoursMinutes = (target: Date, hour: number, minute: number) => {\n const next = new Date(target);\n next.setHours(hour, minute, 0, 0);\n return next;\n};\n\nconst withTimeOf = (target: Date, source: Date) =>\n withHoursMinutes(target, source.getHours(), source.getMinutes());\n\n/** Returns `target` at `time` (\"HH:mm\"); unparseable input leaves it alone. */\nconst atTime = (target: Date, time: string) => {\n const { hour, minute } = parseTime(time);\n return hour === null || minute === null ? target : withHoursMinutes(target, hour, minute);\n};\n\ntype TimeFieldProps = {\n label: string;\n date: Date | undefined;\n onChange: (time: string) => void;\n};\n\n/** Time-of-day for one end of the range, on the same `TimePicker` the rest of the app uses. */\nconst TimeField = ({ label, date, onChange }: TimeFieldProps) => (\n <div className=\"tw:flex tw:items-center tw:gap-2 tw:text-sm\">\n <span className=\"tw:text-muted-foreground\">{label}</span>\n <TimePicker selected={date ? timeOf(date) : null} onSelect={onChange}>\n <Button variant=\"outline\" size=\"small\" disabled={!date} aria-label={`${label} time`}>\n {date ? timeOf(date) : '--:--'}\n </Button>\n </TimePicker>\n </div>\n);\n\n/** Picks a `{ from, to }` range, with optional presets, time row and Apply step; single date: `DatePicker`. */\nexport const DateRangePicker = ({\n align = 'start',\n alignOffset,\n className,\n defaultOpen,\n disabled = false,\n disabledDays,\n formatDate,\n label,\n onChange,\n onOpenChange,\n onPresetSelect,\n open,\n placeholder = 'Pick a date range',\n presets,\n requireApply = false,\n sideOffset,\n value,\n withTime = false,\n}: DateRangePickerProps) => {\n const [draft, setDraft] = useState<DateRange | undefined>(value);\n\n const handleOpenChange = (nextOpen: boolean) => {\n // Reopening discards a cancelled draft.\n if (nextOpen) setDraft(value);\n onOpenChange?.(nextOpen);\n };\n\n const current = requireApply ? draft : value;\n\n const edit = (range: DateRange | undefined) => {\n if (requireApply) setDraft(range);\n else onChange(range);\n };\n\n const handleSelect = (range: DayPickerDateRange | undefined) => {\n if (!range?.from) {\n edit(undefined);\n return;\n }\n\n // Keeps the set time-of-day; otherwise a day click resets it to midnight.\n edit({\n from: current?.from ? withTimeOf(range.from, current.from) : range.from,\n to: range.to && current?.to ? withTimeOf(range.to, current.to) : range.to,\n });\n };\n\n const format =\n formatDate ?? ((date: Date) => (withTime ? `${isoDate(date)} ${timeOf(date)}` : isoDate(date)));\n const triggerLabel = label ?? formatRange(value, format);\n\n return (\n <Popover open={open} defaultOpen={defaultOpen} onOpenChange={handleOpenChange}>\n <Popover.Trigger disabled={disabled} className={cn(overlayTriggerVariants(), className)}>\n <span className={cn('tw:truncate', !triggerLabel && 'tw:text-muted-foreground')}>\n {triggerLabel ?? placeholder}\n </span>\n <ChevronDown className=\"tw:size-4 tw:text-muted-foreground\" />\n </Popover.Trigger>\n <Popover.Content\n align={align}\n alignOffset={alignOffset}\n sideOffset={sideOffset}\n className=\"tw:w-auto tw:p-0\"\n >\n <div className=\"tw:flex\">\n {presets && presets.length > 0 ? (\n <div className=\"tw:flex tw:flex-col tw:gap-1 tw:border-r tw:border-solid tw:border-border tw:p-2\">\n {presets.map((preset) => (\n <Popover.Close asChild key={preset.label}>\n <Button\n variant=\"invisible\"\n size=\"small\"\n className=\"tw:justify-start\"\n onClick={() =>\n onPresetSelect ? onPresetSelect(preset) : onChange(preset.range)\n }\n >\n {preset.label}\n </Button>\n </Popover.Close>\n ))}\n </div>\n ) : null}\n <Calendar\n mode=\"range\"\n selected={current}\n onSelect={handleSelect}\n numberOfMonths={2}\n defaultMonth={current?.from}\n disabled={disabledDays}\n />\n </div>\n {(withTime || requireApply) && (\n <div className=\"tw:flex tw:items-center tw:gap-3 tw:border-t tw:border-solid tw:border-border tw:p-3\">\n {withTime && (\n <>\n <TimeField\n label=\"From\"\n date={current?.from}\n onChange={(time) =>\n current?.from && edit({ ...current, from: atTime(current.from, time) })\n }\n />\n <TimeField\n label=\"To\"\n date={current?.to}\n onChange={(time) =>\n current?.to && edit({ ...current, to: atTime(current.to, time) })\n }\n />\n </>\n )}\n {requireApply && (\n <div className=\"tw:ml-auto tw:flex tw:gap-2\">\n <Popover.Close asChild>\n <Button variant=\"outline\" size=\"small\">\n Cancel\n </Button>\n </Popover.Close>\n <Popover.Close asChild>\n <Button size=\"small\" disabled={!draft?.from} onClick={() => onChange(draft)}>\n Apply\n </Button>\n </Popover.Close>\n </div>\n )}\n </div>\n )}\n </Popover.Content>\n </Popover>\n );\n};\n\nDateRangePicker.displayName = 'DateRangePicker';\n"],"mappings":"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"}
@@ -69,7 +69,7 @@ const ItemIcon = ({ className, children, ...props }) => /* @__PURE__ */ jsx("spa
69
69
  //#endregion
70
70
  //#region src/components/DropdownMenu/styles.ts
71
71
  const itemVariants = cn("tailwindcss-preflight", "tw:outline-hidden", "tw:group", "tw:peer", "tw:relative", "tw:flex", "tw:flex-1", "tw:items-center", "tw:gap-2", "tw:[&_svg:not([class*=\"tw:size-\"])]:size-4", "tw:cursor-pointer", "tw:select-none", "tw:transition-colors", "tw:p-2", "tw:font-sans", "tw:text-sm", "tw:aria-disabled:pointer-events-none", "tw:aria-disabled:opacity-disabled", "tw:focus-visible:outline-hidden", "tw:rounded-md", "tw:text-popover-foreground", "tw:focus:text-[var(--hover-foreground,rgb(var(--primary)))]", "tw:focus:bg-[var(--hover,color-mix(in_oklab,rgb(var(--primary))_10%,transparent))]", "tw:hover:text-[var(--hover-foreground,rgb(var(--primary)))]", "tw:hover:bg-[var(--hover,color-mix(in_oklab,rgb(var(--primary))_10%,transparent))]");
72
- const contentVariants = cn("tailwindcss-preflight", "tw:z-[1055]", "tw:flex", "tw:flex-col", "tw:origin-(--radix-dropdown-menu-content-transform-origin)", "tw:max-h-[var(--radix-dropdown-menu-content-available-height)]", "tw:min-w-32", "tw:border", "tw:border-border", "tw:rounded-popover", "tw:shadow-md", "tw:bg-popover", "tw:text-popover-foreground", "tw:data-[state=open]:animate-in", "tw:data-[state=open]:fade-in-0", "tw:data-[state=open]:zoom-in-95", "tw:data-[state=closed]:animate-out", "tw:data-[state=closed]:fade-out-0", "tw:data-[state=closed]:zoom-out-95", "tw:data-[side=bottom]:slide-in-from-top-2", "tw:data-[side=left]:slide-in-from-right-2", "tw:data-[side=right]:slide-in-from-left-2", "tw:data-[side=top]:slide-in-from-bottom-2");
72
+ const contentVariants = cn("tailwindcss-preflight", "tw:z-overlay", "tw:flex", "tw:flex-col", "tw:origin-(--radix-dropdown-menu-content-transform-origin)", "tw:max-h-[var(--radix-dropdown-menu-content-available-height)]", "tw:min-w-32", "tw:border", "tw:border-border", "tw:rounded-popover", "tw:shadow-md", "tw:bg-popover", "tw:text-popover-foreground", "tw:data-[state=open]:animate-in", "tw:data-[state=open]:fade-in-0", "tw:data-[state=open]:zoom-in-95", "tw:data-[state=closed]:animate-out", "tw:data-[state=closed]:fade-out-0", "tw:data-[state=closed]:zoom-out-95", "tw:data-[side=bottom]:slide-in-from-top-2", "tw:data-[side=left]:slide-in-from-right-2", "tw:data-[side=right]:slide-in-from-left-2", "tw:data-[side=top]:slide-in-from-bottom-2");
73
73
  //#endregion
74
74
  //#region src/components/DropdownMenu/DropdownMenuCheckboxItem.tsx
75
75
  const DropdownMenuCheckboxItem = ({ className, children, checked, closeOnSelect = false, onSelect, indicatorAlign = "start", indicator = "checkbox", isLoading = false, icon, ...props }) => {
@@ -288,4 +288,4 @@ DropdownMenu.ItemDescription = DropdownMenuItemDescription;
288
288
  //#endregion
289
289
  export { DropdownMenu };
290
290
 
291
- //# sourceMappingURL=DropdownMenu-CcVbZ_5u.js.map
291
+ //# sourceMappingURL=DropdownMenu-Bum99mVf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DropdownMenu-Bum99mVf.js","names":["Root"],"sources":["../src/components/DropdownMenu/DropdownMenuItemIndicator.tsx","../src/components/DropdownMenu/ItemIcon.tsx","../src/components/DropdownMenu/styles.ts","../src/components/DropdownMenu/DropdownMenuCheckboxItem.tsx","../src/components/DropdownMenu/DropdownMenuContent.tsx","../src/components/DropdownMenu/DropdownMenuItem.tsx","../src/components/DropdownMenu/DropdownMenuItemDescription.tsx","../src/components/DropdownMenu/DropdownMenuLabel.tsx","../src/components/DropdownMenu/DropdownMenuRadioGroup/DropdownMenuRadioGroup.tsx","../src/components/DropdownMenu/DropdownMenuRadioGroup/DropdownMenuRadioItem.tsx","../src/components/DropdownMenu/DropdownMenuSeparator.tsx","../src/components/DropdownMenu/DropdownMenuSub/DropdownMenuSub.tsx","../src/components/DropdownMenu/DropdownMenuSub/DropdownMenuSubContent.tsx","../src/components/DropdownMenu/DropdownMenuSub/DropdownMenuSubTrigger.tsx","../src/components/DropdownMenu/DropdownMenuTrigger.tsx","../src/components/DropdownMenu/DropdownMenu.tsx"],"sourcesContent":["import type { ComponentProps } from 'react';\nimport * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';\nimport type { VariantProps } from 'class-variance-authority';\nimport { cva } from 'class-variance-authority';\n\nimport { Check, Circle, ToggleRight } from '../../icons';\nimport { cn } from '../../utils';\nimport { radioCircleVariants, radioIndicatorVariants } from '../RadioGroup/styles';\n\nconst variants = cva(\n [\n 'tailwindcss-preflight',\n 'tw:pointer-events-none',\n\n // sizing\n 'tw:size-4',\n 'tw:aspect-square',\n 'tw:shrink-0',\n\n // layout\n 'tw:flex',\n 'tw:items-center',\n 'tw:justify-center',\n ],\n {\n variants: {\n variant: {\n none: [],\n radio: ['tw:data-[state=unchecked]:[&_svg]:hidden'],\n check: ['tw:[&_svg:not([class*=\"tw:size-\"])]:size-3.5', 'tw:[&_svg]:text-primary'],\n checkbox: [\n 'tw:[&_svg]:text-primary-foreground',\n 'tw:border',\n 'tw:border-solid',\n 'tw:rounded',\n 'tw:border-input',\n\n 'tw:[&_svg:not([class*=\"tw:size-\"])]:size-3',\n 'tw:data-[state=unchecked]:[&_svg]:hidden',\n 'tw:data-[state=checked]:border-primary',\n 'tw:data-[state=checked]:bg-primary',\n ],\n switch: [\n 'tw:size-5',\n // Lucide SVGs default to 24×24 — constrain the rendered ToggleRight\n // to the indicator slot so it doesn't overflow.\n 'tw:[&_svg:not([class*=\"tw:size-\"])]:size-5',\n 'tw:text-muted-foreground',\n 'tw:data-[state=unchecked]:rotate-180',\n 'tw:data-[state=checked]:text-primary',\n ],\n },\n },\n },\n);\n\ntype Props = ComponentProps<typeof DropdownMenuPrimitive.ItemIndicator> &\n VariantProps<typeof variants>;\n\nexport const DropdownMenuItemIndicator = ({\n variant,\n className,\n forceMount: forceMountProp,\n ...rest\n}: Props) => {\n const isRadio = variant === 'radio';\n const IconComp = (() => {\n if (variant === 'switch') return ToggleRight;\n if (isRadio) return Circle;\n return Check;\n })();\n\n const forceMount = (() => {\n if (forceMountProp) return true;\n // All variants, except for check, require rendering at all times.\n return variant === 'check' ? undefined : true;\n })();\n\n if (variant === 'none') return null;\n\n return (\n <DropdownMenuPrimitive.ItemIndicator\n {...rest}\n forceMount={forceMount}\n className={cn(variants({ variant }), isRadio && radioCircleVariants(), className)}\n >\n <IconComp className={isRadio ? radioIndicatorVariants() : undefined} />\n </DropdownMenuPrimitive.ItemIndicator>\n );\n};\n","import type { ComponentProps, ReactNode } from 'react';\n\nimport { cn } from '../../utils';\n\ntype Props = ComponentProps<'span'> & {\n children: ReactNode;\n};\n\nexport const ItemIcon = ({ className, children, ...props }: Props) => (\n <span\n {...props}\n className={cn(\n 'tw:inline-flex',\n 'tw:items-center',\n 'tw:justify-center',\n 'tw:aspect-square',\n // 20px container fits the 16px Lucide glyph plus 2px breathing room\n // each side — the previous tw:size-4 + tw:p-0.5 clipped the 16px child.\n 'tw:size-5',\n 'tw:[&_svg:not([class*=\"tw:size-\"])]:size-4',\n 'tw:text-primary',\n 'tw:group-aria-disabled:text-muted-foreground',\n className,\n )}\n >\n {children}\n </span>\n);\n","import { cn } from '../../utils';\n\nexport const itemVariants = cn(\n // reset\n 'tailwindcss-preflight',\n 'tw:outline-hidden',\n 'tw:group',\n 'tw:peer',\n 'tw:relative',\n\n // positioning\n 'tw:flex',\n 'tw:flex-1',\n 'tw:items-center',\n 'tw:gap-2',\n\n // An icon passed as `children` rather than via the `icon` prop misses `ItemIcon`,\n // so without this it falls back to Lucide's 24px default and towers over the\n // siblings this row is laid out for. The `:not()` keeps a call-site size winning.\n 'tw:[&_svg:not([class*=\"tw:size-\"])]:size-4',\n\n 'tw:cursor-pointer',\n 'tw:select-none',\n 'tw:transition-colors',\n\n // spacing\n 'tw:p-2',\n\n // typography\n 'tw:font-sans',\n 'tw:text-sm',\n\n 'tw:aria-disabled:pointer-events-none',\n 'tw:aria-disabled:opacity-disabled',\n\n 'tw:focus-visible:outline-hidden',\n\n 'tw:rounded-md',\n 'tw:text-popover-foreground',\n // Hover and keyboard focus: the theme's `--hover` pair when set; unset, a `primary` tint.\n 'tw:focus:text-[var(--hover-foreground,rgb(var(--primary)))]',\n 'tw:focus:bg-[var(--hover,color-mix(in_oklab,rgb(var(--primary))_10%,transparent))]',\n 'tw:hover:text-[var(--hover-foreground,rgb(var(--primary)))]',\n 'tw:hover:bg-[var(--hover,color-mix(in_oklab,rgb(var(--primary))_10%,transparent))]',\n);\n\nexport const contentVariants = cn(\n 'tailwindcss-preflight',\n 'tw:z-overlay',\n\n // positioning\n 'tw:flex',\n 'tw:flex-col',\n 'tw:origin-(--radix-dropdown-menu-content-transform-origin)',\n\n // sizing\n 'tw:max-h-[var(--radix-dropdown-menu-content-available-height)]',\n 'tw:min-w-32',\n\n // border\n 'tw:border',\n 'tw:border-border',\n 'tw:rounded-popover',\n 'tw:shadow-md',\n\n // surface — semantic tokens, so a portalled menu follows the brand and the scheme\n 'tw:bg-popover',\n 'tw:text-popover-foreground',\n\n // animations\n 'tw:data-[state=open]:animate-in',\n 'tw:data-[state=open]:fade-in-0',\n 'tw:data-[state=open]:zoom-in-95',\n\n 'tw:data-[state=closed]:animate-out',\n 'tw:data-[state=closed]:fade-out-0',\n 'tw:data-[state=closed]:zoom-out-95',\n\n 'tw:data-[side=bottom]:slide-in-from-top-2',\n 'tw:data-[side=left]:slide-in-from-right-2',\n 'tw:data-[side=right]:slide-in-from-left-2',\n 'tw:data-[side=top]:slide-in-from-bottom-2',\n);\n","import type { ComponentProps, ReactNode } from 'react';\nimport * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';\n\nimport { Loader2 } from '../../icons';\nimport { cn } from '../../utils';\n\nimport { DropdownMenuItemIndicator } from './DropdownMenuItemIndicator';\nimport { ItemIcon } from './ItemIcon';\nimport { itemVariants } from './styles';\n\ntype Props = ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem> & {\n closeOnSelect?: boolean;\n indicator?: 'switch' | 'checkbox' | 'check';\n indicatorAlign?: 'start' | 'end';\n isLoading?: boolean;\n /** Leading Lucide icon, drawn like `DropdownMenu.Item`'s so mixed menus line up. */\n icon?: ReactNode;\n};\n\nexport const DropdownMenuCheckboxItem = ({\n className,\n children,\n checked,\n closeOnSelect = false,\n onSelect,\n indicatorAlign = 'start',\n indicator = 'checkbox',\n isLoading = false,\n icon,\n ...props\n}: Props) => {\n const isAtStart = indicatorAlign === 'start';\n const indicatorEle = isLoading ? (\n <ItemIcon className={isAtStart ? '' : 'tw:ml-auto'}>\n <Loader2 className=\"tw:animate-spin\" />\n </ItemIcon>\n ) : (\n <DropdownMenuItemIndicator variant={indicator} className={isAtStart ? '' : 'tw:ml-auto'} />\n );\n\n const handleSelect = (event: Event) => {\n if (!closeOnSelect) event.preventDefault();\n onSelect?.(event);\n };\n\n return (\n <DropdownMenuPrimitive.CheckboxItem\n className={cn(itemVariants, className)}\n checked={checked}\n onSelect={handleSelect}\n {...props}\n >\n {isAtStart && indicatorEle}\n {icon && <ItemIcon>{icon}</ItemIcon>}\n {children}\n {!isAtStart && indicatorEle}\n </DropdownMenuPrimitive.CheckboxItem>\n );\n};\n","import type { ComponentProps } from 'react';\nimport * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';\n\nimport { cn } from '../../utils';\nimport { ScrollArea } from '../ScrollArea';\n\nimport { contentVariants } from './styles';\n\ntype Props = Omit<\n ComponentProps<typeof DropdownMenuPrimitive.Content>,\n 'forceMount' | 'asChild'\n> & {\n forceMount?: boolean;\n /** Classes for the inner scroll area, not the popup. Set a width, not a `max-width` (clips rows). */\n className?: string;\n viewPortClassName?: string;\n container?: HTMLElement | null;\n};\n\nexport const DropdownMenuContent = ({\n className,\n sideOffset = 4,\n forceMount,\n children,\n viewPortClassName,\n container,\n ...props\n}: Props) => (\n <DropdownMenuPrimitive.Portal forceMount={forceMount || undefined} container={container}>\n <DropdownMenuPrimitive.Content {...props} sideOffset={sideOffset} className={contentVariants}>\n <ScrollArea\n className={className}\n viewPortClassName={cn(\n 'tw:p-2',\n 'tw:max-h-[var(--radix-dropdown-menu-content-available-height)]',\n viewPortClassName,\n )}\n scrollBarClassName=\"tw:w-1.5\"\n >\n {children}\n </ScrollArea>\n </DropdownMenuPrimitive.Content>\n </DropdownMenuPrimitive.Portal>\n);\n","import type { ComponentProps, PointerEventHandler, ReactNode } from 'react';\nimport * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';\nimport { Root, Slottable } from '@radix-ui/react-slot';\n\nimport { Loader2 } from '../../icons';\nimport { cn } from '../../utils';\n\nimport { ItemIcon } from './ItemIcon';\nimport { itemVariants } from './styles';\n\ntype Props = ComponentProps<typeof DropdownMenuPrimitive.Item> & {\n /**\n * Stops the closing item stealing focus from the modal it opens (breaks `autoFocus`).\n * https://github.com/radix-ui/primitives/issues/2193#issuecomment-2758461323\n */\n asModalTrigger?: boolean;\n /** Leading Lucide icon. */\n icon?: ReactNode;\n isLoading?: boolean;\n iconClassName?: string;\n};\n\nexport const DropdownMenuItem = ({\n ref,\n className,\n asModalTrigger = false,\n onSelect,\n onPointerLeave,\n onPointerMove,\n children,\n asChild,\n icon,\n iconClassName,\n isLoading = false,\n ...props\n}: Props) => {\n const Comp = asChild ? Root : 'div';\n const adornment = isLoading ? <Loader2 className=\"tw:animate-spin\" /> : icon;\n\n const handleOnSelect = (event: Event) => {\n // keeps the menu open so the modal is not unmounted\n if (asModalTrigger) event.preventDefault();\n onSelect?.(event);\n };\n\n const handlePointerLeave: PointerEventHandler<HTMLDivElement> = (event) => {\n // prevents focus stealing from modal\n if (asModalTrigger) event.preventDefault();\n onPointerLeave?.(event);\n };\n\n const handlePointerMove: PointerEventHandler<HTMLDivElement> = (event) => {\n // prevents focus stealing from modal\n if (asModalTrigger) event.preventDefault();\n onPointerMove?.(event);\n };\n\n return (\n <DropdownMenuPrimitive.Item\n {...props}\n ref={ref}\n onSelect={handleOnSelect}\n onPointerLeave={handlePointerLeave}\n onPointerMove={handlePointerMove}\n className={cn(itemVariants, asChild && 'tw:text-inherit', className)}\n asChild\n >\n <Comp>\n {adornment && <ItemIcon className={iconClassName}>{adornment}</ItemIcon>}\n <Slottable>{children}</Slottable>\n </Comp>\n </DropdownMenuPrimitive.Item>\n );\n};\n","import type { ComponentProps } from 'react';\nimport { cva } from 'class-variance-authority';\n\nimport { cn } from '../../utils';\n\nconst descriptionVariants = cva(\n [\n 'tw:box-border',\n 'tw:ml-auto',\n 'tw:font-sans',\n 'tw:tracking-normal',\n 'tw:font-normal',\n 'tw:text-xs',\n 'tw:text-muted-foreground',\n ],\n {\n variants: {\n hideOnHover: {\n true: ['tw:group-focus-within:hidden', 'tw:group-hover:hidden'],\n false: [],\n },\n },\n defaultVariants: {},\n },\n);\n\ntype Props = ComponentProps<'span'> & {\n hideOnHover?: boolean;\n};\n\nexport const DropdownMenuItemDescription = ({\n className,\n children,\n hideOnHover = false,\n ...props\n}: Props) => {\n return (\n <span {...props} className={cn(descriptionVariants({ hideOnHover }), className)}>\n {children}\n </span>\n );\n};\n","import type { ComponentProps } from 'react';\nimport * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';\n\nimport { cn } from '../../utils';\n\ntype Props = ComponentProps<typeof DropdownMenuPrimitive.Label>;\n\nexport const DropdownMenuLabel = ({ className, ...props }: Props) => {\n return (\n <DropdownMenuPrimitive.Label\n className={cn(\n 'tw:p-2',\n 'tw:font-medium',\n 'tw:text-xs',\n 'tw:text-muted-foreground',\n className,\n )}\n {...props}\n />\n );\n};\n","import type { ComponentProps } from 'react';\nimport * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';\n\ntype Props<Value> = Omit<\n ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>,\n 'value' | 'onValueChange' | 'defaultValue'\n> & {\n value?: Value;\n defaultValue?: Value;\n onValueChange?: (value: Value) => void;\n};\n\nexport const DropdownMenuRadioGroup = <Value extends string = string>({\n value,\n defaultValue,\n onValueChange,\n ...props\n}: Props<Value>) => {\n const handleChange = (value: string) => {\n onValueChange?.(value as Value);\n };\n\n return (\n <DropdownMenuPrimitive.RadioGroup\n {...props}\n value={value}\n defaultValue={defaultValue}\n onValueChange={handleChange}\n />\n );\n};\n","import type { ComponentProps, ReactNode } from 'react';\nimport * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';\n\nimport { Loader2 } from '../../../icons';\nimport { cn } from '../../../utils';\nimport { DropdownMenuItemIndicator } from '../DropdownMenuItemIndicator';\nimport { ItemIcon } from '../ItemIcon';\nimport { itemVariants } from '../styles';\n\ntype Props = ComponentProps<typeof DropdownMenuPrimitive.RadioItem> & {\n closeOnSelect?: boolean;\n indicatorAlign?: 'start' | 'end';\n indicator?: 'radio' | 'check' | 'none';\n icon?: ReactNode;\n iconClassName?: string;\n isLoading?: boolean;\n};\n\nexport const DropdownMenuRadioItem = ({\n className,\n children,\n closeOnSelect,\n onSelect,\n indicatorAlign = 'start',\n indicator = 'radio',\n icon,\n iconClassName,\n isLoading = false,\n ...props\n}: Props) => {\n const isAtStart = indicatorAlign === 'start';\n const indicatorEle = isLoading ? (\n <ItemIcon className={iconClassName}>\n <Loader2 className=\"tw:animate-spin\" />\n </ItemIcon>\n ) : (\n <DropdownMenuItemIndicator variant={indicator} />\n );\n\n const handleSelect = (event: Event) => {\n if (!closeOnSelect) event.preventDefault();\n onSelect?.(event);\n };\n\n return (\n <DropdownMenuPrimitive.RadioItem\n className={cn(\n itemVariants,\n 'tw:data-[state=checked]:cursor-default',\n {\n // The theme's `--selected` when set; unset, a `primary` tint.\n 'tw:data-[state=checked]:bg-[var(--selected,color-mix(in_oklab,rgb(var(--primary))_10%,transparent))]':\n indicator !== 'radio',\n },\n className,\n )}\n onSelect={handleSelect}\n {...props}\n >\n {isAtStart && indicatorEle}\n {icon && <ItemIcon className={iconClassName}>{icon}</ItemIcon>}\n <span className=\"tw:flex tw:min-w-0 tw:flex-1 tw:items-center tw:gap-2\">{children}</span>\n {!isAtStart && indicatorEle}\n </DropdownMenuPrimitive.RadioItem>\n );\n};\n","import type { ComponentProps } from 'react';\nimport * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';\n\nimport { cn } from '../../utils';\n\ntype Props = ComponentProps<typeof DropdownMenuPrimitive.Separator>;\n\nexport const DropdownMenuSeparator = ({ className, ...props }: Props) => (\n <DropdownMenuPrimitive.Separator\n className={cn(\n 'tw:relative',\n 'tw:z-10',\n\n // layout\n 'tw:flex',\n 'tw:items-center',\n 'tw:justify-center',\n 'tw:w-full',\n\n // separator line\n 'tw:before:content-[\"\"]',\n 'tw:before:w-full',\n 'tw:before:h-px',\n 'tw:before:bg-border',\n 'tw:py-1',\n\n className,\n )}\n {...props}\n />\n);\n","import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';\n\nexport const DropdownMenuSub = DropdownMenuPrimitive.Sub;\n","import type { ComponentProps } from 'react';\nimport * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';\n\nimport { cn } from '../../../utils';\nimport { contentVariants } from '../styles';\n\ntype Props = ComponentProps<typeof DropdownMenuPrimitive.SubContent>;\n\nexport const DropdownMenuSubContent = ({ className, ...props }: Props) => (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.SubContent\n className={cn(contentVariants, 'tw:p-2', className)}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n);\n","import type { ComponentProps, ReactNode } from 'react';\nimport * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';\n\nimport { ChevronRight } from '../../../icons';\nimport { cn } from '../../../utils';\nimport { ItemIcon } from '../ItemIcon';\nimport { itemVariants } from '../styles';\n\ntype Props = ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {\n /** Leading Lucide icon, drawn like `DropdownMenu.Item`'s so the trigger lines up with items. */\n icon?: ReactNode;\n};\n\nexport const DropdownMenuSubTrigger = ({ className, children, icon, ...props }: Props) => {\n return (\n <DropdownMenuPrimitive.SubTrigger className={cn(itemVariants, className)} {...props}>\n {icon && <ItemIcon>{icon}</ItemIcon>}\n {children}\n <ChevronRight className=\"tw:ml-auto tw:size-5\" />\n </DropdownMenuPrimitive.SubTrigger>\n );\n};\n","import type { ComponentProps } from 'react';\nimport { Trigger } from '@radix-ui/react-dropdown-menu';\n\nimport { cn } from '../../utils';\n\ntype Props = ComponentProps<typeof Trigger>;\n\nexport const DropdownMenuTrigger = ({ ref, className, ...props }: Props) => (\n <Trigger\n {...props}\n ref={ref}\n data-slot=\"dropdown-menu-trigger\"\n className={cn('tw:group/dropdown-menu-trigger', className)}\n />\n);\n","import type { ComponentProps } from 'react';\nimport { Group, Root } from '@radix-ui/react-dropdown-menu';\n\nimport { DropdownMenuCheckboxItem } from './DropdownMenuCheckboxItem';\nimport { DropdownMenuContent } from './DropdownMenuContent';\nimport { DropdownMenuItem } from './DropdownMenuItem';\nimport { DropdownMenuItemDescription } from './DropdownMenuItemDescription';\nimport { DropdownMenuLabel } from './DropdownMenuLabel';\nimport { DropdownMenuRadioGroup, DropdownMenuRadioItem } from './DropdownMenuRadioGroup';\nimport { DropdownMenuSeparator } from './DropdownMenuSeparator';\nimport { DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger } from './DropdownMenuSub';\nimport { DropdownMenuTrigger } from './DropdownMenuTrigger';\n\ntype Props = ComponentProps<typeof Root>;\n\nexport const DropdownMenu = ({\n // change a default value to false, for modal property, as it is not used in most cases\n modal = false,\n ...props\n}: Props) => <Root {...props} modal={modal} />;\n\n/**\n * Main Layout\n */\nDropdownMenu.Trigger = DropdownMenuTrigger;\nDropdownMenu.Content = DropdownMenuContent;\nDropdownMenu.Group = Group;\n\n/**\n * Sub Layout\n */\nDropdownMenu.Sub = DropdownMenuSub;\nDropdownMenu.SubContent = DropdownMenuSubContent;\nDropdownMenu.SubTrigger = DropdownMenuSubTrigger;\n\n/**\n * Items can be used either Sub ar Main Layout\n */\nDropdownMenu.Separator = DropdownMenuSeparator;\nDropdownMenu.Label = DropdownMenuLabel;\nDropdownMenu.Item = DropdownMenuItem;\nDropdownMenu.CheckboxItem = DropdownMenuCheckboxItem;\nDropdownMenu.RadioGroup = DropdownMenuRadioGroup;\nDropdownMenu.RadioItem = DropdownMenuRadioItem;\n\n// item content\nDropdownMenu.ItemDescription = DropdownMenuItemDescription;\n"],"mappings":"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"}
@@ -2,7 +2,7 @@ import { cn } from "./classNames-DcGnTh2N.js";
2
2
  import { Button } from "./Button-BNkyYU8u.js";
3
3
  import { TextInput } from "./TextInput-CR0_USaY.js";
4
4
  import { Switch } from "./Switch-DccpSpzC.js";
5
- import { Select } from "./Select-B22hB_-w.js";
5
+ import { Select } from "./Select-C6zKeip5.js";
6
6
  import { Checkbox } from "./Checkbox-CHDDJyAA.js";
7
7
  import { FieldItem, fieldContext, formContext, useFieldContext, useFormContext } from "./FieldItem-BHUqgSO1.js";
8
8
  import { NumberInput } from "./internal/blocks/NumberInput.js";
@@ -300,4 +300,4 @@ const setSubmitError = (form, message) => {
300
300
  //#endregion
301
301
  export { setServerFieldErrors, setSubmitError, useAppForm, withForm };
302
302
 
303
- //# sourceMappingURL=Form-CAofWyMI.js.map
303
+ //# sourceMappingURL=Form-Dqbt_tIs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Form-CAofWyMI.js","names":[],"sources":["../src/blocks/Form/components/FormBody.tsx","../src/blocks/Form/components/SubmitButton.tsx","../src/blocks/Form/components/SubmitErrorAlert.tsx","../src/blocks/Form/connectors/CheckboxField.tsx","../src/blocks/Form/connectors/NumberField.tsx","../src/blocks/Form/connectors/OtpInputField.tsx","../src/blocks/Form/connectors/PasswordField.tsx","../src/blocks/Form/connectors/SelectField.tsx","../src/blocks/Form/connectors/SwitchField.tsx","../src/blocks/Form/connectors/TextareaField.tsx","../src/blocks/Form/connectors/TextField.tsx","../src/blocks/Form/formHook.ts","../src/blocks/Form/setServerFieldErrors.ts","../src/blocks/Form/setSubmitError.ts"],"sourcesContent":["import type { ComponentProps, ReactNode } from 'react';\n\nimport { cn } from '../../../utils';\nimport { useFormContext } from '../contexts';\n\ntype Props = {\n children: ReactNode;\n} & Omit<ComponentProps<'form'>, 'onSubmit'>;\n\nexport const FormBody = ({ children, className, ...formProps }: Props) => {\n const form = useFormContext();\n\n return (\n <form\n {...formProps}\n className={cn('tw:flex tw:flex-col tw:gap-4', className)}\n onSubmit={(e) => {\n e.preventDefault();\n e.stopPropagation();\n void form.handleSubmit();\n }}\n >\n {children}\n </form>\n );\n};\n","import type { ComponentProps, ReactNode } from 'react';\n\nimport { Button } from '../../../components/Button';\nimport { useFormContext } from '../contexts';\n\ntype Props = {\n children?: ReactNode;\n} & Omit<ComponentProps<typeof Button>, 'type' | 'isLoading' | 'disabled'>;\n\nexport const SubmitButton = ({ children = 'Submit', ...buttonProps }: Props) => {\n const form = useFormContext();\n\n return (\n <form.Subscribe\n selector={(state) => ({ isSubmitting: state.isSubmitting, canSubmit: state.canSubmit })}\n >\n {({ isSubmitting, canSubmit }) => (\n <Button\n {...buttonProps}\n type=\"submit\"\n isLoading={isSubmitting}\n disabled={!canSubmit || isSubmitting}\n >\n {children}\n </Button>\n )}\n </form.Subscribe>\n );\n};\n","import { Alert } from '../../../components/Alert';\nimport { useFormContext } from '../contexts';\n\n/**\n * Renders the form-level submit error (set via `setSubmitError` → `errorMap.onSubmit`) as an error\n * `Alert`. Place inside `form.FormBody`, typically just above the submit button. Renders nothing when\n * there is no submit error.\n */\nexport const SubmitErrorAlert = () => {\n const form = useFormContext();\n\n return (\n <form.Subscribe selector={(state) => state.errorMap.onSubmit}>\n {(submitError) =>\n typeof submitError === 'string' ? <Alert variant=\"error\" title={submitError} /> : null\n }\n </form.Subscribe>\n );\n};\n","import type { ComponentProps } from 'react';\n\nimport { Checkbox } from '../../../components/Checkbox';\nimport { useFieldContext } from '../contexts';\n\nimport { FieldItem, type FieldItemProps } from './FieldItem';\n\n// Checkbox owns its own label + description (via children), so only the wrapper className applies.\ntype Props = Pick<FieldItemProps, 'className'> &\n Omit<ComponentProps<typeof Checkbox>, 'id' | 'name' | 'checked' | 'onCheckedChange'>;\n\nexport const CheckboxField = ({ className, children, ...checkboxProps }: Props) => {\n // Strictly boolean: coerce Radix's `'indeterminate'` to `false` so a non-boolean never leaks into\n // form state (submit payloads / validators). `'indeterminate'` stays a purely visual state.\n const field = useFieldContext<boolean>();\n\n return (\n <FieldItem className={className}>\n {(control) => (\n <Checkbox\n {...checkboxProps}\n {...control}\n checked={field.state.value ?? false}\n onCheckedChange={(checked) => field.handleChange(checked === true)}\n onBlur={field.handleBlur}\n >\n {children}\n </Checkbox>\n )}\n </FieldItem>\n );\n};\n","import type { ComponentProps } from 'react';\n\nimport type { FormGroup } from '../../FormGroup';\nimport { NumberInput } from '../../NumberInput';\nimport { useFieldContext } from '../contexts';\n\nimport { FieldItem, type FieldItemProps } from './FieldItem';\n\ntype Props = FieldItemProps &\n Omit<\n ComponentProps<typeof FormGroup.NumberInput>,\n 'id' | 'name' | 'value' | 'onValueChange' | 'onBlur'\n >;\n\nexport const NumberField = ({\n label,\n action,\n required,\n requiredMark,\n help,\n tooltip,\n className,\n 'aria-describedby': ariaDescribedBy,\n ...inputProps\n}: Props) => {\n const field = useFieldContext<number | null>();\n\n return (\n <FieldItem\n label={label}\n action={action}\n required={required}\n requiredMark={requiredMark}\n help={help}\n tooltip={tooltip}\n className={className}\n aria-describedby={ariaDescribedBy}\n >\n {(control) => (\n <NumberInput\n {...inputProps}\n {...control}\n value={field.state.value ?? null}\n onValueChange={field.handleChange}\n onBlur={field.handleBlur}\n />\n )}\n </FieldItem>\n );\n};\n","import { OtpInput, type OtpInputProps } from '../../OtpInput';\nimport { useFieldContext } from '../contexts';\n\nimport { FieldItem, type FieldItemProps } from './FieldItem';\n\ntype Props = FieldItemProps &\n Omit<\n OtpInputProps,\n | 'value'\n | 'onChange'\n | 'children'\n | 'id'\n | 'name'\n | 'aria-describedby'\n | 'aria-required'\n | 'aria-invalid'\n >;\n\nexport const OtpInputField = ({\n label,\n action,\n required,\n requiredMark,\n help,\n tooltip,\n className,\n 'aria-describedby': ariaDescribedBy,\n maxLength,\n ...otpProps\n}: Props) => {\n const field = useFieldContext<string>();\n\n return (\n <FieldItem\n label={label}\n action={action}\n required={required}\n requiredMark={requiredMark}\n help={help}\n tooltip={tooltip}\n className={className}\n aria-describedby={ariaDescribedBy}\n >\n {(control) => (\n <OtpInput\n {...otpProps}\n {...control}\n maxLength={maxLength}\n value={field.state.value ?? ''}\n onChange={field.handleChange}\n onBlur={field.handleBlur}\n >\n <OtpInput.Group>\n {Array.from({ length: maxLength }, (_, index) => (\n <OtpInput.Slot key={index} index={index} />\n ))}\n </OtpInput.Group>\n </OtpInput>\n )}\n </FieldItem>\n );\n};\n","import type { ComponentProps } from 'react';\n\nimport { PasswordInput } from '../../PasswordInput';\nimport { useFieldContext } from '../contexts';\n\nimport { FieldItem, type FieldItemProps } from './FieldItem';\n\ntype Props = FieldItemProps &\n Omit<ComponentProps<typeof PasswordInput>, 'id' | 'name' | 'value' | 'onValueChange' | 'onBlur'>;\n\nexport const PasswordField = ({\n label,\n action,\n required,\n requiredMark,\n help,\n tooltip,\n className,\n 'aria-describedby': ariaDescribedBy,\n ...inputProps\n}: Props) => {\n const field = useFieldContext<string>();\n\n return (\n <FieldItem\n label={label}\n action={action}\n required={required}\n requiredMark={requiredMark}\n help={help}\n tooltip={tooltip}\n className={className}\n aria-describedby={ariaDescribedBy}\n >\n {(control) => (\n <PasswordInput\n {...inputProps}\n {...control}\n value={field.state.value ?? ''}\n onValueChange={field.handleChange}\n onBlur={field.handleBlur}\n />\n )}\n </FieldItem>\n );\n};\n","import {\n Select,\n type SelectItem,\n type SelectItemGroup,\n type SelectProps,\n} from '../../../components/Select';\nimport { useFieldContext } from '../contexts';\n\nimport { FieldItem, type FieldItemProps } from './FieldItem';\n\ntype Props = FieldItemProps &\n Omit<\n SelectProps,\n // Owned by the field / `FieldItem` — see the connector rules in AGENTS.md. The naming props\n // are on that list too: `FieldItem` renders the label and hands the control its `id`, so a\n // name from the call site could only disagree with it.\n | 'id'\n | 'aria-label'\n | 'aria-labelledby'\n | 'name'\n | 'value'\n | 'defaultValue'\n | 'onValueChange'\n | 'onBlur'\n | 'aria-describedby'\n | 'aria-invalid'\n | 'aria-required'\n // `className` styles the field frame, so the trigger gets its own prop below.\n | 'className'\n | 'items'\n > & {\n items: readonly (SelectItem | SelectItemGroup)[];\n triggerClassName?: string;\n };\n\nexport const SelectField = ({\n label,\n action,\n required,\n requiredMark,\n help,\n tooltip,\n className,\n 'aria-describedby': ariaDescribedBy,\n triggerClassName,\n ...selectProps\n}: Props) => {\n const field = useFieldContext<string>();\n\n return (\n <FieldItem\n label={label}\n action={action}\n required={required}\n requiredMark={requiredMark}\n help={help}\n tooltip={tooltip}\n className={className}\n aria-describedby={ariaDescribedBy}\n >\n {(control) => (\n // `required` deliberately stays on `FieldItem` (which turns it into `aria-required` via\n // `control`) and is not forwarded to the Radix root: a required hidden native select would\n // fail browser constraint validation and swallow the submit event before the form sees it.\n <Select\n {...selectProps}\n {...control}\n className={triggerClassName ?? 'tw:w-full'}\n value={field.state.value ?? ''}\n onValueChange={field.handleChange}\n onBlur={field.handleBlur}\n />\n )}\n </FieldItem>\n );\n};\n","import type { ComponentProps } from 'react';\n\nimport { Switch } from '../../../components/Switch';\nimport { useFieldContext } from '../contexts';\n\nimport { FieldItem, type FieldItemProps } from './FieldItem';\n\n// Switch owns its own label + description (via children), so only the wrapper className applies.\ntype Props = Pick<FieldItemProps, 'className'> &\n Omit<ComponentProps<typeof Switch>, 'id' | 'name' | 'checked' | 'onCheckedChange'>;\n\nexport const SwitchField = ({ className, children, ...switchProps }: Props) => {\n const field = useFieldContext<boolean>();\n\n return (\n <FieldItem className={className}>\n {(control) => (\n <Switch\n {...switchProps}\n {...control}\n checked={field.state.value ?? false}\n onCheckedChange={field.handleChange}\n onBlur={field.handleBlur}\n >\n {children}\n </Switch>\n )}\n </FieldItem>\n );\n};\n","import type { ComponentProps } from 'react';\n\nimport type { FormGroup } from '../../FormGroup';\nimport { Textarea } from '../../Textarea';\nimport { useFieldContext } from '../contexts';\n\nimport { FieldItem, type FieldItemProps } from './FieldItem';\n\ntype Props = FieldItemProps &\n Omit<\n ComponentProps<typeof FormGroup.Textarea>,\n 'id' | 'name' | 'value' | 'onValueChange' | 'onBlur'\n >;\n\nexport const TextareaField = ({\n label,\n action,\n required,\n requiredMark,\n help,\n tooltip,\n className,\n 'aria-describedby': ariaDescribedBy,\n ...inputProps\n}: Props) => {\n const field = useFieldContext<string>();\n\n return (\n <FieldItem\n label={label}\n action={action}\n required={required}\n requiredMark={requiredMark}\n help={help}\n tooltip={tooltip}\n className={className}\n aria-describedby={ariaDescribedBy}\n >\n {(control) => (\n <Textarea\n {...inputProps}\n {...control}\n value={field.state.value ?? ''}\n onValueChange={field.handleChange}\n onBlur={field.handleBlur}\n />\n )}\n </FieldItem>\n );\n};\n","import type { ComponentProps } from 'react';\n\nimport type { FormGroup } from '../../FormGroup';\nimport { TextInput } from '../../TextInput';\nimport { useFieldContext } from '../contexts';\n\nimport { FieldItem, type FieldItemProps } from './FieldItem';\n\ntype Props = FieldItemProps &\n Omit<ComponentProps<typeof FormGroup.TextInput>, 'id' | 'name' | 'value' | 'onChange' | 'onBlur'>;\n\nexport const TextField = ({\n label,\n action,\n required,\n requiredMark,\n help,\n tooltip,\n className,\n 'aria-describedby': ariaDescribedBy,\n ...inputProps\n}: Props) => {\n const field = useFieldContext<string>();\n\n return (\n <FieldItem\n label={label}\n action={action}\n required={required}\n requiredMark={requiredMark}\n help={help}\n tooltip={tooltip}\n className={className}\n aria-describedby={ariaDescribedBy}\n >\n {(control) => (\n <TextInput\n {...inputProps}\n {...control}\n value={field.state.value ?? ''}\n onValueChange={field.handleChange}\n onBlur={field.handleBlur}\n />\n )}\n </FieldItem>\n );\n};\n","import { createFormHook } from '@tanstack/react-form';\n\nimport { FormBody } from './components/FormBody';\nimport { SubmitButton } from './components/SubmitButton';\nimport { SubmitErrorAlert } from './components/SubmitErrorAlert';\nimport { CheckboxField } from './connectors/CheckboxField';\nimport { NumberField } from './connectors/NumberField';\nimport { OtpInputField } from './connectors/OtpInputField';\nimport { PasswordField } from './connectors/PasswordField';\nimport { SelectField } from './connectors/SelectField';\nimport { SwitchField } from './connectors/SwitchField';\nimport { TextareaField } from './connectors/TextareaField';\nimport { TextField } from './connectors/TextField';\nimport { fieldContext, formContext } from './contexts';\n\n/**\n * Typed form hook + `withForm` binding for forms with validation, server errors or a submit state.\n *\n * - Render `field.*` inside `form.AppForm` → `form.FormBody`; submit via `form.SubmitButton`.\n * - `ComboboxField`, `MultiComboboxField`, `CodeEditorField` are imported by name: no tree-shaking.\n * - Not for a lone `<input>` (`TextInput`) or an unvalidated label + input (`FormGroup`).\n * - Takes any [Standard Schema](https://standardschema.dev/) validator.\n *\n * @see RECIPES.md#modal-form\n */\nexport const { useAppForm, withForm } = createFormHook({\n fieldContext,\n formContext,\n fieldComponents: {\n TextField,\n NumberField,\n PasswordField,\n TextareaField,\n SelectField,\n CheckboxField,\n SwitchField,\n OtpInputField,\n },\n formComponents: {\n FormBody,\n SubmitButton,\n SubmitErrorAlert,\n },\n});\n","import type { AnyFormApi } from '@tanstack/form-core';\n\nexport type ServerFieldError = {\n field: string;\n message: string;\n};\n\n/**\n * Map a list of server-returned field errors onto a TanStack form instance.\n *\n * - Marks each field blurred — that is what `FieldItem` gates the error reveal on.\n * - `isTouched` alongside it, for anything reading TanStack's own meta (`canSubmit`, dirty checks).\n * - Both are needed. Called from a mutation's `onError` there is no submit attempt to fall back on, so\n * without `isBlurred` the message would sit in `errorMap` and render nowhere.\n */\nexport const setServerFieldErrors = (form: AnyFormApi, errors: readonly ServerFieldError[]) => {\n for (const { field, message } of errors) {\n form.setFieldMeta(field, (meta) => ({\n ...meta,\n isBlurred: true,\n isTouched: true,\n errors: [message],\n errorMap: { ...meta.errorMap, onServer: message },\n }));\n }\n};\n","// `form-core`, not `react-form`: a declared dep, so `dist` imports it rather than inlining its own copy.\nimport type { AnyFormApi } from '@tanstack/form-core';\n\n/**\n * Set a **form-level** submit error on a TanStack form instance — a failed submission that isn't tied\n * to a single field (bad credentials, 5xx, network). Stored on `errorMap.onSubmit` and rendered by\n * `SubmitErrorAlert`. For field-specific server errors use `setServerFieldErrors` instead.\n *\n * Note: any error entry makes the form \"invalid\", so pair this with `canSubmitWhenInvalid: true` on\n * the form to keep the submit button retryable (a resubmit re-runs the validators and clears it).\n */\nexport const setSubmitError = (form: AnyFormApi, message: string) => {\n form.setErrorMap({ onSubmit: { form: message, fields: {} } });\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"Form-Dqbt_tIs.js","names":[],"sources":["../src/blocks/Form/components/FormBody.tsx","../src/blocks/Form/components/SubmitButton.tsx","../src/blocks/Form/components/SubmitErrorAlert.tsx","../src/blocks/Form/connectors/CheckboxField.tsx","../src/blocks/Form/connectors/NumberField.tsx","../src/blocks/Form/connectors/OtpInputField.tsx","../src/blocks/Form/connectors/PasswordField.tsx","../src/blocks/Form/connectors/SelectField.tsx","../src/blocks/Form/connectors/SwitchField.tsx","../src/blocks/Form/connectors/TextareaField.tsx","../src/blocks/Form/connectors/TextField.tsx","../src/blocks/Form/formHook.ts","../src/blocks/Form/setServerFieldErrors.ts","../src/blocks/Form/setSubmitError.ts"],"sourcesContent":["import type { ComponentProps, ReactNode } from 'react';\n\nimport { cn } from '../../../utils';\nimport { useFormContext } from '../contexts';\n\ntype Props = {\n children: ReactNode;\n} & Omit<ComponentProps<'form'>, 'onSubmit'>;\n\nexport const FormBody = ({ children, className, ...formProps }: Props) => {\n const form = useFormContext();\n\n return (\n <form\n {...formProps}\n className={cn('tw:flex tw:flex-col tw:gap-4', className)}\n onSubmit={(e) => {\n e.preventDefault();\n e.stopPropagation();\n void form.handleSubmit();\n }}\n >\n {children}\n </form>\n );\n};\n","import type { ComponentProps, ReactNode } from 'react';\n\nimport { Button } from '../../../components/Button';\nimport { useFormContext } from '../contexts';\n\ntype Props = {\n children?: ReactNode;\n} & Omit<ComponentProps<typeof Button>, 'type' | 'isLoading' | 'disabled'>;\n\nexport const SubmitButton = ({ children = 'Submit', ...buttonProps }: Props) => {\n const form = useFormContext();\n\n return (\n <form.Subscribe\n selector={(state) => ({ isSubmitting: state.isSubmitting, canSubmit: state.canSubmit })}\n >\n {({ isSubmitting, canSubmit }) => (\n <Button\n {...buttonProps}\n type=\"submit\"\n isLoading={isSubmitting}\n disabled={!canSubmit || isSubmitting}\n >\n {children}\n </Button>\n )}\n </form.Subscribe>\n );\n};\n","import { Alert } from '../../../components/Alert';\nimport { useFormContext } from '../contexts';\n\n/**\n * Renders the form-level submit error (set via `setSubmitError` → `errorMap.onSubmit`) as an error\n * `Alert`. Place inside `form.FormBody`, typically just above the submit button. Renders nothing when\n * there is no submit error.\n */\nexport const SubmitErrorAlert = () => {\n const form = useFormContext();\n\n return (\n <form.Subscribe selector={(state) => state.errorMap.onSubmit}>\n {(submitError) =>\n typeof submitError === 'string' ? <Alert variant=\"error\" title={submitError} /> : null\n }\n </form.Subscribe>\n );\n};\n","import type { ComponentProps } from 'react';\n\nimport { Checkbox } from '../../../components/Checkbox';\nimport { useFieldContext } from '../contexts';\n\nimport { FieldItem, type FieldItemProps } from './FieldItem';\n\n// Checkbox owns its own label + description (via children), so only the wrapper className applies.\ntype Props = Pick<FieldItemProps, 'className'> &\n Omit<ComponentProps<typeof Checkbox>, 'id' | 'name' | 'checked' | 'onCheckedChange'>;\n\nexport const CheckboxField = ({ className, children, ...checkboxProps }: Props) => {\n // Strictly boolean: coerce Radix's `'indeterminate'` to `false` so a non-boolean never leaks into\n // form state (submit payloads / validators). `'indeterminate'` stays a purely visual state.\n const field = useFieldContext<boolean>();\n\n return (\n <FieldItem className={className}>\n {(control) => (\n <Checkbox\n {...checkboxProps}\n {...control}\n checked={field.state.value ?? false}\n onCheckedChange={(checked) => field.handleChange(checked === true)}\n onBlur={field.handleBlur}\n >\n {children}\n </Checkbox>\n )}\n </FieldItem>\n );\n};\n","import type { ComponentProps } from 'react';\n\nimport type { FormGroup } from '../../FormGroup';\nimport { NumberInput } from '../../NumberInput';\nimport { useFieldContext } from '../contexts';\n\nimport { FieldItem, type FieldItemProps } from './FieldItem';\n\ntype Props = FieldItemProps &\n Omit<\n ComponentProps<typeof FormGroup.NumberInput>,\n 'id' | 'name' | 'value' | 'onValueChange' | 'onBlur'\n >;\n\nexport const NumberField = ({\n label,\n action,\n required,\n requiredMark,\n help,\n tooltip,\n className,\n 'aria-describedby': ariaDescribedBy,\n ...inputProps\n}: Props) => {\n const field = useFieldContext<number | null>();\n\n return (\n <FieldItem\n label={label}\n action={action}\n required={required}\n requiredMark={requiredMark}\n help={help}\n tooltip={tooltip}\n className={className}\n aria-describedby={ariaDescribedBy}\n >\n {(control) => (\n <NumberInput\n {...inputProps}\n {...control}\n value={field.state.value ?? null}\n onValueChange={field.handleChange}\n onBlur={field.handleBlur}\n />\n )}\n </FieldItem>\n );\n};\n","import { OtpInput, type OtpInputProps } from '../../OtpInput';\nimport { useFieldContext } from '../contexts';\n\nimport { FieldItem, type FieldItemProps } from './FieldItem';\n\ntype Props = FieldItemProps &\n Omit<\n OtpInputProps,\n | 'value'\n | 'onChange'\n | 'children'\n | 'id'\n | 'name'\n | 'aria-describedby'\n | 'aria-required'\n | 'aria-invalid'\n >;\n\nexport const OtpInputField = ({\n label,\n action,\n required,\n requiredMark,\n help,\n tooltip,\n className,\n 'aria-describedby': ariaDescribedBy,\n maxLength,\n ...otpProps\n}: Props) => {\n const field = useFieldContext<string>();\n\n return (\n <FieldItem\n label={label}\n action={action}\n required={required}\n requiredMark={requiredMark}\n help={help}\n tooltip={tooltip}\n className={className}\n aria-describedby={ariaDescribedBy}\n >\n {(control) => (\n <OtpInput\n {...otpProps}\n {...control}\n maxLength={maxLength}\n value={field.state.value ?? ''}\n onChange={field.handleChange}\n onBlur={field.handleBlur}\n >\n <OtpInput.Group>\n {Array.from({ length: maxLength }, (_, index) => (\n <OtpInput.Slot key={index} index={index} />\n ))}\n </OtpInput.Group>\n </OtpInput>\n )}\n </FieldItem>\n );\n};\n","import type { ComponentProps } from 'react';\n\nimport { PasswordInput } from '../../PasswordInput';\nimport { useFieldContext } from '../contexts';\n\nimport { FieldItem, type FieldItemProps } from './FieldItem';\n\ntype Props = FieldItemProps &\n Omit<ComponentProps<typeof PasswordInput>, 'id' | 'name' | 'value' | 'onValueChange' | 'onBlur'>;\n\nexport const PasswordField = ({\n label,\n action,\n required,\n requiredMark,\n help,\n tooltip,\n className,\n 'aria-describedby': ariaDescribedBy,\n ...inputProps\n}: Props) => {\n const field = useFieldContext<string>();\n\n return (\n <FieldItem\n label={label}\n action={action}\n required={required}\n requiredMark={requiredMark}\n help={help}\n tooltip={tooltip}\n className={className}\n aria-describedby={ariaDescribedBy}\n >\n {(control) => (\n <PasswordInput\n {...inputProps}\n {...control}\n value={field.state.value ?? ''}\n onValueChange={field.handleChange}\n onBlur={field.handleBlur}\n />\n )}\n </FieldItem>\n );\n};\n","import {\n Select,\n type SelectItem,\n type SelectItemGroup,\n type SelectProps,\n} from '../../../components/Select';\nimport { useFieldContext } from '../contexts';\n\nimport { FieldItem, type FieldItemProps } from './FieldItem';\n\ntype Props = FieldItemProps &\n Omit<\n SelectProps,\n // Owned by the field / `FieldItem` — see the connector rules in AGENTS.md. The naming props\n // are on that list too: `FieldItem` renders the label and hands the control its `id`, so a\n // name from the call site could only disagree with it.\n | 'id'\n | 'aria-label'\n | 'aria-labelledby'\n | 'name'\n | 'value'\n | 'defaultValue'\n | 'onValueChange'\n | 'onBlur'\n | 'aria-describedby'\n | 'aria-invalid'\n | 'aria-required'\n // `className` styles the field frame, so the trigger gets its own prop below.\n | 'className'\n | 'items'\n > & {\n items: readonly (SelectItem | SelectItemGroup)[];\n triggerClassName?: string;\n };\n\nexport const SelectField = ({\n label,\n action,\n required,\n requiredMark,\n help,\n tooltip,\n className,\n 'aria-describedby': ariaDescribedBy,\n triggerClassName,\n ...selectProps\n}: Props) => {\n const field = useFieldContext<string>();\n\n return (\n <FieldItem\n label={label}\n action={action}\n required={required}\n requiredMark={requiredMark}\n help={help}\n tooltip={tooltip}\n className={className}\n aria-describedby={ariaDescribedBy}\n >\n {(control) => (\n // `required` deliberately stays on `FieldItem` (which turns it into `aria-required` via\n // `control`) and is not forwarded to the Radix root: a required hidden native select would\n // fail browser constraint validation and swallow the submit event before the form sees it.\n <Select\n {...selectProps}\n {...control}\n className={triggerClassName ?? 'tw:w-full'}\n value={field.state.value ?? ''}\n onValueChange={field.handleChange}\n onBlur={field.handleBlur}\n />\n )}\n </FieldItem>\n );\n};\n","import type { ComponentProps } from 'react';\n\nimport { Switch } from '../../../components/Switch';\nimport { useFieldContext } from '../contexts';\n\nimport { FieldItem, type FieldItemProps } from './FieldItem';\n\n// Switch owns its own label + description (via children), so only the wrapper className applies.\ntype Props = Pick<FieldItemProps, 'className'> &\n Omit<ComponentProps<typeof Switch>, 'id' | 'name' | 'checked' | 'onCheckedChange'>;\n\nexport const SwitchField = ({ className, children, ...switchProps }: Props) => {\n const field = useFieldContext<boolean>();\n\n return (\n <FieldItem className={className}>\n {(control) => (\n <Switch\n {...switchProps}\n {...control}\n checked={field.state.value ?? false}\n onCheckedChange={field.handleChange}\n onBlur={field.handleBlur}\n >\n {children}\n </Switch>\n )}\n </FieldItem>\n );\n};\n","import type { ComponentProps } from 'react';\n\nimport type { FormGroup } from '../../FormGroup';\nimport { Textarea } from '../../Textarea';\nimport { useFieldContext } from '../contexts';\n\nimport { FieldItem, type FieldItemProps } from './FieldItem';\n\ntype Props = FieldItemProps &\n Omit<\n ComponentProps<typeof FormGroup.Textarea>,\n 'id' | 'name' | 'value' | 'onValueChange' | 'onBlur'\n >;\n\nexport const TextareaField = ({\n label,\n action,\n required,\n requiredMark,\n help,\n tooltip,\n className,\n 'aria-describedby': ariaDescribedBy,\n ...inputProps\n}: Props) => {\n const field = useFieldContext<string>();\n\n return (\n <FieldItem\n label={label}\n action={action}\n required={required}\n requiredMark={requiredMark}\n help={help}\n tooltip={tooltip}\n className={className}\n aria-describedby={ariaDescribedBy}\n >\n {(control) => (\n <Textarea\n {...inputProps}\n {...control}\n value={field.state.value ?? ''}\n onValueChange={field.handleChange}\n onBlur={field.handleBlur}\n />\n )}\n </FieldItem>\n );\n};\n","import type { ComponentProps } from 'react';\n\nimport type { FormGroup } from '../../FormGroup';\nimport { TextInput } from '../../TextInput';\nimport { useFieldContext } from '../contexts';\n\nimport { FieldItem, type FieldItemProps } from './FieldItem';\n\ntype Props = FieldItemProps &\n Omit<ComponentProps<typeof FormGroup.TextInput>, 'id' | 'name' | 'value' | 'onChange' | 'onBlur'>;\n\nexport const TextField = ({\n label,\n action,\n required,\n requiredMark,\n help,\n tooltip,\n className,\n 'aria-describedby': ariaDescribedBy,\n ...inputProps\n}: Props) => {\n const field = useFieldContext<string>();\n\n return (\n <FieldItem\n label={label}\n action={action}\n required={required}\n requiredMark={requiredMark}\n help={help}\n tooltip={tooltip}\n className={className}\n aria-describedby={ariaDescribedBy}\n >\n {(control) => (\n <TextInput\n {...inputProps}\n {...control}\n value={field.state.value ?? ''}\n onValueChange={field.handleChange}\n onBlur={field.handleBlur}\n />\n )}\n </FieldItem>\n );\n};\n","import { createFormHook } from '@tanstack/react-form';\n\nimport { FormBody } from './components/FormBody';\nimport { SubmitButton } from './components/SubmitButton';\nimport { SubmitErrorAlert } from './components/SubmitErrorAlert';\nimport { CheckboxField } from './connectors/CheckboxField';\nimport { NumberField } from './connectors/NumberField';\nimport { OtpInputField } from './connectors/OtpInputField';\nimport { PasswordField } from './connectors/PasswordField';\nimport { SelectField } from './connectors/SelectField';\nimport { SwitchField } from './connectors/SwitchField';\nimport { TextareaField } from './connectors/TextareaField';\nimport { TextField } from './connectors/TextField';\nimport { fieldContext, formContext } from './contexts';\n\n/**\n * Typed form hook + `withForm` binding for forms with validation, server errors or a submit state.\n *\n * - Render `field.*` inside `form.AppForm` → `form.FormBody`; submit via `form.SubmitButton`.\n * - `ComboboxField`, `MultiComboboxField`, `CodeEditorField` are imported by name: no tree-shaking.\n * - Not for a lone `<input>` (`TextInput`) or an unvalidated label + input (`FormGroup`).\n * - Takes any [Standard Schema](https://standardschema.dev/) validator.\n *\n * @see RECIPES.md#modal-form\n */\nexport const { useAppForm, withForm } = createFormHook({\n fieldContext,\n formContext,\n fieldComponents: {\n TextField,\n NumberField,\n PasswordField,\n TextareaField,\n SelectField,\n CheckboxField,\n SwitchField,\n OtpInputField,\n },\n formComponents: {\n FormBody,\n SubmitButton,\n SubmitErrorAlert,\n },\n});\n","import type { AnyFormApi } from '@tanstack/form-core';\n\nexport type ServerFieldError = {\n field: string;\n message: string;\n};\n\n/**\n * Map a list of server-returned field errors onto a TanStack form instance.\n *\n * - Marks each field blurred — that is what `FieldItem` gates the error reveal on.\n * - `isTouched` alongside it, for anything reading TanStack's own meta (`canSubmit`, dirty checks).\n * - Both are needed. Called from a mutation's `onError` there is no submit attempt to fall back on, so\n * without `isBlurred` the message would sit in `errorMap` and render nowhere.\n */\nexport const setServerFieldErrors = (form: AnyFormApi, errors: readonly ServerFieldError[]) => {\n for (const { field, message } of errors) {\n form.setFieldMeta(field, (meta) => ({\n ...meta,\n isBlurred: true,\n isTouched: true,\n errors: [message],\n errorMap: { ...meta.errorMap, onServer: message },\n }));\n }\n};\n","// `form-core`, not `react-form`: a declared dep, so `dist` imports it rather than inlining its own copy.\nimport type { AnyFormApi } from '@tanstack/form-core';\n\n/**\n * Set a **form-level** submit error on a TanStack form instance — a failed submission that isn't tied\n * to a single field (bad credentials, 5xx, network). Stored on `errorMap.onSubmit` and rendered by\n * `SubmitErrorAlert`. For field-specific server errors use `setServerFieldErrors` instead.\n *\n * Note: any error entry makes the form \"invalid\", so pair this with `canSubmitWhenInvalid: true` on\n * the form to keep the submit button retryable (a resubmit re-runs the validators and clears it).\n */\nexport const setSubmitError = (form: AnyFormApi, message: string) => {\n form.setErrorMap({ onSubmit: { form: message, fields: {} } });\n};\n"],"mappings":";;;;;;;;;;;;;;;AASA,MAAa,YAAY,EAAE,UAAU,WAAW,GAAG,gBAAuB;CACxE,MAAM,OAAO,eAAe;CAE5B,OACE,oBAAC,QAAD;EACE,GAAI;EACJ,WAAW,GAAG,gCAAgC,SAAS;EACvD,WAAW,MAAM;GACf,EAAE,eAAe;GACjB,EAAE,gBAAgB;GAClB,KAAU,aAAa;EACzB;EAEC;CACG,CAAA;AAEV;;;AChBA,MAAa,gBAAgB,EAAE,WAAW,UAAU,GAAG,kBAAyB;CAC9E,MAAM,OAAO,eAAe;CAE5B,OACE,oBAAC,KAAK,WAAN;EACE,WAAW,WAAW;GAAE,cAAc,MAAM;GAAc,WAAW,MAAM;EAAU;EAEnF,WAAA,EAAE,cAAc,gBAChB,oBAAC,QAAD;GACE,GAAI;GACJ,MAAK;GACL,WAAW;GACX,UAAU,CAAC,aAAa;GAEvB;EACK,CAAA;CAEI,CAAA;AAEpB;;;;;;;;ACpBA,MAAa,yBAAyB;CACpC,MAAM,OAAO,eAAe;CAE5B,OACE,oBAAC,KAAK,WAAN;EAAgB,WAAW,UAAU,MAAM,SAAS;EAChD,WAAA,gBACA,OAAO,gBAAgB,WAAW,oBAAC,OAAD;GAAO,SAAQ;GAAQ,OAAO;EAAc,CAAA,IAAI;CAEtE,CAAA;AAEpB;;;ACPA,MAAa,iBAAiB,EAAE,WAAW,UAAU,GAAG,oBAA2B;CAGjF,MAAM,QAAQ,gBAAyB;CAEvC,OACE,oBAAC,WAAD;EAAsB;EAClB,WAAA,YACA,oBAAC,UAAD;GACE,GAAI;GACJ,GAAI;GACJ,SAAS,MAAM,MAAM,SAAS;GAC9B,kBAAkB,YAAY,MAAM,aAAa,YAAY,IAAI;GACjE,QAAQ,MAAM;GAEb;EACO,CAAA;CAEH,CAAA;AAEf;;;ACjBA,MAAa,eAAe,EAC1B,OACA,QACA,UACA,cACA,MACA,SACA,WACA,oBAAoB,iBACpB,GAAG,iBACQ;CACX,MAAM,QAAQ,gBAA+B;CAE7C,OACE,oBAAC,WAAD;EACS;EACC;EACE;EACI;EACR;EACG;EACE;EACX,oBAAkB;EAEhB,WAAA,YACA,oBAAC,aAAD;GACE,GAAI;GACJ,GAAI;GACJ,OAAO,MAAM,MAAM,SAAS;GAC5B,eAAe,MAAM;GACrB,QAAQ,MAAM;EACf,CAAA;CAEM,CAAA;AAEf;;;AC/BA,MAAa,iBAAiB,EAC5B,OACA,QACA,UACA,cACA,MACA,SACA,WACA,oBAAoB,iBACpB,WACA,GAAG,eACQ;CACX,MAAM,QAAQ,gBAAwB;CAEtC,OACE,oBAAC,WAAD;EACS;EACC;EACE;EACI;EACR;EACG;EACE;EACX,oBAAkB;EAEhB,WAAA,YACA,oBAAC,UAAD;GACE,GAAI;GACJ,GAAI;GACO;GACX,OAAO,MAAM,MAAM,SAAS;GAC5B,UAAU,MAAM;GAChB,QAAQ,MAAM;GAEd,UAAA,oBAAC,SAAS,OAAV,EAAA,UACG,MAAM,KAAK,EAAE,QAAQ,UAAU,IAAI,GAAG,UACrC,oBAAC,SAAS,MAAV,EAAkC,MAAQ,GAAtB,KAAsB,CAC3C,EACa,CAAA;EACR,CAAA;CAEH,CAAA;AAEf;;;ACnDA,MAAa,iBAAiB,EAC5B,OACA,QACA,UACA,cACA,MACA,SACA,WACA,oBAAoB,iBACpB,GAAG,iBACQ;CACX,MAAM,QAAQ,gBAAwB;CAEtC,OACE,oBAAC,WAAD;EACS;EACC;EACE;EACI;EACR;EACG;EACE;EACX,oBAAkB;EAEhB,WAAA,YACA,oBAAC,eAAD;GACE,GAAI;GACJ,GAAI;GACJ,OAAO,MAAM,MAAM,SAAS;GAC5B,eAAe,MAAM;GACrB,QAAQ,MAAM;EACf,CAAA;CAEM,CAAA;AAEf;;;ACVA,MAAa,eAAe,EAC1B,OACA,QACA,UACA,cACA,MACA,SACA,WACA,oBAAoB,iBACpB,kBACA,GAAG,kBACQ;CACX,MAAM,QAAQ,gBAAwB;CAEtC,OACE,oBAAC,WAAD;EACS;EACC;EACE;EACI;EACR;EACG;EACE;EACX,oBAAkB;EAEhB,WAAA,YAIA,oBAAC,QAAD;GACE,GAAI;GACJ,GAAI;GACJ,WAAW,oBAAoB;GAC/B,OAAO,MAAM,MAAM,SAAS;GAC5B,eAAe,MAAM;GACrB,QAAQ,MAAM;EACf,CAAA;CAEM,CAAA;AAEf;;;AChEA,MAAa,eAAe,EAAE,WAAW,UAAU,GAAG,kBAAyB;CAC7E,MAAM,QAAQ,gBAAyB;CAEvC,OACE,oBAAC,WAAD;EAAsB;EAClB,WAAA,YACA,oBAAC,QAAD;GACE,GAAI;GACJ,GAAI;GACJ,SAAS,MAAM,MAAM,SAAS;GAC9B,iBAAiB,MAAM;GACvB,QAAQ,MAAM;GAEb;EACK,CAAA;CAED,CAAA;AAEf;;;ACfA,MAAa,iBAAiB,EAC5B,OACA,QACA,UACA,cACA,MACA,SACA,WACA,oBAAoB,iBACpB,GAAG,iBACQ;CACX,MAAM,QAAQ,gBAAwB;CAEtC,OACE,oBAAC,WAAD;EACS;EACC;EACE;EACI;EACR;EACG;EACE;EACX,oBAAkB;EAEhB,WAAA,YACA,oBAAC,UAAD;GACE,GAAI;GACJ,GAAI;GACJ,OAAO,MAAM,MAAM,SAAS;GAC5B,eAAe,MAAM;GACrB,QAAQ,MAAM;EACf,CAAA;CAEM,CAAA;AAEf;;;ACtCA,MAAa,aAAa,EACxB,OACA,QACA,UACA,cACA,MACA,SACA,WACA,oBAAoB,iBACpB,GAAG,iBACQ;CACX,MAAM,QAAQ,gBAAwB;CAEtC,OACE,oBAAC,WAAD;EACS;EACC;EACE;EACI;EACR;EACG;EACE;EACX,oBAAkB;EAEhB,WAAA,YACA,oBAAC,WAAD;GACE,GAAI;GACJ,GAAI;GACJ,OAAO,MAAM,MAAM,SAAS;GAC5B,eAAe,MAAM;GACrB,QAAQ,MAAM;EACf,CAAA;CAEM,CAAA;AAEf;;;;;;;;;;;;;ACrBA,MAAa,EAAE,YAAY,aAAa,eAAe;CACrD;CACA;CACA,iBAAiB;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;CACA,gBAAgB;EACd;EACA;EACA;CACF;AACF,CAAC;;;;;;;;;;;AC5BD,MAAa,wBAAwB,MAAkB,WAAwC;CAC7F,KAAK,MAAM,EAAE,OAAO,aAAa,QAC/B,KAAK,aAAa,QAAQ,UAAU;EAClC,GAAG;EACH,WAAW;EACX,WAAW;EACX,QAAQ,CAAC,OAAO;EAChB,UAAU;GAAE,GAAG,KAAK;GAAU,UAAU;EAAQ;CAClD,EAAE;AAEN;;;;;;;;;;;ACdA,MAAa,kBAAkB,MAAkB,YAAoB;CACnE,KAAK,YAAY,EAAE,UAAU;EAAE,MAAM;EAAS,QAAQ,CAAC;CAAE,EAAE,CAAC;AAC9D"}
@@ -0,0 +1,26 @@
1
+ import { cn } from "./classNames-DcGnTh2N.js";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { Content, Portal, Root, Trigger } from "@radix-ui/react-hover-card";
4
+ //#region src/components/HoverCard/HoverCardContent.tsx
5
+ const HoverCardContent = ({ ref, className, align = "center", sideOffset = 4, children, ...props }) => /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(Content, {
6
+ ref,
7
+ align,
8
+ sideOffset,
9
+ "data-slot": "hover-card-content",
10
+ className: cn("tailwindcss-preflight", "tw:z-overlay", "tw:box-border", "tw:border", "tw:rounded-popover", "tw:min-w-32", "tw:origin-(--radix-hover-card-content-transform-origin)", "tw:max-h-[var(--radix-hover-card-content-available-height)]", "tw:p-4", "tw:shadow-md", "tw:border-solid tw:border-border tw:bg-popover tw:text-popover-foreground", "tw:data-[side=bottom]:slide-in-from-top-2", "tw:data-[side=left]:slide-in-from-right-2", "tw:data-[side=right]:slide-in-from-left-2", "tw:data-[side=top]:slide-in-from-bottom-2", "tw:data-[state=open]:animate-in", "tw:data-[state=open]:fade-in-0", "tw:data-[state=open]:zoom-in-95", "tw:data-[state=closed]:animate-out", "tw:data-[state=closed]:fade-out-0", "tw:data-[state=closed]:zoom-out-95", "tw:[&_svg.lucide:not([class*='tw:size-'])]:size-4", "tw:[&_svg]:shrink-0", className),
11
+ ...props,
12
+ children
13
+ }) });
14
+ //#endregion
15
+ //#region src/components/HoverCard/HoverCard.tsx
16
+ const HoverCard = ({ openDelay = 200, closeDelay = 200, ...rest }) => /* @__PURE__ */ jsx(Root, {
17
+ ...rest,
18
+ openDelay,
19
+ closeDelay
20
+ });
21
+ HoverCard.Content = HoverCardContent;
22
+ HoverCard.Trigger = Trigger;
23
+ //#endregion
24
+ export { HoverCard };
25
+
26
+ //# sourceMappingURL=HoverCard-Cf9iYyaW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HoverCard-Cf9iYyaW.js","names":[],"sources":["../src/components/HoverCard/HoverCardContent.tsx","../src/components/HoverCard/HoverCard.tsx"],"sourcesContent":["import type { ComponentProps } from 'react';\nimport { Content, Portal } from '@radix-ui/react-hover-card';\n\nimport { cn } from '../../utils';\n\ntype Props = ComponentProps<typeof Content>;\n\nexport const HoverCardContent = ({\n ref,\n className,\n align = 'center',\n sideOffset = 4,\n children,\n ...props\n}: Props) => (\n <Portal>\n <Content\n ref={ref}\n align={align}\n sideOffset={sideOffset}\n data-slot=\"hover-card-content\"\n className={cn(\n 'tailwindcss-preflight',\n 'tw:z-overlay',\n\n // border\n 'tw:box-border',\n 'tw:border',\n 'tw:rounded-popover',\n\n // sizing\n 'tw:min-w-32',\n 'tw:origin-(--radix-hover-card-content-transform-origin)',\n 'tw:max-h-[var(--radix-hover-card-content-available-height)]',\n\n // padding + shared shadow\n 'tw:p-4',\n 'tw:shadow-md',\n\n // semantic floating-panel tokens\n 'tw:border-solid tw:border-border tw:bg-popover tw:text-popover-foreground',\n\n // directional animations\n 'tw:data-[side=bottom]:slide-in-from-top-2',\n 'tw:data-[side=left]:slide-in-from-right-2',\n 'tw:data-[side=right]:slide-in-from-left-2',\n 'tw:data-[side=top]:slide-in-from-bottom-2',\n\n // animations\n 'tw:data-[state=open]:animate-in',\n 'tw:data-[state=open]:fade-in-0',\n 'tw:data-[state=open]:zoom-in-95',\n 'tw:data-[state=closed]:animate-out',\n 'tw:data-[state=closed]:fade-out-0',\n 'tw:data-[state=closed]:zoom-out-95',\n\n // Default size for nested Lucide icons; callers can override on the icon.\n \"tw:[&_svg.lucide:not([class*='tw:size-'])]:size-4\",\n 'tw:[&_svg]:shrink-0',\n\n className,\n )}\n {...props}\n >\n {children}\n </Content>\n </Portal>\n);\n","import type { ComponentProps } from 'react';\nimport { Root, Trigger } from '@radix-ui/react-hover-card';\n\nimport { HoverCardContent } from './HoverCardContent';\n\ntype Props = ComponentProps<typeof Root>;\n\nexport const HoverCard = ({ openDelay = 200, closeDelay = 200, ...rest }: Props) => (\n <Root {...rest} openDelay={openDelay} closeDelay={closeDelay} />\n);\n\nHoverCard.Content = HoverCardContent;\nHoverCard.Trigger = Trigger;\n"],"mappings":";;;;AAOA,MAAa,oBAAoB,EAC/B,KACA,WACA,QAAQ,UACR,aAAa,GACb,UACA,GAAG,YAEH,oBAAC,QAAD,EAAA,UACE,oBAAC,SAAD;CACO;CACE;CACK;CACZ,aAAU;CACV,WAAW,GACT,yBACA,gBAGA,iBACA,aACA,sBAGA,eACA,2DACA,+DAGA,UACA,gBAGA,6EAGA,6CACA,6CACA,6CACA,6CAGA,mCACA,kCACA,mCACA,sCACA,qCACA,sCAGA,qDACA,uBAEA,SACF;CACA,GAAI;CAEH;AACM,CAAA,EACH,CAAA;;;AC3DV,MAAa,aAAa,EAAE,YAAY,KAAK,aAAa,KAAK,GAAG,WAChE,oBAAC,MAAD;CAAM,GAAI;CAAiB;CAAuB;AAAa,CAAA;AAGjE,UAAU,UAAU;AACpB,UAAU,UAAU"}
@@ -1,7 +1,7 @@
1
1
  import { __exportAll } from "./rolldown-runtime-Bdc48AWt.js";
2
2
  import { DiagramSkeleton } from "./internal/blocks/DiagramShared/DiagramSkeleton.js";
3
3
  import { DiagramSource, makeResponsive } from "./svgTransforms-Hnvev3Vs.js";
4
- import { ZoomableSvg } from "./ZoomableSvg-DnFXo2L4.js";
4
+ import { ZoomableSvg } from "./ZoomableSvg-CxXKanUR.js";
5
5
  import { useThemeAttributes } from "./themeTokens-DCeb62ap.js";
6
6
  import { SERIES_TOKENS, createVegaColorResolver, tierTwoColour } from "./vegaTokens-DCkvpIVE.js";
7
7
  import { createSvgCache, diagramCacheKey } from "./svgCache-Dhmbe-7i.js";
@@ -196,4 +196,4 @@ const MermaidDiagram = ({ code, renderActions }) => {
196
196
  //#endregion
197
197
  export { MermaidDiagram, MermaidDiagram_exports };
198
198
 
199
- //# sourceMappingURL=MermaidDiagram-Te-5gOCU.js.map
199
+ //# sourceMappingURL=MermaidDiagram-2-EuNu1i.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"MermaidDiagram-Te-5gOCU.js","names":[],"sources":["../src/blocks/MermaidDiagram/peleTheme.ts","../src/blocks/MermaidDiagram/MermaidDiagram.tsx"],"sourcesContent":["import type { ResolvedColorScheme } from '../../components/ThemeProvider/types';\nimport { createVegaColorResolver, SERIES_TOKENS, tierTwoColour } from '../../vega/vegaTokens';\n\nexport const DIAGRAM_FONT = 'Inter, system-ui, sans-serif';\n\n/**\n * The `--pele-*` declarations for one scheme, as a `style` attribute fragment.\n *\n * - Resolved colours, not `var()` refs: an exported SVG or PNG has no page CSS to read.\n * - One `getComputedStyle` snapshot per call; never hoist — values follow scheme and brand.\n * - Series 6–8 are the charts' second tier, as in Flint charts.\n */\nexport const peleThemeStyle = (scheme: ResolvedColorScheme, from?: Element | null): string => {\n const token = createVegaColorResolver(scheme, from);\n const series = SERIES_TOKENS.map((name) => token(name));\n\n const vars: Record<string, string> = {\n bg: token('card'),\n fg: token('foreground'),\n muted: token('muted-foreground'),\n line: token('muted-foreground'),\n surface: token('muted'),\n 'surface-alt': token('accent'),\n border: token('border'),\n accent: token('primary'),\n critical: token('destructive'),\n error: token('destructive'),\n font: DIAGRAM_FONT,\n radius: '6px',\n };\n [...series, ...series.map((colour) => tierTwoColour(colour, scheme))]\n .slice(0, 8)\n .forEach((colour, index) => {\n vars[`series-${index + 1}`] = colour;\n });\n\n return Object.entries(vars)\n .map(([name, value]) => `--pele-${name}:${value}`)\n .join(';');\n};\n","import { useEffect, useState } from 'react';\nimport type { ReactNode } from 'react';\nimport type { DiagramType, IconResolver } from 'pele/lazy';\nimport { detectType, load, PeleError, registered, render } from 'pele/lazy';\n\nimport type { ResolvedColorScheme } from '../../components/ThemeProvider/types';\nimport { useThemeAttributes } from '../../components/ThemeProvider/useThemeAttributes';\nimport { ZoomableSvg } from '../../components/ZoomableSvg';\nimport { DiagramSkeleton } from '../DiagramShared/DiagramSkeleton';\nimport { DiagramSource } from '../DiagramShared/DiagramSource';\nimport { createSvgCache, diagramCacheKey } from '../DiagramShared/svgCache';\nimport { makeResponsive } from '../DiagramShared/svgTransforms';\n\nimport { DIAGRAM_FONT, peleThemeStyle } from './peleTheme';\n\ntype IconPack = {\n icons: Record<string, { body: string }>;\n aliases?: Record<string, { parent: string }>;\n};\n\nlet lucidePack: IconPack | null = null;\nlet lucidePromise: Promise<void> | null = null;\n\n// The pack is a lazy local chunk, so no CDN fetch and it works under strict CSP.\nconst loadLucidePack = (): Promise<void> => {\n lucidePromise ??= import('@iconify-json/lucide/icons.json')\n .then((mod) => {\n lucidePack = mod.default;\n })\n .catch((err: unknown) => {\n lucidePromise = null;\n throw err;\n });\n return lucidePromise;\n};\n\n// `lucide:name` refs resolve to the pack's 24×24 stroke body, which is the frame Pele draws.\nconst lucideIcon: IconResolver = (ref) => {\n if (!lucidePack || !ref.startsWith('lucide:')) return null;\n const name = ref.slice('lucide:'.length);\n return (lucidePack.icons[name] ?? lucidePack.icons[lucidePack.aliases?.[name]?.parent ?? ''])\n ?.body;\n};\n\nconst usesLucide = (code: string): boolean => code.includes('lucide:');\n\nconst diagramType = (code: string): DiagramType | null => {\n try {\n return detectType(code);\n } catch (err) {\n console.debug('[MermaidDiagram] no diagram type detected:', err);\n return null;\n }\n};\n\n/**\n * Whether a render error means \"ran out of input\" rather than \"bad syntax\".\n *\n * - A syntax error at the last non-blank character or past it, as in every streaming frame.\n * - No type yet and at most one line after the preamble: the header itself is still arriving.\n * - Lower bound only: a real error on the last character shows as truncated until the grace period.\n */\n// Closed front matter and `%%` directive or comment lines before the type header.\nconst PREAMBLE = /^(?:\\s*---\\n[\\s\\S]*?\\n---[^\\S\\n]*(?:\\n|$)|[^\\S\\n]*%%.*(?:\\n|$)|\\s*\\n)*/;\n\nconst isHeaderArriving = (code: string): boolean => {\n const rest = code.replace(PREAMBLE, '');\n // Front matter whose closing `---` has not arrived yet.\n if (/^\\s*---\\n/.test(rest)) return true;\n return !rest.trim().includes('\\n');\n};\n\nconst isTruncatedDiagram = (err: unknown, code: string): boolean => {\n if (!(err instanceof PeleError)) return false;\n if (err.code === 'unsupported-diagram') return isHeaderArriving(code);\n if (err.code !== 'syntax') return false;\n const tail = code\n .split('\\n')\n .slice(err.line - 1)\n .join('\\n');\n return tail.slice(Math.max(err.column - 1, 0)).trim().length <= 1;\n};\n\n// Longer than the gap between streamed chunks, short enough for an abandoned stream.\nconst TRUNCATION_GRACE_MS = 2_000;\n\nconst svgCache = createSvgCache();\n\n// Every streamed frame shares one theme, so its palette is read once per theme key.\nlet lastTheme = { key: '', style: '' };\nconst themeStyleFor = (themeKey: string, scheme: ResolvedColorScheme, scope: Element | null) => {\n if (lastTheme.key !== themeKey) {\n lastTheme = { key: themeKey, style: peleThemeStyle(scheme, scope) };\n }\n return lastTheme.style;\n};\n\ntype Outcome =\n | { svg: string }\n | { error: unknown; truncated: boolean }\n | { loading: DiagramType | null };\n\ntype Theme = { key: string; scheme: ResolvedColorScheme; scope: Element | null };\n\n/**\n * The diagram for `code`, rendered synchronously.\n *\n * 1. A cached SVG for this code and theme.\n * 2. `loading` while the diagram type's chunk or the icon pack is not loaded yet.\n * 3. A fresh render, or the error Pele threw.\n */\nconst renderNow = (code: string, theme: Theme): Outcome => {\n const cacheKey = diagramCacheKey(code, theme.key);\n const cached = svgCache.get(cacheKey);\n if (cached) return { svg: cached };\n const type = diagramType(code);\n if ((type !== null && !registered(type)) || (usesLucide(code) && lucidePack === null)) {\n return { loading: type };\n }\n try {\n const { svg } = render(code, { fontFamily: DIAGRAM_FONT, icons: lucideIcon });\n const themed = makeResponsive(svg, themeStyleFor(theme.key, theme.scheme, theme.scope));\n svgCache.set(cacheKey, themed);\n return { svg: themed };\n } catch (error) {\n return { error, truncated: isTruncatedDiagram(error, code) };\n }\n};\n\ntype Props = {\n /** Mermaid source. */\n code: string;\n /** Extra toolbar controls forwarded to `ZoomableSvg`; receives the sanitized SVG. */\n renderActions?: (safeSvg: string) => ReactNode;\n};\n\nexport const MermaidDiagram = ({ code, renderActions }: Props) => {\n // - Scheme and key come from one read, so a palette is never cached under the wrong scheme.\n // - `scope` is the element tokens are read off (`null` = `<html>`) and is part of `themeKey`.\n const { scheme, cacheKey: themeKey, scope } = useThemeAttributes();\n const cacheKey = diagramCacheKey(code, themeKey);\n\n const [state, setState] = useState(() => ({\n key: cacheKey,\n outcome: renderNow(code, { key: themeKey, scheme, scope }),\n }));\n const [gaveUpKey, setGaveUpKey] = useState<string | null>(null);\n\n // Render-phase reset avoids a one-frame flash of the previous diagram.\n if (state.key !== cacheKey) {\n setState({ key: cacheKey, outcome: renderNow(code, { key: themeKey, scheme, scope }) });\n }\n const { outcome } = state;\n\n useEffect(() => {\n if (!('loading' in outcome)) return;\n let cancelled = false;\n Promise.all([load(outcome.loading), usesLucide(code) ? loadLucidePack() : null])\n .then(() => renderNow(code, { key: themeKey, scheme, scope }))\n .catch((error: unknown) => ({ error, truncated: false }))\n .then((next) => {\n if (!cancelled) setState({ key: cacheKey, outcome: next });\n });\n return () => {\n cancelled = true;\n };\n }, [outcome, code, cacheKey, themeKey, scheme, scope]);\n\n useEffect(() => {\n if (!('error' in outcome)) return;\n if (!outcome.truncated) {\n console.error('[MermaidDiagram] render failed:', outcome.error);\n return;\n }\n // A streaming diagram is truncated at almost every frame; one that stops arriving shows its source.\n const timer = setTimeout(() => setGaveUpKey(cacheKey), TRUNCATION_GRACE_MS);\n return () => clearTimeout(timer);\n }, [outcome, cacheKey]);\n\n if ('svg' in outcome) {\n return (\n <ZoomableSvg\n key={code}\n html={outcome.svg}\n copyText={`\\`\\`\\`mermaid\\n${code}\\n\\`\\`\\``}\n className=\"tw:my-3\"\n renderActions={renderActions}\n />\n );\n }\n\n if ('error' in outcome && (!outcome.truncated || gaveUpKey === cacheKey)) {\n return <DiagramSource code={code} />;\n }\n\n return <DiagramSkeleton />;\n};\n"],"mappings":";;;;;;;;;;;AAGA,MAAa,eAAe;;;;;;;;AAS5B,MAAa,kBAAkB,QAA6B,SAAkC;CAC5F,MAAM,QAAQ,wBAAwB,QAAQ,IAAI;CAClD,MAAM,SAAS,cAAc,KAAK,SAAS,MAAM,IAAI,CAAC;CAEtD,MAAM,OAA+B;EACnC,IAAI,MAAM,MAAM;EAChB,IAAI,MAAM,YAAY;EACtB,OAAO,MAAM,kBAAkB;EAC/B,MAAM,MAAM,kBAAkB;EAC9B,SAAS,MAAM,OAAO;EACtB,eAAe,MAAM,QAAQ;EAC7B,QAAQ,MAAM,QAAQ;EACtB,QAAQ,MAAM,SAAS;EACvB,UAAU,MAAM,aAAa;EAC7B,OAAO,MAAM,aAAa;EAC1B,MAAM;EACN,QAAQ;CACV;CACA,CAAC,GAAG,QAAQ,GAAG,OAAO,KAAK,WAAW,cAAc,QAAQ,MAAM,CAAC,CAAC,CAAC,CAClE,MAAM,GAAG,CAAC,CAAC,CACX,SAAS,QAAQ,UAAU;EAC1B,KAAK,UAAU,QAAQ,OAAO;CAChC,CAAC;CAEH,OAAO,OAAO,QAAQ,IAAI,CAAC,CACxB,KAAK,CAAC,MAAM,WAAW,UAAU,KAAK,GAAG,OAAO,CAAC,CACjD,KAAK,GAAG;AACb;;;;ACnBA,IAAI,aAA8B;AAClC,IAAI,gBAAsC;AAG1C,MAAM,uBAAsC;CAC1C,kBAAkB,OAAO,kCAAkC,CACxD,MAAM,QAAQ;EACb,aAAa,IAAI;CACnB,CAAC,CAAC,CACD,OAAO,QAAiB;EACvB,gBAAgB;EAChB,MAAM;CACR,CAAC;CACH,OAAO;AACT;AAGA,MAAM,cAA4B,QAAQ;CACxC,IAAI,CAAC,cAAc,CAAC,IAAI,WAAW,SAAS,GAAG,OAAO;CACtD,MAAM,OAAO,IAAI,MAAM,CAAgB;CACvC,QAAQ,WAAW,MAAM,SAAS,WAAW,MAAM,WAAW,UAAU,KAAK,EAAE,UAAU,IAAA,EACrF;AACN;AAEA,MAAM,cAAc,SAA0B,KAAK,SAAS,SAAS;AAErE,MAAM,eAAe,SAAqC;CACxD,IAAI;EACF,OAAO,WAAW,IAAI;CACxB,SAAS,KAAK;EACZ,QAAQ,MAAM,8CAA8C,GAAG;EAC/D,OAAO;CACT;AACF;;;;;;;;AAUA,MAAM,WAAW;AAEjB,MAAM,oBAAoB,SAA0B;CAClD,MAAM,OAAO,KAAK,QAAQ,UAAU,EAAE;CAEtC,IAAI,YAAY,KAAK,IAAI,GAAG,OAAO;CACnC,OAAO,CAAC,KAAK,KAAK,CAAC,CAAC,SAAS,IAAI;AACnC;AAEA,MAAM,sBAAsB,KAAc,SAA0B;CAClE,IAAI,EAAE,eAAe,YAAY,OAAO;CACxC,IAAI,IAAI,SAAS,uBAAuB,OAAO,iBAAiB,IAAI;CACpE,IAAI,IAAI,SAAS,UAAU,OAAO;CAKlC,OAJa,KACV,MAAM,IAAI,CAAC,CACX,MAAM,IAAI,OAAO,CAAC,CAAC,CACnB,KAAK,IACE,CAAC,CAAC,MAAM,KAAK,IAAI,IAAI,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,UAAU;AAClE;AAGA,MAAM,sBAAsB;AAE5B,MAAM,WAAW,eAAe;AAGhC,IAAI,YAAY;CAAE,KAAK;CAAI,OAAO;AAAG;AACrC,MAAM,iBAAiB,UAAkB,QAA6B,UAA0B;CAC9F,IAAI,UAAU,QAAQ,UACpB,YAAY;EAAE,KAAK;EAAU,OAAO,eAAe,QAAQ,KAAK;CAAE;CAEpE,OAAO,UAAU;AACnB;;;;;;;;AAgBA,MAAM,aAAa,MAAc,UAA0B;CACzD,MAAM,WAAW,gBAAgB,MAAM,MAAM,GAAG;CAChD,MAAM,SAAS,SAAS,IAAI,QAAQ;CACpC,IAAI,QAAQ,OAAO,EAAE,KAAK,OAAO;CACjC,MAAM,OAAO,YAAY,IAAI;CAC7B,IAAK,SAAS,QAAQ,CAAC,WAAW,IAAI,KAAO,WAAW,IAAI,KAAK,eAAe,MAC9E,OAAO,EAAE,SAAS,KAAK;CAEzB,IAAI;EACF,MAAM,EAAE,QAAQ,OAAO,MAAM;GAAE,YAAY;GAAc,OAAO;EAAW,CAAC;EAC5E,MAAM,SAAS,eAAe,KAAK,cAAc,MAAM,KAAK,MAAM,QAAQ,MAAM,KAAK,CAAC;EACtF,SAAS,IAAI,UAAU,MAAM;EAC7B,OAAO,EAAE,KAAK,OAAO;CACvB,SAAS,OAAO;EACd,OAAO;GAAE;GAAO,WAAW,mBAAmB,OAAO,IAAI;EAAE;CAC7D;AACF;AASA,MAAa,kBAAkB,EAAE,MAAM,oBAA2B;CAGhE,MAAM,EAAE,QAAQ,UAAU,UAAU,UAAU,mBAAmB;CACjE,MAAM,WAAW,gBAAgB,MAAM,QAAQ;CAE/C,MAAM,CAAC,OAAO,YAAY,gBAAgB;EACxC,KAAK;EACL,SAAS,UAAU,MAAM;GAAE,KAAK;GAAU;GAAQ;EAAM,CAAC;CAC3D,EAAE;CACF,MAAM,CAAC,WAAW,gBAAgB,SAAwB,IAAI;CAG9D,IAAI,MAAM,QAAQ,UAChB,SAAS;EAAE,KAAK;EAAU,SAAS,UAAU,MAAM;GAAE,KAAK;GAAU;GAAQ;EAAM,CAAC;CAAE,CAAC;CAExF,MAAM,EAAE,YAAY;CAEpB,gBAAgB;EACd,IAAI,EAAE,aAAa,UAAU;EAC7B,IAAI,YAAY;EAChB,QAAQ,IAAI,CAAC,KAAK,QAAQ,OAAO,GAAG,WAAW,IAAI,IAAI,eAAe,IAAI,IAAI,CAAC,CAAC,CAC7E,WAAW,UAAU,MAAM;GAAE,KAAK;GAAU;GAAQ;EAAM,CAAC,CAAC,CAAC,CAC7D,OAAO,WAAoB;GAAE;GAAO,WAAW;EAAM,EAAE,CAAC,CACxD,MAAM,SAAS;GACd,IAAI,CAAC,WAAW,SAAS;IAAE,KAAK;IAAU,SAAS;GAAK,CAAC;EAC3D,CAAC;EACH,aAAa;GACX,YAAY;EACd;CACF,GAAG;EAAC;EAAS;EAAM;EAAU;EAAU;EAAQ;CAAK,CAAC;CAErD,gBAAgB;EACd,IAAI,EAAE,WAAW,UAAU;EAC3B,IAAI,CAAC,QAAQ,WAAW;GACtB,QAAQ,MAAM,mCAAmC,QAAQ,KAAK;GAC9D;EACF;EAEA,MAAM,QAAQ,iBAAiB,aAAa,QAAQ,GAAG,mBAAmB;EAC1E,aAAa,aAAa,KAAK;CACjC,GAAG,CAAC,SAAS,QAAQ,CAAC;CAEtB,IAAI,SAAS,SACX,OACE,oBAAC,aAAD;EAEE,MAAM,QAAQ;EACd,UAAU,kBAAkB,KAAK;EACjC,WAAU;EACK;CAChB,GALM,IAKN;CAIL,IAAI,WAAW,YAAY,CAAC,QAAQ,aAAa,cAAc,WAC7D,OAAO,oBAAC,eAAD,EAAqB,KAAO,CAAA;CAGrC,OAAO,oBAAC,iBAAD,CAAkB,CAAA;AAC3B"}
1
+ {"version":3,"file":"MermaidDiagram-2-EuNu1i.js","names":[],"sources":["../src/blocks/MermaidDiagram/peleTheme.ts","../src/blocks/MermaidDiagram/MermaidDiagram.tsx"],"sourcesContent":["import type { ResolvedColorScheme } from '../../components/ThemeProvider/types';\nimport { createVegaColorResolver, SERIES_TOKENS, tierTwoColour } from '../../vega/vegaTokens';\n\nexport const DIAGRAM_FONT = 'Inter, system-ui, sans-serif';\n\n/**\n * The `--pele-*` declarations for one scheme, as a `style` attribute fragment.\n *\n * - Resolved colours, not `var()` refs: an exported SVG or PNG has no page CSS to read.\n * - One `getComputedStyle` snapshot per call; never hoist — values follow scheme and brand.\n * - Series 6–8 are the charts' second tier, as in Flint charts.\n */\nexport const peleThemeStyle = (scheme: ResolvedColorScheme, from?: Element | null): string => {\n const token = createVegaColorResolver(scheme, from);\n const series = SERIES_TOKENS.map((name) => token(name));\n\n const vars: Record<string, string> = {\n bg: token('card'),\n fg: token('foreground'),\n muted: token('muted-foreground'),\n line: token('muted-foreground'),\n surface: token('muted'),\n 'surface-alt': token('accent'),\n border: token('border'),\n accent: token('primary'),\n critical: token('destructive'),\n error: token('destructive'),\n font: DIAGRAM_FONT,\n radius: '6px',\n };\n [...series, ...series.map((colour) => tierTwoColour(colour, scheme))]\n .slice(0, 8)\n .forEach((colour, index) => {\n vars[`series-${index + 1}`] = colour;\n });\n\n return Object.entries(vars)\n .map(([name, value]) => `--pele-${name}:${value}`)\n .join(';');\n};\n","import { useEffect, useState } from 'react';\nimport type { ReactNode } from 'react';\nimport type { DiagramType, IconResolver } from 'pele/lazy';\nimport { detectType, load, PeleError, registered, render } from 'pele/lazy';\n\nimport type { ResolvedColorScheme } from '../../components/ThemeProvider/types';\nimport { useThemeAttributes } from '../../components/ThemeProvider/useThemeAttributes';\nimport { ZoomableSvg } from '../../components/ZoomableSvg';\nimport { DiagramSkeleton } from '../DiagramShared/DiagramSkeleton';\nimport { DiagramSource } from '../DiagramShared/DiagramSource';\nimport { createSvgCache, diagramCacheKey } from '../DiagramShared/svgCache';\nimport { makeResponsive } from '../DiagramShared/svgTransforms';\n\nimport { DIAGRAM_FONT, peleThemeStyle } from './peleTheme';\n\ntype IconPack = {\n icons: Record<string, { body: string }>;\n aliases?: Record<string, { parent: string }>;\n};\n\nlet lucidePack: IconPack | null = null;\nlet lucidePromise: Promise<void> | null = null;\n\n// The pack is a lazy local chunk, so no CDN fetch and it works under strict CSP.\nconst loadLucidePack = (): Promise<void> => {\n lucidePromise ??= import('@iconify-json/lucide/icons.json')\n .then((mod) => {\n lucidePack = mod.default;\n })\n .catch((err: unknown) => {\n lucidePromise = null;\n throw err;\n });\n return lucidePromise;\n};\n\n// `lucide:name` refs resolve to the pack's 24×24 stroke body, which is the frame Pele draws.\nconst lucideIcon: IconResolver = (ref) => {\n if (!lucidePack || !ref.startsWith('lucide:')) return null;\n const name = ref.slice('lucide:'.length);\n return (lucidePack.icons[name] ?? lucidePack.icons[lucidePack.aliases?.[name]?.parent ?? ''])\n ?.body;\n};\n\nconst usesLucide = (code: string): boolean => code.includes('lucide:');\n\nconst diagramType = (code: string): DiagramType | null => {\n try {\n return detectType(code);\n } catch (err) {\n console.debug('[MermaidDiagram] no diagram type detected:', err);\n return null;\n }\n};\n\n/**\n * Whether a render error means \"ran out of input\" rather than \"bad syntax\".\n *\n * - A syntax error at the last non-blank character or past it, as in every streaming frame.\n * - No type yet and at most one line after the preamble: the header itself is still arriving.\n * - Lower bound only: a real error on the last character shows as truncated until the grace period.\n */\n// Closed front matter and `%%` directive or comment lines before the type header.\nconst PREAMBLE = /^(?:\\s*---\\n[\\s\\S]*?\\n---[^\\S\\n]*(?:\\n|$)|[^\\S\\n]*%%.*(?:\\n|$)|\\s*\\n)*/;\n\nconst isHeaderArriving = (code: string): boolean => {\n const rest = code.replace(PREAMBLE, '');\n // Front matter whose closing `---` has not arrived yet.\n if (/^\\s*---\\n/.test(rest)) return true;\n return !rest.trim().includes('\\n');\n};\n\nconst isTruncatedDiagram = (err: unknown, code: string): boolean => {\n if (!(err instanceof PeleError)) return false;\n if (err.code === 'unsupported-diagram') return isHeaderArriving(code);\n if (err.code !== 'syntax') return false;\n const tail = code\n .split('\\n')\n .slice(err.line - 1)\n .join('\\n');\n return tail.slice(Math.max(err.column - 1, 0)).trim().length <= 1;\n};\n\n// Longer than the gap between streamed chunks, short enough for an abandoned stream.\nconst TRUNCATION_GRACE_MS = 2_000;\n\nconst svgCache = createSvgCache();\n\n// Every streamed frame shares one theme, so its palette is read once per theme key.\nlet lastTheme = { key: '', style: '' };\nconst themeStyleFor = (themeKey: string, scheme: ResolvedColorScheme, scope: Element | null) => {\n if (lastTheme.key !== themeKey) {\n lastTheme = { key: themeKey, style: peleThemeStyle(scheme, scope) };\n }\n return lastTheme.style;\n};\n\ntype Outcome =\n | { svg: string }\n | { error: unknown; truncated: boolean }\n | { loading: DiagramType | null };\n\ntype Theme = { key: string; scheme: ResolvedColorScheme; scope: Element | null };\n\n/**\n * The diagram for `code`, rendered synchronously.\n *\n * 1. A cached SVG for this code and theme.\n * 2. `loading` while the diagram type's chunk or the icon pack is not loaded yet.\n * 3. A fresh render, or the error Pele threw.\n */\nconst renderNow = (code: string, theme: Theme): Outcome => {\n const cacheKey = diagramCacheKey(code, theme.key);\n const cached = svgCache.get(cacheKey);\n if (cached) return { svg: cached };\n const type = diagramType(code);\n if ((type !== null && !registered(type)) || (usesLucide(code) && lucidePack === null)) {\n return { loading: type };\n }\n try {\n const { svg } = render(code, { fontFamily: DIAGRAM_FONT, icons: lucideIcon });\n const themed = makeResponsive(svg, themeStyleFor(theme.key, theme.scheme, theme.scope));\n svgCache.set(cacheKey, themed);\n return { svg: themed };\n } catch (error) {\n return { error, truncated: isTruncatedDiagram(error, code) };\n }\n};\n\ntype Props = {\n /** Mermaid source. */\n code: string;\n /** Extra toolbar controls forwarded to `ZoomableSvg`; receives the sanitized SVG. */\n renderActions?: (safeSvg: string) => ReactNode;\n};\n\nexport const MermaidDiagram = ({ code, renderActions }: Props) => {\n // - Scheme and key come from one read, so a palette is never cached under the wrong scheme.\n // - `scope` is the element tokens are read off (`null` = `<html>`) and is part of `themeKey`.\n const { scheme, cacheKey: themeKey, scope } = useThemeAttributes();\n const cacheKey = diagramCacheKey(code, themeKey);\n\n const [state, setState] = useState(() => ({\n key: cacheKey,\n outcome: renderNow(code, { key: themeKey, scheme, scope }),\n }));\n const [gaveUpKey, setGaveUpKey] = useState<string | null>(null);\n\n // Render-phase reset avoids a one-frame flash of the previous diagram.\n if (state.key !== cacheKey) {\n setState({ key: cacheKey, outcome: renderNow(code, { key: themeKey, scheme, scope }) });\n }\n const { outcome } = state;\n\n useEffect(() => {\n if (!('loading' in outcome)) return;\n let cancelled = false;\n Promise.all([load(outcome.loading), usesLucide(code) ? loadLucidePack() : null])\n .then(() => renderNow(code, { key: themeKey, scheme, scope }))\n .catch((error: unknown) => ({ error, truncated: false }))\n .then((next) => {\n if (!cancelled) setState({ key: cacheKey, outcome: next });\n });\n return () => {\n cancelled = true;\n };\n }, [outcome, code, cacheKey, themeKey, scheme, scope]);\n\n useEffect(() => {\n if (!('error' in outcome)) return;\n if (!outcome.truncated) {\n console.error('[MermaidDiagram] render failed:', outcome.error);\n return;\n }\n // A streaming diagram is truncated at almost every frame; one that stops arriving shows its source.\n const timer = setTimeout(() => setGaveUpKey(cacheKey), TRUNCATION_GRACE_MS);\n return () => clearTimeout(timer);\n }, [outcome, cacheKey]);\n\n if ('svg' in outcome) {\n return (\n <ZoomableSvg\n key={code}\n html={outcome.svg}\n copyText={`\\`\\`\\`mermaid\\n${code}\\n\\`\\`\\``}\n className=\"tw:my-3\"\n renderActions={renderActions}\n />\n );\n }\n\n if ('error' in outcome && (!outcome.truncated || gaveUpKey === cacheKey)) {\n return <DiagramSource code={code} />;\n }\n\n return <DiagramSkeleton />;\n};\n"],"mappings":"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"}