@devslab/dds-react 0.24.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.
- package/README.ko.md +3 -2
- package/README.md +3 -2
- package/dist/calendar-view-BxjCQV9k.js +119 -0
- package/dist/calendar-view-BxjCQV9k.js.map +1 -0
- package/dist/calendar-view.d.ts +11 -1
- package/dist/calendar-view.d.ts.map +1 -1
- package/dist/calendar.js +5 -4
- package/dist/calendar.js.map +1 -1
- package/dist/choice-N-5K_ggs.js +309 -0
- package/dist/choice-N-5K_ggs.js.map +1 -0
- package/dist/choice-types-kSaEnZPr.js +23 -0
- package/dist/choice-types-kSaEnZPr.js.map +1 -0
- package/dist/combobox.js +1 -1
- package/dist/date-only-Bu4UmsTP.js +151 -0
- package/dist/date-only-Bu4UmsTP.js.map +1 -0
- package/dist/date-only.d.ts +92 -0
- package/dist/date-only.d.ts.map +1 -1
- package/dist/date-picker.js +69 -68
- package/dist/date-picker.js.map +1 -1
- package/dist/date-range-picker.d.ts +41 -0
- package/dist/date-range-picker.d.ts.map +1 -0
- package/dist/date-range-picker.js +327 -0
- package/dist/date-range-picker.js.map +1 -0
- package/dist/direction-DbZcVPsZ.js +21 -0
- package/dist/direction-DbZcVPsZ.js.map +1 -0
- package/dist/direction.d.ts +5 -0
- package/dist/direction.d.ts.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +108 -103
- package/dist/index.js.map +1 -1
- package/dist/input.d.ts.map +1 -1
- package/dist/input.js +1 -1
- package/dist/input.js.map +1 -1
- package/dist/internal/choice.d.ts +27 -3
- package/dist/internal/choice.d.ts.map +1 -1
- package/dist/month-picker.d.ts +33 -0
- package/dist/month-picker.d.ts.map +1 -0
- package/dist/month-picker.js +242 -0
- package/dist/month-picker.js.map +1 -0
- package/dist/number-input.d.ts +53 -0
- package/dist/number-input.d.ts.map +1 -0
- package/dist/number-input.js +254 -0
- package/dist/number-input.js.map +1 -0
- package/dist/segmented-control.d.ts +40 -0
- package/dist/segmented-control.d.ts.map +1 -0
- package/dist/segmented-control.js +73 -0
- package/dist/segmented-control.js.map +1 -0
- package/dist/select-picker.js +1 -1
- package/dist/time-only.d.ts +32 -0
- package/dist/time-only.d.ts.map +1 -0
- package/dist/time-picker-BQ7BT6-u.js +100 -0
- package/dist/time-picker-BQ7BT6-u.js.map +1 -0
- package/dist/time-picker.d.ts +34 -0
- package/dist/time-picker.d.ts.map +1 -0
- package/dist/time-picker.js +2 -0
- package/package.json +29 -4
- package/styles.css +31 -1
- package/dist/calendar-view-I_sNlioP.js +0 -145
- package/dist/calendar-view-I_sNlioP.js.map +0 -1
- package/dist/choice-B3vNMfKK.js +0 -300
- package/dist/choice-B3vNMfKK.js.map +0 -1
package/dist/date-picker.js.map
CHANGED
|
@@ -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
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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"}
|