@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.
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
package/README.ko.md CHANGED
@@ -76,6 +76,7 @@ validity callback은 최초 mount, 의미 있는 입력·제약·외부 값 변
76
76
  아직 반영되지 않은 로컬 값과 일치하는 부모 값은 해당 발생 건의 응답으로 보고 최신 draft를 유지합니다. B/C/B 반복을 각각 보존하고 blur/Enter 중복 commit을 막습니다. 미반영 목록에 없는 다른 외부 값은 reset으로 처리합니다. 같은 문자열만으로는 미반영 값과 같은 의도적 reset을 응답과 구별할 수 없으므로 명시적 reset은 keyed editor remount를 사용하세요. 로컬 controlled state는 즉시 갱신하고 서버 저장을 분리하세요.
77
77
  ## 입력·선택·메뉴·공유 달력
78
78
 
79
- Input/InputGroup은 검색 전용이 아닌 일반 입력 기반이며 라벨 배치·내용 지우기를 지원합니다. Combobox/SelectPicker는 가상화를, DropdownMenu/Popover는 접근 가능한 팝업을, Calendar/DatePicker는 공유 달력을 제공합니다.
79
+ Input/InputGroup은 검색 전용이 아닌 일반 입력 기반이며 라벨 배치·내용 지우기를 지원합니다. Combobox/SelectPicker는 가상화를, DropdownMenu/Popover는 접근 가능한 팝업을, Calendar/DatePicker/DateRangePicker/MonthPicker는 공유 달력을 제공합니다.
80
80
 
81
- 상세 import: `@devslab/dds-react/input`, `/combobox`, `/select-picker`, `/dropdown-menu`, `/popover`, `/calendar`, `/date-picker`. 기존 루트 import와 `styles.css`는 유지합니다. [공통 사용 가이드](https://github.com/devslab-kr/dds/blob/main/docs/components-input-choice-calendar.ko.md)를 참고하세요.
81
+ 상세 import: `@devslab/dds-react/input`, `/combobox`, `/select-picker`, `/dropdown-menu`, `/popover`, `/calendar`, `/date-picker`, `/date-range-picker`, `/month-picker`. 기존 루트 import와 `styles.css`는 유지합니다. [공통 사용 가이드](https://github.com/devslab-kr/dds/blob/main/docs/components-input-choice-calendar.ko.md)를 참고하세요.
82
+ 상세 import: `@devslab/dds-react/input`, `/combobox`, `/select-picker`, `/dropdown-menu`, `/popover`, `/calendar`, `/date-picker`, `/time-picker`, `/date-range-picker`, `/month-picker`, `/segmented-control`, `/number-input`. 기존 루트 import와 `styles.css`는 유지합니다. [공통 사용 가이드](https://github.com/devslab-kr/dds/blob/main/docs/components-input-choice-calendar.ko.md)를 참고하세요.
package/README.md CHANGED
@@ -110,6 +110,7 @@ const onDateValidity = useCallback((state: DatePickerValidity) => {
110
110
  Delayed controlled echoes matching an outstanding local emission acknowledge that occurrence without replacing a newer draft. Repeated B/C/B is retained as three occurrences; duplicate blur/Enter does not emit again. A changed value not among pending emissions is an external reset and clears pending history. The string-only API cannot distinguish an intentional reset to a still-outstanding identical value from its acknowledgement; use a keyed editor remount for an explicit reset. Keep local controlled state synchronous and persist to the server separately. Unacknowledged emissions are retained until acknowledgement, external reset or unmount.
111
111
  ## Inputs, choices, overlays and shared calendars
112
112
 
113
- Input/InputGroup are general-purpose native inputs, not search-only, with label placement and clear actions. Combobox/SelectPicker support fixed-row virtualization; DropdownMenu/Popover provide accessible overlays; Calendar/DatePicker share a calendar view.
113
+ Input/InputGroup are general-purpose native inputs, not search-only, with label placement and clear actions. Combobox/SelectPicker support fixed-row virtualization; DropdownMenu/Popover provide accessible overlays; Calendar/DatePicker/DateRangePicker/MonthPicker share a calendar view.
114
114
 
115
- Use explicit subpaths `@devslab/dds-react/input`, `/combobox`, `/select-picker`, `/dropdown-menu`, `/popover`, `/calendar`, `/date-picker`, or the existing root exports. Keep importing `styles.css` once. See the [common usage guide](https://github.com/devslab-kr/dds/blob/main/docs/components-input-choice-calendar.md).
115
+ Use explicit subpaths `@devslab/dds-react/input`, `/combobox`, `/select-picker`, `/dropdown-menu`, `/popover`, `/calendar`, `/date-picker`, `/date-range-picker`, `/month-picker`, or the existing root exports. Keep importing `styles.css` once. See the [common usage guide](https://github.com/devslab-kr/dds/blob/main/docs/components-input-choice-calendar.md).
116
+ Use explicit subpaths `@devslab/dds-react/input`, `/combobox`, `/select-picker`, `/dropdown-menu`, `/popover`, `/calendar`, `/date-picker`, `/time-picker`, `/date-range-picker`, `/month-picker`, `/segmented-control`, `/number-input`, or the existing root exports. Keep importing `styles.css` once. See the [common usage guide](https://github.com/devslab-kr/dds/blob/main/docs/components-input-choice-calendar.md).
@@ -0,0 +1,119 @@
1
+ import { t as e } from "./controls-BajigKUv.js";
2
+ import { c as t, f as n, p as r, r as i } from "./date-only-Bu4UmsTP.js";
3
+ import { Fragment as a, jsx as o, jsxs as s } from "react/jsx-runtime";
4
+ import { DatePicker as c } from "@ark-ui/react/date-picker";
5
+ //#region src/calendar-view.tsx
6
+ function l({ next: e = !1 }) {
7
+ return /* @__PURE__ */ o("svg", {
8
+ width: "18",
9
+ height: "18",
10
+ viewBox: "0 0 24 24",
11
+ fill: "none",
12
+ stroke: "currentColor",
13
+ strokeWidth: "1.5",
14
+ "aria-hidden": "true",
15
+ children: /* @__PURE__ */ o("path", { d: e ? "m9 5 7 7-7 7" : "m15 5-7 7 7 7" })
16
+ });
17
+ }
18
+ function u({ locale: u = "ko-KR", timeZone: d = "Asia/Seoul", min: f, max: p, messages: m, disabled: h, readOnly: g, showToday: _ = !0, showClear: v = !0, onClear: y, view: b = "day", presets: x = [], presetsLabel: S }) {
19
+ let C = i(u, m), w = h || g, T = b === "month", E = n(d), D = r(E, !1, f, p, u).valid;
20
+ return /* @__PURE__ */ o(c.View, {
21
+ view: T ? "month" : "day",
22
+ children: /* @__PURE__ */ o(c.Context, { children: (n) => /* @__PURE__ */ s(a, { children: [
23
+ /* @__PURE__ */ s(c.ViewControl, {
24
+ className: "dds-date-picker-header",
25
+ children: [
26
+ /* @__PURE__ */ o(c.PrevTrigger, {
27
+ asChild: !0,
28
+ children: /* @__PURE__ */ o(e, {
29
+ type: "button",
30
+ tone: "secondary",
31
+ "aria-label": T ? C.previousYear : C.previousMonth,
32
+ children: /* @__PURE__ */ o(l, {})
33
+ })
34
+ }),
35
+ T ? /* @__PURE__ */ o("span", {
36
+ className: "dds-date-picker-year",
37
+ "aria-live": "polite",
38
+ children: t(u) ? `${n.focusedValue.year}년` : n.focusedValue.year
39
+ }) : /* @__PURE__ */ o(c.RangeText, {}),
40
+ /* @__PURE__ */ o(c.NextTrigger, {
41
+ asChild: !0,
42
+ children: /* @__PURE__ */ o(e, {
43
+ type: "button",
44
+ tone: "secondary",
45
+ "aria-label": T ? C.nextYear : C.nextMonth,
46
+ children: /* @__PURE__ */ o(l, { next: !0 })
47
+ })
48
+ })
49
+ ]
50
+ }),
51
+ T ? /* @__PURE__ */ o(c.Table, {
52
+ className: "dds-date-picker-table dds-date-picker-table--months",
53
+ children: /* @__PURE__ */ o(c.TableBody, { children: n.getMonthsGrid({
54
+ columns: 3,
55
+ format: "short"
56
+ }).map((e, t) => /* @__PURE__ */ o(c.TableRow, { children: e.map((e, t) => /* @__PURE__ */ o(c.TableCell, {
57
+ value: e.value,
58
+ children: /* @__PURE__ */ o(c.TableCellTrigger, {
59
+ "data-today": E.slice(0, 7) === `${String(n.focusedValue.year).padStart(4, "0")}-${String(e.value).padStart(2, "0")}` ? "" : void 0,
60
+ children: e.label
61
+ })
62
+ }, t)) }, t)) })
63
+ }) : /* @__PURE__ */ s(c.Table, {
64
+ className: "dds-date-picker-table",
65
+ children: [/* @__PURE__ */ o(c.TableHead, { children: /* @__PURE__ */ o(c.TableRow, { children: n.weekDays.map((e, t) => /* @__PURE__ */ o(c.TableHeader, { children: e.short }, t)) }) }), /* @__PURE__ */ o(c.TableBody, { children: n.weeks.map((e, t) => /* @__PURE__ */ o(c.TableRow, { children: e.map((e, t) => /* @__PURE__ */ o(c.TableCell, {
66
+ value: e,
67
+ children: /* @__PURE__ */ o(c.TableCellTrigger, { children: e.day })
68
+ }, t)) }, t)) })]
69
+ }),
70
+ (x.length > 0 || _ || v) && /* @__PURE__ */ s("div", {
71
+ className: "dds-date-picker-footer",
72
+ children: [
73
+ x.length > 0 && /* @__PURE__ */ o("div", {
74
+ className: "dds-date-picker-presets",
75
+ role: "group",
76
+ "aria-label": S,
77
+ children: x.map((t, n) => /* @__PURE__ */ o(e, {
78
+ type: "button",
79
+ tone: "secondary",
80
+ size: "sm",
81
+ disabled: w || t.disabled,
82
+ onClick: () => {
83
+ !w && !t.disabled && t.onSelect();
84
+ },
85
+ children: t.label
86
+ }, n))
87
+ }),
88
+ _ && /* @__PURE__ */ o(e, {
89
+ type: "button",
90
+ tone: "secondary",
91
+ disabled: w || !D,
92
+ onClick: () => {
93
+ !w && D && n.selectToday();
94
+ },
95
+ children: T ? C.thisMonth : C.today
96
+ }),
97
+ v && /* @__PURE__ */ o(c.ClearTrigger, {
98
+ hidden: !1,
99
+ asChild: !0,
100
+ children: /* @__PURE__ */ o(e, {
101
+ type: "button",
102
+ tone: "secondary",
103
+ disabled: w,
104
+ onPointerDown: (e) => e.preventDefault(),
105
+ onClick: () => {
106
+ w || y?.();
107
+ },
108
+ children: C.clear
109
+ })
110
+ })
111
+ ]
112
+ })
113
+ ] }) })
114
+ });
115
+ }
116
+ //#endregion
117
+ export { u as t };
118
+
119
+ //# sourceMappingURL=calendar-view-BxjCQV9k.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar-view-BxjCQV9k.js","names":[],"sources":["../src/calendar-view.tsx"],"sourcesContent":["import { DatePicker as ArkDatePicker } from \"@ark-ui/react/date-picker\";\nimport { Button } from \"./controls\";\nimport {\n dateMessages,\n isKorean,\n todayDate,\n validateInput,\n type CalendarMessages,\n} from \"./date-only\";\nfunction Chevron({ next = false }: { next?: boolean }) {\n return (\n <svg\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n aria-hidden=\"true\"\n >\n <path d={next ? \"m9 5 7 7-7 7\" : \"m15 5-7 7 7 7\"} />\n </svg>\n );\n}\n/** A consumer-supplied footer shortcut (DateRangePicker presets). */\nexport interface CalendarViewPreset {\n label: string;\n disabled?: boolean | undefined;\n onSelect: () => void;\n}\nexport interface CalendarViewProps {\n timeZone?: string | undefined;\n min?: string | undefined;\n max?: string | undefined;\n locale?: string | undefined;\n messages?: CalendarMessages | undefined;\n disabled?: boolean | undefined;\n readOnly?: boolean | undefined;\n showToday?: boolean | undefined;\n showClear?: boolean | undefined;\n onClear?: (() => void) | undefined;\n /** \"month\" renders a 3 × 4 month grid paged by year; the caller sets Ark minView/maxView to match. */\n view?: \"day\" | \"month\" | undefined;\n presets?: CalendarViewPreset[] | undefined;\n presetsLabel?: string | undefined;\n}\n/** Internal view: the caller owns the single Ark root and its selection. */\nexport function CalendarView({\n locale = \"ko-KR\",\n timeZone = \"Asia/Seoul\",\n min,\n max,\n messages,\n disabled,\n readOnly,\n showToday = true,\n showClear = true,\n onClear,\n view = \"day\",\n presets = [],\n presetsLabel,\n}: CalendarViewProps) {\n const text = dateMessages(locale, messages),\n locked = disabled || readOnly,\n months = view === \"month\",\n today = todayDate(timeZone),\n todayAllowed = validateInput(today, false, min, max, locale).valid;\n return (\n <ArkDatePicker.View view={months ? \"month\" : \"day\"}>\n <ArkDatePicker.Context>\n {(picker) => (\n <>\n <ArkDatePicker.ViewControl className=\"dds-date-picker-header\">\n <ArkDatePicker.PrevTrigger asChild>\n <Button\n type=\"button\"\n tone=\"secondary\"\n aria-label={months ? text.previousYear : text.previousMonth}\n >\n <Chevron />\n </Button>\n </ArkDatePicker.PrevTrigger>\n {months ? (\n <span className=\"dds-date-picker-year\" aria-live=\"polite\">\n {isKorean(locale)\n ? `${picker.focusedValue.year}년`\n : picker.focusedValue.year}\n </span>\n ) : (\n <ArkDatePicker.RangeText />\n )}\n <ArkDatePicker.NextTrigger asChild>\n <Button\n type=\"button\"\n tone=\"secondary\"\n aria-label={months ? text.nextYear : text.nextMonth}\n >\n <Chevron next />\n </Button>\n </ArkDatePicker.NextTrigger>\n </ArkDatePicker.ViewControl>\n {/* Index keys keep rows and cells in place across Ark updates, so focus stays in the grid. */}\n {months ? (\n <ArkDatePicker.Table className=\"dds-date-picker-table dds-date-picker-table--months\">\n <ArkDatePicker.TableBody>\n {picker\n .getMonthsGrid({ columns: 3, format: \"short\" })\n .map((row, rowIndex) => (\n <ArkDatePicker.TableRow key={rowIndex}>\n {row.map((month, index) => (\n <ArkDatePicker.TableCell key={index} value={month.value}>\n <ArkDatePicker.TableCellTrigger\n data-today={\n today.slice(0, 7) ===\n `${String(picker.focusedValue.year).padStart(4, \"0\")}-${String(month.value).padStart(2, \"0\")}`\n ? \"\"\n : undefined\n }\n >\n {month.label}\n </ArkDatePicker.TableCellTrigger>\n </ArkDatePicker.TableCell>\n ))}\n </ArkDatePicker.TableRow>\n ))}\n </ArkDatePicker.TableBody>\n </ArkDatePicker.Table>\n ) : (\n <ArkDatePicker.Table className=\"dds-date-picker-table\">\n <ArkDatePicker.TableHead>\n <ArkDatePicker.TableRow>\n {picker.weekDays.map((day, index) => (\n <ArkDatePicker.TableHeader key={index}>\n {day.short}\n </ArkDatePicker.TableHeader>\n ))}\n </ArkDatePicker.TableRow>\n </ArkDatePicker.TableHead>\n <ArkDatePicker.TableBody>\n {picker.weeks.map((week, rowIndex) => (\n <ArkDatePicker.TableRow key={rowIndex}>\n {week.map((day, index) => (\n <ArkDatePicker.TableCell key={index} value={day}>\n <ArkDatePicker.TableCellTrigger>\n {day.day}\n </ArkDatePicker.TableCellTrigger>\n </ArkDatePicker.TableCell>\n ))}\n </ArkDatePicker.TableRow>\n ))}\n </ArkDatePicker.TableBody>\n </ArkDatePicker.Table>\n )}\n {(presets.length > 0 || showToday || showClear) && (\n <div className=\"dds-date-picker-footer\">\n {presets.length > 0 && (\n <div\n className=\"dds-date-picker-presets\"\n role=\"group\"\n aria-label={presetsLabel}\n >\n {presets.map((preset, index) => (\n <Button\n key={index}\n type=\"button\"\n tone=\"secondary\"\n size=\"sm\"\n disabled={locked || preset.disabled}\n onClick={() => {\n if (!locked && !preset.disabled) preset.onSelect();\n }}\n >\n {preset.label}\n </Button>\n ))}\n </div>\n )}\n {showToday && (\n <Button\n type=\"button\"\n tone=\"secondary\"\n disabled={locked || !todayAllowed}\n onClick={() => {\n if (!locked && todayAllowed) picker.selectToday();\n }}\n >\n {months ? text.thisMonth : text.today}\n </Button>\n )}\n {showClear && (\n <ArkDatePicker.ClearTrigger hidden={false} asChild>\n <Button\n type=\"button\"\n tone=\"secondary\"\n disabled={locked}\n onPointerDown={(event) => event.preventDefault()}\n onClick={() => {\n if (!locked) onClear?.();\n }}\n >\n {text.clear}\n </Button>\n </ArkDatePicker.ClearTrigger>\n )}\n </div>\n )}\n </>\n )}\n </ArkDatePicker.Context>\n </ArkDatePicker.View>\n );\n}\n"],"mappings":"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"}
@@ -1,4 +1,10 @@
1
1
  import { type CalendarMessages } from "./date-only";
2
+ /** A consumer-supplied footer shortcut (DateRangePicker presets). */
3
+ export interface CalendarViewPreset {
4
+ label: string;
5
+ disabled?: boolean | undefined;
6
+ onSelect: () => void;
7
+ }
2
8
  export interface CalendarViewProps {
3
9
  timeZone?: string | undefined;
4
10
  min?: string | undefined;
@@ -10,7 +16,11 @@ export interface CalendarViewProps {
10
16
  showToday?: boolean | undefined;
11
17
  showClear?: boolean | undefined;
12
18
  onClear?: (() => void) | undefined;
19
+ /** "month" renders a 3 × 4 month grid paged by year; the caller sets Ark minView/maxView to match. */
20
+ view?: "day" | "month" | undefined;
21
+ presets?: CalendarViewPreset[] | undefined;
22
+ presetsLabel?: string | undefined;
13
23
  }
14
24
  /** Internal view: the caller owns the single Ark root and its selection. */
15
- export declare function CalendarView({ locale, timeZone, min, max, messages, disabled, readOnly, showToday, showClear, onClear, }: CalendarViewProps): import("react").JSX.Element;
25
+ export declare function CalendarView({ locale, timeZone, min, max, messages, disabled, readOnly, showToday, showClear, onClear, view, presets, presetsLabel, }: CalendarViewProps): import("react").JSX.Element;
16
26
  //# sourceMappingURL=calendar-view.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"calendar-view.d.ts","sourceRoot":"","sources":["../src/calendar-view.tsx"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,gBAAgB,EACtB,MAAM,aAAa,CAAC;AAgBrB,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,QAAQ,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC/B,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC/B,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAChC,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAChC,OAAO,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;CACpC;AACD,4EAA4E;AAC5E,wBAAgB,YAAY,CAAC,EAC3B,MAAgB,EAChB,QAAuB,EACvB,GAAG,EACH,GAAG,EACH,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,SAAgB,EAChB,SAAgB,EAChB,OAAO,GACR,EAAE,iBAAiB,+BAqGnB"}
1
+ {"version":3,"file":"calendar-view.d.ts","sourceRoot":"","sources":["../src/calendar-view.tsx"],"names":[],"mappings":"AAEA,OAAO,EAKL,KAAK,gBAAgB,EACtB,MAAM,aAAa,CAAC;AAgBrB,qEAAqE;AACrE,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC/B,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AACD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,QAAQ,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC/B,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC/B,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAChC,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAChC,OAAO,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IACnC,sGAAsG;IACtG,IAAI,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,SAAS,CAAC;IACnC,OAAO,CAAC,EAAE,kBAAkB,EAAE,GAAG,SAAS,CAAC;IAC3C,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC;AACD,4EAA4E;AAC5E,wBAAgB,YAAY,CAAC,EAC3B,MAAgB,EAChB,QAAuB,EACvB,GAAG,EACH,GAAG,EACH,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,SAAgB,EAChB,SAAgB,EAChB,OAAO,EACP,IAAY,EACZ,OAAY,EACZ,YAAY,GACb,EAAE,iBAAiB,+BAsJnB"}
package/dist/calendar.js CHANGED
@@ -1,9 +1,10 @@
1
- import { a as e, r as t, s as n, t as r } from "./calendar-view-I_sNlioP.js";
1
+ import { o as e, p as t, r as n } from "./date-only-Bu4UmsTP.js";
2
+ import { t as r } from "./calendar-view-BxjCQV9k.js";
2
3
  import { jsx as i } from "react/jsx-runtime";
3
4
  import { DatePicker as a, parseDate as o } from "@ark-ui/react/date-picker";
4
5
  //#region src/calendar.tsx
5
6
  function s({ label: s, value: c, onChange: l, locale: u = "ko-KR", timeZone: d = "Asia/Seoul", min: f, max: p, disabled: m = !1, readOnly: h = !1, startOfWeek: g = 0, messages: _, showToday: v = !0, clearable: y = !0 }) {
6
- let b = t(u, _);
7
+ let b = n(u, _);
7
8
  return /* @__PURE__ */ i(a.Root, {
8
9
  className: "dds-calendar",
9
10
  "aria-label": s,
@@ -25,8 +26,8 @@ function s({ label: s, value: c, onChange: l, locale: u = "ko-KR", timeZone: d =
25
26
  clearTrigger: b.clear
26
27
  },
27
28
  onValueChange: (e) => {
28
- let t = e.value[0]?.toString() ?? "";
29
- !m && !h && n(t, !1, f, p, u).valid && l(t);
29
+ let n = e.value[0]?.toString() ?? "";
30
+ !m && !h && t(n, !1, f, p, u).valid && l(n);
30
31
  },
31
32
  children: /* @__PURE__ */ i(a.Content, {
32
33
  className: "dds-date-picker-content",
@@ -1 +1 @@
1
- {"version":3,"file":"calendar.js","names":[],"sources":["../src/calendar.tsx"],"sourcesContent":["import {\n DatePicker as ArkDatePicker,\n parseDate,\n} from \"@ark-ui/react/date-picker\";\nimport { CalendarView } from \"./calendar-view\";\nimport {\n isCalendarDate,\n validateInput,\n dateMessages,\n type CalendarMessages,\n} from \"./date-only\";\nexport interface CalendarProps {\n label: string;\n value: string;\n onChange: (value: string) => void;\n locale?: string;\n timeZone?: string;\n min?: string;\n max?: string;\n disabled?: boolean;\n readOnly?: boolean;\n startOfWeek?: 0 | 1 | 2 | 3 | 4 | 5 | 6;\n messages?: CalendarMessages;\n showToday?: boolean;\n clearable?: boolean;\n}\nexport type { CalendarMessages } from \"./date-only\";\nexport function Calendar({\n label,\n value,\n onChange,\n locale = \"ko-KR\",\n timeZone = \"Asia/Seoul\",\n min,\n max,\n disabled = false,\n readOnly = false,\n startOfWeek = 0,\n messages,\n showToday = true,\n clearable = true,\n}: CalendarProps) {\n const text = dateMessages(locale, messages);\n return (\n <ArkDatePicker.Root\n className=\"dds-calendar\"\n aria-label={label}\n role=\"group\"\n inline\n locale={locale}\n timeZone={timeZone}\n disabled={disabled}\n readOnly={readOnly}\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 value={isCalendarDate(value) ? [parseDate(value)] : []}\n translations={{\n dayCell: (state) => text.selectDate(state.valueText),\n clearTrigger: text.clear,\n }}\n onValueChange={(details) => {\n const next = details.value[0]?.toString() ?? \"\";\n if (\n !disabled &&\n !readOnly &&\n validateInput(next, false, min, max, locale).valid\n )\n onChange(next);\n }}\n >\n <ArkDatePicker.Content\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 />\n </ArkDatePicker.Content>\n </ArkDatePicker.Root>\n );\n}\n"],"mappings":";;;;AA2BA,SAAgB,EAAS,EACvB,UACA,UACA,aACA,YAAS,SACT,cAAW,cACX,QACA,QACA,cAAW,IACX,cAAW,IACX,iBAAc,GACd,aACA,eAAY,IACZ,eAAY,MACI;CAChB,IAAM,IAAO,EAAa,GAAQ,CAAQ;CAC1C,OACE,kBAAC,EAAc,MAAf;EACE,WAAU;EACV,cAAY;EACZ,MAAK;EACL,QAAA;EACQ;EACE;EACA;EACA;EACV,KAAK,KAAO,EAAe,CAAG,IAAI,EAAU,CAAG,IAAI,KAAA;EACnD,KAAK,KAAO,EAAe,CAAG,IAAI,EAAU,CAAG,IAAI,KAAA;EACtC;EACb,SAAQ;EACR,SAAQ;EACR,YAAA;EACA,OAAO,EAAe,CAAK,IAAI,CAAC,EAAU,CAAK,CAAC,IAAI,CAAC;EACrD,cAAc;GACZ,UAAU,MAAU,EAAK,WAAW,EAAM,SAAS;GACnD,cAAc,EAAK;EACrB;EACA,gBAAgB,MAAY;GAC1B,IAAM,IAAO,EAAQ,MAAM,EAAE,EAAE,SAAS,KAAK;GAC7C,AACE,CAAC,KACD,CAAC,KACD,EAAc,GAAM,IAAO,GAAK,GAAK,CAAM,CAAC,CAAC,SAE7C,EAAS,CAAI;EACjB;EAEA,UAAA,kBAAC,EAAc,SAAf;GACE,WAAU;GACV,cAAY;GAEZ,UAAA,kBAAC,GAAD;IACY;IACL;IACA;IACG;IACE;IACA;IACA;IACC;IACX,WAAW;GACZ,CAAA;EACoB,CAAA;CACL,CAAA;AAExB"}
1
+ {"version":3,"file":"calendar.js","names":[],"sources":["../src/calendar.tsx"],"sourcesContent":["import {\n DatePicker as ArkDatePicker,\n parseDate,\n} from \"@ark-ui/react/date-picker\";\nimport { CalendarView } from \"./calendar-view\";\nimport {\n isCalendarDate,\n validateInput,\n dateMessages,\n type CalendarMessages,\n} from \"./date-only\";\nexport interface CalendarProps {\n label: string;\n value: string;\n onChange: (value: string) => void;\n locale?: string;\n timeZone?: string;\n min?: string;\n max?: string;\n disabled?: boolean;\n readOnly?: boolean;\n startOfWeek?: 0 | 1 | 2 | 3 | 4 | 5 | 6;\n messages?: CalendarMessages;\n showToday?: boolean;\n clearable?: boolean;\n}\nexport type { CalendarMessages } from \"./date-only\";\nexport function Calendar({\n label,\n value,\n onChange,\n locale = \"ko-KR\",\n timeZone = \"Asia/Seoul\",\n min,\n max,\n disabled = false,\n readOnly = false,\n startOfWeek = 0,\n messages,\n showToday = true,\n clearable = true,\n}: CalendarProps) {\n const text = dateMessages(locale, messages);\n return (\n <ArkDatePicker.Root\n className=\"dds-calendar\"\n aria-label={label}\n role=\"group\"\n inline\n locale={locale}\n timeZone={timeZone}\n disabled={disabled}\n readOnly={readOnly}\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 value={isCalendarDate(value) ? [parseDate(value)] : []}\n translations={{\n dayCell: (state) => text.selectDate(state.valueText),\n clearTrigger: text.clear,\n }}\n onValueChange={(details) => {\n const next = details.value[0]?.toString() ?? \"\";\n if (\n !disabled &&\n !readOnly &&\n validateInput(next, false, min, max, locale).valid\n )\n onChange(next);\n }}\n >\n <ArkDatePicker.Content\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 />\n </ArkDatePicker.Content>\n </ArkDatePicker.Root>\n );\n}\n"],"mappings":";;;;;AA2BA,SAAgB,EAAS,EACvB,UACA,UACA,aACA,YAAS,SACT,cAAW,cACX,QACA,QACA,cAAW,IACX,cAAW,IACX,iBAAc,GACd,aACA,eAAY,IACZ,eAAY,MACI;CAChB,IAAM,IAAO,EAAa,GAAQ,CAAQ;CAC1C,OACE,kBAAC,EAAc,MAAf;EACE,WAAU;EACV,cAAY;EACZ,MAAK;EACL,QAAA;EACQ;EACE;EACA;EACA;EACV,KAAK,KAAO,EAAe,CAAG,IAAI,EAAU,CAAG,IAAI,KAAA;EACnD,KAAK,KAAO,EAAe,CAAG,IAAI,EAAU,CAAG,IAAI,KAAA;EACtC;EACb,SAAQ;EACR,SAAQ;EACR,YAAA;EACA,OAAO,EAAe,CAAK,IAAI,CAAC,EAAU,CAAK,CAAC,IAAI,CAAC;EACrD,cAAc;GACZ,UAAU,MAAU,EAAK,WAAW,EAAM,SAAS;GACnD,cAAc,EAAK;EACrB;EACA,gBAAgB,MAAY;GAC1B,IAAM,IAAO,EAAQ,MAAM,EAAE,EAAE,SAAS,KAAK;GAC7C,AACE,CAAC,KACD,CAAC,KACD,EAAc,GAAM,IAAO,GAAK,GAAK,CAAM,CAAC,CAAC,SAE7C,EAAS,CAAI;EACjB;EAEA,UAAA,kBAAC,EAAc,SAAf;GACE,WAAU;GACV,cAAY;GAEZ,UAAA,kBAAC,GAAD;IACY;IACL;IACA;IACG;IACE;IACA;IACA;IACC;IACX,WAAW;GACZ,CAAA;EACoB,CAAA;CACL,CAAA;AAExB"}
@@ -0,0 +1,309 @@
1
+ import { n as e, r as t, t as n } from "./choice-types-kSaEnZPr.js";
2
+ import { useEffect as r, useMemo as i, useRef as a, useState as o } from "react";
3
+ import { jsx as s, jsxs as c } from "react/jsx-runtime";
4
+ import { Portal as l } from "@ark-ui/react/portal";
5
+ import { Combobox as u, createListCollection as d } from "@ark-ui/react/combobox";
6
+ import { Select as f } from "@ark-ui/react/select";
7
+ import { defaultRangeExtractor as p, useVirtualizer as m } from "@tanstack/react-virtual";
8
+ //#region src/internal/choice.tsx
9
+ var h = {
10
+ position: "absolute",
11
+ width: 1,
12
+ height: 1,
13
+ padding: 0,
14
+ border: 0,
15
+ clipPath: "inset(50%)",
16
+ overflow: "hidden",
17
+ whiteSpace: "nowrap"
18
+ };
19
+ function g(g) {
20
+ t(g.items);
21
+ let [_, v] = o(g.defaultValue ?? ""), y = g.value ?? _, b = g.items.find((e) => e.value === y) ?? (g.selectedOption?.value === y ? g.selectedOption : void 0), x = b?.label ?? y, [S, C] = o(g.defaultInputValue ?? x), w = g.inputValue ?? S, T = (e) => {
22
+ C(e), g.onDraftChange?.(e);
23
+ }, [E, D] = o(!1), [O, k] = o(null), A = a(null), j = a(null), M = a(null), [N, P] = o(null);
24
+ r(() => {
25
+ let e = A.current;
26
+ e && P(e.closest("[role=\"dialog\"], [role=\"alertdialog\"]") ?? e.ownerDocument.body);
27
+ }, []);
28
+ let F = a(null), I = a(!1), L = a({
29
+ value: y,
30
+ label: x
31
+ }), R = a(null), z = (e) => g.items.find((t) => t.value === e)?.label ?? (g.selectedOption?.value === e ? g.selectedOption.label : e), B = {
32
+ ...n,
33
+ ...g.messages
34
+ }, V = g.disabled || g.readOnly, H = (e) => {
35
+ (R.current?.from !== w || R.current.to !== e) && (R.current = null, g.inputValue === void 0 && T(e), g.onInputValueChange?.(e));
36
+ }, U = (e) => {
37
+ e !== w && (R.current?.from !== w || R.current.to !== e) && (R.current = {
38
+ from: w,
39
+ to: e
40
+ }, g.inputValue === void 0 ? T(e) : g.onInputValueChange?.(e));
41
+ }, W = (e) => {
42
+ g.value === void 0 && v(e), g.onValueChange?.(e);
43
+ };
44
+ r(() => {
45
+ (L.current.value !== y || L.current.label !== x) && (L.current = {
46
+ value: y,
47
+ label: x
48
+ }, U(x));
49
+ }, [y, x]), r(() => {
50
+ e() && y && !b && console.warn(`DDS choice: no label supplied for selected ID ${JSON.stringify(y)}; pass selectedOption when the selection is outside items.`);
51
+ }, [y, b]), r(() => {
52
+ let e = j.current?.form;
53
+ if (!e) return;
54
+ let t = (e) => setTimeout(() => {
55
+ if (e.defaultPrevented) return;
56
+ g.onFormReset?.();
57
+ let t = g.value ?? g.defaultValue ?? "", n = z(t);
58
+ L.current = {
59
+ value: t,
60
+ label: n
61
+ }, g.value === void 0 && v(t);
62
+ let r = g.defaultInputValue ?? n;
63
+ R.current = null, g.inputValue === void 0 ? T(r) : U(r), D(!1), A.current instanceof HTMLInputElement && (A.current.value = g.inputValue ?? r), j.current && (j.current.value = t);
64
+ });
65
+ return e.addEventListener("reset", t), () => e.removeEventListener("reset", t);
66
+ }, [
67
+ g.defaultValue,
68
+ g.defaultInputValue,
69
+ g.value,
70
+ g.inputValue,
71
+ g.items,
72
+ g.selectedOption,
73
+ g.form
74
+ ]);
75
+ let G = i(() => g.searchable && g.filterMode !== "external" && w !== x ? g.items.filter((e) => g.matchItem ? g.matchItem(e, w) : e.label.toLocaleLowerCase().includes(w.toLocaleLowerCase())) : g.items, [
76
+ g.items,
77
+ g.searchable,
78
+ g.filterMode,
79
+ w,
80
+ x,
81
+ g.matchItem
82
+ ]), K = i(() => d({
83
+ items: G,
84
+ itemToString: (e) => e.label,
85
+ itemToValue: (e) => e.value,
86
+ isItemDisabled: (e) => !!e.disabled
87
+ }), [G]), q = !!g.virtualization, J = g.virtualization ? g.virtualization.itemHeight : void 0, Y = Number.isFinite(J) ? Math.max(40, J) : 40, X = G.findIndex((e) => e.value === O), Z = m({
88
+ count: G.length,
89
+ getScrollElement: () => M.current,
90
+ estimateSize: () => Y,
91
+ overscan: g.virtualization ? g.virtualization.overscan ?? 5 : 5,
92
+ enabled: q && E,
93
+ initialRect: {
94
+ width: 0,
95
+ height: 320
96
+ },
97
+ rangeExtractor: (e) => {
98
+ let t = p(e);
99
+ return X >= 0 && !t.includes(X) && t.push(X), t.sort((e, t) => e - t);
100
+ }
101
+ });
102
+ r(() => {
103
+ k(null), q && E && Z.scrollToIndex(Math.max(0, G.findIndex((e) => e.value === y)), { align: g.centerSelected ? "center" : "auto" });
104
+ }, [G, E]), r(() => {
105
+ let e = M.current;
106
+ if (!g.centerSelected || !E || q || !e) return;
107
+ let t = requestAnimationFrame(() => {
108
+ let t = e.querySelector("[data-part=\"item\"][data-state=\"checked\"]");
109
+ if (!t) return;
110
+ let n = e.getBoundingClientRect(), r = t.getBoundingClientRect();
111
+ e.scrollTop += r.top - n.top - (e.clientHeight - r.height) / 2;
112
+ });
113
+ return () => cancelAnimationFrame(t);
114
+ }, [
115
+ E,
116
+ g.centerSelected,
117
+ q
118
+ ]);
119
+ let Q = g.searchable ? u : f, $ = q ? Z.getVirtualItems().map((e) => ({
120
+ index: e.index,
121
+ start: e.start
122
+ })) : G.map((e, t) => ({
123
+ index: t,
124
+ start: 0
125
+ }));
126
+ q && X >= 0 && !$.some((e) => e.index === X) && $.push({
127
+ index: X,
128
+ start: X * Y
129
+ });
130
+ let ee = g.loading ? B.loading : g.error ? typeof g.error == "string" ? g.error : B.error : G.length === 0 ? B.empty : "", te = {
131
+ collection: K,
132
+ value: y ? [y] : [],
133
+ open: E && !V,
134
+ disabled: g.disabled,
135
+ readOnly: g.readOnly,
136
+ invalid: g.invalid,
137
+ onOpenChange: (e) => {
138
+ V || D(e.open);
139
+ },
140
+ onValueChange: (e) => {
141
+ if (V || I.current) return;
142
+ let t = e.value[0] ?? "";
143
+ t !== y && W(t);
144
+ },
145
+ onHighlightChange: (e) => k(e.highlightedValue),
146
+ scrollToIndexFn: q ? ({ index: e }) => Z.scrollToIndex(e, { align: "auto" }) : void 0,
147
+ positioning: {
148
+ placement: "bottom-start",
149
+ sameWidth: !0,
150
+ gutter: 4,
151
+ strategy: N?.matches("[role=\"dialog\"], [role=\"alertdialog\"]") ? "fixed" : "absolute",
152
+ hideWhenDetached: !!N?.matches("[role=\"dialog\"], [role=\"alertdialog\"]")
153
+ }
154
+ }, ne = g.searchable ? {
155
+ inputValue: w,
156
+ onInputValueChange: (e) => {
157
+ let t = F.current === e.inputValue && e.reason === "input-change" && A.current?.ownerDocument.activeElement !== A.current;
158
+ F.current = null, !t && !V && e.inputValue !== w && H(e.inputValue);
159
+ },
160
+ selectionBehavior: "preserve",
161
+ ...g.autoHighlight ? { inputBehavior: "autohighlight" } : {}
162
+ } : {};
163
+ return /* @__PURE__ */ c(Q.Root, {
164
+ ...te,
165
+ ...ne,
166
+ id: g.id,
167
+ className: g.rootClass ? `dds-choice ${g.rootClass}` : "dds-choice",
168
+ "data-label-placement": g.labelPlacement ?? "outside",
169
+ "data-has-value": y || w ? "" : void 0,
170
+ children: [
171
+ g.label && /* @__PURE__ */ s(Q.Label, {
172
+ className: "dds-choice-label",
173
+ onClick: () => A.current?.focus(),
174
+ children: g.label
175
+ }),
176
+ /* @__PURE__ */ c(Q.Control, {
177
+ className: "dds-choice-control",
178
+ children: [
179
+ g.searchable ? /* @__PURE__ */ s(u.Input, {
180
+ ref: (e) => {
181
+ A.current = e;
182
+ },
183
+ className: "dds-choice-input",
184
+ "aria-label": g["aria-label"],
185
+ "aria-labelledby": g["aria-labelledby"],
186
+ "aria-describedby": g["aria-describedby"],
187
+ "aria-required": g.required,
188
+ placeholder: g.placeholder,
189
+ inputMode: g.inputMode,
190
+ onCompositionStart: () => {
191
+ I.current = !0;
192
+ },
193
+ onCompositionEnd: () => {
194
+ I.current = !1;
195
+ },
196
+ onKeyDown: (e) => {
197
+ I.current && e.key === "Enter" && (e.preventDefault(), e.stopPropagation());
198
+ },
199
+ onBlur: (e) => {
200
+ if (g.commitDraft) {
201
+ F.current = e.currentTarget.value;
202
+ let t = V ? null : g.commitDraft(e.currentTarget.value);
203
+ t !== null && t !== y ? (W(t), U(z(t))) : U(x);
204
+ return;
205
+ }
206
+ y && U(x);
207
+ }
208
+ }) : null,
209
+ /* @__PURE__ */ s(Q.Trigger, {
210
+ ref: (e) => {
211
+ g.searchable || (A.current = e);
212
+ },
213
+ className: "dds-choice-trigger",
214
+ "aria-label": g.searchable ? B.open : g["aria-label"],
215
+ "aria-labelledby": g["aria-labelledby"],
216
+ "aria-describedby": g["aria-describedby"],
217
+ "aria-required": g.required,
218
+ children: g.searchable ? g.triggerContent ?? "⌄" : /* @__PURE__ */ s("span", {
219
+ className: "dds-choice-value",
220
+ children: x || g.placeholder || B.open
221
+ })
222
+ }),
223
+ g.clearable && !V && (y || w) ? /* @__PURE__ */ s("button", {
224
+ className: "dds-choice-clear",
225
+ type: "button",
226
+ "aria-label": B.clear,
227
+ onPointerDown: (e) => e.preventDefault(),
228
+ onClick: () => {
229
+ W(""), H(""), D(!1), A.current?.focus();
230
+ },
231
+ children: "×"
232
+ }) : null
233
+ ]
234
+ }),
235
+ /* @__PURE__ */ s("input", {
236
+ ref: j,
237
+ className: "dds-choice-validation",
238
+ style: h,
239
+ tabIndex: -1,
240
+ "aria-hidden": "true",
241
+ name: g.name,
242
+ form: g.form,
243
+ value: y,
244
+ required: g.required,
245
+ disabled: g.disabled,
246
+ onChange: () => {},
247
+ onInvalid: (e) => {
248
+ e.preventDefault(), A.current?.focus();
249
+ }
250
+ }),
251
+ /* @__PURE__ */ c("div", {
252
+ className: "dds-choice-status",
253
+ role: "status",
254
+ "aria-live": "polite",
255
+ children: [ee, g.error && g.onRetry ? /* @__PURE__ */ s("button", {
256
+ className: "dds-choice-retry",
257
+ type: "button",
258
+ onClick: g.onRetry,
259
+ children: B.retry
260
+ }) : null]
261
+ }),
262
+ N && /* @__PURE__ */ s(l, {
263
+ container: { current: N },
264
+ children: /* @__PURE__ */ s(Q.Positioner, {
265
+ className: "dds-choice-positioner",
266
+ children: /* @__PURE__ */ s(Q.Content, {
267
+ ref: M,
268
+ className: "dds-choice-content",
269
+ style: {
270
+ maxHeight: "min(320px, var(--available-height, 320px))",
271
+ overflow: "auto"
272
+ },
273
+ children: /* @__PURE__ */ s("div", {
274
+ style: q ? {
275
+ height: Z.getTotalSize(),
276
+ position: "relative"
277
+ } : void 0,
278
+ children: $.map((e) => {
279
+ let t = G[e.index];
280
+ return /* @__PURE__ */ c(Q.Item, {
281
+ item: t,
282
+ className: "dds-choice-item",
283
+ "aria-posinset": e.index + 1,
284
+ "aria-setsize": G.length,
285
+ style: q ? {
286
+ position: "absolute",
287
+ top: 0,
288
+ left: 0,
289
+ width: "100%",
290
+ height: Y,
291
+ transform: `translateY(${e.start}px)`
292
+ } : void 0,
293
+ children: [/* @__PURE__ */ s(Q.ItemText, { children: t.label }), t.description ? /* @__PURE__ */ s("span", {
294
+ className: "dds-choice-description",
295
+ children: t.description
296
+ }) : null]
297
+ }, t.value);
298
+ })
299
+ })
300
+ })
301
+ })
302
+ })
303
+ ]
304
+ });
305
+ }
306
+ //#endregion
307
+ export { g as t };
308
+
309
+ //# sourceMappingURL=choice-N-5K_ggs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"choice-N-5K_ggs.js","names":[],"sources":["../src/internal/choice.tsx"],"sourcesContent":["import { Combobox as C, createListCollection } from \"@ark-ui/react/combobox\";\nimport { Select as S } from \"@ark-ui/react/select\";\nimport { Portal } from \"@ark-ui/react/portal\";\nimport { defaultRangeExtractor, useVirtualizer } from \"@tanstack/react-virtual\";\nimport { useEffect, useMemo, useRef, useState, type HTMLAttributes, type ReactNode } from \"react\";\nimport {\n choiceMessages,\n choiceWarningsEnabled,\n validateOptions,\n type ChoiceOption,\n type ComboboxProps,\n} from \"../choice-types\";\n\n/**\n * Options for DDS components built on Choice (TimePicker). They are not part\n * of the public Combobox/SelectPicker props; every default keeps the existing\n * Combobox and SelectPicker behavior. Mirrors the Solid Choice internals.\n */\nexport interface ChoiceInternals {\n searchable: boolean;\n /** Replaces the default case-insensitive label substring filter. */\n matchItem?: (item: ChoiceOption, query: string) => boolean;\n /** On blur, the value the typed text stands for, \"\" to clear, or null to restore the label. */\n commitDraft?: (text: string) => string | null;\n /** Content of the searchable trigger button (default \"⌄\"). */\n triggerContent?: ReactNode;\n rootClass?: string;\n invalid?: boolean;\n /** Highlight the first match while typing so Enter picks it. */\n autoHighlight?: boolean;\n /** Scroll the selected option to the middle of the list when it opens. */\n centerSelected?: boolean;\n inputMode?: HTMLAttributes<HTMLInputElement>[\"inputMode\"];\n /** Called before a native form reset restores the value. */\n onFormReset?: () => void;\n /** Observes every change of the uncontrolled input text, including restores. */\n onDraftChange?: (text: string) => void;\n}\n\n/** The native validation input stores one ID, never a second option collection. */\nconst validationStyle = {\n position: \"absolute\",\n width: 1,\n height: 1,\n padding: 0,\n border: 0,\n clipPath: \"inset(50%)\",\n overflow: \"hidden\",\n whiteSpace: \"nowrap\",\n} as const;\nexport function Choice(props: ComboboxProps & ChoiceInternals) {\n validateOptions(props.items);\n const [internal, setInternal] = useState(props.defaultValue ?? \"\");\n const value = props.value ?? internal;\n const selected =\n props.items.find((item) => item.value === value) ??\n (props.selectedOption?.value === value ? props.selectedOption : undefined);\n const label = selected?.label ?? value;\n const [draft, setDraft] = useState(props.defaultInputValue ?? label);\n const inputValue = props.inputValue ?? draft;\n const changeDraft = (next: string) => {\n setDraft(next);\n props.onDraftChange?.(next);\n };\n const [open, setOpen] = useState(false),\n [highlight, setHighlight] = useState<string | null>(null);\n const visibleRef = useRef<HTMLInputElement | HTMLButtonElement>(null),\n validationRef = useRef<HTMLInputElement>(null),\n scrollRef = useRef<HTMLDivElement>(null);\n const [portalMount, setPortalMount] = useState<HTMLElement | null>(null);\n useEffect(() => {\n const control = visibleRef.current;\n if (control) {\n // Modal isolation hides body siblings. Keep nested choices in the modal's\n // DOM subtree so their options remain available to assistive technology.\n setPortalMount(\n control.closest<HTMLElement>('[role=\"dialog\"], [role=\"alertdialog\"]') ??\n control.ownerDocument.body,\n );\n }\n }, []);\n // Text the blur already committed; Ark may still report that keystroke afterwards.\n const consumedOnBlur = useRef<string | null>(null);\n const composing = useRef(false),\n previousSelection = useRef({ value, label });\n const pendingRestore = useRef<{ from: string; to: string } | null>(null);\n const resolveLabel = (id: string) =>\n props.items.find((item) => item.value === id)?.label ??\n (props.selectedOption?.value === id ? props.selectedOption.label : id);\n const messages = { ...choiceMessages, ...props.messages };\n const blocked = props.disabled || props.readOnly;\n const setInput = (next: string) => {\n if (\n pendingRestore.current?.from === inputValue &&\n pendingRestore.current.to === next\n )\n return;\n pendingRestore.current = null;\n if (props.inputValue === undefined) changeDraft(next);\n props.onInputValueChange?.(next);\n };\n const restoreInput = (next: string) => {\n if (next === inputValue) return;\n if (\n pendingRestore.current?.from === inputValue &&\n pendingRestore.current.to === next\n )\n return;\n pendingRestore.current = { from: inputValue, to: next };\n if (props.inputValue === undefined) changeDraft(next);\n else props.onInputValueChange?.(next);\n };\n const setValue = (next: string) => {\n if (props.value === undefined) setInternal(next);\n props.onValueChange?.(next);\n };\n useEffect(() => {\n if (\n previousSelection.current.value !== value ||\n previousSelection.current.label !== label\n ) {\n previousSelection.current = { value, label };\n restoreInput(label);\n }\n }, [value, label]);\n useEffect(() => {\n if (choiceWarningsEnabled() && value && !selected)\n console.warn(\n `DDS choice: no label supplied for selected ID ${JSON.stringify(value)}; pass selectedOption when the selection is outside items.`,\n );\n }, [value, selected]);\n useEffect(() => {\n const form = validationRef.current?.form;\n if (!form) return;\n // A task, not a microtask: after a reset-button click, microtasks run\n // before the browser resets the controls and would be overwritten.\n const reset = (event: Event) =>\n setTimeout(() => {\n if (event.defaultPrevented) return;\n props.onFormReset?.();\n const resetValue = props.value ?? props.defaultValue ?? \"\";\n const resetLabel = resolveLabel(resetValue);\n previousSelection.current = { value: resetValue, label: resetLabel };\n if (props.value === undefined) setInternal(resetValue);\n const resetQuery = props.defaultInputValue ?? resetLabel;\n pendingRestore.current = null;\n if (props.inputValue === undefined) changeDraft(resetQuery);\n else restoreInput(resetQuery);\n setOpen(false);\n if (visibleRef.current instanceof HTMLInputElement)\n visibleRef.current.value = props.inputValue ?? resetQuery;\n if (validationRef.current) validationRef.current.value = resetValue;\n });\n form.addEventListener(\"reset\", reset);\n return () => form.removeEventListener(\"reset\", reset);\n }, [\n props.defaultValue,\n props.defaultInputValue,\n props.value,\n props.inputValue,\n props.items,\n props.selectedOption,\n props.form,\n ]);\n const items = useMemo(\n () =>\n props.searchable &&\n props.filterMode !== \"external\" &&\n inputValue !== label\n ? props.items.filter((item) =>\n props.matchItem\n ? props.matchItem(item, inputValue)\n : item.label\n .toLocaleLowerCase()\n .includes(inputValue.toLocaleLowerCase()),\n )\n : props.items,\n [props.items, props.searchable, props.filterMode, inputValue, label, props.matchItem],\n );\n const collection = useMemo(\n () =>\n createListCollection({\n items,\n itemToString: (item) => item.label,\n itemToValue: (item) => item.value,\n isItemDisabled: (item) => !!item.disabled,\n }),\n [items],\n );\n const virtual = !!props.virtualization;\n const configuredHeight = props.virtualization\n ? props.virtualization.itemHeight\n : undefined;\n const height = Number.isFinite(configuredHeight)\n ? Math.max(40, configuredHeight!)\n : 40;\n const activeIndex = items.findIndex((item) => item.value === highlight);\n const virtualizer = useVirtualizer({\n count: items.length,\n getScrollElement: () => scrollRef.current,\n estimateSize: () => height,\n overscan: props.virtualization ? (props.virtualization.overscan ?? 5) : 5,\n enabled: virtual && open,\n initialRect: { width: 0, height: 320 },\n rangeExtractor: (range) => {\n const indexes = defaultRangeExtractor(range);\n if (activeIndex >= 0 && !indexes.includes(activeIndex))\n indexes.push(activeIndex);\n return indexes.sort((a, b) => a - b);\n },\n });\n useEffect(() => {\n setHighlight(null);\n if (virtual && open)\n virtualizer.scrollToIndex(\n Math.max(\n 0,\n items.findIndex((item) => item.value === value),\n ),\n { align: props.centerSelected ? \"center\" : \"auto\" },\n );\n }, [items, open]);\n useEffect(() => {\n const content = scrollRef.current;\n if (!props.centerSelected || !open || virtual || !content) return;\n // Ark only scrolls the highlighted option to the nearest edge.\n const frame = requestAnimationFrame(() => {\n const chosen = content.querySelector<HTMLElement>(\n '[data-part=\"item\"][data-state=\"checked\"]',\n );\n if (!chosen) return;\n const list = content.getBoundingClientRect(),\n row = chosen.getBoundingClientRect();\n content.scrollTop +=\n row.top - list.top - (content.clientHeight - row.height) / 2;\n });\n return () => cancelAnimationFrame(frame);\n }, [open, props.centerSelected, virtual]);\n const Parts = props.searchable ? C : S;\n const rows = virtual\n ? virtualizer\n .getVirtualItems()\n .map((row) => ({ index: row.index, start: row.start }))\n : items.map((_, index) => ({ index, start: 0 }));\n // Keep the active row mounted even before the scroll element has a measured range.\n if (\n virtual &&\n activeIndex >= 0 &&\n !rows.some((row) => row.index === activeIndex)\n )\n rows.push({ index: activeIndex, start: activeIndex * height });\n const status = props.loading\n ? messages.loading\n : props.error\n ? typeof props.error === \"string\"\n ? props.error\n : messages.error\n : items.length === 0\n ? messages.empty\n : \"\";\n const rootProps = {\n collection,\n value: value ? [value] : [],\n open: open && !blocked,\n disabled: props.disabled,\n readOnly: props.readOnly,\n invalid: props.invalid,\n onOpenChange: (details: { open: boolean }) => {\n if (!blocked) setOpen(details.open);\n },\n onValueChange: (details: { value: string[] }) => {\n if (blocked || composing.current) return;\n const next = details.value[0] ?? \"\";\n if (next !== value) setValue(next);\n },\n onHighlightChange: (details: { highlightedValue: string | null }) =>\n setHighlight(details.highlightedValue),\n scrollToIndexFn: virtual\n ? ({ index }: { index: number }) =>\n virtualizer.scrollToIndex(index, { align: \"auto\" })\n : undefined,\n positioning: {\n placement: \"bottom-start\" as const,\n sameWidth: true,\n gutter: 4,\n strategy: portalMount?.matches('[role=\"dialog\"], [role=\"alertdialog\"]')\n ? (\"fixed\" as const)\n : (\"absolute\" as const),\n hideWhenDetached: !!portalMount?.matches(\n '[role=\"dialog\"], [role=\"alertdialog\"]',\n ),\n },\n };\n const inputProps = props.searchable\n ? {\n inputValue,\n onInputValueChange: (details: {\n inputValue: string;\n reason?: string;\n }) => {\n const stale =\n consumedOnBlur.current === details.inputValue &&\n details.reason === \"input-change\" &&\n visibleRef.current?.ownerDocument.activeElement !== visibleRef.current;\n consumedOnBlur.current = null;\n if (stale) return;\n if (!blocked && details.inputValue !== inputValue)\n setInput(details.inputValue);\n },\n selectionBehavior: \"preserve\" as const,\n ...(props.autoHighlight\n ? { inputBehavior: \"autohighlight\" as const }\n : {}),\n }\n : {};\n return (\n <Parts.Root\n {...rootProps}\n {...inputProps}\n id={props.id}\n className={props.rootClass ? `dds-choice ${props.rootClass}` : \"dds-choice\"}\n data-label-placement={props.labelPlacement ?? \"outside\"}\n data-has-value={value || inputValue ? \"\" : undefined}\n >\n {props.label && (\n <Parts.Label\n className=\"dds-choice-label\"\n onClick={() => visibleRef.current?.focus()}\n >\n {props.label}\n </Parts.Label>\n )}\n <Parts.Control className=\"dds-choice-control\">\n {props.searchable ? (\n <C.Input\n ref={(node) => {\n visibleRef.current = node;\n }}\n className=\"dds-choice-input\"\n aria-label={props[\"aria-label\"]}\n aria-labelledby={props[\"aria-labelledby\"]}\n aria-describedby={props[\"aria-describedby\"]}\n aria-required={props.required}\n placeholder={props.placeholder}\n inputMode={props.inputMode}\n onCompositionStart={() => {\n composing.current = true;\n }}\n onCompositionEnd={() => {\n composing.current = false;\n }}\n onKeyDown={(event) => {\n if (composing.current && event.key === \"Enter\") {\n event.preventDefault();\n event.stopPropagation();\n }\n }}\n onBlur={(event) => {\n if (props.commitDraft) {\n // The DOM holds the latest keystroke; Ark's input state may still be queued.\n consumedOnBlur.current = event.currentTarget.value;\n const next = blocked\n ? null\n : props.commitDraft(event.currentTarget.value);\n if (next !== null && next !== value) {\n setValue(next);\n restoreInput(resolveLabel(next));\n } else restoreInput(label);\n return;\n }\n if (value) restoreInput(label);\n }}\n />\n ) : null}\n <Parts.Trigger\n ref={(node) => {\n if (!props.searchable) visibleRef.current = node;\n }}\n className=\"dds-choice-trigger\"\n aria-label={props.searchable ? messages.open : props[\"aria-label\"]}\n aria-labelledby={props[\"aria-labelledby\"]}\n aria-describedby={props[\"aria-describedby\"]}\n aria-required={props.required}\n >\n {props.searchable ? (\n (props.triggerContent ?? \"⌄\")\n ) : (\n <span className=\"dds-choice-value\">\n {label || props.placeholder || messages.open}\n </span>\n )}\n </Parts.Trigger>\n {props.clearable && !blocked && (value || inputValue) ? (\n <button\n className=\"dds-choice-clear\"\n type=\"button\"\n aria-label={messages.clear}\n onPointerDown={(event) => event.preventDefault()}\n onClick={() => {\n setValue(\"\");\n setInput(\"\");\n setOpen(false);\n visibleRef.current?.focus();\n }}\n >\n ×\n </button>\n ) : null}\n </Parts.Control>\n <input\n ref={validationRef}\n className=\"dds-choice-validation\"\n style={validationStyle}\n tabIndex={-1}\n aria-hidden=\"true\"\n name={props.name}\n form={props.form}\n value={value}\n required={props.required}\n disabled={props.disabled}\n onChange={() => {}}\n onInvalid={(event) => {\n event.preventDefault();\n visibleRef.current?.focus();\n }}\n />\n <div className=\"dds-choice-status\" role=\"status\" aria-live=\"polite\">\n {status}\n {props.error && props.onRetry ? (\n <button\n className=\"dds-choice-retry\"\n type=\"button\"\n onClick={props.onRetry}\n >\n {messages.retry}\n </button>\n ) : null}\n </div>\n {portalMount && (\n <Portal container={{ current: portalMount }}>\n <Parts.Positioner className=\"dds-choice-positioner\">\n <Parts.Content\n ref={scrollRef}\n className=\"dds-choice-content\"\n style={{\n maxHeight: \"min(320px, var(--available-height, 320px))\",\n overflow: \"auto\",\n }}\n >\n <div\n style={\n virtual\n ? {\n height: virtualizer.getTotalSize(),\n position: \"relative\",\n }\n : undefined\n }\n >\n {rows.map((row) => {\n const item = items[row.index]!;\n return (\n <Parts.Item\n key={item.value}\n item={item}\n className=\"dds-choice-item\"\n aria-posinset={row.index + 1}\n aria-setsize={items.length}\n style={\n virtual\n ? {\n position: \"absolute\",\n top: 0,\n left: 0,\n width: \"100%\",\n height,\n transform: `translateY(${row.start}px)`,\n }\n : undefined\n }\n >\n <Parts.ItemText>{item.label}</Parts.ItemText>\n {item.description ? (\n <span className=\"dds-choice-description\">\n {item.description}\n </span>\n ) : null}\n </Parts.Item>\n );\n })}\n </div>\n </Parts.Content>\n </Parts.Positioner>\n </Portal>\n )}\n </Parts.Root>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ //#region src/choice-types.ts
2
+ function e(e) {
3
+ let t = /* @__PURE__ */ new Set();
4
+ for (let n of e) {
5
+ if (!n.value || t.has(n.value)) throw Error(`DDS choice: option IDs must be nonempty and unique (${JSON.stringify(n.value)})`);
6
+ t.add(n.value);
7
+ }
8
+ }
9
+ var t = {
10
+ open: "선택 열기",
11
+ clear: "선택 지우기",
12
+ loading: "불러오는 중",
13
+ empty: "결과 없음",
14
+ error: "불러오지 못했습니다",
15
+ retry: "다시 시도"
16
+ };
17
+ function n() {
18
+ return globalThis.process?.env?.NODE_ENV !== "production";
19
+ }
20
+ //#endregion
21
+ export { n, e as r, t };
22
+
23
+ //# sourceMappingURL=choice-types-kSaEnZPr.js.map