@devslab/dds-solid 0.22.1 → 0.24.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 (89) hide show
  1. package/README.ko.md +49 -3
  2. package/README.md +47 -3
  3. package/dist/assets/{calendar-view-1RO2mtf1.js → calendar-view-BBQGmkJ7.js} +181 -145
  4. package/dist/assets/calendar-view-BBQGmkJ7.js.map +1 -0
  5. package/dist/assets/{choice-DoXiK8nc.js → choice-DPmk9AHn.js} +41 -29
  6. package/dist/assets/choice-DPmk9AHn.js.map +1 -0
  7. package/dist/assets/choice-types-h4YVL8xH.js +24 -0
  8. package/dist/assets/choice-types-h4YVL8xH.js.map +1 -0
  9. package/dist/assets/date-only-0Ldsjp43.js +174 -0
  10. package/dist/assets/date-only-0Ldsjp43.js.map +1 -0
  11. package/dist/assets/direction-BpTqmXs-.js +24 -0
  12. package/dist/assets/direction-BpTqmXs-.js.map +1 -0
  13. package/dist/calendar-view-CZLsC57_.js +481 -0
  14. package/dist/calendar-view-CZLsC57_.js.map +1 -0
  15. package/dist/calendar-view.d.ts +10 -0
  16. package/dist/calendar-view.d.ts.map +1 -1
  17. package/dist/calendar.js +7 -6
  18. package/dist/calendar.js.map +1 -1
  19. package/dist/calendar.server.js +2 -1
  20. package/dist/calendar.server.js.map +1 -1
  21. package/dist/choice-CTNeFOVo.js +403 -0
  22. package/dist/choice-CTNeFOVo.js.map +1 -0
  23. package/dist/choice-types-kSaEnZPr.js +23 -0
  24. package/dist/choice-types-kSaEnZPr.js.map +1 -0
  25. package/dist/combobox.js +1 -1
  26. package/dist/combobox.server.js +1 -1
  27. package/dist/date-only-Bu4UmsTP.js +151 -0
  28. package/dist/date-only-Bu4UmsTP.js.map +1 -0
  29. package/dist/date-only.d.ts +92 -0
  30. package/dist/date-only.d.ts.map +1 -1
  31. package/dist/date-picker.js +51 -50
  32. package/dist/date-picker.js.map +1 -1
  33. package/dist/date-picker.server.js +2 -1
  34. package/dist/date-picker.server.js.map +1 -1
  35. package/dist/date-range-picker.d.ts +41 -0
  36. package/dist/date-range-picker.d.ts.map +1 -0
  37. package/dist/date-range-picker.js +368 -0
  38. package/dist/date-range-picker.js.map +1 -0
  39. package/dist/date-range-picker.server.js +347 -0
  40. package/dist/date-range-picker.server.js.map +1 -0
  41. package/dist/direction-CS85IDNU.js +21 -0
  42. package/dist/direction-CS85IDNU.js.map +1 -0
  43. package/dist/index.d.ts +6 -0
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +193 -176
  46. package/dist/index.js.map +1 -1
  47. package/dist/internal/choice.d.ts +25 -3
  48. package/dist/internal/choice.d.ts.map +1 -1
  49. package/dist/month-picker.d.ts +33 -0
  50. package/dist/month-picker.d.ts.map +1 -0
  51. package/dist/month-picker.js +287 -0
  52. package/dist/month-picker.js.map +1 -0
  53. package/dist/month-picker.server.js +282 -0
  54. package/dist/month-picker.server.js.map +1 -0
  55. package/dist/number-input.d.ts +53 -0
  56. package/dist/number-input.d.ts.map +1 -0
  57. package/dist/number-input.js +267 -0
  58. package/dist/number-input.js.map +1 -0
  59. package/dist/number-input.server.js +237 -0
  60. package/dist/number-input.server.js.map +1 -0
  61. package/dist/pending-action.d.ts +36 -0
  62. package/dist/pending-action.d.ts.map +1 -0
  63. package/dist/segmented-control.d.ts +40 -0
  64. package/dist/segmented-control.d.ts.map +1 -0
  65. package/dist/segmented-control.js +133 -0
  66. package/dist/segmented-control.js.map +1 -0
  67. package/dist/segmented-control.server.js +138 -0
  68. package/dist/segmented-control.server.js.map +1 -0
  69. package/dist/select-picker.js +1 -1
  70. package/dist/select-picker.server.js +1 -1
  71. package/dist/server.js +49 -23
  72. package/dist/server.js.map +1 -1
  73. package/dist/time-only.d.ts +32 -0
  74. package/dist/time-only.d.ts.map +1 -0
  75. package/dist/time-picker-BlMWCQwk.js +113 -0
  76. package/dist/time-picker-BlMWCQwk.js.map +1 -0
  77. package/dist/time-picker.d.ts +34 -0
  78. package/dist/time-picker.d.ts.map +1 -0
  79. package/dist/time-picker.js +2 -0
  80. package/dist/time-picker.server.js +152 -0
  81. package/dist/time-picker.server.js.map +1 -0
  82. package/package.json +44 -4
  83. package/styles.css +31 -1
  84. package/dist/assets/calendar-view-1RO2mtf1.js.map +0 -1
  85. package/dist/assets/choice-DoXiK8nc.js.map +0 -1
  86. package/dist/calendar-view-CTBTPB4T.js +0 -444
  87. package/dist/calendar-view-CTBTPB4T.js.map +0 -1
  88. package/dist/choice-BPMiJlPJ.js +0 -395
  89. package/dist/choice-BPMiJlPJ.js.map +0 -1
@@ -0,0 +1,113 @@
1
+ import { t as e } from "./choice-CTNeFOVo.js";
2
+ import { createMemo as t, createSignal as n, splitProps as r } from "solid-js";
3
+ import { createComponent as i, getNextElement as a, mergeProps as o, template as s } from "solid-js/web";
4
+ //#region src/time-only.ts
5
+ var c = /^([01]\d|2[0-3]):([0-5]\d)(?::[0-5]\d(?:\.\d+)?)?$/;
6
+ function l(e) {
7
+ let t = c.exec(e);
8
+ return t ? `${t[1]}:${t[2]}` : null;
9
+ }
10
+ var u = (e) => String(e).padStart(2, "0"), d = (e, t) => e <= 23 && t <= 59 ? `${u(e)}:${u(t)}` : null;
11
+ function f(e) {
12
+ let t = e.trim().replace(/[:.]/g, ":"), n = /^(\d{1,2}):(\d{2})(?::\d{2})?$/.exec(t);
13
+ return n ? d(Number(n[1]), Number(n[2])) : /^\d{4}$/.test(t) ? d(Number(t.slice(0, 2)), Number(t.slice(2))) : /^\d{3}$/.test(t) && Number(t.slice(0, 2)) > 23 ? d(Number(t[0]), Number(t.slice(1))) : null;
14
+ }
15
+ function p(e) {
16
+ let t = Number.isFinite(e) ? Math.max(1, Math.floor(e)) : 10, n = [];
17
+ for (let e = 0; e < 1440; e += t) n.push(`${u(Math.floor(e / 60))}:${u(e % 60)}`);
18
+ return n;
19
+ }
20
+ function m(e, t) {
21
+ let n = t.trim().replace(/[:.]/g, ":");
22
+ if (n === "") return !0;
23
+ let r = f(n);
24
+ if (r) return e === r;
25
+ if (n.includes(":")) {
26
+ let [t = "", r = "", ...i] = n.split(":");
27
+ return i.length || !/^\d{1,2}$/.test(t) || !/^\d{0,2}$/.test(r) ? !1 : e.startsWith(`${t.padStart(2, "0")}:${r}`);
28
+ }
29
+ if (!/^\d{1,4}$/.test(n)) return !1;
30
+ let i = e.replace(":", "");
31
+ return i.startsWith(n) ? !0 : (n.length % 2 == 1 || Number(n.slice(0, 2)) > 23) && i.startsWith(`0${n}`);
32
+ }
33
+ function h(e, t = {}) {
34
+ let n = /^ko(?:-|$)/i.test(e);
35
+ return {
36
+ open: n ? "시간 목록 열기" : "Open time list",
37
+ clear: n ? "시간 지우기" : "Clear time",
38
+ empty: n ? "맞는 시간이 없습니다" : "No matching time",
39
+ ...t
40
+ };
41
+ }
42
+ //#endregion
43
+ //#region src/time-picker.tsx
44
+ var g = /*#__PURE__*/ s("<svg width=20 height=20 viewBox=\"0 0 24 24\"fill=none stroke=currentColor stroke-width=1.6 stroke-linecap=round stroke-linejoin=round aria-hidden=true><path d=\"M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18z\"></path><path d=\"M12 7v5l3 2\">"), _ = 300;
45
+ function v() {
46
+ return a(g);
47
+ }
48
+ function y(a) {
49
+ let [s, c] = r(a, [
50
+ "value",
51
+ "defaultValue",
52
+ "onValueChange",
53
+ "step",
54
+ "placeholder",
55
+ "invalid",
56
+ "locale",
57
+ "messages"
58
+ ]), u = () => l(s.defaultValue ?? "") ?? "", [d, g] = n(u()), y = () => s.value ?? d(), b = () => y() === "" ? "" : l(y()), x = () => b() ?? y(), [S, C] = n(x()), w = t(() => {
59
+ let e = new Set(p(s.step ?? 10)), t = b(), n = f(S());
60
+ return t && e.add(t), n && e.add(n), [...e].sort().map((e) => ({
61
+ value: e,
62
+ label: e
63
+ }));
64
+ });
65
+ return i(e, o(c, {
66
+ searchable: !0,
67
+ rootClass: "dds-time-picker",
68
+ get items() {
69
+ return w();
70
+ },
71
+ get value() {
72
+ return x();
73
+ },
74
+ get selectedOption() {
75
+ return {
76
+ value: x(),
77
+ label: x()
78
+ };
79
+ },
80
+ onValueChange: (e) => {
81
+ s.value === void 0 && g(e), s.onValueChange?.(e);
82
+ },
83
+ onFormReset: () => {
84
+ s.value === void 0 && g(u());
85
+ },
86
+ get inputValue() {
87
+ return S();
88
+ },
89
+ onInputValueChange: C,
90
+ matchItem: (e, t) => m(e.value, t),
91
+ commitDraft: (e) => e.trim() === "" ? "" : f(e),
92
+ triggerContent: () => i(v, {}),
93
+ autoHighlight: !0,
94
+ centerSelected: !0,
95
+ inputMode: "numeric",
96
+ get virtualization() {
97
+ return w().length > _ && {};
98
+ },
99
+ get messages() {
100
+ return h(s.locale ?? "ko-KR", s.messages);
101
+ },
102
+ get placeholder() {
103
+ return s.placeholder ?? "HH:MM";
104
+ },
105
+ get invalid() {
106
+ return s.invalid === !0 || b() === null;
107
+ }
108
+ }));
109
+ }
110
+ //#endregion
111
+ export { y as t };
112
+
113
+ //# sourceMappingURL=time-picker-BlMWCQwk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time-picker-BlMWCQwk.js","names":["createMemo","createSignal","splitProps","ChoiceOption","Choice","matchesTimeQuery","normalizeTime","parseTypedTime","timeMessages","timeOptions","TimeMessages","TimePickerProps","value","defaultValue","onValueChange","step","label","labelPlacement","id","name","form","placeholder","clearable","disabled","readOnly","required","invalid","locale","messages","VIRTUALIZE_AFTER","ClockIcon","_$getNextElement","_tmpl$","TimePicker","props","local","shared","initial","internal","setInternal","raw","canonical","current","draft","setDraft","items","values","Set","selected","typed","add","sort","map","_$createComponent","_$mergeProps","searchable","rootClass","selectedOption","next","undefined","onFormReset","inputValue","onInputValueChange","matchItem","item","query","commitDraft","text","trim","triggerContent","autoHighlight","centerSelected","inputMode","virtualization","length"],"sources":["../src/time-only.ts","../src/time-picker.tsx"],"sourcesContent":["// Time-of-day values are 24-hour \"HH:MM\" strings; \"\" is empty. Servers may send\n// \"HH:MM:SS\" — it is accepted and shown as HH:MM, but never rewritten until the\n// user picks a time.\nconst API_TIME = /^([01]\\d|2[0-3]):([0-5]\\d)(?::[0-5]\\d(?:\\.\\d+)?)?$/;\n\n/** Canonical \"HH:MM\" for an API value, or null when it is not a time. */\nexport function normalizeTime(value: string): string | null {\n const match = API_TIME.exec(value);\n return match ? `${match[1]}:${match[2]}` : null;\n}\n\nconst pad = (value: number) => String(value).padStart(2, \"0\");\nconst fromParts = (hour: number, minute: number) =>\n hour <= 23 && minute <= 59 ? `${pad(hour)}:${pad(minute)}` : null;\n\n/**\n * What a person typed, read as a complete time: \"9:05\", \"09:05\", \"09:05:00\",\n * \"0905\", or \"905\" when the first two digits cannot be an hour. Full-width\n * colons and dots count as colons. Partial text (\"10\", \"10:4\", and \"103\",\n * which is still on its way to 10:30) is not a time.\n */\nexport function parseTypedTime(text: string): string | null {\n const value = text.trim().replace(/[:.]/g, \":\");\n const separated = /^(\\d{1,2}):(\\d{2})(?::\\d{2})?$/.exec(value);\n if (separated) return fromParts(Number(separated[1]), Number(separated[2]));\n if (/^\\d{4}$/.test(value))\n return fromParts(Number(value.slice(0, 2)), Number(value.slice(2)));\n if (/^\\d{3}$/.test(value) && Number(value.slice(0, 2)) > 23)\n return fromParts(Number(value[0]), Number(value.slice(1)));\n return null;\n}\n\n/** 00:00 up to the last step before 24:00. Steps below one minute become one; a non-number becomes 10. */\nexport function timeOptions(step: number) {\n const minutes = Number.isFinite(step) ? Math.max(1, Math.floor(step)) : 10;\n const values: string[] = [];\n for (let at = 0; at < 24 * 60; at += minutes)\n values.push(`${pad(Math.floor(at / 60))}:${pad(at % 60)}`);\n return values;\n}\n\n/**\n * Whether a \"HH:MM\" option matches partial typing. Digits read as the start of\n * the time (\"10\" → 10:00–10:59, \"1030\" → 10:30); an odd digit count or an\n * impossible hour also tries a leading zero (\"9\" → 09:xx, \"930\" → 09:30).\n * With a colon the hour may be one digit (\"9:3\" → 09:30–09:39).\n */\nexport function matchesTimeQuery(option: string, query: string) {\n const text = query.trim().replace(/[:.]/g, \":\");\n if (text === \"\") return true;\n const typed = parseTypedTime(text);\n if (typed) return option === typed;\n if (text.includes(\":\")) {\n const [hour = \"\", minute = \"\", ...rest] = text.split(\":\");\n if (rest.length || !/^\\d{1,2}$/.test(hour) || !/^\\d{0,2}$/.test(minute))\n return false;\n return option.startsWith(`${hour.padStart(2, \"0\")}:${minute}`);\n }\n if (!/^\\d{1,4}$/.test(text)) return false;\n const digits = option.replace(\":\", \"\");\n if (digits.startsWith(text)) return true;\n return (\n (text.length % 2 === 1 || Number(text.slice(0, 2)) > 23) &&\n digits.startsWith(`0${text}`)\n );\n}\n\nexport interface TimeMessages {\n /** Accessible name of the clock button that opens the list. */\n open?: string;\n /** Accessible name of the clear button. */\n clear?: string;\n /** Status when nothing in the list matches the typed text. */\n empty?: string;\n}\nexport function timeMessages(locale: string, messages: TimeMessages = {}) {\n const ko = /^ko(?:-|$)/i.test(locale);\n return {\n open: ko ? \"시간 목록 열기\" : \"Open time list\",\n clear: ko ? \"시간 지우기\" : \"Clear time\",\n empty: ko ? \"맞는 시간이 없습니다\" : \"No matching time\",\n ...messages,\n };\n}\n","import { createMemo, createSignal, splitProps } from \"solid-js\";\nimport type { ChoiceOption } from \"./choice-types\";\nimport { Choice } from \"./internal/choice\";\nimport {\n matchesTimeQuery,\n normalizeTime,\n parseTypedTime,\n timeMessages,\n timeOptions,\n type TimeMessages,\n} from \"./time-only\";\nexport type { TimeMessages } from \"./time-only\";\n\nexport interface TimePickerProps {\n /** 24-hour \"HH:MM\" (\"\" is empty). \"HH:MM:SS\" is accepted and shown as HH:MM. */\n value?: string;\n defaultValue?: string;\n /** Receives \"HH:MM\" or \"\" — only when the person picks, types or clears a time. */\n onValueChange?: (value: string) => void;\n /** Minutes between listed times, from 00:00 (default 10). Typed times off the step are still accepted. */\n step?: number;\n label?: string;\n labelPlacement?: \"outside\" | \"inside\" | \"hidden\";\n \"aria-label\"?: string;\n \"aria-labelledby\"?: string;\n \"aria-describedby\"?: string;\n id?: string;\n name?: string;\n form?: string;\n placeholder?: string;\n clearable?: boolean;\n disabled?: boolean;\n readOnly?: boolean;\n required?: boolean;\n invalid?: boolean;\n /** Chooses the built-in Korean or English text (default \"ko-KR\"). */\n locale?: string;\n messages?: TimeMessages;\n}\n\n/** Above this many rows the list is virtualized (1-minute steps list 1,440 times). */\nconst VIRTUALIZE_AFTER = 300;\n\n// The dds-icons \"clock\" glyph, inlined like DatePicker's calendar so this\n// subpath does not pull in the whole icon set.\nfunction ClockIcon() {\n return (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.6\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18z\" />\n <path d=\"M12 7v5l3 2\" />\n </svg>\n );\n}\n\n/**\n * A time-of-day field: type a time or pick one from the list. Built on the\n * same Ark combobox as Combobox, so list, keyboard and form behavior match.\n */\nexport function TimePicker(props: TimePickerProps) {\n const [local, shared] = splitProps(props, [\n \"value\",\n \"defaultValue\",\n \"onValueChange\",\n \"step\",\n \"placeholder\",\n \"invalid\",\n \"locale\",\n \"messages\",\n ]);\n const initial = () => normalizeTime(local.defaultValue ?? \"\") ?? \"\";\n const [internal, setInternal] = createSignal(initial());\n const raw = () => local.value ?? internal();\n const canonical = () => (raw() === \"\" ? \"\" : normalizeTime(raw()));\n // A value that is not a time is shown as it came, marked invalid, and never rewritten.\n const current = () => canonical() ?? raw();\n const [draft, setDraft] = createSignal(current());\n const items = createMemo<ChoiceOption[]>(() => {\n const values = new Set(timeOptions(local.step ?? 10));\n const selected = canonical(),\n typed = parseTypedTime(draft());\n if (selected) values.add(selected);\n if (typed) values.add(typed);\n return [...values].sort().map((value) => ({ value, label: value }));\n });\n return (\n <Choice\n {...shared}\n searchable\n rootClass=\"dds-time-picker\"\n items={items()}\n value={current()}\n // Only read when the value is not a listed time (an invalid server value).\n selectedOption={{ value: current(), label: current() }}\n onValueChange={(next) => {\n if (local.value === undefined) setInternal(next);\n local.onValueChange?.(next);\n }}\n onFormReset={() => {\n if (local.value === undefined) setInternal(initial());\n }}\n inputValue={draft()}\n onInputValueChange={setDraft}\n matchItem={(item, query) => matchesTimeQuery(item.value, query)}\n commitDraft={(text) => (text.trim() === \"\" ? \"\" : parseTypedTime(text))}\n triggerContent={() => <ClockIcon />}\n autoHighlight\n centerSelected\n inputMode=\"numeric\"\n virtualization={items().length > VIRTUALIZE_AFTER ? {} : false}\n messages={timeMessages(local.locale ?? \"ko-KR\", local.messages)}\n placeholder={local.placeholder ?? \"HH:MM\"}\n invalid={local.invalid === true || canonical() === null}\n />\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import { type TimeMessages } from "./time-only";
2
+ export type { TimeMessages } from "./time-only";
3
+ export interface TimePickerProps {
4
+ /** 24-hour "HH:MM" ("" is empty). "HH:MM:SS" is accepted and shown as HH:MM. */
5
+ value?: string;
6
+ defaultValue?: string;
7
+ /** Receives "HH:MM" or "" — only when the person picks, types or clears a time. */
8
+ onValueChange?: (value: string) => void;
9
+ /** Minutes between listed times, from 00:00 (default 10). Typed times off the step are still accepted. */
10
+ step?: number;
11
+ label?: string;
12
+ labelPlacement?: "outside" | "inside" | "hidden";
13
+ "aria-label"?: string;
14
+ "aria-labelledby"?: string;
15
+ "aria-describedby"?: string;
16
+ id?: string;
17
+ name?: string;
18
+ form?: string;
19
+ placeholder?: string;
20
+ clearable?: boolean;
21
+ disabled?: boolean;
22
+ readOnly?: boolean;
23
+ required?: boolean;
24
+ invalid?: boolean;
25
+ /** Chooses the built-in Korean or English text (default "ko-KR"). */
26
+ locale?: string;
27
+ messages?: TimeMessages;
28
+ }
29
+ /**
30
+ * A time-of-day field: type a time or pick one from the list. Built on the
31
+ * same Ark combobox as Combobox, so list, keyboard and form behavior match.
32
+ */
33
+ export declare function TimePicker(props: TimePickerProps): import("solid-js").JSX.Element;
34
+ //# sourceMappingURL=time-picker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time-picker.d.ts","sourceRoot":"","sources":["../src/time-picker.tsx"],"names":[],"mappings":"AAGA,OAAO,EAML,KAAK,YAAY,EAClB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,WAAW,eAAe;IAC9B,gFAAgF;IAChF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mFAAmF;IACnF,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,0GAA0G;IAC1G,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACjD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,YAAY,CAAC;CACzB;AA0BD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,kCAwDhD"}
@@ -0,0 +1,2 @@
1
+ import { t as e } from "./time-picker-BlMWCQwk.js";
2
+ export { e as TimePicker };
@@ -0,0 +1,152 @@
1
+ import { t as Choice } from "./assets/choice-DPmk9AHn.js";
2
+ import { createMemo, createSignal, splitProps } from "solid-js";
3
+ import { createComponent, mergeProps as mergeProps$1, ssr, ssrHydrationKey } from "solid-js/web";
4
+ //#region src/time-only.ts
5
+ var API_TIME = /^([01]\d|2[0-3]):([0-5]\d)(?::[0-5]\d(?:\.\d+)?)?$/;
6
+ /** Canonical "HH:MM" for an API value, or null when it is not a time. */
7
+ function normalizeTime(value) {
8
+ const match = API_TIME.exec(value);
9
+ return match ? `${match[1]}:${match[2]}` : null;
10
+ }
11
+ var pad = (value) => String(value).padStart(2, "0");
12
+ var fromParts = (hour, minute) => hour <= 23 && minute <= 59 ? `${pad(hour)}:${pad(minute)}` : null;
13
+ /**
14
+ * What a person typed, read as a complete time: "9:05", "09:05", "09:05:00",
15
+ * "0905", or "905" when the first two digits cannot be an hour. Full-width
16
+ * colons and dots count as colons. Partial text ("10", "10:4", and "103",
17
+ * which is still on its way to 10:30) is not a time.
18
+ */
19
+ function parseTypedTime(text) {
20
+ const value = text.trim().replace(/[:.]/g, ":");
21
+ const separated = /^(\d{1,2}):(\d{2})(?::\d{2})?$/.exec(value);
22
+ if (separated) return fromParts(Number(separated[1]), Number(separated[2]));
23
+ if (/^\d{4}$/.test(value)) return fromParts(Number(value.slice(0, 2)), Number(value.slice(2)));
24
+ if (/^\d{3}$/.test(value) && Number(value.slice(0, 2)) > 23) return fromParts(Number(value[0]), Number(value.slice(1)));
25
+ return null;
26
+ }
27
+ /** 00:00 up to the last step before 24:00. Steps below one minute become one; a non-number becomes 10. */
28
+ function timeOptions(step) {
29
+ const minutes = Number.isFinite(step) ? Math.max(1, Math.floor(step)) : 10;
30
+ const values = [];
31
+ for (let at = 0; at < 1440; at += minutes) values.push(`${pad(Math.floor(at / 60))}:${pad(at % 60)}`);
32
+ return values;
33
+ }
34
+ /**
35
+ * Whether a "HH:MM" option matches partial typing. Digits read as the start of
36
+ * the time ("10" → 10:00–10:59, "1030" → 10:30); an odd digit count or an
37
+ * impossible hour also tries a leading zero ("9" → 09:xx, "930" → 09:30).
38
+ * With a colon the hour may be one digit ("9:3" → 09:30–09:39).
39
+ */
40
+ function matchesTimeQuery(option, query) {
41
+ const text = query.trim().replace(/[:.]/g, ":");
42
+ if (text === "") return true;
43
+ const typed = parseTypedTime(text);
44
+ if (typed) return option === typed;
45
+ if (text.includes(":")) {
46
+ const [hour = "", minute = "", ...rest] = text.split(":");
47
+ if (rest.length || !/^\d{1,2}$/.test(hour) || !/^\d{0,2}$/.test(minute)) return false;
48
+ return option.startsWith(`${hour.padStart(2, "0")}:${minute}`);
49
+ }
50
+ if (!/^\d{1,4}$/.test(text)) return false;
51
+ const digits = option.replace(":", "");
52
+ if (digits.startsWith(text)) return true;
53
+ return (text.length % 2 === 1 || Number(text.slice(0, 2)) > 23) && digits.startsWith(`0${text}`);
54
+ }
55
+ function timeMessages(locale, messages = {}) {
56
+ const ko = /^ko(?:-|$)/i.test(locale);
57
+ return {
58
+ open: ko ? "시간 목록 열기" : "Open time list",
59
+ clear: ko ? "시간 지우기" : "Clear time",
60
+ empty: ko ? "맞는 시간이 없습니다" : "No matching time",
61
+ ...messages
62
+ };
63
+ }
64
+ //#endregion
65
+ //#region src/time-picker.tsx
66
+ var _tmpl$ = ["<svg", " width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18z\"></path><path d=\"M12 7v5l3 2\"></path></svg>"];
67
+ /** Above this many rows the list is virtualized (1-minute steps list 1,440 times). */
68
+ var VIRTUALIZE_AFTER = 300;
69
+ function ClockIcon() {
70
+ return ssr(_tmpl$, ssrHydrationKey());
71
+ }
72
+ /**
73
+ * A time-of-day field: type a time or pick one from the list. Built on the
74
+ * same Ark combobox as Combobox, so list, keyboard and form behavior match.
75
+ */
76
+ function TimePicker(props) {
77
+ const [local, shared] = splitProps(props, [
78
+ "value",
79
+ "defaultValue",
80
+ "onValueChange",
81
+ "step",
82
+ "placeholder",
83
+ "invalid",
84
+ "locale",
85
+ "messages"
86
+ ]);
87
+ const initial = () => normalizeTime(local.defaultValue ?? "") ?? "";
88
+ const [internal, setInternal] = createSignal(initial());
89
+ const raw = () => local.value ?? internal();
90
+ const canonical = () => raw() === "" ? "" : normalizeTime(raw());
91
+ const current = () => canonical() ?? raw();
92
+ const [draft, setDraft] = createSignal(current());
93
+ const items = createMemo(() => {
94
+ const values = new Set(timeOptions(local.step ?? 10));
95
+ const selected = canonical(), typed = parseTypedTime(draft());
96
+ if (selected) values.add(selected);
97
+ if (typed) values.add(typed);
98
+ return [...values].sort().map((value) => ({
99
+ value,
100
+ label: value
101
+ }));
102
+ });
103
+ return createComponent(Choice, mergeProps$1(shared, {
104
+ searchable: true,
105
+ rootClass: "dds-time-picker",
106
+ get items() {
107
+ return items();
108
+ },
109
+ get value() {
110
+ return current();
111
+ },
112
+ get selectedOption() {
113
+ return {
114
+ value: current(),
115
+ label: current()
116
+ };
117
+ },
118
+ onValueChange: (next) => {
119
+ if (local.value === void 0) setInternal(next);
120
+ local.onValueChange?.(next);
121
+ },
122
+ onFormReset: () => {
123
+ if (local.value === void 0) setInternal(initial());
124
+ },
125
+ get inputValue() {
126
+ return draft();
127
+ },
128
+ onInputValueChange: setDraft,
129
+ matchItem: (item, query) => matchesTimeQuery(item.value, query),
130
+ commitDraft: (text) => text.trim() === "" ? "" : parseTypedTime(text),
131
+ triggerContent: () => createComponent(ClockIcon, {}),
132
+ autoHighlight: true,
133
+ centerSelected: true,
134
+ inputMode: "numeric",
135
+ get virtualization() {
136
+ return items().length > VIRTUALIZE_AFTER ? {} : false;
137
+ },
138
+ get messages() {
139
+ return timeMessages(local.locale ?? "ko-KR", local.messages);
140
+ },
141
+ get placeholder() {
142
+ return local.placeholder ?? "HH:MM";
143
+ },
144
+ get invalid() {
145
+ return local.invalid === true || canonical() === null;
146
+ }
147
+ }));
148
+ }
149
+ //#endregion
150
+ export { TimePicker };
151
+
152
+ //# sourceMappingURL=time-picker.server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time-picker.server.js","names":["createMemo","createSignal","splitProps","ChoiceOption","Choice","matchesTimeQuery","normalizeTime","parseTypedTime","timeMessages","timeOptions","TimeMessages","TimePickerProps","value","defaultValue","onValueChange","step","label","labelPlacement","id","name","form","placeholder","clearable","disabled","readOnly","required","invalid","locale","messages","VIRTUALIZE_AFTER","ClockIcon","_$ssr","_tmpl$","_$ssrHydrationKey","TimePicker","props","local","shared","initial","internal","setInternal","raw","canonical","current","draft","setDraft","items","values","Set","selected","typed","add","sort","map","_$createComponent","_$mergeProps","searchable","rootClass","selectedOption","next","undefined","onFormReset","inputValue","onInputValueChange","matchItem","item","query","commitDraft","text","trim","triggerContent","autoHighlight","centerSelected","inputMode","virtualization","length"],"sources":["../src/time-only.ts","../src/time-picker.tsx"],"sourcesContent":["// Time-of-day values are 24-hour \"HH:MM\" strings; \"\" is empty. Servers may send\n// \"HH:MM:SS\" — it is accepted and shown as HH:MM, but never rewritten until the\n// user picks a time.\nconst API_TIME = /^([01]\\d|2[0-3]):([0-5]\\d)(?::[0-5]\\d(?:\\.\\d+)?)?$/;\n\n/** Canonical \"HH:MM\" for an API value, or null when it is not a time. */\nexport function normalizeTime(value: string): string | null {\n const match = API_TIME.exec(value);\n return match ? `${match[1]}:${match[2]}` : null;\n}\n\nconst pad = (value: number) => String(value).padStart(2, \"0\");\nconst fromParts = (hour: number, minute: number) =>\n hour <= 23 && minute <= 59 ? `${pad(hour)}:${pad(minute)}` : null;\n\n/**\n * What a person typed, read as a complete time: \"9:05\", \"09:05\", \"09:05:00\",\n * \"0905\", or \"905\" when the first two digits cannot be an hour. Full-width\n * colons and dots count as colons. Partial text (\"10\", \"10:4\", and \"103\",\n * which is still on its way to 10:30) is not a time.\n */\nexport function parseTypedTime(text: string): string | null {\n const value = text.trim().replace(/[:.]/g, \":\");\n const separated = /^(\\d{1,2}):(\\d{2})(?::\\d{2})?$/.exec(value);\n if (separated) return fromParts(Number(separated[1]), Number(separated[2]));\n if (/^\\d{4}$/.test(value))\n return fromParts(Number(value.slice(0, 2)), Number(value.slice(2)));\n if (/^\\d{3}$/.test(value) && Number(value.slice(0, 2)) > 23)\n return fromParts(Number(value[0]), Number(value.slice(1)));\n return null;\n}\n\n/** 00:00 up to the last step before 24:00. Steps below one minute become one; a non-number becomes 10. */\nexport function timeOptions(step: number) {\n const minutes = Number.isFinite(step) ? Math.max(1, Math.floor(step)) : 10;\n const values: string[] = [];\n for (let at = 0; at < 24 * 60; at += minutes)\n values.push(`${pad(Math.floor(at / 60))}:${pad(at % 60)}`);\n return values;\n}\n\n/**\n * Whether a \"HH:MM\" option matches partial typing. Digits read as the start of\n * the time (\"10\" → 10:00–10:59, \"1030\" → 10:30); an odd digit count or an\n * impossible hour also tries a leading zero (\"9\" → 09:xx, \"930\" → 09:30).\n * With a colon the hour may be one digit (\"9:3\" → 09:30–09:39).\n */\nexport function matchesTimeQuery(option: string, query: string) {\n const text = query.trim().replace(/[:.]/g, \":\");\n if (text === \"\") return true;\n const typed = parseTypedTime(text);\n if (typed) return option === typed;\n if (text.includes(\":\")) {\n const [hour = \"\", minute = \"\", ...rest] = text.split(\":\");\n if (rest.length || !/^\\d{1,2}$/.test(hour) || !/^\\d{0,2}$/.test(minute))\n return false;\n return option.startsWith(`${hour.padStart(2, \"0\")}:${minute}`);\n }\n if (!/^\\d{1,4}$/.test(text)) return false;\n const digits = option.replace(\":\", \"\");\n if (digits.startsWith(text)) return true;\n return (\n (text.length % 2 === 1 || Number(text.slice(0, 2)) > 23) &&\n digits.startsWith(`0${text}`)\n );\n}\n\nexport interface TimeMessages {\n /** Accessible name of the clock button that opens the list. */\n open?: string;\n /** Accessible name of the clear button. */\n clear?: string;\n /** Status when nothing in the list matches the typed text. */\n empty?: string;\n}\nexport function timeMessages(locale: string, messages: TimeMessages = {}) {\n const ko = /^ko(?:-|$)/i.test(locale);\n return {\n open: ko ? \"시간 목록 열기\" : \"Open time list\",\n clear: ko ? \"시간 지우기\" : \"Clear time\",\n empty: ko ? \"맞는 시간이 없습니다\" : \"No matching time\",\n ...messages,\n };\n}\n","import { createMemo, createSignal, splitProps } from \"solid-js\";\nimport type { ChoiceOption } from \"./choice-types\";\nimport { Choice } from \"./internal/choice\";\nimport {\n matchesTimeQuery,\n normalizeTime,\n parseTypedTime,\n timeMessages,\n timeOptions,\n type TimeMessages,\n} from \"./time-only\";\nexport type { TimeMessages } from \"./time-only\";\n\nexport interface TimePickerProps {\n /** 24-hour \"HH:MM\" (\"\" is empty). \"HH:MM:SS\" is accepted and shown as HH:MM. */\n value?: string;\n defaultValue?: string;\n /** Receives \"HH:MM\" or \"\" — only when the person picks, types or clears a time. */\n onValueChange?: (value: string) => void;\n /** Minutes between listed times, from 00:00 (default 10). Typed times off the step are still accepted. */\n step?: number;\n label?: string;\n labelPlacement?: \"outside\" | \"inside\" | \"hidden\";\n \"aria-label\"?: string;\n \"aria-labelledby\"?: string;\n \"aria-describedby\"?: string;\n id?: string;\n name?: string;\n form?: string;\n placeholder?: string;\n clearable?: boolean;\n disabled?: boolean;\n readOnly?: boolean;\n required?: boolean;\n invalid?: boolean;\n /** Chooses the built-in Korean or English text (default \"ko-KR\"). */\n locale?: string;\n messages?: TimeMessages;\n}\n\n/** Above this many rows the list is virtualized (1-minute steps list 1,440 times). */\nconst VIRTUALIZE_AFTER = 300;\n\n// The dds-icons \"clock\" glyph, inlined like DatePicker's calendar so this\n// subpath does not pull in the whole icon set.\nfunction ClockIcon() {\n return (\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.6\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18z\" />\n <path d=\"M12 7v5l3 2\" />\n </svg>\n );\n}\n\n/**\n * A time-of-day field: type a time or pick one from the list. Built on the\n * same Ark combobox as Combobox, so list, keyboard and form behavior match.\n */\nexport function TimePicker(props: TimePickerProps) {\n const [local, shared] = splitProps(props, [\n \"value\",\n \"defaultValue\",\n \"onValueChange\",\n \"step\",\n \"placeholder\",\n \"invalid\",\n \"locale\",\n \"messages\",\n ]);\n const initial = () => normalizeTime(local.defaultValue ?? \"\") ?? \"\";\n const [internal, setInternal] = createSignal(initial());\n const raw = () => local.value ?? internal();\n const canonical = () => (raw() === \"\" ? \"\" : normalizeTime(raw()));\n // A value that is not a time is shown as it came, marked invalid, and never rewritten.\n const current = () => canonical() ?? raw();\n const [draft, setDraft] = createSignal(current());\n const items = createMemo<ChoiceOption[]>(() => {\n const values = new Set(timeOptions(local.step ?? 10));\n const selected = canonical(),\n typed = parseTypedTime(draft());\n if (selected) values.add(selected);\n if (typed) values.add(typed);\n return [...values].sort().map((value) => ({ value, label: value }));\n });\n return (\n <Choice\n {...shared}\n searchable\n rootClass=\"dds-time-picker\"\n items={items()}\n value={current()}\n // Only read when the value is not a listed time (an invalid server value).\n selectedOption={{ value: current(), label: current() }}\n onValueChange={(next) => {\n if (local.value === undefined) setInternal(next);\n local.onValueChange?.(next);\n }}\n onFormReset={() => {\n if (local.value === undefined) setInternal(initial());\n }}\n inputValue={draft()}\n onInputValueChange={setDraft}\n matchItem={(item, query) => matchesTimeQuery(item.value, query)}\n commitDraft={(text) => (text.trim() === \"\" ? \"\" : parseTypedTime(text))}\n triggerContent={() => <ClockIcon />}\n autoHighlight\n centerSelected\n inputMode=\"numeric\"\n virtualization={items().length > VIRTUALIZE_AFTER ? {} : false}\n messages={timeMessages(local.locale ?? \"ko-KR\", local.messages)}\n placeholder={local.placeholder ?? \"HH:MM\"}\n invalid={local.invalid === true || canonical() === null}\n />\n );\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devslab/dds-solid",
3
- "version": "0.22.1",
3
+ "version": "0.24.0",
4
4
  "description": "Accessible SolidJS primitives for the DevsLab Design System",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -90,13 +90,53 @@
90
90
  "browser": "./dist/date-picker.js",
91
91
  "node": "./dist/date-picker.server.js",
92
92
  "default": "./dist/date-picker.js"
93
+ },
94
+ "./time-picker": {
95
+ "types": "./dist/time-picker.d.ts",
96
+ "worker": "./dist/time-picker.server.js",
97
+ "workerd": "./dist/time-picker.server.js",
98
+ "browser": "./dist/time-picker.js",
99
+ "node": "./dist/time-picker.server.js",
100
+ "default": "./dist/time-picker.js"
101
+ },
102
+ "./segmented-control": {
103
+ "types": "./dist/segmented-control.d.ts",
104
+ "worker": "./dist/segmented-control.server.js",
105
+ "workerd": "./dist/segmented-control.server.js",
106
+ "browser": "./dist/segmented-control.js",
107
+ "node": "./dist/segmented-control.server.js",
108
+ "default": "./dist/segmented-control.js"
109
+ },
110
+ "./number-input": {
111
+ "types": "./dist/number-input.d.ts",
112
+ "worker": "./dist/number-input.server.js",
113
+ "workerd": "./dist/number-input.server.js",
114
+ "browser": "./dist/number-input.js",
115
+ "node": "./dist/number-input.server.js",
116
+ "default": "./dist/number-input.js"
117
+ },
118
+ "./date-range-picker": {
119
+ "types": "./dist/date-range-picker.d.ts",
120
+ "worker": "./dist/date-range-picker.server.js",
121
+ "workerd": "./dist/date-range-picker.server.js",
122
+ "browser": "./dist/date-range-picker.js",
123
+ "node": "./dist/date-range-picker.server.js",
124
+ "default": "./dist/date-range-picker.js"
125
+ },
126
+ "./month-picker": {
127
+ "types": "./dist/month-picker.d.ts",
128
+ "worker": "./dist/month-picker.server.js",
129
+ "workerd": "./dist/month-picker.server.js",
130
+ "browser": "./dist/month-picker.js",
131
+ "node": "./dist/month-picker.server.js",
132
+ "default": "./dist/month-picker.js"
93
133
  }
94
134
  },
95
135
  "dependencies": {
96
136
  "@ark-ui/solid": "5.39.3",
97
- "@devslab/dds-css": "0.22.1",
98
- "@devslab/dds-icons": "0.22.1",
99
- "@devslab/dds-tokens": "0.22.1",
137
+ "@devslab/dds-css": "0.24.0",
138
+ "@devslab/dds-icons": "0.24.0",
139
+ "@devslab/dds-tokens": "0.24.0",
100
140
  "@tanstack/solid-virtual": "3.13.48",
101
141
  "@zag-js/aria-hidden": "1.45.0",
102
142
  "@zag-js/focus-trap": "1.45.0"
package/styles.css CHANGED
@@ -33,7 +33,37 @@
33
33
  .dds-date-picker-table [data-part="table-cell-trigger"][data-selected] {background:var(--dds-color-bg-brand);color:var(--dds-color-text-on-brand);}
34
34
  .dds-date-picker-table [data-today]:not([data-selected]) {text-decoration:underline;text-underline-offset:4px;}
35
35
  .dds-date-picker-content :focus-visible {outline:2px solid var(--dds-color-text-brand);outline-offset:2px;}
36
- .dds-date-picker-footer {display:flex;justify-content:space-between;gap:12px;margin-top:12px;padding-top:12px;border-top:1px solid var(--dds-color-border-default);}
36
+ .dds-date-picker-footer {display:flex;flex-wrap:wrap;justify-content:space-between;gap:12px;margin-top:12px;padding-top:12px;border-top:1px solid var(--dds-color-border-default);}
37
+
38
+ /* Text box shared by DatePicker, MonthPicker and the DateRangePicker pair: same 40px DDS input look. */
39
+ .dds-date-picker-control > input,.dds-date-range-box {box-sizing:border-box;flex:1;min-inline-size:0;block-size:var(--dds-space-40);border:1px solid var(--dds-color-border-strong);border-radius:var(--dds-radius-md);background:var(--dds-color-bg-default);color:var(--dds-color-text-primary);font-family:inherit;font-size:var(--dds-typo-body-2-font-size);font-variant-numeric:tabular-nums;}
40
+ .dds-date-picker-control > input {padding-inline:var(--dds-space-12);}
41
+ .dds-date-picker-control > input:focus-visible,.dds-date-range-box:focus-within {outline:var(--dds-space-2) solid var(--dds-color-border-focus);outline-offset:0;}
42
+ .dds-date-picker-control > input[aria-invalid="true"],.dds-date-range-box[data-invalid] {border-color:var(--dds-color-status-danger);}
43
+ .dds-date-picker-control > input:disabled,.dds-date-range-box[data-disabled] {opacity:.45;cursor:not-allowed;background:var(--dds-color-bg-subtle);}
44
+ .dds-date-picker-control > input::placeholder,.dds-date-range-input::placeholder {color:var(--dds-color-text-muted);}
45
+ .dds-date-range-box {display:flex;align-items:center;gap:var(--dds-space-8);padding-inline:var(--dds-space-12);}
46
+ .dds-date-range-box[hidden] {display:none;}
47
+ .dds-date-range-input {flex:1;inline-size:100%;min-inline-size:0;block-size:100%;padding:0;border:0;background:transparent;color:inherit;font:inherit;font-variant-numeric:tabular-nums;outline:none;}
48
+ .dds-date-range-input:disabled {cursor:not-allowed;}
49
+ .dds-date-range-separator {flex:none;color:var(--dds-color-text-secondary);}
50
+ .dds-field__error {font-size:var(--dds-typo-caption-font-size);line-height:var(--dds-typo-caption-line-height);color:var(--dds-color-status-danger);}
51
+ @media (pointer:coarse) {.dds-date-picker-control > input,.dds-date-range-box {min-block-size:44px;}}
52
+
53
+ /* Range selection: ends filled, days between tinted, hover previews the end being chosen. */
54
+ .dds-date-picker-table [data-part="table-cell-trigger"][data-in-range] {background:var(--dds-color-bg-brand-subtle);color:var(--dds-color-text-primary);border-radius:0;}
55
+ .dds-date-picker-table [data-part="table-cell-trigger"]:is([data-range-start],[data-range-end]) {background:var(--dds-color-bg-brand);color:var(--dds-color-text-on-brand);border-radius:var(--dds-radius-sm);}
56
+ .dds-date-picker-table [data-part="table-cell-trigger"][data-hover-range-end]:not([data-range-start]) {box-shadow:inset 0 0 0 2px var(--dds-color-bg-brand);border-radius:var(--dds-radius-sm);}
57
+ .dds-date-picker-presets {display:flex;flex-wrap:wrap;gap:var(--dds-space-8);flex:1 1 100%;}
58
+ .dds-date-picker-presets[hidden] {display:none;}
59
+ .dds-date-picker-footer > [data-part="clear-trigger"] {margin-inline-start:auto;}
60
+ /* Days and months outside min/max read as unavailable, not as ordinary choices. */
61
+ .dds-date-picker-table [data-part="table-cell-trigger"][data-disabled] {opacity:.45;cursor:not-allowed;background:transparent;}
62
+
63
+ /* Month grid (MonthPicker): 3 columns × 4 rows, year paged in the header. */
64
+ .dds-date-picker-year {font-variant-numeric:tabular-nums;}
65
+ .dds-date-picker-table--months td {padding:var(--dds-space-4);}
66
+ .dds-date-picker-table--months [data-part="table-cell-trigger"] {height:var(--dds-space-40);}
37
67
 
38
68
  /* Standalone Calendar shares the DatePicker view without popup positioning. */
39
69
  .dds-calendar {display:block;}
@@ -1 +0,0 @@
1
- {"version":3,"file":"calendar-view-1RO2mtf1.js","names":["createUniqueId","splitProps","JSX","ParentProps","createControllableSignal","useCheckbox","useSwitch","Field","ArkField","classes","describedBy","ButtonTone","ControlSize","ButtonProps","Omit","ButtonHTMLAttributes","HTMLButtonElement","class","tone","size","loading","Button","props","local","rest","_$ssrElement","_$mergeProps","type","undefined","disabled","aria-busy","_tmpl$","_$ssrHydrationKey","_$escape","children","IconButtonProps","Element","IconButton","FieldControlProps","id","FieldProps","label","helpText","error","required","generated","helpId","errorId","control","_$createComponent","Root","invalid","Boolean","ids","helperText","errorText","Label","for","_$ssr","_tmpl$2","HelperText","ErrorText","role","SelectProps","SelectHTMLAttributes","HTMLSelectElement","Select","_tmpl$3","_$ssrAttribute","aria-invalid","CheckableProps","InputHTMLAttributes","HTMLInputElement","checked","defaultChecked","onCheckedChange","inputClass","Checkable","setChecked","value","defaultValue","onChange","_tmpl$4","CheckboxProps","Checkbox","ArkCheckable","kind","RadioProps","Radio","SwitchProps","Switch","options","hiddenInput","details","readOnly","readonly","name","form","String","api","rootProps","attributes","getRootProps","getHiddenInputProps","style","getLabelProps","callInputHandler","handler","FocusEventHandlerUnion","FocusEvent","event","currentTarget","target","DatePicker","ArkDatePicker","For","Show","Button","dateMessages","todayDate","validateInput","CalendarMessages","Chevron","props","next","_$ssr","_tmpl$","_$ssrHydrationKey","_$ssrAttribute","CalendarViewProps","timeZone","min","max","locale","messages","disabled","readOnly","showToday","showClear","onClear","CalendarView","text","locked","_$createComponent","View","view","children","Context","picker","ViewControl","PrevTrigger","aria-label","previousMonth","RangeText","NextTrigger","nextMonth","Table","TableHead","TableRow","each","weekDays","day","TableHeader","short","TableBody","weeks","week","TableCell","value","TableCellTrigger","_tmpl$2","_$escape","when","type","tone","valid","onClick","selectToday","today","ClearTrigger","hidden","onPointerDown","event","preventDefault","clear"],"sources":["../../src/controllable.ts","../../src/controls.tsx","../../src/date-only.ts","../../src/calendar-view.tsx"],"sourcesContent":["import { createSignal, type Accessor } from \"solid-js\";\n\nexport interface ControllableOptions<T> {\n value: Accessor<T | undefined>;\n defaultValue: T;\n onChange: ((value: T) => void) | undefined;\n}\n\nexport type ControllableSetter<T> = (next: T | ((previous: T) => T)) => T;\n\nexport function createControllableSignal<T>(options: ControllableOptions<T>): [Accessor<T>, ControllableSetter<T>] {\n const [internal, setInternal] = createSignal(options.defaultValue);\n const value: Accessor<T> = () => options.value() ?? internal();\n const setInternalValue = setInternal as unknown as ControllableSetter<T>;\n const setValue: ControllableSetter<T> = (next) => {\n const resolved = typeof next === \"function\"\n ? (next as (previous: T) => T)(value())\n : next;\n if (options.value() === undefined) setInternalValue(() => resolved);\n options.onChange?.(resolved);\n return resolved;\n };\n return [value, setValue];\n}\n","import {\n createUniqueId,\n splitProps,\n type JSX,\n type ParentProps,\n} from \"solid-js\";\n\nimport { createControllableSignal } from \"./controllable\";\nimport { useCheckbox } from \"@ark-ui/solid/checkbox\";\nimport { useSwitch } from \"@ark-ui/solid/switch\";\nimport { Field as ArkField } from \"@ark-ui/solid/field\";\nimport { classes, describedBy } from \"./utils\";\n\nexport type ButtonTone = \"primary\" | \"secondary\" | \"ghost\" | \"danger\";\nexport type ControlSize = \"sm\" | \"md\" | \"lg\";\n\nexport interface ButtonProps extends Omit<JSX.ButtonHTMLAttributes<HTMLButtonElement>, \"class\"> {\n class?: string;\n tone?: ButtonTone;\n size?: ControlSize;\n loading?: boolean;\n}\n\nexport function Button(props: ParentProps<ButtonProps>) {\n const [local, rest] = splitProps(props, [\"class\", \"tone\", \"size\", \"loading\", \"disabled\", \"type\", \"children\"]);\n return (\n <button\n {...rest}\n type={local.type ?? \"button\"}\n class={classes(\"dds-btn\", `dds-btn--${local.tone ?? \"primary\"}`, local.size !== \"md\" && local.size ? `dds-btn--${local.size}` : undefined, local.class)}\n disabled={local.disabled || local.loading}\n aria-busy={local.loading ? \"true\" : undefined}\n >\n {local.loading && <span class=\"dds-spinner\" aria-hidden=\"true\" />}\n {local.children}\n </button>\n );\n}\n\nexport interface IconButtonProps extends Omit<ButtonProps, \"tone\" | \"children\"> {\n \"aria-label\": string;\n tone?: \"ghost\" | \"secondary\" | \"danger\";\n children: JSX.Element;\n}\n\nexport function IconButton(props: IconButtonProps) {\n const [local, rest] = splitProps(props, [\"class\", \"tone\", \"size\", \"loading\", \"disabled\", \"type\", \"children\"]);\n return (\n <button\n {...rest}\n type={local.type ?? \"button\"}\n class={classes(\"dds-iconbtn\", local.tone && local.tone !== \"ghost\" ? `dds-iconbtn--${local.tone}` : undefined, local.size !== \"md\" && local.size ? `dds-iconbtn--${local.size}` : undefined, local.class)}\n disabled={local.disabled || local.loading}\n aria-busy={local.loading ? \"true\" : undefined}\n >\n {local.loading ? <span class=\"dds-spinner\" aria-hidden=\"true\" /> : local.children}\n </button>\n );\n}\n\nexport interface FieldControlProps {\n id: string;\n \"aria-describedby\": string | undefined;\n \"aria-invalid\": \"true\" | undefined;\n \"aria-required\": \"true\" | undefined;\n}\n\nexport interface FieldProps {\n id?: string;\n label: JSX.Element;\n helpText?: JSX.Element;\n error?: JSX.Element;\n required?: boolean;\n class?: string;\n children: JSX.Element | ((props: FieldControlProps) => JSX.Element);\n}\n\nexport function Field(props: FieldProps) {\n const generated = createUniqueId();\n const id = () => props.id ?? `dds-field-${generated}`;\n const helpId = () => props.helpText ? `${id()}-help` : undefined;\n const errorId = () => props.error ? `${id()}-error` : undefined;\n const control = (): FieldControlProps => ({\n id: id(),\n \"aria-describedby\": describedBy(helpId(), errorId()),\n \"aria-invalid\": props.error ? \"true\" : undefined,\n \"aria-required\": props.required ? \"true\" : undefined,\n });\n return (\n <ArkField.Root id={id()} required={props.required ?? false} invalid={Boolean(props.error)} ids={{ control: `${id()}-root`, helperText: `${id()}-help`, errorText: `${id()}-error` }} class={classes(\"dds-field\", props.error ? \"dds-field--error\" : undefined, props.class)}>\n <ArkField.Label class=\"dds-field__label\" for={id()}>{props.label}{props.required && <span aria-hidden=\"true\"> *</span>}</ArkField.Label>\n {typeof props.children === \"function\" ? props.children(control()) : props.children}\n {props.helpText && <ArkField.HelperText class=\"dds-field__help\">{props.helpText}</ArkField.HelperText>}\n {props.error && <ArkField.ErrorText class=\"dds-field__error\" role=\"alert\">{props.error}</ArkField.ErrorText>}\n </ArkField.Root>\n );\n}\n\nexport interface SelectProps extends Omit<JSX.SelectHTMLAttributes<HTMLSelectElement>, \"class\"> {\n class?: string;\n invalid?: boolean;\n}\n\nexport function Select(props: ParentProps<SelectProps>) {\n const [local, rest] = splitProps(props, [\"class\", \"invalid\", \"children\"]);\n return (\n <span class={classes(\"dds-select\", local.class)}>\n <select {...rest} class=\"dds-select__input\" aria-invalid={local.invalid ? \"true\" : undefined}>\n {local.children}\n </select>\n </span>\n );\n}\n\ninterface CheckableProps extends Omit<JSX.InputHTMLAttributes<HTMLInputElement>, \"checked\" | \"class\" | \"onChange\" | \"role\" | \"type\"> {\n checked?: boolean;\n defaultChecked?: boolean;\n onCheckedChange?: (checked: boolean) => void;\n label: JSX.Element;\n class?: string;\n inputClass?: string;\n}\n\nfunction Checkable(props: CheckableProps & { type: \"checkbox\" | \"radio\"; role?: \"switch\" }) {\n const [local, rest] = splitProps(props, [\"checked\", \"defaultChecked\", \"onCheckedChange\", \"label\", \"class\", \"inputClass\", \"type\", \"role\"]);\n const [checked, setChecked] = createControllableSignal({\n value: () => local.checked,\n defaultValue: local.defaultChecked ?? false,\n onChange: local.onCheckedChange,\n });\n return (\n <label class={classes(local.role === \"switch\" ? \"dds-switch\" : \"dds-check\", local.class)}>\n <input\n {...rest}\n type={local.type}\n role={local.role}\n class={classes(local.role === \"switch\" ? \"dds-switch__input\" : \"dds-check__input\", local.inputClass)}\n checked={checked()}\n onChange={(event) => setChecked(event.currentTarget.checked)}\n />\n <span>{local.label}</span>\n </label>\n );\n}\n\nexport type CheckboxProps = CheckableProps;\nexport const Checkbox = (props: CheckboxProps) => <ArkCheckable {...props} kind=\"checkbox\" />;\n\nexport type RadioProps = CheckableProps;\nexport const Radio = (props: RadioProps) => <Checkable {...props} type=\"radio\" />;\n\nexport type SwitchProps = CheckableProps;\nexport const Switch = (props: SwitchProps) => <ArkCheckable {...props} kind=\"switch\" />;\n\nfunction ArkCheckable(props: CheckableProps & { kind: \"checkbox\" | \"switch\" }) {\n const generated = createUniqueId();\n const [local, rest] = splitProps(props, [\"checked\", \"defaultChecked\", \"onCheckedChange\", \"label\", \"class\", \"inputClass\", \"kind\", \"id\", \"onClick\", \"onFocusIn\", \"onFocusOut\", \"style\"]);\n const options = () => ({\n id: `dds-check-${generated}`,\n ids: { hiddenInput: local.id ?? `dds-check-${generated}-input` },\n checked: local.checked, defaultChecked: local.defaultChecked,\n onCheckedChange: (details: { checked: boolean | \"indeterminate\" }) => local.onCheckedChange?.(details.checked === true),\n disabled: rest.disabled, required: rest.required, readOnly: rest.readonly,\n name: rest.name, form: rest.form, value: String(rest.value ?? \"on\"),\n });\n const api = local.kind === \"switch\" ? useSwitch(options) : useCheckbox(options);\n const inputClass = () => local.kind === \"switch\" ? \"dds-switch__input\" : \"dds-check__input\";\n const rootProps = () => {\n const [, attributes] = splitProps(api().getRootProps(), [\"onClick\"]);\n return attributes;\n };\n return <label {...rootProps()} class={classes(local.kind === \"switch\" ? \"dds-switch\" : \"dds-check\", local.class)}>\n <input {...api().getHiddenInputProps()} {...rest}\n ref={(input) => {\n // Ark normalizes defaultChecked to checked. Preserve the native reset\n // baseline as well when rendering its input visibly with DDS CSS.\n input.defaultChecked = local.checked ?? local.defaultChecked ?? false;\n if (typeof rest.ref === \"function\") rest.ref(input);\n }}\n type=\"checkbox\" role={local.kind === \"switch\" ? \"switch\" : undefined}\n class={classes(inputClass(), local.inputClass)}\n style={local.style ?? {}} checked={api().checked}\n onFocusIn={(event) => {\n callInputHandler(api().getHiddenInputProps().onFocusIn, event);\n callInputHandler(local.onFocusIn, event);\n }}\n onFocusOut={(event) => {\n callInputHandler(api().getHiddenInputProps().onFocusOut, event);\n callInputHandler(local.onFocusOut, event);\n }}\n onClick={(event) => {\n if (typeof local.onClick === \"function\") local.onClick(event);\n else if (local.onClick) local.onClick[0](local.onClick[1], event);\n if (!event.defaultPrevented) {\n const handler = api().getHiddenInputProps().onClick;\n if (typeof handler === \"function\") handler(event);\n else if (handler) handler[0](handler[1], event);\n }\n }}\n />\n <span {...api().getLabelProps()}>{local.label}</span>\n </label>;\n}\n\nfunction callInputHandler(handler: JSX.FocusEventHandlerUnion<HTMLInputElement, FocusEvent> | undefined, event: FocusEvent & { currentTarget: HTMLInputElement; target: HTMLInputElement }) {\n if (typeof handler === \"function\") handler(event);\n else if (handler) handler[0](handler[1], event);\n}\n","export interface DatePickerValidity {\n /** Exact displayed draft; never persist this display text as an API date. */\n inputValue: string;\n /** Valid ISO date, optional empty string, or null when invalid/incomplete. */\n value: string | null;\n valid: boolean;\n reason:\n | \"valid\"\n | \"required\"\n | \"incomplete\"\n | \"invalid\"\n | \"rangeUnderflow\"\n | \"rangeOverflow\";\n}\n// Date-only Gregorian validation: never let a permissive parser repair user text.\nexport function isCalendarDate(value: string) {\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(value)) return false;\n const year = Number(value.slice(0, 4)),\n month = Number(value.slice(5, 7)),\n day = Number(value.slice(8, 10));\n if (year < 1 || month < 1 || month > 12 || day < 1) return false;\n const leap = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);\n return (\n day <=\n [31, leap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month - 1]!\n );\n}\nexport function isKorean(locale: string) {\n return /^ko(?:-|$)/i.test(locale);\n}\nexport function displayDate(value: string, locale: string) {\n return isKorean(locale) && isCalendarDate(value)\n ? value.replaceAll(\"-\", \"/\")\n : value;\n}\nexport function canonicalInput(inputValue: string, locale: string) {\n return isKorean(locale) && /^\\d{4}\\/\\d{2}\\/\\d{2}$/.test(inputValue)\n ? inputValue.replaceAll(\"/\", \"-\")\n : inputValue;\n}\nexport function validateInput(\n inputValue: string,\n required: boolean,\n min?: string,\n max?: string,\n locale = \"en-US\",\n): DatePickerValidity {\n const canonical = canonicalInput(inputValue, locale);\n const incomplete =\n inputValue.length < 10 &&\n (/^\\d{0,4}(?:-\\d{0,2}(?:-\\d{0,2})?)?$/.test(inputValue) ||\n (isKorean(locale) &&\n /^\\d{0,4}(?:\\/\\d{0,2}(?:\\/\\d{0,2})?)?$/.test(inputValue)));\n let reason: DatePickerValidity[\"reason\"] = \"valid\";\n if (inputValue === \"\") reason = required ? \"required\" : \"valid\";\n else if (!isCalendarDate(canonical))\n reason = incomplete ? \"incomplete\" : \"invalid\";\n else if (\n (min && !isCalendarDate(min)) ||\n (max && !isCalendarDate(max)) ||\n (min && max && min > max)\n )\n reason = \"invalid\";\n else if (min && canonical < min) reason = \"rangeUnderflow\";\n else if (max && canonical > max) reason = \"rangeOverflow\";\n return {\n inputValue,\n value: reason === \"valid\" ? canonical : null,\n valid: reason === \"valid\",\n reason,\n };\n}\n\nexport interface CalendarMessages {\n previousMonth?: string;\n nextMonth?: string;\n today?: string;\n clear?: string;\n openCalendar?: string;\n selectDate?: (dateText: string) => string;\n required?: string;\n invalid?: string;\n}\nexport function dateMessages(locale: string, messages: CalendarMessages = {}) {\n const ko = isKorean(locale);\n return {\n previousMonth: ko ? \"이전 달\" : \"Previous month\",\n nextMonth: ko ? \"다음 달\" : \"Next month\",\n today: ko ? \"오늘\" : \"Today\",\n clear: ko ? \"선택 날짜 지우기\" : \"Clear selected date\",\n openCalendar: ko ? \"달력 열기\" : \"Open calendar\",\n selectDate: (text: string) => (ko ? `${text} 선택` : `Choose ${text}`),\n required: ko ? \"날짜를 입력해 주세요.\" : \"Enter a date.\",\n invalid: ko\n ? \"YYYY/MM/DD 형식의 유효한 범위 내 날짜를 입력해 주세요.\"\n : \"Enter a valid date within the allowed range (YYYY-MM-DD).\",\n ...messages,\n };\n}\n\n/** Today is the sole timestamp boundary; stored dates remain Gregorian date-only strings. */\nexport function todayDate(timeZone: string) {\n const parts = new Intl.DateTimeFormat(\"en-US-u-ca-gregory-nu-latn\", {\n timeZone,\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n }).formatToParts(new Date());\n const part = (type: string) =>\n parts.find((item) => item.type === type)!.value;\n return `${part(\"year\").padStart(4, \"0\")}-${part(\"month\")}-${part(\"day\")}`;\n}\n","import { DatePicker as ArkDatePicker } from \"@ark-ui/solid/date-picker\";\nimport { For, Show } from \"solid-js\";\nimport { Button } from \"./controls\";\nimport {\n dateMessages,\n todayDate,\n validateInput,\n type CalendarMessages,\n} from \"./date-only\";\nfunction Chevron(props: { 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 stroke-width=\"1.5\"\n aria-hidden=\"true\"\n >\n <path d={props.next ? \"m9 5 7 7-7 7\" : \"m15 5-7 7 7 7\"} />\n </svg>\n );\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}\n/** Internal view: the caller owns the single Ark root and its selection. */\nexport function CalendarView(props: CalendarViewProps) {\n const text = () => dateMessages(props.locale ?? \"ko-KR\", props.messages),\n locked = () => props.disabled || props.readOnly;\n return (\n <ArkDatePicker.View view=\"day\">\n <ArkDatePicker.Context>\n {(picker) => (\n <>\n <ArkDatePicker.ViewControl class=\"dds-date-picker-header\">\n <ArkDatePicker.PrevTrigger\n class=\"dds-btn dds-btn--secondary\"\n aria-label={text().previousMonth}\n >\n <Chevron />\n </ArkDatePicker.PrevTrigger>\n <ArkDatePicker.RangeText />\n <ArkDatePicker.NextTrigger\n class=\"dds-btn dds-btn--secondary\"\n aria-label={text().nextMonth}\n >\n <Chevron next />\n </ArkDatePicker.NextTrigger>\n </ArkDatePicker.ViewControl>\n <ArkDatePicker.Table class=\"dds-date-picker-table\">\n <ArkDatePicker.TableHead>\n <ArkDatePicker.TableRow>\n <For each={picker().weekDays}>\n {(day) => (\n <ArkDatePicker.TableHeader>\n {day.short}\n </ArkDatePicker.TableHeader>\n )}\n </For>\n </ArkDatePicker.TableRow>\n </ArkDatePicker.TableHead>\n <ArkDatePicker.TableBody>\n <For each={picker().weeks}>\n {(week) => (\n <ArkDatePicker.TableRow>\n <For each={week}>\n {(day) => (\n <ArkDatePicker.TableCell value={day}>\n <ArkDatePicker.TableCellTrigger>\n {day.day}\n </ArkDatePicker.TableCellTrigger>\n </ArkDatePicker.TableCell>\n )}\n </For>\n </ArkDatePicker.TableRow>\n )}\n </For>\n </ArkDatePicker.TableBody>\n </ArkDatePicker.Table>\n <div class=\"dds-date-picker-footer\">\n <Show when={props.showToday !== false}>\n <Button\n type=\"button\"\n tone=\"secondary\"\n disabled={\n locked() ||\n !validateInput(\n todayDate(props.timeZone ?? \"Asia/Seoul\"),\n false,\n props.min,\n props.max,\n props.locale,\n ).valid\n }\n onClick={() => {\n if (\n !locked() &&\n validateInput(\n todayDate(props.timeZone ?? \"Asia/Seoul\"),\n false,\n props.min,\n props.max,\n props.locale,\n ).valid\n )\n picker().selectToday();\n }}\n >\n {text().today}\n </Button>\n </Show>\n <Show when={props.showClear !== false}>\n <ArkDatePicker.ClearTrigger\n hidden={false}\n class=\"dds-btn dds-btn--secondary\"\n disabled={locked()}\n onPointerDown={(event) => event.preventDefault()}\n onClick={() => {\n if (!locked()) props.onClear?.();\n }}\n >\n {text().clear}\n </ArkDatePicker.ClearTrigger>\n </Show>\n </div>\n </>\n )}\n </ArkDatePicker.Context>\n </ArkDatePicker.View>\n );\n}\n"],"mappings":"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"}