@linyao.tw/ui 0.0.0-snapshot.07df57

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 (169) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +85 -0
  3. package/dist/components/date-time/calendar.d.ts +20 -0
  4. package/dist/components/date-time/calendar.js +102 -0
  5. package/dist/components/date-time/calendar.js.map +1 -0
  6. package/dist/components/date-time/date-field.d.ts +11 -0
  7. package/dist/components/date-time/date-field.js +44 -0
  8. package/dist/components/date-time/date-field.js.map +1 -0
  9. package/dist/components/date-time/date-picker.d.ts +28 -0
  10. package/dist/components/date-time/date-picker.js +74 -0
  11. package/dist/components/date-time/date-picker.js.map +1 -0
  12. package/dist/components/date-time/date-range-picker.d.ts +11 -0
  13. package/dist/components/date-time/date-range-picker.js +79 -0
  14. package/dist/components/date-time/date-range-picker.js.map +1 -0
  15. package/dist/components/date-time/date-types.d.ts +110 -0
  16. package/dist/components/date-time/index.d.ts +8 -0
  17. package/dist/components/date-time/index.js +8 -0
  18. package/dist/components/date-time/shared.d.ts +25 -0
  19. package/dist/components/date-time/shared.js +53 -0
  20. package/dist/components/date-time/shared.js.map +1 -0
  21. package/dist/components/date-time/time-field.d.ts +13 -0
  22. package/dist/components/date-time/time-field.js +52 -0
  23. package/dist/components/date-time/time-field.js.map +1 -0
  24. package/dist/components/feedback/alert.d.ts +21 -0
  25. package/dist/components/feedback/alert.js +44 -0
  26. package/dist/components/feedback/alert.js.map +1 -0
  27. package/dist/components/feedback/banner.d.ts +8 -0
  28. package/dist/components/feedback/banner.js +20 -0
  29. package/dist/components/feedback/banner.js.map +1 -0
  30. package/dist/components/feedback/empty-state.d.ts +12 -0
  31. package/dist/components/feedback/empty-state.js +48 -0
  32. package/dist/components/feedback/empty-state.js.map +1 -0
  33. package/dist/components/feedback/feedback.module.js +42 -0
  34. package/dist/components/feedback/feedback.module.js.map +1 -0
  35. package/dist/components/feedback/feedback.types.d.ts +8 -0
  36. package/dist/components/feedback/feedback.types.js +24 -0
  37. package/dist/components/feedback/feedback.types.js.map +1 -0
  38. package/dist/components/feedback/index.d.ts +9 -0
  39. package/dist/components/feedback/meter.d.ts +12 -0
  40. package/dist/components/feedback/meter.js +28 -0
  41. package/dist/components/feedback/meter.js.map +1 -0
  42. package/dist/components/feedback/progress.d.ts +12 -0
  43. package/dist/components/feedback/progress.js +28 -0
  44. package/dist/components/feedback/progress.js.map +1 -0
  45. package/dist/components/feedback/skeleton.d.ts +5 -0
  46. package/dist/components/feedback/skeleton.js +18 -0
  47. package/dist/components/feedback/skeleton.js.map +1 -0
  48. package/dist/components/feedback/spinner.d.ts +23 -0
  49. package/dist/components/feedback/spinner.js +35 -0
  50. package/dist/components/feedback/spinner.js.map +1 -0
  51. package/dist/components/feedback/toast.d.ts +33 -0
  52. package/dist/components/feedback/toast.js +76 -0
  53. package/dist/components/feedback/toast.js.map +1 -0
  54. package/dist/components/forms/CodeField.d.ts +23 -0
  55. package/dist/components/forms/CodeField.js +63 -0
  56. package/dist/components/forms/CodeField.js.map +1 -0
  57. package/dist/components/forms/FileUpload.d.ts +34 -0
  58. package/dist/components/forms/FileUpload.js +319 -0
  59. package/dist/components/forms/FileUpload.js.map +1 -0
  60. package/dist/components/forms/Input.d.ts +14 -0
  61. package/dist/components/forms/Input.js +33 -0
  62. package/dist/components/forms/Input.js.map +1 -0
  63. package/dist/components/forms/NumberField.d.ts +15 -0
  64. package/dist/components/forms/NumberField.js +71 -0
  65. package/dist/components/forms/NumberField.js.map +1 -0
  66. package/dist/components/forms/OTPField.d.ts +15 -0
  67. package/dist/components/forms/OTPField.js +54 -0
  68. package/dist/components/forms/OTPField.js.map +1 -0
  69. package/dist/components/forms/TextField.d.ts +61 -0
  70. package/dist/components/forms/TextField.js +199 -0
  71. package/dist/components/forms/TextField.js.map +1 -0
  72. package/dist/components/forms/index.d.ts +7 -0
  73. package/dist/components/forms/internal.d.ts +33 -0
  74. package/dist/components/forms/internal.js +61 -0
  75. package/dist/components/forms/internal.js.map +1 -0
  76. package/dist/components/foundations/Avatar.d.ts +33 -0
  77. package/dist/components/foundations/Avatar.js +45 -0
  78. package/dist/components/foundations/Avatar.js.map +1 -0
  79. package/dist/components/foundations/Badge.d.ts +15 -0
  80. package/dist/components/foundations/Badge.js +32 -0
  81. package/dist/components/foundations/Badge.js.map +1 -0
  82. package/dist/components/foundations/Button.d.ts +18 -0
  83. package/dist/components/foundations/Button.js +47 -0
  84. package/dist/components/foundations/Button.js.map +1 -0
  85. package/dist/components/foundations/Card.d.ts +47 -0
  86. package/dist/components/foundations/Card.js +57 -0
  87. package/dist/components/foundations/Card.js.map +1 -0
  88. package/dist/components/foundations/IconButton.d.ts +25 -0
  89. package/dist/components/foundations/IconButton.js +19 -0
  90. package/dist/components/foundations/IconButton.js.map +1 -0
  91. package/dist/components/foundations/Link.d.ts +19 -0
  92. package/dist/components/foundations/Link.js +40 -0
  93. package/dist/components/foundations/Link.js.map +1 -0
  94. package/dist/components/foundations/ListCell.d.ts +68 -0
  95. package/dist/components/foundations/ListCell.js +105 -0
  96. package/dist/components/foundations/ListCell.js.map +1 -0
  97. package/dist/components/foundations/SectionHeading.d.ts +17 -0
  98. package/dist/components/foundations/SectionHeading.js +50 -0
  99. package/dist/components/foundations/SectionHeading.js.map +1 -0
  100. package/dist/components/foundations/Separator.d.ts +11 -0
  101. package/dist/components/foundations/Separator.js +21 -0
  102. package/dist/components/foundations/Separator.js.map +1 -0
  103. package/dist/components/foundations/index.d.ts +9 -0
  104. package/dist/components/foundations/shared.d.ts +5 -0
  105. package/dist/components/foundations/shared.js +8 -0
  106. package/dist/components/foundations/shared.js.map +1 -0
  107. package/dist/components/navigation-data/breadcrumb-pagination.d.ts +34 -0
  108. package/dist/components/navigation-data/breadcrumb-pagination.js +161 -0
  109. package/dist/components/navigation-data/breadcrumb-pagination.js.map +1 -0
  110. package/dist/components/navigation-data/command-palette.d.ts +35 -0
  111. package/dist/components/navigation-data/command-palette.js +151 -0
  112. package/dist/components/navigation-data/command-palette.js.map +1 -0
  113. package/dist/components/navigation-data/header-tab-bar.d.ts +23 -0
  114. package/dist/components/navigation-data/header-tab-bar.js +102 -0
  115. package/dist/components/navigation-data/header-tab-bar.js.map +1 -0
  116. package/dist/components/navigation-data/index.d.ts +7 -0
  117. package/dist/components/navigation-data/menubar-toolbar.d.ts +26 -0
  118. package/dist/components/navigation-data/menubar-toolbar.js +161 -0
  119. package/dist/components/navigation-data/menubar-toolbar.js.map +1 -0
  120. package/dist/components/navigation-data/navigation-menu.d.ts +14 -0
  121. package/dist/components/navigation-data/navigation-menu.js +87 -0
  122. package/dist/components/navigation-data/navigation-menu.js.map +1 -0
  123. package/dist/components/navigation-data/scroll-area.d.ts +6 -0
  124. package/dist/components/navigation-data/scroll-area.js +52 -0
  125. package/dist/components/navigation-data/scroll-area.js.map +1 -0
  126. package/dist/components/navigation-data/table-collection.d.ts +61 -0
  127. package/dist/components/navigation-data/table-collection.js +181 -0
  128. package/dist/components/navigation-data/table-collection.js.map +1 -0
  129. package/dist/components/navigation-data/utils.d.ts +2 -0
  130. package/dist/components/navigation-data/utils.js +11 -0
  131. package/dist/components/navigation-data/utils.js.map +1 -0
  132. package/dist/components/overlays/class-names.d.ts +6 -0
  133. package/dist/components/overlays/class-names.js +11 -0
  134. package/dist/components/overlays/class-names.js.map +1 -0
  135. package/dist/components/overlays/dialog.d.ts +98 -0
  136. package/dist/components/overlays/dialog.js +158 -0
  137. package/dist/components/overlays/dialog.js.map +1 -0
  138. package/dist/components/overlays/disclosure.d.ts +40 -0
  139. package/dist/components/overlays/disclosure.js +138 -0
  140. package/dist/components/overlays/disclosure.js.map +1 -0
  141. package/dist/components/overlays/drawer.d.ts +88 -0
  142. package/dist/components/overlays/drawer.js +192 -0
  143. package/dist/components/overlays/drawer.js.map +1 -0
  144. package/dist/components/overlays/floating.d.ts +83 -0
  145. package/dist/components/overlays/floating.js +220 -0
  146. package/dist/components/overlays/floating.js.map +1 -0
  147. package/dist/components/overlays/index.d.ts +4 -0
  148. package/dist/components/selection/classnames.d.ts +4 -0
  149. package/dist/components/selection/classnames.js +14 -0
  150. package/dist/components/selection/classnames.js.map +1 -0
  151. package/dist/components/selection/combobox.d.ts +118 -0
  152. package/dist/components/selection/combobox.js +284 -0
  153. package/dist/components/selection/combobox.js.map +1 -0
  154. package/dist/components/selection/controls.d.ts +65 -0
  155. package/dist/components/selection/controls.js +171 -0
  156. package/dist/components/selection/controls.js.map +1 -0
  157. package/dist/components/selection/index.d.ts +7 -0
  158. package/dist/components/selection/menu.d.ts +87 -0
  159. package/dist/components/selection/menu.js +157 -0
  160. package/dist/components/selection/menu.js.map +1 -0
  161. package/dist/components/selection/select.d.ts +55 -0
  162. package/dist/components/selection/select.js +138 -0
  163. package/dist/components/selection/select.js.map +1 -0
  164. package/dist/components/selection/selection.module.js +51 -0
  165. package/dist/components/selection/selection.module.js.map +1 -0
  166. package/dist/index.d.ts +7 -0
  167. package/dist/index.js +52 -0
  168. package/dist/styles.css +2 -0
  169. package/package.json +74 -0
@@ -0,0 +1,319 @@
1
+ /* empty css */
2
+ import { FieldFrame as e, cx as t } from "./internal.js";
3
+ import { Button as n } from "../foundations/Button.js";
4
+ import * as r from "react";
5
+ import { jsx as i, jsxs as a } from "react/jsx-runtime";
6
+ import { Input as o } from "@base-ui/react/input";
7
+ import { FileIcon as s } from "@phosphor-icons/react/dist/csr/File";
8
+ import { PlusIcon as c } from "@phosphor-icons/react/dist/csr/Plus";
9
+ //#region src/components/forms/FileUpload.tsx
10
+ function l({ file: e }) {
11
+ let [t, n] = r.useState(null);
12
+ return r.useEffect(() => {
13
+ if (typeof URL.createObjectURL != "function" || typeof URL.revokeObjectURL != "function") return;
14
+ let t = URL.createObjectURL(e), r = !1;
15
+ return queueMicrotask(() => {
16
+ r || n({
17
+ file: e,
18
+ url: t
19
+ });
20
+ }), () => {
21
+ r = !0, URL.revokeObjectURL(t);
22
+ };
23
+ }, [e]), t?.file === e ? /* @__PURE__ */ i("img", {
24
+ className: "lyds-file-selection__thumbnail",
25
+ src: t.url,
26
+ alt: "",
27
+ width: 48,
28
+ height: 48,
29
+ loading: "lazy",
30
+ decoding: "async"
31
+ }) : /* @__PURE__ */ i(s, {
32
+ "aria-hidden": "true",
33
+ weight: "regular"
34
+ });
35
+ }
36
+ function u(e, t) {
37
+ if (!t?.trim()) return !0;
38
+ let n = e.name.toLocaleLowerCase(), r = e.type.toLocaleLowerCase();
39
+ return t.split(",").some((e) => {
40
+ let t = e.trim().toLocaleLowerCase();
41
+ return t ? t.startsWith(".") ? n.endsWith(t) : t.endsWith("/*") ? r.startsWith(t.slice(0, -1)) : r === t : !1;
42
+ });
43
+ }
44
+ function d({ accept: e, files: n, invalidFileLabel: r, summaryId: o }) {
45
+ return /* @__PURE__ */ a("div", {
46
+ className: t("lyds-file-selection", n.length === 0 && "lyds-sr-only"),
47
+ children: [/* @__PURE__ */ i("p", {
48
+ id: o,
49
+ className: "lyds-file-selection__summary",
50
+ role: "status",
51
+ "aria-live": "polite",
52
+ "aria-atomic": "true",
53
+ children: n.length > 0 ? `已選擇 ${n.length} 個檔案` : null
54
+ }), n.length > 0 ? /* @__PURE__ */ i("ul", {
55
+ className: "lyds-file-selection__list",
56
+ "aria-label": "已選擇的檔案",
57
+ children: n.map((t, n) => {
58
+ let o = u(t, e);
59
+ return /* @__PURE__ */ a("li", {
60
+ className: "lyds-file-selection__item",
61
+ "data-invalid": o ? void 0 : "",
62
+ children: [/* @__PURE__ */ i("span", {
63
+ className: "lyds-file-selection__visual",
64
+ children: t.type.startsWith("image/") ? /* @__PURE__ */ i(l, { file: t }) : /* @__PURE__ */ i(s, {
65
+ "aria-hidden": "true",
66
+ weight: "regular"
67
+ })
68
+ }), /* @__PURE__ */ a("span", {
69
+ className: "lyds-file-selection__details",
70
+ children: [/* @__PURE__ */ i("span", {
71
+ className: "lyds-file-selection__name",
72
+ title: t.name,
73
+ children: t.name
74
+ }), o ? null : /* @__PURE__ */ i("span", {
75
+ className: "lyds-file-selection__status",
76
+ children: r
77
+ })]
78
+ })]
79
+ }, `${t.name}-${t.size}-${t.lastModified}-${n}`);
80
+ })
81
+ }) : null]
82
+ });
83
+ }
84
+ function ee(e, t, n) {
85
+ r.useEffect(() => {
86
+ let t = e.current?.form;
87
+ if (t == null) return;
88
+ let r = () => n([]);
89
+ return t.addEventListener("reset", r), () => t.removeEventListener("reset", r);
90
+ }, [
91
+ t,
92
+ e,
93
+ n
94
+ ]);
95
+ }
96
+ var f = r.forwardRef(function({ label: s, description: c, error: l, invalid: u, disabled: f, readOnly: p, required: m, name: h, size: g = "md", className: _, style: v, requiredIndicator: y, validate: b, validationMode: x, validationDebounceTime: S, dirty: C, touched: w, actionsRef: T, inputClassName: E, inputStyle: D, triggerLabel: O = "選擇檔案", invalidFileLabel: k = "不支援的檔案類型", onChange: A, onFilesChange: j, id: M, ...N }, P) {
97
+ let F = r.useId(), I = M ?? F, L = `${I}-label`, R = `${I}-description`, z = `${I}-error`, B = `${I}-trigger-label`, V = `${I}-selection-summary`, H = r.useRef(null), [U, W] = r.useState([]);
98
+ ee(H, N.form, W), r.useImperativeHandle(P, () => H.current);
99
+ let G = (e) => {
100
+ if (!(f || p) && (A?.(e), !e.defaultPrevented)) {
101
+ let t = Array.from(e.currentTarget.files ?? []);
102
+ W(t), j?.(t, e);
103
+ }
104
+ };
105
+ return /* @__PURE__ */ i(e, {
106
+ label: s,
107
+ description: c,
108
+ error: l,
109
+ invalid: u,
110
+ disabled: f,
111
+ readOnly: p,
112
+ required: m,
113
+ name: h,
114
+ size: g,
115
+ className: _,
116
+ style: v,
117
+ requiredIndicator: y,
118
+ labelId: L,
119
+ descriptionId: R,
120
+ errorId: z,
121
+ validate: b,
122
+ validationMode: x,
123
+ validationDebounceTime: S,
124
+ dirty: C,
125
+ touched: w,
126
+ actionsRef: T,
127
+ children: /* @__PURE__ */ a("div", {
128
+ className: "lyds-file-upload",
129
+ "data-size": g,
130
+ children: [
131
+ /* @__PURE__ */ i(o, {
132
+ ...N,
133
+ ref: H,
134
+ id: I,
135
+ type: "file",
136
+ className: t("lyds-file-upload__input", E),
137
+ style: D,
138
+ disabled: f || p,
139
+ readOnly: p,
140
+ required: m,
141
+ "aria-invalid": u || void 0,
142
+ "aria-labelledby": s == null ? B : `${L} ${B}`,
143
+ "aria-describedby": [
144
+ c == null ? null : R,
145
+ U.length > 0 ? V : null,
146
+ z
147
+ ].filter(Boolean).join(" "),
148
+ tabIndex: -1,
149
+ onChange: G
150
+ }),
151
+ /* @__PURE__ */ i(n, {
152
+ className: "lyds-file-upload__trigger",
153
+ disabled: f || p,
154
+ size: g,
155
+ variant: "secondary",
156
+ onClick: () => H.current?.click(),
157
+ children: /* @__PURE__ */ i("span", {
158
+ id: B,
159
+ children: O
160
+ })
161
+ }),
162
+ /* @__PURE__ */ i(d, {
163
+ accept: N.accept,
164
+ files: U,
165
+ invalidFileLabel: k,
166
+ summaryId: V
167
+ })
168
+ ]
169
+ })
170
+ });
171
+ }), p = r.forwardRef(function({ label: s, description: l, error: u, invalid: f, disabled: p, readOnly: m, required: h, name: g, size: _ = "md", className: v, style: y, requiredIndicator: b, validate: x, validationMode: S, validationDebounceTime: C, dirty: w, touched: T, actionsRef: E, inputClassName: D, primaryLabel: O = "將檔案拖曳至此", secondaryLabel: k = "或從裝置選擇檔案", browseLabel: A = "選擇檔案", invalidFileLabel: j = "不支援的檔案類型", onChange: M, onFilesChange: N, onDragEnter: P, onDragOver: F, onDragLeave: I, onDrop: L, id: R, ...z }, B) {
172
+ let V = r.useId(), H = R ?? V, U = `${H}-label`, W = `${H}-description`, G = `${H}-error`, K = `${H}-trigger-label`, q = `${H}-selection-summary`, J = r.useRef(null), [te, Y] = r.useState(!1), [X, Z] = r.useState([]), Q = r.useRef(0), $ = r.useRef(null);
173
+ ee(J, z.form, Z), r.useImperativeHandle(B, () => J.current);
174
+ let ne = (e) => {
175
+ if (p || m || (M?.(e), e.defaultPrevented)) return;
176
+ let t = $.current;
177
+ if (t != null) {
178
+ t.handled = !0, Z(t.files), N?.(t.files, {
179
+ source: "drop",
180
+ event: t.event
181
+ });
182
+ return;
183
+ }
184
+ let n = Array.from(e.currentTarget.files ?? []);
185
+ Z(n), N?.(n, {
186
+ source: "input",
187
+ event: e
188
+ });
189
+ }, re = (e) => {
190
+ if (p || m) {
191
+ P?.(e);
192
+ return;
193
+ }
194
+ e.preventDefault(), P?.(e), Q.current += 1, Y(!0);
195
+ }, ie = (e) => {
196
+ if (p || m) {
197
+ F?.(e);
198
+ return;
199
+ }
200
+ e.preventDefault(), e.dataTransfer.dropEffect = "copy", F?.(e);
201
+ }, ae = (e) => {
202
+ I?.(e), !(p || m) && (Q.current = Math.max(0, Q.current - 1), Q.current === 0 && Y(!1));
203
+ }, oe = (e) => {
204
+ if (p || m) {
205
+ L?.(e);
206
+ return;
207
+ }
208
+ e.preventDefault(), L?.(e), Q.current = 0, Y(!1);
209
+ let t = Array.from(e.dataTransfer.files ?? []);
210
+ if (J.current != null) {
211
+ try {
212
+ J.current.files = e.dataTransfer.files;
213
+ } catch {}
214
+ let n = {
215
+ event: e,
216
+ files: t,
217
+ handled: !1
218
+ };
219
+ $.current = n, J.current.dispatchEvent(new Event("change", { bubbles: !0 })), $.current = null, n.handled || (Z(t), N?.(t, {
220
+ source: "drop",
221
+ event: e
222
+ }));
223
+ return;
224
+ }
225
+ Z(t), N?.(t, {
226
+ source: "drop",
227
+ event: e
228
+ });
229
+ };
230
+ return /* @__PURE__ */ a(e, {
231
+ label: s,
232
+ description: l,
233
+ error: u,
234
+ invalid: f,
235
+ disabled: p,
236
+ readOnly: m,
237
+ required: h,
238
+ name: g,
239
+ size: _,
240
+ className: v,
241
+ style: y,
242
+ requiredIndicator: b,
243
+ labelId: U,
244
+ descriptionId: W,
245
+ errorId: G,
246
+ validate: x,
247
+ validationMode: S,
248
+ validationDebounceTime: C,
249
+ dirty: w,
250
+ touched: T,
251
+ actionsRef: E,
252
+ children: [/* @__PURE__ */ i(o, {
253
+ ...z,
254
+ ref: J,
255
+ id: H,
256
+ type: "file",
257
+ className: t("lyds-drop-zone__input", D),
258
+ disabled: p || m,
259
+ readOnly: m,
260
+ required: h,
261
+ "aria-invalid": f || void 0,
262
+ "aria-labelledby": s == null ? K : `${U} ${K}`,
263
+ "aria-describedby": [
264
+ l == null ? null : W,
265
+ X.length > 0 ? q : null,
266
+ G
267
+ ].filter(Boolean).join(" "),
268
+ tabIndex: -1,
269
+ onChange: ne
270
+ }), /* @__PURE__ */ a("div", {
271
+ className: "lyds-drop-zone",
272
+ "data-size": _,
273
+ "data-dragging": te || void 0,
274
+ "data-disabled": p || void 0,
275
+ "data-readonly": m || void 0,
276
+ onDragEnter: re,
277
+ onDragOver: ie,
278
+ onDragLeave: ae,
279
+ onDrop: oe,
280
+ children: [
281
+ /* @__PURE__ */ a("span", {
282
+ className: "lyds-drop-zone__copy",
283
+ children: [/* @__PURE__ */ i("span", {
284
+ className: "lyds-drop-zone__primary",
285
+ children: O
286
+ }), /* @__PURE__ */ i("span", {
287
+ className: "lyds-drop-zone__secondary",
288
+ children: k
289
+ })]
290
+ }),
291
+ /* @__PURE__ */ i(n, {
292
+ className: "lyds-drop-zone__button",
293
+ disabled: p || m,
294
+ size: _,
295
+ startIcon: /* @__PURE__ */ i(c, {
296
+ "aria-hidden": "true",
297
+ weight: "bold"
298
+ }),
299
+ variant: "secondary",
300
+ onClick: () => J.current?.click(),
301
+ children: /* @__PURE__ */ i("span", {
302
+ id: K,
303
+ children: A
304
+ })
305
+ }),
306
+ /* @__PURE__ */ i(d, {
307
+ accept: z.accept,
308
+ files: X,
309
+ invalidFileLabel: j,
310
+ summaryId: q
311
+ })
312
+ ]
313
+ })]
314
+ });
315
+ });
316
+ //#endregion
317
+ export { p as DropZone, f as FileUpload };
318
+
319
+ //# sourceMappingURL=FileUpload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileUpload.js","names":[],"sources":["../../../src/components/forms/FileUpload.tsx"],"sourcesContent":["import { Input as BaseInput } from \"@base-ui/react/input\";\nimport { FileIcon } from \"@phosphor-icons/react/dist/csr/File\";\nimport { PlusIcon } from \"@phosphor-icons/react/dist/csr/Plus\";\nimport * as React from \"react\";\nimport { Button } from \"../foundations/Button\";\nimport \"./forms.css\";\nimport { cx, FieldFrame, type FieldAnatomyProps } from \"./internal\";\n\ntype NativeFileInputProps = Omit<\n\tReact.InputHTMLAttributes<HTMLInputElement>,\n\t\"children\" | \"className\" | \"defaultValue\" | \"disabled\" | \"name\" | \"onChange\" | \"readOnly\" | \"required\" | \"size\" | \"style\" | \"type\" | \"value\"\n>;\n\nfunction FileImagePreview({ file }: { file: File }) {\n\tconst [preview, setPreview] = React.useState<{ file: File; url: string } | null>(null);\n\n\tReact.useEffect(() => {\n\t\tif (typeof URL.createObjectURL !== \"function\" || typeof URL.revokeObjectURL !== \"function\") return;\n\n\t\tconst previewUrl = URL.createObjectURL(file);\n\t\tlet disposed = false;\n\t\tqueueMicrotask(() => {\n\t\t\tif (!disposed) {\n\t\t\t\tsetPreview({ file, url: previewUrl });\n\t\t\t}\n\t\t});\n\n\t\treturn () => {\n\t\t\tdisposed = true;\n\t\t\tURL.revokeObjectURL(previewUrl);\n\t\t};\n\t}, [file]);\n\n\tif (preview?.file !== file) return <FileIcon aria-hidden=\"true\" weight=\"regular\" />;\n\treturn <img className=\"lyds-file-selection__thumbnail\" src={preview.url} alt=\"\" width={48} height={48} loading=\"lazy\" decoding=\"async\" />;\n}\n\nfunction isFileAccepted(file: File, accept: string | undefined): boolean {\n\tif (!accept?.trim()) return true;\n\n\tconst fileName = file.name.toLocaleLowerCase();\n\tconst mimeType = file.type.toLocaleLowerCase();\n\treturn accept.split(\",\").some(rawRule => {\n\t\tconst rule = rawRule.trim().toLocaleLowerCase();\n\t\tif (!rule) return false;\n\t\tif (rule.startsWith(\".\")) return fileName.endsWith(rule);\n\t\tif (rule.endsWith(\"/*\")) return mimeType.startsWith(rule.slice(0, -1));\n\t\treturn mimeType === rule;\n\t});\n}\n\ninterface FileSelectionPreviewProps {\n\taccept: string | undefined;\n\tfiles: readonly File[];\n\tinvalidFileLabel: React.ReactNode;\n\tsummaryId: string;\n}\n\nfunction FileSelectionPreview({ accept, files, invalidFileLabel, summaryId }: FileSelectionPreviewProps) {\n\treturn (\n\t\t<div className={cx(\"lyds-file-selection\", files.length === 0 && \"lyds-sr-only\")}>\n\t\t\t<p id={summaryId} className=\"lyds-file-selection__summary\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">\n\t\t\t\t{files.length > 0 ? `已選擇 ${files.length} 個檔案` : null}\n\t\t\t</p>\n\t\t\t{files.length > 0 ? (\n\t\t\t\t<ul className=\"lyds-file-selection__list\" aria-label=\"已選擇的檔案\">\n\t\t\t\t\t{files.map((file, index) => {\n\t\t\t\t\t\tconst accepted = isFileAccepted(file, accept);\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<li className=\"lyds-file-selection__item\" data-invalid={accepted ? undefined : \"\"} key={`${file.name}-${file.size}-${file.lastModified}-${index}`}>\n\t\t\t\t\t\t\t\t<span className=\"lyds-file-selection__visual\">{file.type.startsWith(\"image/\") ? <FileImagePreview file={file} /> : <FileIcon aria-hidden=\"true\" weight=\"regular\" />}</span>\n\t\t\t\t\t\t\t\t<span className=\"lyds-file-selection__details\">\n\t\t\t\t\t\t\t\t\t<span className=\"lyds-file-selection__name\" title={file.name}>\n\t\t\t\t\t\t\t\t\t\t{file.name}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t{accepted ? null : <span className=\"lyds-file-selection__status\">{invalidFileLabel}</span>}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t);\n\t\t\t\t\t})}\n\t\t\t\t</ul>\n\t\t\t) : null}\n\t\t</div>\n\t);\n}\n\nfunction useClearFileSelectionOnFormReset(inputRef: React.RefObject<HTMLInputElement | null>, formId: string | undefined, setSelectedFiles: React.Dispatch<React.SetStateAction<readonly File[]>>) {\n\tReact.useEffect(() => {\n\t\tconst form = inputRef.current?.form;\n\t\tif (form == null) return;\n\n\t\tconst handleReset = () => setSelectedFiles([]);\n\t\tform.addEventListener(\"reset\", handleReset);\n\t\treturn () => form.removeEventListener(\"reset\", handleReset);\n\t}, [formId, inputRef, setSelectedFiles]);\n}\n\nexport interface FileUploadProps extends NativeFileInputProps, FieldAnatomyProps {\n\tinputClassName?: string;\n\tinputStyle?: React.CSSProperties;\n\ttriggerLabel?: React.ReactNode;\n\tinvalidFileLabel?: React.ReactNode;\n\tonChange?: React.ChangeEventHandler<HTMLInputElement>;\n\tonFilesChange?: (files: readonly File[], event: React.ChangeEvent<HTMLInputElement>) => void;\n}\n\nexport const FileUpload = React.forwardRef<HTMLInputElement, FileUploadProps>(function FileUpload(\n\t{\n\t\tlabel,\n\t\tdescription,\n\t\terror,\n\t\tinvalid,\n\t\tdisabled,\n\t\treadOnly,\n\t\trequired,\n\t\tname,\n\t\tsize = \"md\",\n\t\tclassName,\n\t\tstyle,\n\t\trequiredIndicator,\n\t\tvalidate,\n\t\tvalidationMode,\n\t\tvalidationDebounceTime,\n\t\tdirty,\n\t\ttouched,\n\t\tactionsRef,\n\t\tinputClassName,\n\t\tinputStyle,\n\t\ttriggerLabel = \"選擇檔案\",\n\t\tinvalidFileLabel = \"不支援的檔案類型\",\n\t\tonChange,\n\t\tonFilesChange,\n\t\tid: idProp,\n\t\t...inputProps\n\t},\n\tforwardedRef\n) {\n\tconst generatedId = React.useId();\n\tconst id = idProp ?? generatedId;\n\tconst labelId = `${id}-label`;\n\tconst descriptionId = `${id}-description`;\n\tconst errorId = `${id}-error`;\n\tconst triggerId = `${id}-trigger-label`;\n\tconst selectionSummaryId = `${id}-selection-summary`;\n\tconst inputRef = React.useRef<HTMLInputElement>(null);\n\tconst [selectedFiles, setSelectedFiles] = React.useState<readonly File[]>([]);\n\tuseClearFileSelectionOnFormReset(inputRef, inputProps.form, setSelectedFiles);\n\tReact.useImperativeHandle(forwardedRef, () => inputRef.current as HTMLInputElement);\n\n\tconst handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n\t\tif (disabled || readOnly) return;\n\t\tonChange?.(event);\n\t\tif (!event.defaultPrevented) {\n\t\t\tconst files = Array.from(event.currentTarget.files ?? []);\n\t\t\tsetSelectedFiles(files);\n\t\t\tonFilesChange?.(files, event);\n\t\t}\n\t};\n\n\treturn (\n\t\t<FieldFrame\n\t\t\tlabel={label}\n\t\t\tdescription={description}\n\t\t\terror={error}\n\t\t\tinvalid={invalid}\n\t\t\tdisabled={disabled}\n\t\t\treadOnly={readOnly}\n\t\t\trequired={required}\n\t\t\tname={name}\n\t\t\tsize={size}\n\t\t\tclassName={className}\n\t\t\tstyle={style}\n\t\t\trequiredIndicator={requiredIndicator}\n\t\t\tlabelId={labelId}\n\t\t\tdescriptionId={descriptionId}\n\t\t\terrorId={errorId}\n\t\t\tvalidate={validate}\n\t\t\tvalidationMode={validationMode}\n\t\t\tvalidationDebounceTime={validationDebounceTime}\n\t\t\tdirty={dirty}\n\t\t\ttouched={touched}\n\t\t\tactionsRef={actionsRef}\n\t\t>\n\t\t\t<div className=\"lyds-file-upload\" data-size={size}>\n\t\t\t\t<BaseInput\n\t\t\t\t\t{...inputProps}\n\t\t\t\t\tref={inputRef}\n\t\t\t\t\tid={id}\n\t\t\t\t\ttype=\"file\"\n\t\t\t\t\tclassName={cx(\"lyds-file-upload__input\", inputClassName)}\n\t\t\t\t\tstyle={inputStyle}\n\t\t\t\t\tdisabled={disabled || readOnly}\n\t\t\t\t\treadOnly={readOnly}\n\t\t\t\t\trequired={required}\n\t\t\t\t\taria-invalid={invalid || undefined}\n\t\t\t\t\taria-labelledby={label != null ? `${labelId} ${triggerId}` : triggerId}\n\t\t\t\t\taria-describedby={[description != null ? descriptionId : null, selectedFiles.length > 0 ? selectionSummaryId : null, errorId].filter(Boolean).join(\" \")}\n\t\t\t\t\ttabIndex={-1}\n\t\t\t\t\tonChange={handleChange}\n\t\t\t\t/>\n\t\t\t\t<Button className=\"lyds-file-upload__trigger\" disabled={disabled || readOnly} size={size} variant=\"secondary\" onClick={() => inputRef.current?.click()}>\n\t\t\t\t\t<span id={triggerId}>{triggerLabel}</span>\n\t\t\t\t</Button>\n\t\t\t\t<FileSelectionPreview accept={inputProps.accept} files={selectedFiles} invalidFileLabel={invalidFileLabel} summaryId={selectionSummaryId} />\n\t\t\t</div>\n\t\t</FieldFrame>\n\t);\n});\n\nexport type DropZoneChangeDetails = { source: \"input\"; event: React.ChangeEvent<HTMLInputElement> } | { source: \"drop\"; event: React.DragEvent<HTMLDivElement> };\n\nexport interface DropZoneProps extends NativeFileInputProps, FieldAnatomyProps {\n\tinputClassName?: string;\n\tprimaryLabel?: React.ReactNode;\n\tsecondaryLabel?: React.ReactNode;\n\tbrowseLabel?: string;\n\tinvalidFileLabel?: React.ReactNode;\n\tonChange?: React.ChangeEventHandler<HTMLInputElement>;\n\tonFilesChange?: (files: readonly File[], details: DropZoneChangeDetails) => void;\n\tonDragEnter?: React.DragEventHandler<HTMLDivElement>;\n\tonDragOver?: React.DragEventHandler<HTMLDivElement>;\n\tonDragLeave?: React.DragEventHandler<HTMLDivElement>;\n\tonDrop?: React.DragEventHandler<HTMLDivElement>;\n}\n\nexport const DropZone = React.forwardRef<HTMLInputElement, DropZoneProps>(function DropZone(\n\t{\n\t\tlabel,\n\t\tdescription,\n\t\terror,\n\t\tinvalid,\n\t\tdisabled,\n\t\treadOnly,\n\t\trequired,\n\t\tname,\n\t\tsize = \"md\",\n\t\tclassName,\n\t\tstyle,\n\t\trequiredIndicator,\n\t\tvalidate,\n\t\tvalidationMode,\n\t\tvalidationDebounceTime,\n\t\tdirty,\n\t\ttouched,\n\t\tactionsRef,\n\t\tinputClassName,\n\t\tprimaryLabel = \"將檔案拖曳至此\",\n\t\tsecondaryLabel = \"或從裝置選擇檔案\",\n\t\tbrowseLabel = \"選擇檔案\",\n\t\tinvalidFileLabel = \"不支援的檔案類型\",\n\t\tonChange,\n\t\tonFilesChange,\n\t\tonDragEnter,\n\t\tonDragOver,\n\t\tonDragLeave,\n\t\tonDrop,\n\t\tid: idProp,\n\t\t...inputProps\n\t},\n\tforwardedRef\n) {\n\tconst generatedId = React.useId();\n\tconst id = idProp ?? generatedId;\n\tconst labelId = `${id}-label`;\n\tconst descriptionId = `${id}-description`;\n\tconst errorId = `${id}-error`;\n\tconst triggerId = `${id}-trigger-label`;\n\tconst selectionSummaryId = `${id}-selection-summary`;\n\tconst inputRef = React.useRef<HTMLInputElement>(null);\n\tconst [dragging, setDragging] = React.useState(false);\n\tconst [selectedFiles, setSelectedFiles] = React.useState<readonly File[]>([]);\n\tconst dragDepth = React.useRef(0);\n\tconst pendingDrop = React.useRef<{ event: React.DragEvent<HTMLDivElement>; files: readonly File[]; handled: boolean } | null>(null);\n\tuseClearFileSelectionOnFormReset(inputRef, inputProps.form, setSelectedFiles);\n\n\tReact.useImperativeHandle(forwardedRef, () => inputRef.current as HTMLInputElement);\n\n\tconst handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n\t\tif (disabled || readOnly) return;\n\t\tonChange?.(event);\n\t\tif (event.defaultPrevented) return;\n\n\t\tconst drop = pendingDrop.current;\n\t\tif (drop != null) {\n\t\t\tdrop.handled = true;\n\t\t\tsetSelectedFiles(drop.files);\n\t\t\tonFilesChange?.(drop.files, { source: \"drop\", event: drop.event });\n\t\t\treturn;\n\t\t}\n\n\t\tconst files = Array.from(event.currentTarget.files ?? []);\n\t\tsetSelectedFiles(files);\n\t\tonFilesChange?.(files, { source: \"input\", event });\n\t};\n\n\tconst handleDragEnter = (event: React.DragEvent<HTMLDivElement>) => {\n\t\tif (disabled || readOnly) {\n\t\t\tonDragEnter?.(event);\n\t\t\treturn;\n\t\t}\n\t\tevent.preventDefault();\n\t\tonDragEnter?.(event);\n\t\tdragDepth.current += 1;\n\t\tsetDragging(true);\n\t};\n\n\tconst handleDragOver = (event: React.DragEvent<HTMLDivElement>) => {\n\t\tif (disabled || readOnly) {\n\t\t\tonDragOver?.(event);\n\t\t\treturn;\n\t\t}\n\t\tevent.preventDefault();\n\t\tevent.dataTransfer.dropEffect = \"copy\";\n\t\tonDragOver?.(event);\n\t};\n\n\tconst handleDragLeave = (event: React.DragEvent<HTMLDivElement>) => {\n\t\tonDragLeave?.(event);\n\t\tif (disabled || readOnly) return;\n\t\tdragDepth.current = Math.max(0, dragDepth.current - 1);\n\t\tif (dragDepth.current === 0) setDragging(false);\n\t};\n\n\tconst handleDrop = (event: React.DragEvent<HTMLDivElement>) => {\n\t\tif (disabled || readOnly) {\n\t\t\tonDrop?.(event);\n\t\t\treturn;\n\t\t}\n\t\tevent.preventDefault();\n\t\tonDrop?.(event);\n\t\tdragDepth.current = 0;\n\t\tsetDragging(false);\n\t\tconst files = Array.from(event.dataTransfer.files ?? []);\n\t\tif (inputRef.current != null) {\n\t\t\ttry {\n\t\t\t\tinputRef.current.files = event.dataTransfer.files;\n\t\t\t} catch {\n\t\t\t\t// 部分瀏覽器會提供唯讀的 FileList。回呼仍是檔案狀態的主要來源,\n\t\t\t\t// 觸發 change 事件則可同步更新原生驗證狀態。\n\t\t\t}\n\n\t\t\tconst drop = { event, files, handled: false };\n\t\t\tpendingDrop.current = drop;\n\t\t\tinputRef.current.dispatchEvent(new Event(\"change\", { bubbles: true }));\n\t\t\tpendingDrop.current = null;\n\t\t\tif (!drop.handled) {\n\t\t\t\tsetSelectedFiles(files);\n\t\t\t\tonFilesChange?.(files, { source: \"drop\", event });\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tsetSelectedFiles(files);\n\t\tonFilesChange?.(files, { source: \"drop\", event });\n\t};\n\n\treturn (\n\t\t<FieldFrame\n\t\t\tlabel={label}\n\t\t\tdescription={description}\n\t\t\terror={error}\n\t\t\tinvalid={invalid}\n\t\t\tdisabled={disabled}\n\t\t\treadOnly={readOnly}\n\t\t\trequired={required}\n\t\t\tname={name}\n\t\t\tsize={size}\n\t\t\tclassName={className}\n\t\t\tstyle={style}\n\t\t\trequiredIndicator={requiredIndicator}\n\t\t\tlabelId={labelId}\n\t\t\tdescriptionId={descriptionId}\n\t\t\terrorId={errorId}\n\t\t\tvalidate={validate}\n\t\t\tvalidationMode={validationMode}\n\t\t\tvalidationDebounceTime={validationDebounceTime}\n\t\t\tdirty={dirty}\n\t\t\ttouched={touched}\n\t\t\tactionsRef={actionsRef}\n\t\t>\n\t\t\t<BaseInput\n\t\t\t\t{...inputProps}\n\t\t\t\tref={inputRef}\n\t\t\t\tid={id}\n\t\t\t\ttype=\"file\"\n\t\t\t\tclassName={cx(\"lyds-drop-zone__input\", inputClassName)}\n\t\t\t\tdisabled={disabled || readOnly}\n\t\t\t\treadOnly={readOnly}\n\t\t\t\trequired={required}\n\t\t\t\taria-invalid={invalid || undefined}\n\t\t\t\taria-labelledby={label != null ? `${labelId} ${triggerId}` : triggerId}\n\t\t\t\taria-describedby={[description != null ? descriptionId : null, selectedFiles.length > 0 ? selectionSummaryId : null, errorId].filter(Boolean).join(\" \")}\n\t\t\t\ttabIndex={-1}\n\t\t\t\tonChange={handleInputChange}\n\t\t\t/>\n\t\t\t<div\n\t\t\t\tclassName=\"lyds-drop-zone\"\n\t\t\t\tdata-size={size}\n\t\t\t\tdata-dragging={dragging || undefined}\n\t\t\t\tdata-disabled={disabled || undefined}\n\t\t\t\tdata-readonly={readOnly || undefined}\n\t\t\t\tonDragEnter={handleDragEnter}\n\t\t\t\tonDragOver={handleDragOver}\n\t\t\t\tonDragLeave={handleDragLeave}\n\t\t\t\tonDrop={handleDrop}\n\t\t\t>\n\t\t\t\t<span className=\"lyds-drop-zone__copy\">\n\t\t\t\t\t<span className=\"lyds-drop-zone__primary\">{primaryLabel}</span>\n\t\t\t\t\t<span className=\"lyds-drop-zone__secondary\">{secondaryLabel}</span>\n\t\t\t\t</span>\n\t\t\t\t<Button\n\t\t\t\t\tclassName=\"lyds-drop-zone__button\"\n\t\t\t\t\tdisabled={disabled || readOnly}\n\t\t\t\t\tsize={size}\n\t\t\t\t\tstartIcon={<PlusIcon aria-hidden=\"true\" weight=\"bold\" />}\n\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\tonClick={() => inputRef.current?.click()}\n\t\t\t\t>\n\t\t\t\t\t<span id={triggerId}>{browseLabel}</span>\n\t\t\t\t</Button>\n\t\t\t\t<FileSelectionPreview accept={inputProps.accept} files={selectedFiles} invalidFileLabel={invalidFileLabel} summaryId={selectionSummaryId} />\n\t\t\t</div>\n\t\t</FieldFrame>\n\t);\n});\n"],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { Input as BaseInput } from '@base-ui/react/input';
2
+ import { FieldSize } from './internal.js';
3
+ import * as React from "react";
4
+ export interface InputProps extends Omit<BaseInput.Props, "size"> {
5
+ /** Linyao Design System 的控制項尺寸。原生 HTML `size` 屬性請使用 `inputSize`。 */
6
+ size?: FieldSize;
7
+ inputSize?: number;
8
+ invalid?: boolean;
9
+ }
10
+ /**
11
+ * 使用 Linyao Design System 樣式與 Base UI 值變更資訊的基礎文字輸入元件。
12
+ * 需要可見標籤、說明或錯誤訊息時,請使用 TextField。
13
+ */
14
+ export declare const Input: React.ForwardRefExoticComponent<Omit<InputProps, "ref"> & React.RefAttributes<HTMLInputElement>>;
@@ -0,0 +1,33 @@
1
+ /* empty css */
2
+ import { withStateClassName as e } from "./internal.js";
3
+ import * as t from "react";
4
+ import { jsx as n } from "react/jsx-runtime";
5
+ import { Field as r } from "@base-ui/react/field";
6
+ import { Input as i } from "@base-ui/react/input";
7
+ //#region src/components/forms/Input.tsx
8
+ var a = t.forwardRef(function({ size: t = "md", inputSize: a, invalid: o, className: s, disabled: c, readOnly: l, required: u, name: d, "aria-invalid": f, ...p }, m) {
9
+ return /* @__PURE__ */ n(r.Root, {
10
+ className: "lyds-input-root",
11
+ name: d,
12
+ disabled: c,
13
+ invalid: o,
14
+ "data-size": t,
15
+ "data-readonly": l || void 0,
16
+ "data-required": u || void 0,
17
+ children: /* @__PURE__ */ n(i, {
18
+ ...p,
19
+ ref: m,
20
+ className: e("lyds-input", s),
21
+ disabled: c,
22
+ readOnly: l,
23
+ required: u,
24
+ size: a,
25
+ "aria-invalid": o ? !0 : f,
26
+ "data-size": t
27
+ })
28
+ });
29
+ });
30
+ //#endregion
31
+ export { a as Input };
32
+
33
+ //# sourceMappingURL=Input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Input.js","names":[],"sources":["../../../src/components/forms/Input.tsx"],"sourcesContent":["import { Field as BaseField } from \"@base-ui/react/field\";\nimport { Input as BaseInput } from \"@base-ui/react/input\";\nimport * as React from \"react\";\nimport \"./forms.css\";\nimport { withStateClassName, type FieldSize } from \"./internal\";\n\nexport interface InputProps extends Omit<BaseInput.Props, \"size\"> {\n\t/** Linyao Design System 的控制項尺寸。原生 HTML `size` 屬性請使用 `inputSize`。 */\n\tsize?: FieldSize;\n\tinputSize?: number;\n\tinvalid?: boolean;\n}\n\n/**\n * 使用 Linyao Design System 樣式與 Base UI 值變更資訊的基礎文字輸入元件。\n * 需要可見標籤、說明或錯誤訊息時,請使用 TextField。\n */\nexport const Input = React.forwardRef<HTMLInputElement, InputProps>(function Input(\n\t{ size = \"md\", inputSize, invalid, className, disabled, readOnly, required, name, \"aria-invalid\": ariaInvalid, ...props },\n\tref\n) {\n\treturn (\n\t\t<BaseField.Root className=\"lyds-input-root\" name={name} disabled={disabled} invalid={invalid} data-size={size} data-readonly={readOnly || undefined} data-required={required || undefined}>\n\t\t\t<BaseInput\n\t\t\t\t{...props}\n\t\t\t\tref={ref}\n\t\t\t\tclassName={withStateClassName<BaseInput.State>(\"lyds-input\", className)}\n\t\t\t\tdisabled={disabled}\n\t\t\t\treadOnly={readOnly}\n\t\t\t\trequired={required}\n\t\t\t\tsize={inputSize}\n\t\t\t\taria-invalid={invalid ? true : ariaInvalid}\n\t\t\t\tdata-size={size}\n\t\t\t/>\n\t\t</BaseField.Root>\n\t);\n});\n"],"mappings":";;;;;;;AAiBA,IAAa,IAAQ,EAAM,WAAyC,SACnE,EAAE,UAAO,MAAM,cAAW,YAAS,cAAW,aAAU,aAAU,aAAU,SAAM,gBAAgB,GAAa,GAAG,KAClH,GACC;CACD,OACC,kBAAC,EAAU,MAAX;EAAgB,WAAU;EAAwB;EAAgB;EAAmB;EAAS,aAAW;EAAM,iBAAe,KAAY,KAAA;EAAW,iBAAe,KAAY,KAAA;EAC/K,UAAA,kBAAC,GAAD;GACC,GAAI;GACC;GACL,WAAW,EAAoC,cAAc,CAAS;GAC5D;GACA;GACA;GACV,MAAM;GACN,gBAAc,IAAU,KAAO;GAC/B,aAAW;EACX,CAAA;CACc,CAAA;AAElB,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { NumberField as BaseNumberField } from '@base-ui/react/number-field';
2
+ import { FieldAnatomyProps } from './internal.js';
3
+ import * as React from "react";
4
+ type NumberRootProps = Omit<BaseNumberField.Root.Props, "className" | "disabled" | "name" | "readOnly" | "required" | "style">;
5
+ export interface NumberFieldProps extends NumberRootProps, FieldAnatomyProps {
6
+ inputClassName?: BaseNumberField.Input.Props["className"];
7
+ inputStyle?: React.CSSProperties;
8
+ groupClassName?: BaseNumberField.Group.Props["className"];
9
+ showSteppers?: boolean;
10
+ incrementLabel?: string;
11
+ decrementLabel?: string;
12
+ }
13
+ /** 以 Base UI Number Field 實作、支援地區格式的數字輸入元件。 */
14
+ export declare const NumberField: React.ForwardRefExoticComponent<Omit<NumberFieldProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
15
+ export {};
@@ -0,0 +1,71 @@
1
+ /* empty css */
2
+ import { FieldFrame as e, cx as t, withStateClassName as n } from "./internal.js";
3
+ import * as r from "react";
4
+ import { jsx as i, jsxs as a } from "react/jsx-runtime";
5
+ import { PlusIcon as o } from "@phosphor-icons/react/dist/csr/Plus";
6
+ import { NumberField as s } from "@base-ui/react/number-field";
7
+ import { MinusIcon as c } from "@phosphor-icons/react/dist/csr/Minus";
8
+ //#region src/components/forms/NumberField.tsx
9
+ var l = r.forwardRef(function({ label: r, description: l, error: u, invalid: d, disabled: f, readOnly: p, required: m, name: h, size: g = "md", className: _, style: v, requiredIndicator: y, validate: b, validationMode: x, validationDebounceTime: S, dirty: C, touched: w, actionsRef: T, inputClassName: E, inputStyle: D, groupClassName: O, showSteppers: k = !0, incrementLabel: A = "增加數值", decrementLabel: j = "減少數值", ...M }, N) {
10
+ let P = M["aria-label"], F = M["aria-labelledby"];
11
+ return /* @__PURE__ */ i(e, {
12
+ label: r,
13
+ description: l,
14
+ error: u,
15
+ invalid: d,
16
+ disabled: f,
17
+ readOnly: p,
18
+ required: m,
19
+ name: h,
20
+ size: g,
21
+ className: _,
22
+ style: v,
23
+ requiredIndicator: y,
24
+ validate: b,
25
+ validationMode: x,
26
+ validationDebounceTime: S,
27
+ dirty: C,
28
+ touched: w,
29
+ actionsRef: T,
30
+ children: /* @__PURE__ */ i(s.Root, {
31
+ ...M,
32
+ ref: N,
33
+ className: "lyds-number-field",
34
+ name: h,
35
+ disabled: f,
36
+ readOnly: p,
37
+ required: m,
38
+ "data-size": g,
39
+ children: /* @__PURE__ */ a(s.Group, {
40
+ className: n("lyds-number-field__group", O),
41
+ children: [/* @__PURE__ */ i(s.Input, {
42
+ "aria-label": P,
43
+ "aria-labelledby": F,
44
+ className: n("lyds-number-field__input", E),
45
+ style: D
46
+ }), k ? /* @__PURE__ */ a("span", {
47
+ className: "lyds-number-field__steppers",
48
+ children: [/* @__PURE__ */ i(s.Decrement, {
49
+ className: t("lyds-number-field__stepper", "lyds-number-field__stepper--decrement"),
50
+ "aria-label": j,
51
+ children: /* @__PURE__ */ i(c, {
52
+ "aria-hidden": "true",
53
+ weight: "bold"
54
+ })
55
+ }), /* @__PURE__ */ i(s.Increment, {
56
+ className: t("lyds-number-field__stepper", "lyds-number-field__stepper--increment"),
57
+ "aria-label": A,
58
+ children: /* @__PURE__ */ i(o, {
59
+ "aria-hidden": "true",
60
+ weight: "bold"
61
+ })
62
+ })]
63
+ }) : null]
64
+ })
65
+ })
66
+ });
67
+ });
68
+ //#endregion
69
+ export { l as NumberField };
70
+
71
+ //# sourceMappingURL=NumberField.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NumberField.js","names":[],"sources":["../../../src/components/forms/NumberField.tsx"],"sourcesContent":["import { NumberField as BaseNumberField } from \"@base-ui/react/number-field\";\nimport { MinusIcon } from \"@phosphor-icons/react/dist/csr/Minus\";\nimport { PlusIcon } from \"@phosphor-icons/react/dist/csr/Plus\";\nimport * as React from \"react\";\nimport \"./forms.css\";\nimport { cx, FieldFrame, withStateClassName, type FieldAnatomyProps } from \"./internal\";\n\ntype NumberRootProps = Omit<BaseNumberField.Root.Props, \"className\" | \"disabled\" | \"name\" | \"readOnly\" | \"required\" | \"style\">;\n\nexport interface NumberFieldProps extends NumberRootProps, FieldAnatomyProps {\n\tinputClassName?: BaseNumberField.Input.Props[\"className\"];\n\tinputStyle?: React.CSSProperties;\n\tgroupClassName?: BaseNumberField.Group.Props[\"className\"];\n\tshowSteppers?: boolean;\n\tincrementLabel?: string;\n\tdecrementLabel?: string;\n}\n\n/** 以 Base UI Number Field 實作、支援地區格式的數字輸入元件。 */\nexport const NumberField = React.forwardRef<HTMLDivElement, NumberFieldProps>(function NumberField(\n\t{\n\t\tlabel,\n\t\tdescription,\n\t\terror,\n\t\tinvalid,\n\t\tdisabled,\n\t\treadOnly,\n\t\trequired,\n\t\tname,\n\t\tsize = \"md\",\n\t\tclassName,\n\t\tstyle,\n\t\trequiredIndicator,\n\t\tvalidate,\n\t\tvalidationMode,\n\t\tvalidationDebounceTime,\n\t\tdirty,\n\t\ttouched,\n\t\tactionsRef,\n\t\tinputClassName,\n\t\tinputStyle,\n\t\tgroupClassName,\n\t\tshowSteppers = true,\n\t\tincrementLabel = \"增加數值\",\n\t\tdecrementLabel = \"減少數值\",\n\t\t...numberProps\n\t},\n\tref\n) {\n\tconst ariaLabel = numberProps[\"aria-label\"];\n\tconst ariaLabelledBy = numberProps[\"aria-labelledby\"];\n\n\treturn (\n\t\t<FieldFrame\n\t\t\tlabel={label}\n\t\t\tdescription={description}\n\t\t\terror={error}\n\t\t\tinvalid={invalid}\n\t\t\tdisabled={disabled}\n\t\t\treadOnly={readOnly}\n\t\t\trequired={required}\n\t\t\tname={name}\n\t\t\tsize={size}\n\t\t\tclassName={className}\n\t\t\tstyle={style}\n\t\t\trequiredIndicator={requiredIndicator}\n\t\t\tvalidate={validate}\n\t\t\tvalidationMode={validationMode}\n\t\t\tvalidationDebounceTime={validationDebounceTime}\n\t\t\tdirty={dirty}\n\t\t\ttouched={touched}\n\t\t\tactionsRef={actionsRef}\n\t\t>\n\t\t\t<BaseNumberField.Root {...numberProps} ref={ref} className=\"lyds-number-field\" name={name} disabled={disabled} readOnly={readOnly} required={required} data-size={size}>\n\t\t\t\t<BaseNumberField.Group className={withStateClassName<BaseNumberField.Group.State>(\"lyds-number-field__group\", groupClassName)}>\n\t\t\t\t\t<BaseNumberField.Input\n\t\t\t\t\t\taria-label={ariaLabel}\n\t\t\t\t\t\taria-labelledby={ariaLabelledBy}\n\t\t\t\t\t\tclassName={withStateClassName<BaseNumberField.Input.State>(\"lyds-number-field__input\", inputClassName)}\n\t\t\t\t\t\tstyle={inputStyle}\n\t\t\t\t\t/>\n\t\t\t\t\t{showSteppers ? (\n\t\t\t\t\t\t<span className=\"lyds-number-field__steppers\">\n\t\t\t\t\t\t\t<BaseNumberField.Decrement className={cx(\"lyds-number-field__stepper\", \"lyds-number-field__stepper--decrement\")} aria-label={decrementLabel}>\n\t\t\t\t\t\t\t\t<MinusIcon aria-hidden=\"true\" weight=\"bold\" />\n\t\t\t\t\t\t\t</BaseNumberField.Decrement>\n\t\t\t\t\t\t\t<BaseNumberField.Increment className={cx(\"lyds-number-field__stepper\", \"lyds-number-field__stepper--increment\")} aria-label={incrementLabel}>\n\t\t\t\t\t\t\t\t<PlusIcon aria-hidden=\"true\" weight=\"bold\" />\n\t\t\t\t\t\t\t</BaseNumberField.Increment>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t) : null}\n\t\t\t\t</BaseNumberField.Group>\n\t\t\t</BaseNumberField.Root>\n\t\t</FieldFrame>\n\t);\n});\n"],"mappings":";;;;;;;;AAmBA,IAAa,IAAc,EAAM,WAA6C,SAC7E,EACC,UACA,gBACA,UACA,YACA,aACA,aACA,aACA,SACA,UAAO,MACP,cACA,UACA,sBACA,aACA,mBACA,2BACA,UACA,YACA,eACA,mBACA,eACA,mBACA,kBAAe,IACf,oBAAiB,QACjB,oBAAiB,QACjB,GAAG,KAEJ,GACC;CACD,IAAM,IAAY,EAAY,eACxB,IAAiB,EAAY;CAEnC,OACC,kBAAC,GAAD;EACQ;EACM;EACN;EACE;EACC;EACA;EACA;EACJ;EACA;EACK;EACJ;EACY;EACT;EACM;EACQ;EACjB;EACE;EACG;EAEZ,UAAA,kBAAC,EAAgB,MAAjB;GAAsB,GAAI;GAAkB;GAAK,WAAU;GAA0B;GAAgB;GAAoB;GAAoB;GAAU,aAAW;GACjK,UAAA,kBAAC,EAAgB,OAAjB;IAAuB,WAAW,EAAgD,4BAA4B,CAAc;IAA5H,UAAA,CACC,kBAAC,EAAgB,OAAjB;KACC,cAAY;KACZ,mBAAiB;KACjB,WAAW,EAAgD,4BAA4B,CAAc;KACrG,OAAO;IACP,CAAA,GACA,IACA,kBAAC,QAAD;KAAM,WAAU;KAAhB,UAAA,CACC,kBAAC,EAAgB,WAAjB;MAA2B,WAAW,EAAG,8BAA8B,uCAAuC;MAAG,cAAY;MAC5H,UAAA,kBAAC,GAAD;OAAW,eAAY;OAAO,QAAO;MAAQ,CAAA;KACnB,CAAA,GAC3B,kBAAC,EAAgB,WAAjB;MAA2B,WAAW,EAAG,8BAA8B,uCAAuC;MAAG,cAAY;MAC5H,UAAA,kBAAC,GAAD;OAAU,eAAY;OAAO,QAAO;MAAQ,CAAA;KAClB,CAAA,CACtB;IACH,CAAA,IAAA,IACkB;;EACF,CAAA;CACX,CAAA;AAEd,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { OTPField as BaseOTPField } from '@base-ui/react/otp-field';
2
+ import { FieldAnatomyProps } from './internal.js';
3
+ import * as React from "react";
4
+ type OTPRootProps = Omit<BaseOTPField.Root.Props, "className" | "disabled" | "name" | "readOnly" | "required" | "style">;
5
+ export interface OTPFieldProps extends OTPRootProps, FieldAnatomyProps {
6
+ inputClassName?: BaseOTPField.Input.Props["className"];
7
+ inputStyle?: React.CSSProperties;
8
+ /** 第一格之後各輸入格的選用在地化無障礙標籤。 */
9
+ getSlotLabel?: (index: number) => string;
10
+ separator?: React.ReactNode;
11
+ separatorAfter?: readonly number[];
12
+ }
13
+ /** 以 Base UI OTP Field 實作的多格驗證碼輸入元件。 */
14
+ export declare const OTPField: React.ForwardRefExoticComponent<Omit<OTPFieldProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
15
+ export {};
@@ -0,0 +1,54 @@
1
+ /* empty css */
2
+ import { FieldFrame as e, withStateClassName as t } from "./internal.js";
3
+ import * as n from "react";
4
+ import { jsx as r, jsxs as i } from "react/jsx-runtime";
5
+ import { OTPField as a } from "@base-ui/react/otp-field";
6
+ //#region src/components/forms/OTPField.tsx
7
+ var o = n.forwardRef(function({ label: o, description: s, error: c, invalid: l, disabled: u, readOnly: d, required: f, name: p, size: m = "md", className: h, style: g, requiredIndicator: _, validate: v, validationMode: y, validationDebounceTime: b, dirty: x, touched: S, actionsRef: C, inputClassName: w, inputStyle: T, getSlotLabel: E, separator: D = /* @__PURE__ */ r("span", {
8
+ "aria-hidden": "true",
9
+ children: "—"
10
+ }), separatorAfter: O = [], length: k, ...A }, j) {
11
+ return /* @__PURE__ */ r(e, {
12
+ label: o,
13
+ description: s,
14
+ error: c,
15
+ invalid: l,
16
+ disabled: u,
17
+ readOnly: d,
18
+ required: f,
19
+ name: p,
20
+ size: m,
21
+ className: h,
22
+ style: g,
23
+ requiredIndicator: _,
24
+ validate: v,
25
+ validationMode: y,
26
+ validationDebounceTime: b,
27
+ dirty: x,
28
+ touched: S,
29
+ actionsRef: C,
30
+ children: /* @__PURE__ */ r(a.Root, {
31
+ ...A,
32
+ ref: j,
33
+ className: "lyds-otp-field",
34
+ name: p,
35
+ disabled: u,
36
+ readOnly: d,
37
+ required: f,
38
+ length: k,
39
+ "data-size": m,
40
+ children: Array.from({ length: k }, (e, o) => /* @__PURE__ */ i(n.Fragment, { children: [/* @__PURE__ */ r(a.Input, {
41
+ className: t("lyds-otp-field__input", w),
42
+ style: T,
43
+ "aria-label": o > 0 ? E?.(o) ?? `第 ${o + 1} 個字元,共 ${k} 個` : void 0
44
+ }), O.includes(o + 1) && o < k - 1 ? /* @__PURE__ */ r("span", {
45
+ className: "lyds-otp-field__separator",
46
+ children: D
47
+ }) : null] }, o))
48
+ })
49
+ });
50
+ });
51
+ //#endregion
52
+ export { o as OTPField };
53
+
54
+ //# sourceMappingURL=OTPField.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OTPField.js","names":[],"sources":["../../../src/components/forms/OTPField.tsx"],"sourcesContent":["import { OTPField as BaseOTPField } from \"@base-ui/react/otp-field\";\nimport * as React from \"react\";\nimport \"./forms.css\";\nimport { FieldFrame, withStateClassName, type FieldAnatomyProps } from \"./internal\";\n\ntype OTPRootProps = Omit<BaseOTPField.Root.Props, \"className\" | \"disabled\" | \"name\" | \"readOnly\" | \"required\" | \"style\">;\n\nexport interface OTPFieldProps extends OTPRootProps, FieldAnatomyProps {\n\tinputClassName?: BaseOTPField.Input.Props[\"className\"];\n\tinputStyle?: React.CSSProperties;\n\t/** 第一格之後各輸入格的選用在地化無障礙標籤。 */\n\tgetSlotLabel?: (index: number) => string;\n\tseparator?: React.ReactNode;\n\tseparatorAfter?: readonly number[];\n}\n\n/** 以 Base UI OTP Field 實作的多格驗證碼輸入元件。 */\nexport const OTPField = React.forwardRef<HTMLDivElement, OTPFieldProps>(function OTPField(\n\t{\n\t\tlabel,\n\t\tdescription,\n\t\terror,\n\t\tinvalid,\n\t\tdisabled,\n\t\treadOnly,\n\t\trequired,\n\t\tname,\n\t\tsize = \"md\",\n\t\tclassName,\n\t\tstyle,\n\t\trequiredIndicator,\n\t\tvalidate,\n\t\tvalidationMode,\n\t\tvalidationDebounceTime,\n\t\tdirty,\n\t\ttouched,\n\t\tactionsRef,\n\t\tinputClassName,\n\t\tinputStyle,\n\t\tgetSlotLabel,\n\t\tseparator = <span aria-hidden=\"true\">—</span>,\n\t\tseparatorAfter = [],\n\t\tlength,\n\t\t...otpProps\n\t},\n\tref\n) {\n\treturn (\n\t\t<FieldFrame\n\t\t\tlabel={label}\n\t\t\tdescription={description}\n\t\t\terror={error}\n\t\t\tinvalid={invalid}\n\t\t\tdisabled={disabled}\n\t\t\treadOnly={readOnly}\n\t\t\trequired={required}\n\t\t\tname={name}\n\t\t\tsize={size}\n\t\t\tclassName={className}\n\t\t\tstyle={style}\n\t\t\trequiredIndicator={requiredIndicator}\n\t\t\tvalidate={validate}\n\t\t\tvalidationMode={validationMode}\n\t\t\tvalidationDebounceTime={validationDebounceTime}\n\t\t\tdirty={dirty}\n\t\t\ttouched={touched}\n\t\t\tactionsRef={actionsRef}\n\t\t>\n\t\t\t<BaseOTPField.Root {...otpProps} ref={ref} className=\"lyds-otp-field\" name={name} disabled={disabled} readOnly={readOnly} required={required} length={length} data-size={size}>\n\t\t\t\t{Array.from({ length }, (_, index) => (\n\t\t\t\t\t<React.Fragment key={index}>\n\t\t\t\t\t\t<BaseOTPField.Input\n\t\t\t\t\t\t\tclassName={withStateClassName<BaseOTPField.Input.State>(\"lyds-otp-field__input\", inputClassName)}\n\t\t\t\t\t\t\tstyle={inputStyle}\n\t\t\t\t\t\t\taria-label={index > 0 ? (getSlotLabel?.(index) ?? `第 ${index + 1} 個字元,共 ${length} 個`) : undefined}\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t{separatorAfter.includes(index + 1) && index < length - 1 ? <span className=\"lyds-otp-field__separator\">{separator}</span> : null}\n\t\t\t\t\t</React.Fragment>\n\t\t\t\t))}\n\t\t\t</BaseOTPField.Root>\n\t\t</FieldFrame>\n\t);\n});\n"],"mappings":";;;;;;AAiBA,IAAa,IAAW,EAAM,WAA0C,SACvE,EACC,UACA,gBACA,UACA,YACA,aACA,aACA,aACA,SACA,UAAO,MACP,cACA,UACA,sBACA,aACA,mBACA,2BACA,UACA,YACA,eACA,mBACA,eACA,iBACA,eAAY,kBAAC,QAAD;CAAM,eAAY;CAAO,UAAA;AAAO,CAAA,GAC5C,oBAAiB,CAAC,GAClB,WACA,GAAG,KAEJ,GACC;CACD,OACC,kBAAC,GAAD;EACQ;EACM;EACN;EACE;EACC;EACA;EACA;EACJ;EACA;EACK;EACJ;EACY;EACT;EACM;EACQ;EACjB;EACE;EACG;EAEZ,UAAA,kBAAC,EAAa,MAAd;GAAmB,GAAI;GAAe;GAAK,WAAU;GAAuB;GAAgB;GAAoB;GAAoB;GAAkB;GAAQ,aAAW;GACvK,UAAA,MAAM,KAAK,EAAE,UAAO,IAAI,GAAG,MAC3B,kBAAC,EAAM,UAAP,EAAA,UAAA,CACC,kBAAC,EAAa,OAAd;IACC,WAAW,EAA6C,yBAAyB,CAAc;IAC/F,OAAO;IACP,cAAY,IAAQ,IAAK,IAAe,CAAK,KAAK,KAAK,IAAQ,EAAE,SAAS,EAAO,MAAO,KAAA;GACxF,CAAA,GACA,EAAe,SAAS,IAAQ,CAAC,KAAK,IAAQ,IAAS,IAAI,kBAAC,QAAD;IAAM,WAAU;IAA6B,UAAA;GAAgB,CAAA,IAAI,IAC9G,EAAA,GAPK,CAOL,CAChB;EACiB,CAAA;CACR,CAAA;AAEd,CAAC"}