@devslab/dds-react 0.23.0 → 0.25.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 (62) hide show
  1. package/README.ko.md +3 -2
  2. package/README.md +3 -2
  3. package/dist/calendar-view-BxjCQV9k.js +119 -0
  4. package/dist/calendar-view-BxjCQV9k.js.map +1 -0
  5. package/dist/calendar-view.d.ts +11 -1
  6. package/dist/calendar-view.d.ts.map +1 -1
  7. package/dist/calendar.js +5 -4
  8. package/dist/calendar.js.map +1 -1
  9. package/dist/choice-N-5K_ggs.js +309 -0
  10. package/dist/choice-N-5K_ggs.js.map +1 -0
  11. package/dist/choice-types-kSaEnZPr.js +23 -0
  12. package/dist/choice-types-kSaEnZPr.js.map +1 -0
  13. package/dist/combobox.js +1 -1
  14. package/dist/date-only-Bu4UmsTP.js +151 -0
  15. package/dist/date-only-Bu4UmsTP.js.map +1 -0
  16. package/dist/date-only.d.ts +92 -0
  17. package/dist/date-only.d.ts.map +1 -1
  18. package/dist/date-picker.js +69 -68
  19. package/dist/date-picker.js.map +1 -1
  20. package/dist/date-range-picker.d.ts +41 -0
  21. package/dist/date-range-picker.d.ts.map +1 -0
  22. package/dist/date-range-picker.js +327 -0
  23. package/dist/date-range-picker.js.map +1 -0
  24. package/dist/direction-DbZcVPsZ.js +21 -0
  25. package/dist/direction-DbZcVPsZ.js.map +1 -0
  26. package/dist/direction.d.ts +5 -0
  27. package/dist/direction.d.ts.map +1 -0
  28. package/dist/index.d.ts +5 -0
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +108 -103
  31. package/dist/index.js.map +1 -1
  32. package/dist/input.d.ts.map +1 -1
  33. package/dist/input.js +1 -1
  34. package/dist/input.js.map +1 -1
  35. package/dist/internal/choice.d.ts +27 -3
  36. package/dist/internal/choice.d.ts.map +1 -1
  37. package/dist/month-picker.d.ts +33 -0
  38. package/dist/month-picker.d.ts.map +1 -0
  39. package/dist/month-picker.js +242 -0
  40. package/dist/month-picker.js.map +1 -0
  41. package/dist/number-input.d.ts +53 -0
  42. package/dist/number-input.d.ts.map +1 -0
  43. package/dist/number-input.js +254 -0
  44. package/dist/number-input.js.map +1 -0
  45. package/dist/segmented-control.d.ts +40 -0
  46. package/dist/segmented-control.d.ts.map +1 -0
  47. package/dist/segmented-control.js +73 -0
  48. package/dist/segmented-control.js.map +1 -0
  49. package/dist/select-picker.js +1 -1
  50. package/dist/time-only.d.ts +32 -0
  51. package/dist/time-only.d.ts.map +1 -0
  52. package/dist/time-picker-BQ7BT6-u.js +100 -0
  53. package/dist/time-picker-BQ7BT6-u.js.map +1 -0
  54. package/dist/time-picker.d.ts +34 -0
  55. package/dist/time-picker.d.ts.map +1 -0
  56. package/dist/time-picker.js +2 -0
  57. package/package.json +29 -4
  58. package/styles.css +31 -1
  59. package/dist/calendar-view-I_sNlioP.js +0 -145
  60. package/dist/calendar-view-I_sNlioP.js.map +0 -1
  61. package/dist/choice-B3vNMfKK.js +0 -300
  62. package/dist/choice-B3vNMfKK.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"date-picker.js","names":[],"sources":["../src/date-picker.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport {\n DatePicker as ArkDatePicker,\n parseDate,\n} from \"@ark-ui/react/date-picker\";\nimport { Portal } from \"@ark-ui/react/portal\";\nimport { Button, Field } from \"./controls\";\nimport { CalendarView } from \"./calendar-view\";\nimport {\n isCalendarDate,\n isKorean,\n displayDate,\n canonicalInput,\n validateInput,\n dateMessages,\n type CalendarMessages,\n type DatePickerValidity,\n} from \"./date-only\";\nexport type { DatePickerValidity, CalendarMessages } from \"./date-only\";\n\nexport interface DatePickerProps {\n label: string;\n /** ISO calendar date (YYYY-MM-DD), or an empty string. */\n value: string;\n onChange: (value: string) => void;\n locale?: string;\n timeZone?: string;\n disabled?: boolean;\n readOnly?: boolean;\n required?: boolean;\n /** Initial mount and semantic draft changes, deduped across callback identity changes. Key by editor identity for a fresh initial report. Button/API saves must guard validity and use its canonical value. */\n onValidityChange?: (state: DatePickerValidity) => void;\n min?: string;\n max?: string;\n startOfWeek?: 0 | 1 | 2 | 3 | 4 | 5 | 6;\n labelPlacement?: \"outside\" | \"inside\" | \"hidden\";\n messages?: CalendarMessages;\n clearable?: boolean;\n showToday?: boolean;\n}\nfunction CalendarIcon() {\n return (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n aria-hidden=\"true\"\n >\n <rect x=\"3.5\" y=\"5.5\" width=\"17\" height=\"15\" rx=\"2\" />\n <path d=\"M7.5 3v5M16.5 3v5M3.5 10.5h17\" />\n </svg>\n );\n}\nfunction calendarSelection(value: string) {\n return isCalendarDate(value) ? [parseDate(value)] : [];\n}\n\nexport function DatePicker({\n label,\n value,\n onChange,\n locale = \"ko-KR\",\n timeZone = \"Asia/Seoul\",\n disabled = false,\n readOnly = false,\n required = false,\n onValidityChange,\n min,\n max,\n startOfWeek = 0,\n labelPlacement = \"outside\",\n messages,\n clearable = true,\n showToday = true,\n}: DatePickerProps) {\n const [draft, setDraft] = useState(() => displayDate(value, locale));\n const [selection, setSelection] = useState(() => calendarSelection(value));\n const [open, setOpen] = useState(false);\n const inputRef = useRef<HTMLInputElement>(null);\n const triggerRef = useRef<HTMLButtonElement>(null);\n const escapeFrame = useRef<number | undefined>(undefined);\n useEffect(\n () => () => {\n if (escapeFrame.current !== undefined)\n cancelAnimationFrame(escapeFrame.current);\n },\n [],\n );\n const [portalMount, setPortalMount] = useState<HTMLElement | null>(null);\n useEffect(() => {\n const input = inputRef.current;\n if (input) {\n // A modal hides its body siblings from assistive technology. Keep the\n // calendar within that modal while preserving the server Portal boundary.\n setPortalMount(\n input.closest<HTMLElement>('[role=\"dialog\"], [role=\"alertdialog\"]') ??\n input.ownerDocument.body,\n );\n }\n }, []);\n const restoreInputFocus = useRef(false);\n const observedValue = useRef(value);\n const observedLocale = useRef(locale);\n // Every outstanding emission is retained, including repeated B/C/B values.\n // Entries end on acknowledgement, an unmatched external reset, or unmount.\n const pendingEchoes = useRef<string[]>([]);\n const emittedValue = useRef(value);\n const notified = useRef(\"\");\n // Convert a complete draft before reporting validity in the new locale.\n const canonicalDraft = canonicalInput(draft, observedLocale.current);\n const effectiveDraft =\n observedLocale.current !== locale && isCalendarDate(canonicalDraft)\n ? displayDate(canonicalDraft, locale)\n : draft;\n const validity = validateInput(effectiveDraft, required, min, max, locale);\n const text = dateMessages(locale, messages);\n const error = validity.valid\n ? undefined\n : validity.reason === \"required\"\n ? text.required\n : text.invalid;\n useEffect(() => {\n const previousLocale = observedLocale.current;\n observedLocale.current = locale;\n if (observedValue.current === value) {\n if (previousLocale !== locale) setDraft(effectiveDraft);\n return;\n }\n observedValue.current = value;\n // A matched outstanding value is an acknowledgement, not a draft reset.\n const acknowledged = pendingEchoes.current.indexOf(value);\n if (acknowledged !== -1) {\n pendingEchoes.current.splice(acknowledged, 1);\n return;\n }\n pendingEchoes.current = [];\n emittedValue.current = value;\n setDraft(displayDate(value, locale));\n if (value === \"\" || isCalendarDate(value))\n setSelection(calendarSelection(value));\n }, [value, locale]);\n useEffect(() => {\n inputRef.current?.setCustomValidity(error ?? \"\");\n const key = JSON.stringify(validity);\n if (onValidityChange && notified.current !== key) {\n notified.current = key;\n onValidityChange(validity);\n }\n }, [draft, required, min, max, locale, error, onValidityChange]);\n useEffect(() => {\n if (disabled || readOnly) {\n restoreInputFocus.current = false;\n setOpen(false);\n }\n }, [disabled, readOnly]);\n // Ark's calendar restores focus to its trigger when it does not own an Input.\n // Return to the DDS input after that calendar frame; cancel on lock/unmount.\n useEffect(() => {\n if (!restoreInputFocus.current || disabled || readOnly) return;\n const frame = requestAnimationFrame(() => {\n restoreInputFocus.current = false;\n inputRef.current?.focus({ preventScroll: true });\n });\n return () => cancelAnimationFrame(frame);\n }, [open, selection, disabled, readOnly]);\n function commit(next: string) {\n const state = validateInput(next, required, min, max, locale);\n if (next !== \"\" && !state.valid) return;\n const canonical = next === \"\" ? \"\" : state.value!;\n setSelection(calendarSelection(canonical));\n // Blur/Enter must not emit the same local commit again while props lag.\n if (canonical !== emittedValue.current) {\n emittedValue.current = canonical;\n pendingEchoes.current.push(canonical);\n onChange(canonical);\n }\n }\n function changeDraft(next: string) {\n setDraft(next);\n const state = validateInput(next, required, min, max, locale);\n // Native form submission and callback-based saves both see this edit.\n inputRef.current?.setCustomValidity(\n state.valid ? \"\" : (error ?? \"Enter a valid date (YYYY-MM-DD).\"),\n );\n if (next === \"\" || state.valid) {\n setDraft(displayDate(state.value ?? \"\", locale));\n commit(next);\n }\n }\n return (\n <Field\n label={label}\n required={required}\n error={error}\n className={`dds-date-picker dds-date-picker--${labelPlacement}`}\n data-filled={effectiveDraft !== \"\" ? \"true\" : undefined}\n >\n {(control) => (\n <ArkDatePicker.Root\n locale={locale}\n timeZone={timeZone}\n disabled={disabled}\n readOnly={readOnly}\n required={required}\n invalid={!validity.valid}\n open={open && !disabled && !readOnly}\n onOpenChange={(details) =>\n setOpen(details.open && !disabled && !readOnly)\n }\n min={min && isCalendarDate(min) ? parseDate(min) : undefined}\n max={max && isCalendarDate(max) ? parseDate(max) : undefined}\n startOfWeek={startOfWeek}\n minView=\"day\"\n maxView=\"day\"\n fixedWeeks\n translations={{\n dayCell: (state) => text.selectDate(state.valueText),\n clearTrigger: text.clear,\n }}\n value={selection}\n format={(v) => displayDate(v.toString(), locale)}\n onValueChange={(details) => {\n const next = details.value[0]?.toString() || \"\";\n if (\n next !== \"\" &&\n !validateInput(next, required, min, max, locale).valid\n )\n return;\n restoreInputFocus.current = true;\n setDraft(displayDate(next, locale));\n commit(next);\n }}\n positioning={{\n placement: \"bottom-start\",\n gutter: 8,\n strategy: portalMount?.matches(\n '[role=\"dialog\"], [role=\"alertdialog\"]',\n )\n ? \"fixed\"\n : \"absolute\",\n hideWhenDetached: !!portalMount?.matches(\n '[role=\"dialog\"], [role=\"alertdialog\"]',\n ),\n }}\n >\n {/* DDS owns the raw text input; Ark owns calendar interaction, not draft DOM writes. */}\n <ArkDatePicker.Control className=\"dds-date-picker-control\">\n <input\n {...control}\n ref={inputRef}\n type=\"text\"\n value={effectiveDraft}\n onChange={() => {}}\n required={required}\n readOnly={readOnly}\n disabled={disabled}\n placeholder={isKorean(locale) ? \"YYYY/MM/DD\" : \"YYYY-MM-DD\"}\n autoComplete=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n onInputCapture={(event) => {\n if (disabled || readOnly) return;\n event.stopPropagation();\n changeDraft(event.currentTarget.value);\n }}\n onBlur={() => {\n if (!disabled && !readOnly) commit(effectiveDraft);\n }}\n onKeyDownCapture={(event) => {\n if (event.key === \"Enter\" && !event.nativeEvent.isComposing) {\n event.preventDefault();\n event.stopPropagation();\n if (!disabled && !readOnly) commit(effectiveDraft);\n }\n }}\n />\n <ArkDatePicker.Trigger asChild>\n <Button\n ref={triggerRef}\n type=\"button\"\n tone=\"secondary\"\n aria-label={`${label} ${text.openCalendar}`}\n >\n <CalendarIcon />\n </Button>\n </ArkDatePicker.Trigger>\n </ArkDatePicker.Control>\n <Portal\n container={portalMount ? { current: portalMount } : undefined}\n >\n <ArkDatePicker.Positioner className=\"dds-date-picker-positioner\">\n <ArkDatePicker.Content\n onKeyDownCapture={(event) => {\n if (event.key !== \"Escape\") return;\n restoreInputFocus.current = false;\n if (escapeFrame.current !== undefined)\n cancelAnimationFrame(escapeFrame.current);\n escapeFrame.current = requestAnimationFrame(() => {\n escapeFrame.current = requestAnimationFrame(() => {\n if (!disabled && !readOnly)\n triggerRef.current?.focus({ preventScroll: true });\n });\n });\n }}\n className=\"dds-date-picker-content\"\n aria-label={`${label} 날짜 선택`}\n >\n <CalendarView\n timeZone={timeZone}\n min={min}\n max={max}\n locale={locale}\n messages={messages}\n disabled={disabled}\n readOnly={readOnly}\n showToday={showToday}\n showClear={clearable}\n onClear={() => {\n setDraft(\"\");\n commit(\"\");\n }}\n />\n </ArkDatePicker.Content>\n </ArkDatePicker.Positioner>\n </Portal>\n </ArkDatePicker.Root>\n )}\n </Field>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"date-picker.js","names":[],"sources":["../src/date-picker.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport {\n DatePicker as ArkDatePicker,\n parseDate,\n} from \"@ark-ui/react/date-picker\";\nimport { Portal } from \"@ark-ui/react/portal\";\nimport { Button, Field } from \"./controls\";\nimport { CalendarView } from \"./calendar-view\";\nimport {\n isCalendarDate,\n isKorean,\n displayDate,\n canonicalInput,\n validateInput,\n dateMessages,\n type CalendarMessages,\n type DatePickerValidity,\n} from \"./date-only\";\nexport type { DatePickerValidity, CalendarMessages } from \"./date-only\";\n\nexport interface DatePickerProps {\n label: string;\n /** ISO calendar date (YYYY-MM-DD), or an empty string. */\n value: string;\n onChange: (value: string) => void;\n locale?: string;\n timeZone?: string;\n disabled?: boolean;\n readOnly?: boolean;\n required?: boolean;\n /** Initial mount and semantic draft changes, deduped across callback identity changes. Key by editor identity for a fresh initial report. Button/API saves must guard validity and use its canonical value. */\n onValidityChange?: (state: DatePickerValidity) => void;\n min?: string;\n max?: string;\n startOfWeek?: 0 | 1 | 2 | 3 | 4 | 5 | 6;\n labelPlacement?: \"outside\" | \"inside\" | \"hidden\";\n messages?: CalendarMessages;\n clearable?: boolean;\n showToday?: boolean;\n}\nfunction CalendarIcon() {\n return (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n aria-hidden=\"true\"\n >\n <rect x=\"3.5\" y=\"5.5\" width=\"17\" height=\"15\" rx=\"2\" />\n <path d=\"M7.5 3v5M16.5 3v5M3.5 10.5h17\" />\n </svg>\n );\n}\nfunction calendarSelection(value: string) {\n return isCalendarDate(value) ? [parseDate(value)] : [];\n}\n\nexport function DatePicker({\n label,\n value,\n onChange,\n locale = \"ko-KR\",\n timeZone = \"Asia/Seoul\",\n disabled = false,\n readOnly = false,\n required = false,\n onValidityChange,\n min,\n max,\n startOfWeek = 0,\n labelPlacement = \"outside\",\n messages,\n clearable = true,\n showToday = true,\n}: DatePickerProps) {\n const [draft, setDraft] = useState(() => displayDate(value, locale));\n const [selection, setSelection] = useState(() => calendarSelection(value));\n const [open, setOpen] = useState(false);\n const inputRef = useRef<HTMLInputElement>(null);\n const triggerRef = useRef<HTMLButtonElement>(null);\n const escapeFrame = useRef<number | undefined>(undefined);\n useEffect(\n () => () => {\n if (escapeFrame.current !== undefined)\n cancelAnimationFrame(escapeFrame.current);\n },\n [],\n );\n const [portalMount, setPortalMount] = useState<HTMLElement | null>(null);\n useEffect(() => {\n const input = inputRef.current;\n if (input) {\n // A modal hides its body siblings from assistive technology. Keep the\n // calendar within that modal while preserving the server Portal boundary.\n setPortalMount(\n input.closest<HTMLElement>('[role=\"dialog\"], [role=\"alertdialog\"]') ??\n input.ownerDocument.body,\n );\n }\n }, []);\n const restoreInputFocus = useRef(false);\n const observedValue = useRef(value);\n const observedLocale = useRef(locale);\n // Every outstanding emission is retained, including repeated B/C/B values.\n // Entries end on acknowledgement, an unmatched external reset, or unmount.\n const pendingEchoes = useRef<string[]>([]);\n const emittedValue = useRef(value);\n const notified = useRef(\"\");\n // Convert a complete draft before reporting validity in the new locale.\n const canonicalDraft = canonicalInput(draft, observedLocale.current);\n const effectiveDraft =\n observedLocale.current !== locale && isCalendarDate(canonicalDraft)\n ? displayDate(canonicalDraft, locale)\n : draft;\n const validity = validateInput(effectiveDraft, required, min, max, locale);\n const text = dateMessages(locale, messages);\n const error = validity.valid\n ? undefined\n : validity.reason === \"required\"\n ? text.required\n : text.invalid;\n useEffect(() => {\n const previousLocale = observedLocale.current;\n observedLocale.current = locale;\n if (observedValue.current === value) {\n if (previousLocale !== locale) setDraft(effectiveDraft);\n return;\n }\n observedValue.current = value;\n // A matched outstanding value is an acknowledgement, not a draft reset.\n const acknowledged = pendingEchoes.current.indexOf(value);\n if (acknowledged !== -1) {\n pendingEchoes.current.splice(acknowledged, 1);\n return;\n }\n pendingEchoes.current = [];\n emittedValue.current = value;\n setDraft(displayDate(value, locale));\n if (value === \"\" || isCalendarDate(value))\n setSelection(calendarSelection(value));\n }, [value, locale]);\n useEffect(() => {\n inputRef.current?.setCustomValidity(error ?? \"\");\n const key = JSON.stringify(validity);\n if (onValidityChange && notified.current !== key) {\n notified.current = key;\n onValidityChange(validity);\n }\n }, [draft, required, min, max, locale, error, onValidityChange]);\n useEffect(() => {\n if (disabled || readOnly) {\n restoreInputFocus.current = false;\n setOpen(false);\n }\n }, [disabled, readOnly]);\n // Ark's calendar restores focus to its trigger when it does not own an Input.\n // Return to the DDS input after that calendar frame; cancel on lock/unmount.\n useEffect(() => {\n if (!restoreInputFocus.current || disabled || readOnly) return;\n const frame = requestAnimationFrame(() => {\n restoreInputFocus.current = false;\n inputRef.current?.focus({ preventScroll: true });\n });\n return () => cancelAnimationFrame(frame);\n }, [open, selection, disabled, readOnly]);\n function commit(next: string) {\n const state = validateInput(next, required, min, max, locale);\n if (next !== \"\" && !state.valid) return;\n const canonical = next === \"\" ? \"\" : state.value!;\n setSelection(calendarSelection(canonical));\n // Blur/Enter must not emit the same local commit again while props lag.\n if (canonical !== emittedValue.current) {\n emittedValue.current = canonical;\n pendingEchoes.current.push(canonical);\n onChange(canonical);\n }\n }\n function changeDraft(next: string) {\n setDraft(next);\n const state = validateInput(next, required, min, max, locale);\n // Native form submission and callback-based saves both see this edit.\n inputRef.current?.setCustomValidity(\n state.valid ? \"\" : (error ?? \"Enter a valid date (YYYY-MM-DD).\"),\n );\n if (next === \"\" || state.valid) {\n setDraft(displayDate(state.value ?? \"\", locale));\n commit(next);\n }\n }\n return (\n <Field\n label={label}\n required={required}\n error={error}\n className={`dds-date-picker dds-date-picker--${labelPlacement}`}\n data-filled={effectiveDraft !== \"\" ? \"true\" : undefined}\n >\n {(control) => (\n <ArkDatePicker.Root\n locale={locale}\n timeZone={timeZone}\n disabled={disabled}\n readOnly={readOnly}\n required={required}\n invalid={!validity.valid}\n open={open && !disabled && !readOnly}\n onOpenChange={(details) =>\n setOpen(details.open && !disabled && !readOnly)\n }\n min={min && isCalendarDate(min) ? parseDate(min) : undefined}\n max={max && isCalendarDate(max) ? parseDate(max) : undefined}\n startOfWeek={startOfWeek}\n minView=\"day\"\n maxView=\"day\"\n fixedWeeks\n translations={{\n dayCell: (state) => text.selectDate(state.valueText),\n clearTrigger: text.clear,\n }}\n value={selection}\n format={(v) => displayDate(v.toString(), locale)}\n onValueChange={(details) => {\n const next = details.value[0]?.toString() || \"\";\n if (\n next !== \"\" &&\n !validateInput(next, required, min, max, locale).valid\n )\n return;\n restoreInputFocus.current = true;\n setDraft(displayDate(next, locale));\n commit(next);\n }}\n positioning={{\n placement: \"bottom-start\",\n gutter: 8,\n strategy: portalMount?.matches(\n '[role=\"dialog\"], [role=\"alertdialog\"]',\n )\n ? \"fixed\"\n : \"absolute\",\n hideWhenDetached: !!portalMount?.matches(\n '[role=\"dialog\"], [role=\"alertdialog\"]',\n ),\n }}\n >\n {/* DDS owns the raw text input; Ark owns calendar interaction, not draft DOM writes. */}\n <ArkDatePicker.Control className=\"dds-date-picker-control\">\n <input\n {...control}\n ref={inputRef}\n type=\"text\"\n value={effectiveDraft}\n onChange={() => {}}\n required={required}\n readOnly={readOnly}\n disabled={disabled}\n placeholder={isKorean(locale) ? \"YYYY/MM/DD\" : \"YYYY-MM-DD\"}\n autoComplete=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n onInputCapture={(event) => {\n if (disabled || readOnly) return;\n event.stopPropagation();\n changeDraft(event.currentTarget.value);\n }}\n onBlur={() => {\n if (!disabled && !readOnly) commit(effectiveDraft);\n }}\n onKeyDownCapture={(event) => {\n if (event.key === \"Enter\" && !event.nativeEvent.isComposing) {\n event.preventDefault();\n event.stopPropagation();\n if (!disabled && !readOnly) commit(effectiveDraft);\n }\n }}\n />\n <ArkDatePicker.Trigger asChild>\n <Button\n ref={triggerRef}\n type=\"button\"\n tone=\"secondary\"\n aria-label={`${label} ${text.openCalendar}`}\n >\n <CalendarIcon />\n </Button>\n </ArkDatePicker.Trigger>\n </ArkDatePicker.Control>\n <Portal\n container={portalMount ? { current: portalMount } : undefined}\n >\n <ArkDatePicker.Positioner className=\"dds-date-picker-positioner\">\n <ArkDatePicker.Content\n onKeyDownCapture={(event) => {\n if (event.key !== \"Escape\") return;\n restoreInputFocus.current = false;\n if (escapeFrame.current !== undefined)\n cancelAnimationFrame(escapeFrame.current);\n escapeFrame.current = requestAnimationFrame(() => {\n escapeFrame.current = requestAnimationFrame(() => {\n if (!disabled && !readOnly)\n triggerRef.current?.focus({ preventScroll: true });\n });\n });\n }}\n className=\"dds-date-picker-content\"\n aria-label={`${label} 날짜 선택`}\n >\n <CalendarView\n timeZone={timeZone}\n min={min}\n max={max}\n locale={locale}\n messages={messages}\n disabled={disabled}\n readOnly={readOnly}\n showToday={showToday}\n showClear={clearable}\n onClear={() => {\n setDraft(\"\");\n commit(\"\");\n }}\n />\n </ArkDatePicker.Content>\n </ArkDatePicker.Positioner>\n </Portal>\n </ArkDatePicker.Root>\n )}\n </Field>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ import { type DateRange, type DateRangeMessages } from "./date-only";
2
+ export type { DateRange, DateRangeMessages, DateRangeValidity, } from "./date-only";
3
+ /** A consumer-supplied shortcut shown in the calendar footer. DDS ships no built-in list. */
4
+ export interface DateRangePreset {
5
+ label: string;
6
+ value: DateRange;
7
+ }
8
+ export interface DateRangePickerProps {
9
+ label?: string;
10
+ /** Two inputs share one field label; "inside" is not offered. */
11
+ labelPlacement?: "outside" | "hidden";
12
+ "aria-label"?: string;
13
+ "aria-labelledby"?: string;
14
+ "aria-describedby"?: string;
15
+ /** Id of the start input; the end input receives `${id}-end`. */
16
+ id?: string;
17
+ value?: DateRange;
18
+ defaultValue?: DateRange;
19
+ /** Called on user changes only, with YYYY-MM-DD or "" on each side; never with start after end. */
20
+ onValueChange?: (next: DateRange) => void;
21
+ locale?: string;
22
+ timeZone?: string;
23
+ min?: string;
24
+ max?: string;
25
+ startOfWeek?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
26
+ messages?: DateRangeMessages;
27
+ clearable?: boolean;
28
+ presets?: DateRangePreset[];
29
+ /** Both dates are required. */
30
+ required?: boolean;
31
+ disabled?: boolean;
32
+ readOnly?: boolean;
33
+ invalid?: boolean;
34
+ /** Form field name submitting the start date (YYYY-MM-DD or ""). */
35
+ startName?: string;
36
+ /** Form field name submitting the end date (YYYY-MM-DD or ""). */
37
+ endName?: string;
38
+ form?: string;
39
+ }
40
+ export declare function DateRangePicker(props: DateRangePickerProps): import("react").JSX.Element;
41
+ //# sourceMappingURL=date-range-picker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date-range-picker.d.ts","sourceRoot":"","sources":["../src/date-range-picker.tsx"],"names":[],"mappings":"AAeA,OAAO,EAOL,KAAK,SAAS,EACd,KAAK,iBAAiB,EACvB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,SAAS,EACT,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,aAAa,CAAC;AAErB,6FAA6F;AAC7F,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,SAAS,CAAC;CAClB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,cAAc,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iEAAiE;IACjE,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,mGAAmG;IACnG,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACxC,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;IAC5B,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kEAAkE;IAClE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAmCD,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,+BA2b1D"}
@@ -0,0 +1,327 @@
1
+ import { t as e } from "./controls-BajigKUv.js";
2
+ import { c as t, d as n, h as r, i, o as a, t as o } from "./date-only-Bu4UmsTP.js";
3
+ import { t as ee } from "./calendar-view-BxjCQV9k.js";
4
+ import { useEffect as s, useId as te, useRef as c, useState as l } from "react";
5
+ import { jsx as u, jsxs as d } from "react/jsx-runtime";
6
+ import { Portal as ne } from "@ark-ui/react/portal";
7
+ import { DatePicker as f, parseDate as p } from "@ark-ui/react/date-picker";
8
+ //#region src/date-range-picker.tsx
9
+ var m = {
10
+ start: "",
11
+ end: ""
12
+ }, re = (e, t) => e.start === t.start && e.end === t.end, h = (...e) => e.filter(Boolean).join(" ") || void 0;
13
+ function g(e) {
14
+ if (!a(e.start)) return [];
15
+ let t = p(e.start);
16
+ return a(e.end) && e.start <= e.end ? [t, p(e.end)] : [t];
17
+ }
18
+ function ie() {
19
+ return /* @__PURE__ */ d("svg", {
20
+ width: "20",
21
+ height: "20",
22
+ viewBox: "0 0 24 24",
23
+ fill: "none",
24
+ stroke: "currentColor",
25
+ strokeWidth: "1.5",
26
+ "aria-hidden": "true",
27
+ children: [/* @__PURE__ */ u("rect", {
28
+ x: "3.5",
29
+ y: "5.5",
30
+ width: "17",
31
+ height: "15",
32
+ rx: "2"
33
+ }), /* @__PURE__ */ u("path", { d: "M7.5 3v5M16.5 3v5M3.5 10.5h17" })]
34
+ });
35
+ }
36
+ function _(_) {
37
+ let v = _.locale ?? "ko-KR", ae = te(), y = _.id ?? `dds-date-range-${ae}`, oe = `${y}-end`, b = `${y}-label`, x = `${y}-error`, S = n(v, _.messages), [se, C] = l(() => _.defaultValue ?? m), w = _.value ?? se, T = (e, t = v) => ({
38
+ start: i(e.start, t),
39
+ end: i(e.end, t)
40
+ }), [ce] = l(() => ({
41
+ ...T(w),
42
+ locale: v
43
+ })), E = c(ce), [, D] = l(0), O = (e, t) => {
44
+ let n = o(e, t);
45
+ return t !== v && a(n) ? i(n, v) : e;
46
+ }, k = () => ({
47
+ start: O(E.current.start, E.current.locale),
48
+ end: O(E.current.end, E.current.locale)
49
+ }), A = k(), j = (e) => {
50
+ E.current = {
51
+ ...e,
52
+ locale: v
53
+ }, D((e) => e + 1);
54
+ }, [le, M] = l(() => g(w)), [N, P] = l(!1), F = c(null), I = c(null), L = c(null), R = c(w), z = c(void 0), [B, ue] = l(null);
55
+ s(() => {
56
+ let e = F.current;
57
+ e && ue(e.closest("[role=\"dialog\"], [role=\"alertdialog\"]") ?? e.ownerDocument.body);
58
+ }, []);
59
+ let V = !!(_.disabled || _.readOnly), H = r(A.start, A.end, _.required ?? !1, _.min, _.max, v), U = (e) => e === "required" ? S.required : e === "order" ? S.order : S.invalid, W = H.valid ? void 0 : U(H.reason), G = !!_.invalid || !H.start.valid, K = !!_.invalid || !H.end.valid || H.reason === "order", q = _.label ?? _["aria-label"] ?? "", J = c({
60
+ props: _,
61
+ locale: v,
62
+ blocked: V,
63
+ display: T
64
+ });
65
+ J.current = {
66
+ props: _,
67
+ locale: v,
68
+ blocked: V,
69
+ display: T
70
+ }, s(() => {
71
+ re(w, R.current) || (R.current = {
72
+ start: w.start,
73
+ end: w.end
74
+ }, j(T(R.current)), M(g(R.current)));
75
+ }, [w.start, w.end]);
76
+ let Y = H.start.valid ? "" : U(H.start.reason), X = H.end.valid ? H.reason === "order" ? S.order : "" : U(H.end.reason);
77
+ s(() => {
78
+ F.current?.setCustomValidity(Y), I.current?.setCustomValidity(X);
79
+ }, [Y, X]), s(() => {
80
+ V && (P(!1), z.current !== void 0 && cancelAnimationFrame(z.current));
81
+ }, [V]), s(() => {
82
+ let e = F.current?.ownerDocument;
83
+ if (!e) return;
84
+ let t = /* @__PURE__ */ new Set(), n = (n) => {
85
+ let { props: r } = J.current, i = r.form ? e.getElementById(r.form) : F.current?.form;
86
+ if (!i || n.target !== i) return;
87
+ let a = setTimeout(() => {
88
+ if (t.delete(a), n.defaultPrevented) return;
89
+ let e = J.current, r = e.props.value ?? e.props.defaultValue ?? m;
90
+ R.current = r, e.props.value === void 0 && C(r);
91
+ let i = e.display(r, e.locale);
92
+ E.current = {
93
+ ...i,
94
+ locale: e.locale
95
+ }, D((e) => e + 1), M(g(r)), F.current && (F.current.value = i.start), I.current && (I.current.value = i.end);
96
+ }, 0);
97
+ t.add(a);
98
+ };
99
+ return e.addEventListener("reset", n, !0), () => {
100
+ e.removeEventListener("reset", n, !0);
101
+ for (let e of t) clearTimeout(e);
102
+ };
103
+ }, []), s(() => () => {
104
+ z.current !== void 0 && cancelAnimationFrame(z.current);
105
+ }, []);
106
+ function Z(e, t = 1) {
107
+ z.current !== void 0 && cancelAnimationFrame(z.current);
108
+ let n = (t) => {
109
+ z.current = requestAnimationFrame(() => {
110
+ if (t > 1) return n(t - 1);
111
+ z.current = void 0, J.current.blocked || e()?.focus({ preventScroll: !0 });
112
+ });
113
+ };
114
+ n(t);
115
+ }
116
+ let Q = c(null);
117
+ function de(e) {
118
+ Q.current = e, Z(e, 2);
119
+ }
120
+ s(() => {
121
+ let e = Q.current;
122
+ N || !e || (Q.current = null, Z(e, 2));
123
+ }, [N]);
124
+ function fe(e) {
125
+ V || (M(g(e)), !re(e, R.current) && (R.current = e, _.value === void 0 && C(e), _.onValueChange?.(e)));
126
+ }
127
+ function pe(e, t) {
128
+ if (V) return;
129
+ let n = {
130
+ ...k(),
131
+ [e]: t
132
+ }, a = r(n.start, n.end, !1, _.min, _.max, v), o = a[e];
133
+ o.valid && (n[e] = i(o.value ?? "", v)), j(n), a.valid && fe(a.value);
134
+ }
135
+ function $(e) {
136
+ j(T(e)), fe(e);
137
+ }
138
+ let me = (_.presets ?? []).map((e) => {
139
+ let t = r(e.value.start, e.value.end, !1, _.min, _.max, "en-US");
140
+ return {
141
+ label: e.label,
142
+ disabled: !t.valid,
143
+ onSelect: () => {
144
+ V || !t.valid || ($(t.value), P(!1), de(() => I.current));
145
+ }
146
+ };
147
+ }), he = !!B?.matches("[role=\"dialog\"], [role=\"alertdialog\"]"), ge = t(v) ? "YYYY/MM/DD" : "YYYY-MM-DD", _e = (e) => {
148
+ e.key === "Enter" && !e.nativeEvent.isComposing && (e.preventDefault(), e.stopPropagation());
149
+ };
150
+ return /* @__PURE__ */ d("div", {
151
+ className: `dds-field dds-date-picker dds-date-range-picker dds-date-picker--${_.labelPlacement ?? "outside"}${W ? " dds-field--error" : ""}`,
152
+ role: "group",
153
+ "aria-labelledby": _["aria-labelledby"] ?? (_.label ? b : void 0),
154
+ "aria-label": _.label || _["aria-labelledby"] ? void 0 : _["aria-label"],
155
+ "data-filled": A.start !== "" || A.end !== "" ? "true" : void 0,
156
+ "data-invalid": G || K ? "" : void 0,
157
+ "data-disabled": _.disabled ? "" : void 0,
158
+ children: [
159
+ _.label && /* @__PURE__ */ d("label", {
160
+ id: b,
161
+ className: "dds-field__label",
162
+ htmlFor: y,
163
+ children: [_.label, _.required && /* @__PURE__ */ u("span", {
164
+ "aria-hidden": "true",
165
+ children: " *"
166
+ })]
167
+ }),
168
+ /* @__PURE__ */ d(f.Root, {
169
+ locale: v,
170
+ timeZone: _.timeZone ?? "Asia/Seoul",
171
+ selectionMode: "range",
172
+ disabled: _.disabled,
173
+ readOnly: _.readOnly,
174
+ required: _.required,
175
+ invalid: !!_.invalid || !H.valid,
176
+ open: N && !V,
177
+ onOpenChange: (e) => {
178
+ P(e.open && !V), e.open || M(g(R.current));
179
+ },
180
+ min: _.min && a(_.min) ? p(_.min) : void 0,
181
+ max: _.max && a(_.max) ? p(_.max) : void 0,
182
+ startOfWeek: _.startOfWeek ?? 0,
183
+ minView: "day",
184
+ maxView: "day",
185
+ fixedWeeks: !0,
186
+ translations: {
187
+ dayCell: (e) => S.selectDate(e.valueText),
188
+ clearTrigger: S.clear
189
+ },
190
+ value: le,
191
+ onValueChange: (e) => {
192
+ if (V || (M(e.value), e.value.length < 2)) return;
193
+ let [t, n] = e.value.map((e) => e.toString()).sort(), i = r(t, n, !1, _.min, _.max, "en-US");
194
+ i.valid && ($(i.value), de(() => I.current));
195
+ },
196
+ positioning: {
197
+ placement: "bottom-start",
198
+ gutter: 8,
199
+ strategy: he ? "fixed" : "absolute",
200
+ hideWhenDetached: he
201
+ },
202
+ children: [/* @__PURE__ */ d(f.Control, {
203
+ className: "dds-date-picker-control",
204
+ children: [/* @__PURE__ */ d("div", {
205
+ className: "dds-date-range-box",
206
+ "data-invalid": G || K ? "" : void 0,
207
+ "data-disabled": _.disabled ? "" : void 0,
208
+ children: [
209
+ /* @__PURE__ */ u("input", {
210
+ type: "text",
211
+ className: "dds-date-range-input",
212
+ autoComplete: "off",
213
+ autoCorrect: "off",
214
+ spellCheck: !1,
215
+ placeholder: ge,
216
+ id: y,
217
+ ref: F,
218
+ form: _.form,
219
+ "aria-label": S.startLabel,
220
+ "aria-invalid": G ? "true" : void 0,
221
+ "aria-required": _.required ? "true" : void 0,
222
+ "aria-describedby": h(_["aria-describedby"], W && x),
223
+ value: A.start,
224
+ onChange: () => {},
225
+ required: _.required,
226
+ readOnly: _.readOnly,
227
+ disabled: _.disabled,
228
+ onInputCapture: (e) => {
229
+ e.stopPropagation(), pe("start", e.currentTarget.value);
230
+ },
231
+ onKeyDown: _e
232
+ }),
233
+ /* @__PURE__ */ u("span", {
234
+ className: "dds-date-range-separator",
235
+ "aria-hidden": "true",
236
+ children: "~"
237
+ }),
238
+ /* @__PURE__ */ u("input", {
239
+ type: "text",
240
+ className: "dds-date-range-input",
241
+ autoComplete: "off",
242
+ autoCorrect: "off",
243
+ spellCheck: !1,
244
+ placeholder: ge,
245
+ id: oe,
246
+ ref: I,
247
+ form: _.form,
248
+ "aria-label": S.endLabel,
249
+ "aria-invalid": K ? "true" : void 0,
250
+ "aria-required": _.required ? "true" : void 0,
251
+ "aria-describedby": h(_["aria-describedby"], W && x),
252
+ value: A.end,
253
+ onChange: () => {},
254
+ required: _.required,
255
+ readOnly: _.readOnly,
256
+ disabled: _.disabled,
257
+ onInputCapture: (e) => {
258
+ e.stopPropagation(), pe("end", e.currentTarget.value);
259
+ },
260
+ onKeyDown: _e
261
+ })
262
+ ]
263
+ }), /* @__PURE__ */ u(f.Trigger, {
264
+ asChild: !0,
265
+ children: /* @__PURE__ */ u(e, {
266
+ ref: L,
267
+ type: "button",
268
+ tone: "secondary",
269
+ "aria-label": `${q} ${S.openCalendar}`.trim(),
270
+ children: /* @__PURE__ */ u(ie, {})
271
+ })
272
+ })]
273
+ }), /* @__PURE__ */ u(ne, {
274
+ container: B ? { current: B } : void 0,
275
+ children: /* @__PURE__ */ u(f.Positioner, {
276
+ className: "dds-date-picker-positioner",
277
+ children: /* @__PURE__ */ u(f.Content, {
278
+ onKeyDownCapture: (e) => {
279
+ e.key === "Escape" && (Q.current = null, Z(() => L.current, 2));
280
+ },
281
+ className: "dds-date-picker-content dds-date-range-content",
282
+ "aria-label": `${q} ${S.chooseRange}`.trim(),
283
+ children: /* @__PURE__ */ u(ee, {
284
+ timeZone: _.timeZone,
285
+ min: _.min,
286
+ max: _.max,
287
+ locale: v,
288
+ messages: S,
289
+ disabled: _.disabled,
290
+ readOnly: _.readOnly,
291
+ showToday: !1,
292
+ showClear: _.clearable,
293
+ presets: me,
294
+ presetsLabel: S.presets,
295
+ onClear: () => $(m)
296
+ })
297
+ })
298
+ })
299
+ })]
300
+ }),
301
+ _.startName && /* @__PURE__ */ u("input", {
302
+ type: "hidden",
303
+ name: _.startName,
304
+ form: _.form,
305
+ value: w.start,
306
+ disabled: _.disabled
307
+ }),
308
+ _.endName && /* @__PURE__ */ u("input", {
309
+ type: "hidden",
310
+ name: _.endName,
311
+ form: _.form,
312
+ value: w.end,
313
+ disabled: _.disabled
314
+ }),
315
+ W && /* @__PURE__ */ u("span", {
316
+ id: x,
317
+ className: "dds-field__error",
318
+ role: "alert",
319
+ children: W
320
+ })
321
+ ]
322
+ });
323
+ }
324
+ //#endregion
325
+ export { _ as DateRangePicker };
326
+
327
+ //# sourceMappingURL=date-range-picker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date-range-picker.js","names":[],"sources":["../src/date-range-picker.tsx"],"sourcesContent":["import {\n useEffect,\n useId,\n useRef,\n useState,\n type KeyboardEvent,\n} from \"react\";\nimport {\n DatePicker as ArkDatePicker,\n parseDate,\n type DateValue,\n} from \"@ark-ui/react/date-picker\";\nimport { Portal } from \"@ark-ui/react/portal\";\nimport { Button } from \"./controls\";\nimport { CalendarView } from \"./calendar-view\";\nimport {\n canonicalInput,\n displayDate,\n isCalendarDate,\n isKorean,\n rangeMessages,\n validateRange,\n type DateRange,\n type DateRangeMessages,\n} from \"./date-only\";\nexport type {\n DateRange,\n DateRangeMessages,\n DateRangeValidity,\n} from \"./date-only\";\n\n/** A consumer-supplied shortcut shown in the calendar footer. DDS ships no built-in list. */\nexport interface DateRangePreset {\n label: string;\n value: DateRange;\n}\n\nexport interface DateRangePickerProps {\n label?: string;\n /** Two inputs share one field label; \"inside\" is not offered. */\n labelPlacement?: \"outside\" | \"hidden\";\n \"aria-label\"?: string;\n \"aria-labelledby\"?: string;\n \"aria-describedby\"?: string;\n /** Id of the start input; the end input receives `${id}-end`. */\n id?: string;\n value?: DateRange;\n defaultValue?: DateRange;\n /** Called on user changes only, with YYYY-MM-DD or \"\" on each side; never with start after end. */\n onValueChange?: (next: DateRange) => void;\n locale?: string;\n timeZone?: string;\n min?: string;\n max?: string;\n startOfWeek?: 0 | 1 | 2 | 3 | 4 | 5 | 6;\n messages?: DateRangeMessages;\n clearable?: boolean;\n presets?: DateRangePreset[];\n /** Both dates are required. */\n required?: boolean;\n disabled?: boolean;\n readOnly?: boolean;\n invalid?: boolean;\n /** Form field name submitting the start date (YYYY-MM-DD or \"\"). */\n startName?: string;\n /** Form field name submitting the end date (YYYY-MM-DD or \"\"). */\n endName?: string;\n form?: string;\n}\n\nconst EMPTY: DateRange = { start: \"\", end: \"\" };\nconst same = (a: DateRange, b: DateRange) =>\n a.start === b.start && a.end === b.end;\nconst describedBy = (...ids: Array<string | false | null | undefined>) =>\n ids.filter(Boolean).join(\" \") || undefined;\n\nfunction selectionOf(range: DateRange): DateValue[] {\n if (!isCalendarDate(range.start)) return [];\n const start = parseDate(range.start);\n return isCalendarDate(range.end) && range.start <= range.end\n ? [start, parseDate(range.end)]\n : [start];\n}\n\nfunction CalendarIcon() {\n return (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n aria-hidden=\"true\"\n >\n <rect x=\"3.5\" y=\"5.5\" width=\"17\" height=\"15\" rx=\"2\" />\n <path d=\"M7.5 3v5M16.5 3v5M3.5 10.5h17\" />\n </svg>\n );\n}\n\ntype Drafts = DateRange & { locale: string };\n\nexport function DateRangePicker(props: DateRangePickerProps) {\n const locale = props.locale ?? \"ko-KR\",\n generated = useId(),\n id = props.id ?? `dds-date-range-${generated}`,\n endId = `${id}-end`,\n labelId = `${id}-label`,\n errorId = `${id}-error`;\n const text = rangeMessages(locale, props.messages);\n const [internal, setInternal] = useState<DateRange>(\n () => props.defaultValue ?? EMPTY,\n );\n const value = props.value ?? internal;\n const display = (range: DateRange, at = locale) => ({\n start: displayDate(range.start, at),\n end: displayDate(range.end, at),\n });\n // Drafts keep their formatting locale so a locale change re-displays complete dates only.\n const [initialDrafts] = useState<Drafts>(() => ({\n ...display(value),\n locale,\n }));\n const draftRef = useRef(initialDrafts);\n const [, setDraftVersion] = useState(0);\n const relocalize = (draft: string, from: string) => {\n const canonical = canonicalInput(draft, from);\n return from !== locale && isCalendarDate(canonical)\n ? displayDate(canonical, locale)\n : draft;\n };\n const currentDrafts = (): DateRange => ({\n start: relocalize(draftRef.current.start, draftRef.current.locale),\n end: relocalize(draftRef.current.end, draftRef.current.locale),\n });\n const drafts = currentDrafts();\n const setDrafts = (next: DateRange) => {\n draftRef.current = { ...next, locale };\n setDraftVersion((version) => version + 1);\n };\n const [selection, setSelection] = useState(() => selectionOf(value));\n const [open, setOpen] = useState(false);\n const startRef = useRef<HTMLInputElement>(null),\n endRef = useRef<HTMLInputElement>(null),\n triggerRef = useRef<HTMLButtonElement>(null),\n emitted = useRef(value),\n focusFrame = useRef<number | undefined>(undefined);\n const [portalMount, setPortalMount] = useState<HTMLElement | null>(null);\n useEffect(() => {\n const input = startRef.current;\n if (input)\n setPortalMount(\n input.closest<HTMLElement>('[role=\"dialog\"], [role=\"alertdialog\"]') ??\n input.ownerDocument.body,\n );\n }, []);\n const blocked = Boolean(props.disabled || props.readOnly);\n const validity = validateRange(\n drafts.start,\n drafts.end,\n props.required ?? false,\n props.min,\n props.max,\n locale,\n );\n const messageFor = (reason: string) =>\n reason === \"required\"\n ? text.required\n : reason === \"order\"\n ? text.order\n : text.invalid;\n const error = validity.valid ? undefined : messageFor(validity.reason);\n const startInvalid = Boolean(props.invalid) || !validity.start.valid;\n const endInvalid =\n Boolean(props.invalid) ||\n !validity.end.valid ||\n validity.reason === \"order\";\n const fieldName = props.label ?? props[\"aria-label\"] ?? \"\";\n // Handlers registered once (form reset, frames) read the latest render through this ref.\n const latest = useRef({ props, locale, blocked, display });\n latest.current = { props, locale, blocked, display };\n\n useEffect(() => {\n if (same(value, emitted.current)) return;\n emitted.current = { start: value.start, end: value.end };\n setDrafts(display(emitted.current));\n setSelection(selectionOf(emitted.current));\n }, [value.start, value.end]);\n const startMessage = validity.start.valid\n ? \"\"\n : messageFor(validity.start.reason);\n const endMessage = !validity.end.valid\n ? messageFor(validity.end.reason)\n : validity.reason === \"order\"\n ? text.order\n : \"\";\n useEffect(() => {\n startRef.current?.setCustomValidity(startMessage);\n endRef.current?.setCustomValidity(endMessage);\n }, [startMessage, endMessage]);\n useEffect(() => {\n if (!blocked) return;\n setOpen(false);\n if (focusFrame.current !== undefined)\n cancelAnimationFrame(focusFrame.current);\n }, [blocked]);\n // Resolve the owning form when a reset happens: the field may mount before it joins its form.\n useEffect(() => {\n const doc = startRef.current?.ownerDocument;\n if (!doc) return;\n const timers = new Set<ReturnType<typeof setTimeout>>();\n const reset = (event: Event) => {\n const { props: now } = latest.current;\n const form = now.form\n ? doc.getElementById(now.form)\n : startRef.current?.form;\n if (!form || event.target !== form) return;\n // A task, not a microtask: a user-triggered reset runs its listeners before rewriting the controls.\n const timer = setTimeout(() => {\n timers.delete(timer);\n if (event.defaultPrevented) return;\n const current = latest.current;\n const next = current.props.value ?? current.props.defaultValue ?? EMPTY;\n emitted.current = next;\n if (current.props.value === undefined) setInternal(next);\n const shown = current.display(next, current.locale);\n draftRef.current = { ...shown, locale: current.locale };\n setDraftVersion((version) => version + 1);\n setSelection(selectionOf(next));\n // Native reset rewrote the visible inputs; the drafts may not have changed.\n if (startRef.current) startRef.current.value = shown.start;\n if (endRef.current) endRef.current.value = shown.end;\n }, 0);\n timers.add(timer);\n };\n doc.addEventListener(\"reset\", reset, true);\n return () => {\n doc.removeEventListener(\"reset\", reset, true);\n for (const timer of timers) clearTimeout(timer);\n };\n }, []);\n useEffect(\n () => () => {\n if (focusFrame.current !== undefined)\n cancelAnimationFrame(focusFrame.current);\n },\n [],\n );\n\n function focusSoon(target: () => HTMLElement | null, frames = 1) {\n if (focusFrame.current !== undefined)\n cancelAnimationFrame(focusFrame.current);\n const run = (left: number) => {\n focusFrame.current = requestAnimationFrame(() => {\n if (left > 1) return run(left - 1);\n focusFrame.current = undefined;\n if (!latest.current.blocked) target()?.focus({ preventScroll: true });\n });\n };\n run(frames);\n }\n // Ark returns focus to its trigger once it sees the calendar closed; move it on after that.\n const pendingFocus = useRef<(() => HTMLElement | null) | null>(null);\n function focusAfterClose(target: () => HTMLElement | null) {\n // If the calendar stays open (This month), move focus now as well.\n pendingFocus.current = target;\n focusSoon(target, 2);\n }\n useEffect(() => {\n const target = pendingFocus.current;\n // Ark sees the closed prop in this same commit and schedules its own focus one frame out.\n if (open || !target) return;\n pendingFocus.current = null;\n focusSoon(target, 2);\n }, [open]);\n function commit(next: DateRange) {\n if (blocked) return;\n setSelection(selectionOf(next));\n if (same(next, emitted.current)) return;\n emitted.current = next;\n if (props.value === undefined) setInternal(next);\n props.onValueChange?.(next);\n }\n /** Committing ignores `required` like DatePicker: an emptied side is still reported. */\n function changeDraft(side: \"start\" | \"end\", typed: string) {\n if (blocked) return;\n const next = { ...currentDrafts(), [side]: typed };\n const loose = validateRange(\n next.start,\n next.end,\n false,\n props.min,\n props.max,\n locale,\n );\n const part = loose[side];\n if (part.valid) next[side] = displayDate(part.value ?? \"\", locale);\n setDrafts(next);\n if (loose.valid) commit(loose.value!);\n }\n function choose(range: DateRange) {\n setDrafts(display(range));\n commit(range);\n }\n const presets = (props.presets ?? []).map((preset) => {\n const checked = validateRange(\n preset.value.start,\n preset.value.end,\n false,\n props.min,\n props.max,\n \"en-US\",\n );\n return {\n label: preset.label,\n disabled: !checked.valid,\n onSelect: () => {\n if (blocked || !checked.valid) return;\n choose(checked.value!);\n setOpen(false);\n focusAfterClose(() => endRef.current);\n },\n };\n });\n const dialogMount = !!portalMount?.matches(\n '[role=\"dialog\"], [role=\"alertdialog\"]',\n );\n const placeholder = isKorean(locale) ? \"YYYY/MM/DD\" : \"YYYY-MM-DD\";\n const stopEnter = (event: KeyboardEvent<HTMLInputElement>) => {\n if (event.key === \"Enter\" && !event.nativeEvent.isComposing) {\n event.preventDefault();\n event.stopPropagation();\n }\n };\n\n return (\n <div\n className={`dds-field dds-date-picker dds-date-range-picker dds-date-picker--${props.labelPlacement ?? \"outside\"}${error ? \" dds-field--error\" : \"\"}`}\n role=\"group\"\n aria-labelledby={\n props[\"aria-labelledby\"] ?? (props.label ? labelId : undefined)\n }\n aria-label={\n props.label || props[\"aria-labelledby\"] ? undefined : props[\"aria-label\"]\n }\n data-filled={drafts.start !== \"\" || drafts.end !== \"\" ? \"true\" : undefined}\n data-invalid={startInvalid || endInvalid ? \"\" : undefined}\n data-disabled={props.disabled ? \"\" : undefined}\n >\n {props.label && (\n <label id={labelId} className=\"dds-field__label\" htmlFor={id}>\n {props.label}\n {props.required && <span aria-hidden=\"true\"> *</span>}\n </label>\n )}\n <ArkDatePicker.Root\n locale={locale}\n timeZone={props.timeZone ?? \"Asia/Seoul\"}\n selectionMode=\"range\"\n disabled={props.disabled}\n readOnly={props.readOnly}\n required={props.required}\n invalid={Boolean(props.invalid) || !validity.valid}\n open={open && !blocked}\n onOpenChange={(details) => {\n setOpen(details.open && !blocked);\n // A half-chosen period is not a value: closing restores the committed one.\n if (!details.open) setSelection(selectionOf(emitted.current));\n }}\n min={\n props.min && isCalendarDate(props.min)\n ? parseDate(props.min)\n : undefined\n }\n max={\n props.max && isCalendarDate(props.max)\n ? parseDate(props.max)\n : undefined\n }\n startOfWeek={props.startOfWeek ?? 0}\n minView=\"day\"\n maxView=\"day\"\n fixedWeeks\n translations={{\n dayCell: (state) => text.selectDate(state.valueText),\n clearTrigger: text.clear,\n }}\n value={selection}\n onValueChange={(details) => {\n if (blocked) return;\n setSelection(details.value);\n if (details.value.length < 2) return;\n const [start, end] = details.value\n .map((day) => day.toString())\n .sort();\n const checked = validateRange(\n start!,\n end!,\n false,\n props.min,\n props.max,\n \"en-US\",\n );\n if (!checked.valid) return;\n choose(checked.value!);\n focusAfterClose(() => endRef.current);\n }}\n positioning={{\n placement: \"bottom-start\",\n gutter: 8,\n strategy: dialogMount ? \"fixed\" : \"absolute\",\n hideWhenDetached: dialogMount,\n }}\n >\n <ArkDatePicker.Control className=\"dds-date-picker-control\">\n <div\n className=\"dds-date-range-box\"\n data-invalid={startInvalid || endInvalid ? \"\" : undefined}\n data-disabled={props.disabled ? \"\" : undefined}\n >\n <input\n type=\"text\"\n className=\"dds-date-range-input\"\n autoComplete=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n placeholder={placeholder}\n id={id}\n ref={startRef}\n form={props.form}\n aria-label={text.startLabel}\n aria-invalid={startInvalid ? \"true\" : undefined}\n aria-required={props.required ? \"true\" : undefined}\n aria-describedby={describedBy(\n props[\"aria-describedby\"],\n error && errorId,\n )}\n value={drafts.start}\n onChange={() => {}}\n required={props.required}\n readOnly={props.readOnly}\n disabled={props.disabled}\n onInputCapture={(event) => {\n event.stopPropagation();\n changeDraft(\"start\", event.currentTarget.value);\n }}\n onKeyDown={stopEnter}\n />\n <span className=\"dds-date-range-separator\" aria-hidden=\"true\">\n ~\n </span>\n <input\n type=\"text\"\n className=\"dds-date-range-input\"\n autoComplete=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n placeholder={placeholder}\n id={endId}\n ref={endRef}\n form={props.form}\n aria-label={text.endLabel}\n aria-invalid={endInvalid ? \"true\" : undefined}\n aria-required={props.required ? \"true\" : undefined}\n aria-describedby={describedBy(\n props[\"aria-describedby\"],\n error && errorId,\n )}\n value={drafts.end}\n onChange={() => {}}\n required={props.required}\n readOnly={props.readOnly}\n disabled={props.disabled}\n onInputCapture={(event) => {\n event.stopPropagation();\n changeDraft(\"end\", event.currentTarget.value);\n }}\n onKeyDown={stopEnter}\n />\n </div>\n <ArkDatePicker.Trigger asChild>\n <Button\n ref={triggerRef}\n type=\"button\"\n tone=\"secondary\"\n aria-label={`${fieldName} ${text.openCalendar}`.trim()}\n >\n <CalendarIcon />\n </Button>\n </ArkDatePicker.Trigger>\n </ArkDatePicker.Control>\n <Portal container={portalMount ? { current: portalMount } : undefined}>\n <ArkDatePicker.Positioner className=\"dds-date-picker-positioner\">\n <ArkDatePicker.Content\n onKeyDownCapture={(event) => {\n if (event.key !== \"Escape\") return;\n pendingFocus.current = null;\n focusSoon(() => triggerRef.current, 2);\n }}\n className=\"dds-date-picker-content dds-date-range-content\"\n aria-label={`${fieldName} ${text.chooseRange}`.trim()}\n >\n <CalendarView\n timeZone={props.timeZone}\n min={props.min}\n max={props.max}\n locale={locale}\n messages={text}\n disabled={props.disabled}\n readOnly={props.readOnly}\n showToday={false}\n showClear={props.clearable}\n presets={presets}\n presetsLabel={text.presets}\n onClear={() => choose(EMPTY)}\n />\n </ArkDatePicker.Content>\n </ArkDatePicker.Positioner>\n </Portal>\n </ArkDatePicker.Root>\n {props.startName && (\n <input\n type=\"hidden\"\n name={props.startName}\n form={props.form}\n value={value.start}\n disabled={props.disabled}\n />\n )}\n {props.endName && (\n <input\n type=\"hidden\"\n name={props.endName}\n form={props.form}\n value={value.end}\n disabled={props.disabled}\n />\n )}\n {error && (\n <span id={errorId} className=\"dds-field__error\" role=\"alert\">\n {error}\n </span>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { useEffect as e, useState as t } from "react";
2
+ //#region src/direction.ts
3
+ function n(n, r) {
4
+ let [i, a] = t("ltr");
5
+ return e(() => {
6
+ let e = n.current?.parentElement;
7
+ if (!e) return;
8
+ let t = () => a(getComputedStyle(e).direction === "rtl" ? "rtl" : "ltr");
9
+ t();
10
+ let r = new MutationObserver(t);
11
+ return r.observe(e.ownerDocument.documentElement, {
12
+ attributes: !0,
13
+ subtree: !0,
14
+ attributeFilter: ["dir"]
15
+ }), () => r.disconnect();
16
+ }, [n]), r ?? i;
17
+ }
18
+ //#endregion
19
+ export { n as t };
20
+
21
+ //# sourceMappingURL=direction-DbZcVPsZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"direction-DbZcVPsZ.js","names":[],"sources":["../src/direction.ts"],"sourcesContent":["import { useEffect, useState, type RefObject } from \"react\";\n\nexport type Direction = \"ltr\" | \"rtl\";\n\n/** SSR callers may supply direction; clients also inherit their containing DOM. */\nexport function useDirection(\n element: RefObject<HTMLElement | null>,\n explicit: Direction | undefined,\n): Direction {\n const [ambient, setAmbient] = useState<Direction>(\"ltr\");\n useEffect(() => {\n const parent = element.current?.parentElement;\n if (!parent) return;\n const update = () =>\n setAmbient(getComputedStyle(parent).direction === \"rtl\" ? \"rtl\" : \"ltr\");\n update();\n const observer = new MutationObserver(update);\n observer.observe(parent.ownerDocument.documentElement, {\n attributes: true,\n subtree: true,\n attributeFilter: [\"dir\"],\n });\n return () => observer.disconnect();\n }, [element]);\n return explicit ?? ambient;\n}\n"],"mappings":";;AAKA,SAAgB,EACd,GACA,GACW;CACX,IAAM,CAAC,GAAS,KAAc,EAAoB,KAAK;CAevD,OAdA,QAAgB;EACd,IAAM,IAAS,EAAQ,SAAS;EAChC,IAAI,CAAC,GAAQ;EACb,IAAM,UACJ,EAAW,iBAAiB,CAAM,CAAC,CAAC,cAAc,QAAQ,QAAQ,KAAK;EACzE,EAAO;EACP,IAAM,IAAW,IAAI,iBAAiB,CAAM;EAM5C,OALA,EAAS,QAAQ,EAAO,cAAc,iBAAiB;GACrD,YAAY;GACZ,SAAS;GACT,iBAAiB,CAAC,KAAK;EACzB,CAAC,SACY,EAAS,WAAW;CACnC,GAAG,CAAC,CAAO,CAAC,GACL,KAAY;AACrB"}
@@ -0,0 +1,5 @@
1
+ import { type RefObject } from "react";
2
+ export type Direction = "ltr" | "rtl";
3
+ /** SSR callers may supply direction; clients also inherit their containing DOM. */
4
+ export declare function useDirection(element: RefObject<HTMLElement | null>, explicit: Direction | undefined): Direction;
5
+ //# sourceMappingURL=direction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"direction.d.ts","sourceRoot":"","sources":["../src/direction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE5D,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,KAAK,CAAC;AAEtC,mFAAmF;AACnF,wBAAgB,YAAY,CAC1B,OAAO,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,EACtC,QAAQ,EAAE,SAAS,GAAG,SAAS,GAC9B,SAAS,CAiBX"}
package/dist/index.d.ts CHANGED
@@ -13,6 +13,8 @@ export { Switch as ArkSwitch } from "@ark-ui/react/switch";
13
13
  export { Field as ArkField } from "@ark-ui/react/field";
14
14
  export { Toast as ArkToast } from "@ark-ui/react/toast";
15
15
  export * from "./date-picker";
16
+ export * from "./date-range-picker";
17
+ export * from "./month-picker";
16
18
  export { DatePicker as ArkDatePicker } from "@ark-ui/react/date-picker";
17
19
  export * from "./status-pill";
18
20
  export * from "./pending-action";
@@ -22,4 +24,7 @@ export * from "./select-picker";
22
24
  export * from "./dropdown-menu";
23
25
  export * from "./popover";
24
26
  export * from "./calendar";
27
+ export { TimePicker, type TimePickerProps, type TimeMessages } from "./time-picker";
28
+ export * from "./segmented-control";
29
+ export * from "./number-input";
25
30
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC;AACxB,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,IAAI,IAAI,OAAO,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,UAAU,IAAI,aAAa,EAAE,MAAM,2BAA2B,CAAC;AACxE,OAAO,EAAE,QAAQ,IAAI,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,KAAK,IAAI,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,KAAK,IAAI,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAExD,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,UAAU,IAAI,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAExE,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AAEjC,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC;AACxB,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,IAAI,IAAI,OAAO,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,UAAU,IAAI,aAAa,EAAE,MAAM,2BAA2B,CAAC;AACxE,OAAO,EAAE,QAAQ,IAAI,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,KAAK,IAAI,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,KAAK,IAAI,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAExD,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,UAAU,IAAI,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAExE,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AAEjC,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AACpF,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC"}