@zyncat/ui 0.8.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 (334) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +133 -0
  3. package/dist/alert.css +132 -0
  4. package/dist/alert.d.ts +46 -0
  5. package/dist/alert.js +80 -0
  6. package/dist/alert.js.map +1 -0
  7. package/dist/avatar-group.d.ts +24 -0
  8. package/dist/avatar-group.js +23 -0
  9. package/dist/avatar-group.js.map +1 -0
  10. package/dist/avatar.css +200 -0
  11. package/dist/avatar.d.ts +35 -0
  12. package/dist/avatar.js +67 -0
  13. package/dist/avatar.js.map +1 -0
  14. package/dist/badge.css +182 -0
  15. package/dist/badge.d.ts +34 -0
  16. package/dist/badge.js +4 -0
  17. package/dist/badge.js.map +1 -0
  18. package/dist/button.css +269 -0
  19. package/dist/button.d.ts +44 -0
  20. package/dist/button.js +4 -0
  21. package/dist/button.js.map +1 -0
  22. package/dist/checkbox.css +177 -0
  23. package/dist/checkbox.d.ts +35 -0
  24. package/dist/checkbox.js +5 -0
  25. package/dist/checkbox.js.map +1 -0
  26. package/dist/chunk-2ERBBFZS.js +12 -0
  27. package/dist/chunk-2ERBBFZS.js.map +1 -0
  28. package/dist/chunk-2HORSLXJ.js +191 -0
  29. package/dist/chunk-2HORSLXJ.js.map +1 -0
  30. package/dist/chunk-36WVAQKL.js +40 -0
  31. package/dist/chunk-36WVAQKL.js.map +1 -0
  32. package/dist/chunk-3SBCBYB7.js +575 -0
  33. package/dist/chunk-3SBCBYB7.js.map +1 -0
  34. package/dist/chunk-4R2GQO43.js +125 -0
  35. package/dist/chunk-4R2GQO43.js.map +1 -0
  36. package/dist/chunk-64UU4LGU.js +258 -0
  37. package/dist/chunk-64UU4LGU.js.map +1 -0
  38. package/dist/chunk-7SZCJ7WI.js +35 -0
  39. package/dist/chunk-7SZCJ7WI.js.map +1 -0
  40. package/dist/chunk-BIDVNLJO.js +38 -0
  41. package/dist/chunk-BIDVNLJO.js.map +1 -0
  42. package/dist/chunk-CONSWNIV.js +17 -0
  43. package/dist/chunk-CONSWNIV.js.map +1 -0
  44. package/dist/chunk-EQ32F2QJ.js +75 -0
  45. package/dist/chunk-EQ32F2QJ.js.map +1 -0
  46. package/dist/chunk-GY7JOPUQ.js +111 -0
  47. package/dist/chunk-GY7JOPUQ.js.map +1 -0
  48. package/dist/chunk-I4XQ4PV2.js +30 -0
  49. package/dist/chunk-I4XQ4PV2.js.map +1 -0
  50. package/dist/chunk-JSKXZMLH.js +67 -0
  51. package/dist/chunk-JSKXZMLH.js.map +1 -0
  52. package/dist/chunk-L3Q3VDIW.js +295 -0
  53. package/dist/chunk-L3Q3VDIW.js.map +1 -0
  54. package/dist/chunk-LDC3RIYA.js +62 -0
  55. package/dist/chunk-LDC3RIYA.js.map +1 -0
  56. package/dist/chunk-MKIQFK7S.js +43 -0
  57. package/dist/chunk-MKIQFK7S.js.map +1 -0
  58. package/dist/chunk-MMRIQNEN.js +20 -0
  59. package/dist/chunk-MMRIQNEN.js.map +1 -0
  60. package/dist/chunk-MXOPCFWR.js +59 -0
  61. package/dist/chunk-MXOPCFWR.js.map +1 -0
  62. package/dist/chunk-NEF5XAHG.js +17 -0
  63. package/dist/chunk-NEF5XAHG.js.map +1 -0
  64. package/dist/chunk-NNXJCLTV.js +22 -0
  65. package/dist/chunk-NNXJCLTV.js.map +1 -0
  66. package/dist/chunk-O4N2OBTR.js +94 -0
  67. package/dist/chunk-O4N2OBTR.js.map +1 -0
  68. package/dist/chunk-PMECHR3A.js +38 -0
  69. package/dist/chunk-PMECHR3A.js.map +1 -0
  70. package/dist/chunk-QDK66S4G.js +44 -0
  71. package/dist/chunk-QDK66S4G.js.map +1 -0
  72. package/dist/chunk-QGNC7LH5.js +8 -0
  73. package/dist/chunk-QGNC7LH5.js.map +1 -0
  74. package/dist/chunk-QMSJZCK3.js +398 -0
  75. package/dist/chunk-QMSJZCK3.js.map +1 -0
  76. package/dist/chunk-S5ZTZANS.js +57 -0
  77. package/dist/chunk-S5ZTZANS.js.map +1 -0
  78. package/dist/chunk-S7B34VGN.js +14 -0
  79. package/dist/chunk-S7B34VGN.js.map +1 -0
  80. package/dist/chunk-TCUCYFT7.js +25 -0
  81. package/dist/chunk-TCUCYFT7.js.map +1 -0
  82. package/dist/chunk-TYHR4VNM.js +193 -0
  83. package/dist/chunk-TYHR4VNM.js.map +1 -0
  84. package/dist/chunk-U5QQZC3U.js +56 -0
  85. package/dist/chunk-U5QQZC3U.js.map +1 -0
  86. package/dist/chunk-UE63OOVG.js +13 -0
  87. package/dist/chunk-UE63OOVG.js.map +1 -0
  88. package/dist/chunk-VTJTGVZZ.js +22 -0
  89. package/dist/chunk-VTJTGVZZ.js.map +1 -0
  90. package/dist/chunk-W3SHPKSB.js +49 -0
  91. package/dist/chunk-W3SHPKSB.js.map +1 -0
  92. package/dist/chunk-XZAEIQDR.js +188 -0
  93. package/dist/chunk-XZAEIQDR.js.map +1 -0
  94. package/dist/chunk-YGGCQNNU.js +92 -0
  95. package/dist/chunk-YGGCQNNU.js.map +1 -0
  96. package/dist/collapse.css +88 -0
  97. package/dist/collapse.d.ts +46 -0
  98. package/dist/collapse.js +5 -0
  99. package/dist/collapse.js.map +1 -0
  100. package/dist/count-badge.d.ts +13 -0
  101. package/dist/count-badge.js +13 -0
  102. package/dist/count-badge.js.map +1 -0
  103. package/dist/date-field.d.ts +25 -0
  104. package/dist/date-field.js +87 -0
  105. package/dist/date-field.js.map +1 -0
  106. package/dist/date-picker.css +595 -0
  107. package/dist/date-range-field.d.ts +33 -0
  108. package/dist/date-range-field.js +404 -0
  109. package/dist/date-range-field.js.map +1 -0
  110. package/dist/datetime-field.d.ts +29 -0
  111. package/dist/datetime-field.js +155 -0
  112. package/dist/datetime-field.js.map +1 -0
  113. package/dist/dialog.css +180 -0
  114. package/dist/dialog.d.ts +42 -0
  115. package/dist/dialog.js +128 -0
  116. package/dist/dialog.js.map +1 -0
  117. package/dist/dom-props-C0jrllBw.d.ts +5 -0
  118. package/dist/field-chrome-CMPOQSLs.d.ts +28 -0
  119. package/dist/field-shell-Cuda-feL.d.ts +24 -0
  120. package/dist/glide.d.ts +15 -0
  121. package/dist/glide.js +5 -0
  122. package/dist/glide.js.map +1 -0
  123. package/dist/icon.css +33 -0
  124. package/dist/input.css +333 -0
  125. package/dist/mcp.js +359 -0
  126. package/dist/motion-devtools.css +265 -0
  127. package/dist/motion-devtools.d.ts +51 -0
  128. package/dist/motion-devtools.js +354 -0
  129. package/dist/motion-devtools.js.map +1 -0
  130. package/dist/motion-scale-Canq4stZ.d.ts +18 -0
  131. package/dist/motion-tokens.d.ts +28 -0
  132. package/dist/motion-tokens.js +3 -0
  133. package/dist/motion-tokens.js.map +1 -0
  134. package/dist/multi-select.d.ts +44 -0
  135. package/dist/multi-select.js +109 -0
  136. package/dist/multi-select.js.map +1 -0
  137. package/dist/number-field.d.ts +36 -0
  138. package/dist/number-field.js +112 -0
  139. package/dist/number-field.js.map +1 -0
  140. package/dist/odometer.css +62 -0
  141. package/dist/otp-field.d.ts +31 -0
  142. package/dist/otp-field.js +98 -0
  143. package/dist/otp-field.js.map +1 -0
  144. package/dist/overlay.css +23 -0
  145. package/dist/pagination.css +43 -0
  146. package/dist/pagination.d.ts +29 -0
  147. package/dist/pagination.js +107 -0
  148. package/dist/pagination.js.map +1 -0
  149. package/dist/popover.css +69 -0
  150. package/dist/popover.d.ts +35 -0
  151. package/dist/popover.js +15 -0
  152. package/dist/popover.js.map +1 -0
  153. package/dist/radio-group.css +300 -0
  154. package/dist/radio-group.d.ts +52 -0
  155. package/dist/radio-group.js +115 -0
  156. package/dist/radio-group.js.map +1 -0
  157. package/dist/select.css +416 -0
  158. package/dist/select.d.ts +49 -0
  159. package/dist/select.js +99 -0
  160. package/dist/select.js.map +1 -0
  161. package/dist/sheet.css +26 -0
  162. package/dist/sheet.d.ts +31 -0
  163. package/dist/sheet.js +14 -0
  164. package/dist/sheet.js.map +1 -0
  165. package/dist/status-badge.d.ts +19 -0
  166. package/dist/status-badge.js +72 -0
  167. package/dist/status-badge.js.map +1 -0
  168. package/dist/table.css +348 -0
  169. package/dist/table.d.ts +75 -0
  170. package/dist/table.js +262 -0
  171. package/dist/table.js.map +1 -0
  172. package/dist/tabs.css +208 -0
  173. package/dist/tabs.d.ts +71 -0
  174. package/dist/tabs.js +181 -0
  175. package/dist/tabs.js.map +1 -0
  176. package/dist/tag.css +248 -0
  177. package/dist/tag.d.ts +52 -0
  178. package/dist/tag.js +72 -0
  179. package/dist/tag.js.map +1 -0
  180. package/dist/text-field.d.ts +28 -0
  181. package/dist/text-field.js +69 -0
  182. package/dist/text-field.js.map +1 -0
  183. package/dist/textarea.css +219 -0
  184. package/dist/textarea.d.ts +38 -0
  185. package/dist/textarea.js +144 -0
  186. package/dist/textarea.js.map +1 -0
  187. package/dist/time-field.d.ts +28 -0
  188. package/dist/time-field.js +66 -0
  189. package/dist/time-field.js.map +1 -0
  190. package/dist/timing-7JA_zQHP.d.ts +27 -0
  191. package/dist/toast-store.d.ts +86 -0
  192. package/dist/toast-store.js +3 -0
  193. package/dist/toast-store.js.map +1 -0
  194. package/dist/toast.css +257 -0
  195. package/dist/toast.d.ts +12 -0
  196. package/dist/toast.js +310 -0
  197. package/dist/toast.js.map +1 -0
  198. package/dist/toggle-tag.d.ts +34 -0
  199. package/dist/toggle-tag.js +57 -0
  200. package/dist/toggle-tag.js.map +1 -0
  201. package/dist/toggle.css +152 -0
  202. package/dist/toggle.d.ts +31 -0
  203. package/dist/toggle.js +75 -0
  204. package/dist/toggle.js.map +1 -0
  205. package/dist/tooltip.css +86 -0
  206. package/dist/tooltip.d.ts +30 -0
  207. package/dist/tooltip.js +268 -0
  208. package/dist/tooltip.js.map +1 -0
  209. package/dist/types-SGMShK7R.d.ts +22 -0
  210. package/llms.txt +196 -0
  211. package/next.d.mts +7 -0
  212. package/next.mjs +59 -0
  213. package/package.json +257 -0
  214. package/src/components/composites/alert/Alert.tsx +141 -0
  215. package/src/components/composites/alert/alert.css +132 -0
  216. package/src/components/composites/date-picker/DateField.tsx +80 -0
  217. package/src/components/composites/date-picker/DateRangeField.tsx +110 -0
  218. package/src/components/composites/date-picker/DateTimeField.tsx +162 -0
  219. package/src/components/composites/date-picker/TimeField.tsx +78 -0
  220. package/src/components/composites/date-picker/calendar-panel.tsx +216 -0
  221. package/src/components/composites/date-picker/date-picker.css +595 -0
  222. package/src/components/composites/date-picker/date-utils.ts +56 -0
  223. package/src/components/composites/date-picker/field-shell.tsx +85 -0
  224. package/src/components/composites/date-picker/range-panel.tsx +363 -0
  225. package/src/components/composites/date-picker/time-core.tsx +290 -0
  226. package/src/components/composites/date-picker/use-day-focus.ts +35 -0
  227. package/src/components/composites/dialog/Dialog.tsx +198 -0
  228. package/src/components/composites/dialog/dialog.css +180 -0
  229. package/src/components/composites/pagination/Pagination.tsx +131 -0
  230. package/src/components/composites/pagination/pagination.css +43 -0
  231. package/src/components/composites/popover/Popover.tsx +141 -0
  232. package/src/components/composites/popover/popover.css +69 -0
  233. package/src/components/composites/select/MultiSelect.tsx +133 -0
  234. package/src/components/composites/select/Select.tsx +122 -0
  235. package/src/components/composites/select/core/index.ts +4 -0
  236. package/src/components/composites/select/core/menu.tsx +100 -0
  237. package/src/components/composites/select/core/panel.tsx +154 -0
  238. package/src/components/composites/select/core/trigger.tsx +74 -0
  239. package/src/components/composites/select/core/types.ts +39 -0
  240. package/src/components/composites/select/core/use-listbox.ts +182 -0
  241. package/src/components/composites/select/select.css +416 -0
  242. package/src/components/composites/sheet/Sheet.tsx +135 -0
  243. package/src/components/composites/sheet/sheet.css +26 -0
  244. package/src/components/composites/sheet/use-sheet-drag.ts +126 -0
  245. package/src/components/composites/table/Table.tsx +377 -0
  246. package/src/components/composites/table/table.css +348 -0
  247. package/src/components/composites/tabs/Tabs.tsx +278 -0
  248. package/src/components/composites/tabs/tabs.css +208 -0
  249. package/src/components/composites/toast/Toast.tsx +380 -0
  250. package/src/components/composites/toast/toast-store.ts +295 -0
  251. package/src/components/composites/toast/toast.css +257 -0
  252. package/src/components/composites/tooltip/Tooltip.tsx +110 -0
  253. package/src/components/composites/tooltip/tooltip-host.tsx +184 -0
  254. package/src/components/composites/tooltip/tooltip-store.ts +81 -0
  255. package/src/components/composites/tooltip/tooltip.css +86 -0
  256. package/src/components/dev/MotionDevtools.tsx +200 -0
  257. package/src/components/dev/motion-devtools.css +265 -0
  258. package/src/components/dev/slowmo-engine.ts +230 -0
  259. package/src/components/internal/glass/glass.css +100 -0
  260. package/src/components/internal/glass/glint.ts +9 -0
  261. package/src/components/internal/hooks/use-controllable.ts +21 -0
  262. package/src/components/internal/hooks/use-scroll-edges.ts +46 -0
  263. package/src/components/internal/icon/Icon.tsx +66 -0
  264. package/src/components/internal/icon/IconSlot.tsx +10 -0
  265. package/src/components/internal/icon/icon.css +33 -0
  266. package/src/components/internal/overlay/focus.ts +68 -0
  267. package/src/components/internal/overlay/layer.tsx +149 -0
  268. package/src/components/internal/overlay/modal.tsx +141 -0
  269. package/src/components/internal/overlay/overlay.css +23 -0
  270. package/src/components/internal/overlay/position.ts +103 -0
  271. package/src/components/internal/utils/cx.ts +3 -0
  272. package/src/components/internal/utils/token-px.ts +8 -0
  273. package/src/components/primitives/avatar/Avatar.tsx +120 -0
  274. package/src/components/primitives/avatar/AvatarGroup.tsx +56 -0
  275. package/src/components/primitives/avatar/avatar.css +200 -0
  276. package/src/components/primitives/badge/Badge.tsx +75 -0
  277. package/src/components/primitives/badge/CountBadge.tsx +20 -0
  278. package/src/components/primitives/badge/StatusBadge.tsx +111 -0
  279. package/src/components/primitives/badge/badge.css +182 -0
  280. package/src/components/primitives/badge/odometer.css +62 -0
  281. package/src/components/primitives/badge/odometer.tsx +36 -0
  282. package/src/components/primitives/button/Button.tsx +102 -0
  283. package/src/components/primitives/button/button.css +269 -0
  284. package/src/components/primitives/checkbox/Checkbox.tsx +76 -0
  285. package/src/components/primitives/checkbox/check-glyph.tsx +28 -0
  286. package/src/components/primitives/checkbox/checkbox.css +177 -0
  287. package/src/components/primitives/collapse/Collapse.tsx +86 -0
  288. package/src/components/primitives/collapse/collapse.css +88 -0
  289. package/src/components/primitives/collapse/collapse.typecheck.tsx +29 -0
  290. package/src/components/primitives/input/NumberField.tsx +139 -0
  291. package/src/components/primitives/input/OtpField.tsx +134 -0
  292. package/src/components/primitives/input/TextField.tsx +110 -0
  293. package/src/components/primitives/input/field-chrome.tsx +83 -0
  294. package/src/components/primitives/input/input.css +333 -0
  295. package/src/components/primitives/radio-group/RadioGroup.tsx +183 -0
  296. package/src/components/primitives/radio-group/radio-group.css +300 -0
  297. package/src/components/primitives/tag/Tag.tsx +143 -0
  298. package/src/components/primitives/tag/ToggleTag.tsx +97 -0
  299. package/src/components/primitives/tag/tag.css +248 -0
  300. package/src/components/primitives/textarea/Textarea.tsx +190 -0
  301. package/src/components/primitives/textarea/textarea.css +219 -0
  302. package/src/components/primitives/toggle/Toggle.tsx +105 -0
  303. package/src/components/primitives/toggle/toggle.css +152 -0
  304. package/src/css.d.ts +1 -0
  305. package/src/dom-props.ts +1 -0
  306. package/src/engine/animate.ts +141 -0
  307. package/src/engine/drag.ts +53 -0
  308. package/src/engine/ease.ts +155 -0
  309. package/src/engine/flip.ts +59 -0
  310. package/src/engine/index.ts +13 -0
  311. package/src/mcp/server.ts +420 -0
  312. package/src/motion/element.tsx +53 -0
  313. package/src/motion/flip.tsx +87 -0
  314. package/src/motion/glide.tsx +47 -0
  315. package/src/motion/motion-timing.ts +33 -0
  316. package/src/motion/presence-context.ts +18 -0
  317. package/src/motion/presence.tsx +91 -0
  318. package/src/motion/timing.ts +49 -0
  319. package/src/motion/use-motion.ts +64 -0
  320. package/src/styles.css +26 -0
  321. package/src/tokens/avatar.css +20 -0
  322. package/src/tokens/color.css +58 -0
  323. package/src/tokens/elevation.css +22 -0
  324. package/src/tokens/fonts.css +3 -0
  325. package/src/tokens/glass.css +20 -0
  326. package/src/tokens/icons.css +7 -0
  327. package/src/tokens/layers.css +6 -0
  328. package/src/tokens/motion-scale.ts +17 -0
  329. package/src/tokens/motion-tokens.ts +92 -0
  330. package/src/tokens/motion.css +49 -0
  331. package/src/tokens/radius.css +11 -0
  332. package/src/tokens/semantic.css +65 -0
  333. package/src/tokens/spacing.css +26 -0
  334. package/src/tokens/typography.css +52 -0
@@ -0,0 +1,69 @@
1
+ 'use client';import { IconSlot } from './chunk-2ERBBFZS.js';
2
+ import { resolveFieldMessage, FieldLabel, FieldMessage } from './chunk-I4XQ4PV2.js';
3
+ import { Icon } from './chunk-3SBCBYB7.js';
4
+ import './chunk-7SZCJ7WI.js';
5
+ import './chunk-VTJTGVZZ.js';
6
+ import { cx } from './chunk-QGNC7LH5.js';
7
+ import './input.css';
8
+ import { useRef } from 'react';
9
+ import { jsxs, jsx } from 'react/jsx-runtime';
10
+
11
+ function TextField({
12
+ label,
13
+ helper,
14
+ error,
15
+ warning,
16
+ success,
17
+ leadingIcon,
18
+ clearable,
19
+ size,
20
+ value,
21
+ htmlProps,
22
+ className,
23
+ style,
24
+ optional,
25
+ ...rest
26
+ }) {
27
+ const { state, msg, msgIcon } = resolveFieldMessage(error, warning, success, helper);
28
+ const inputRef = useRef(null);
29
+ const showClear = clearable && value && !rest.disabled && !rest.readOnly;
30
+ function clear() {
31
+ const el = inputRef.current;
32
+ if (!el) return;
33
+ const setValue = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value").set;
34
+ setValue.call(el, "");
35
+ el.dispatchEvent(new Event("input", { bubbles: true }));
36
+ el.focus();
37
+ }
38
+ const cls = cx(
39
+ "fld",
40
+ size === "sm" ? "fld--sm" : size === "lg" ? "fld--lg" : "",
41
+ leadingIcon && "fld--has-lead",
42
+ showClear && "fld--has-action",
43
+ state,
44
+ className
45
+ );
46
+ return /* @__PURE__ */ jsxs("div", { className: cls, style, children: [
47
+ /* @__PURE__ */ jsx(FieldLabel, { id: rest.id, label, required: rest.required, optional }),
48
+ /* @__PURE__ */ jsxs("div", { className: "fld__control", children: [
49
+ leadingIcon && /* @__PURE__ */ jsx("span", { className: "fld__icon fld__icon--lead", children: /* @__PURE__ */ jsx(IconSlot, { size, children: leadingIcon }) }),
50
+ /* @__PURE__ */ jsx(
51
+ "input",
52
+ {
53
+ ref: inputRef,
54
+ className: "fld__input",
55
+ value,
56
+ "aria-invalid": error ? true : void 0,
57
+ ...rest,
58
+ ...htmlProps
59
+ }
60
+ ),
61
+ showClear && /* @__PURE__ */ jsx("button", { type: "button", className: "fld__action", "aria-label": "Clear", onClick: clear, children: /* @__PURE__ */ jsx(Icon, { name: "close", size }) })
62
+ ] }),
63
+ /* @__PURE__ */ jsx(FieldMessage, { message: msg, icon: msgIcon })
64
+ ] });
65
+ }
66
+
67
+ export { TextField };
68
+ //# sourceMappingURL=text-field.js.map
69
+ //# sourceMappingURL=text-field.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/primitives/input/TextField.tsx"],"names":[],"mappings":";;;;;;;;;;AA8CO,SAAS,SAAA,CAAU;AAAA,EACxB,KAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA,OAAA;AAAA,EACA,OAAA;AAAA,EACA,WAAA;AAAA,EACA,SAAA;AAAA,EACA,IAAA;AAAA,EACA,KAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,KAAA;AAAA,EACA,QAAA;AAAA,EACA,GAAG;AACL,CAAA,EAAmB;AACjB,EAAA,MAAM,EAAE,OAAO,GAAA,EAAK,OAAA,KAAY,mBAAA,CAAoB,KAAA,EAAO,OAAA,EAAS,OAAA,EAAS,MAAM,CAAA;AACnF,EAAA,MAAM,QAAA,GAAW,OAAyB,IAAI,CAAA;AAC9C,EAAA,MAAM,YAAY,SAAA,IAAa,KAAA,IAAS,CAAC,IAAA,CAAK,QAAA,IAAY,CAAC,IAAA,CAAK,QAAA;AAEhE,EAAA,SAAS,KAAA,GAAQ;AACf,IAAA,MAAM,KAAK,QAAA,CAAS,OAAA;AACpB,IAAA,IAAI,CAAC,EAAA,EAAI;AACT,IAAA,MAAM,WAAW,MAAA,CAAO,wBAAA,CAAyB,gBAAA,CAAiB,SAAA,EAAW,OAAO,CAAA,CAAG,GAAA;AACvF,IAAA,QAAA,CAAS,IAAA,CAAK,IAAI,EAAE,CAAA;AACpB,IAAA,EAAA,CAAG,aAAA,CAAc,IAAI,KAAA,CAAM,OAAA,EAAS,EAAE,OAAA,EAAS,IAAA,EAAM,CAAC,CAAA;AACtD,IAAA,EAAA,CAAG,KAAA,EAAM;AAAA,EACX;AACA,EAAA,MAAM,GAAA,GAAM,EAAA;AAAA,IACV,KAAA;AAAA,IACA,IAAA,KAAS,IAAA,GAAO,SAAA,GAAY,IAAA,KAAS,OAAO,SAAA,GAAY,EAAA;AAAA,IACxD,WAAA,IAAe,eAAA;AAAA,IACf,SAAA,IAAa,iBAAA;AAAA,IACb,KAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,GAAA,EAAK,KAAA,EACnB,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,UAAA,EAAA,EAAW,IAAI,IAAA,CAAK,EAAA,EAAI,OAAc,QAAA,EAAU,IAAA,CAAK,UAAU,QAAA,EAAoB,CAAA;AAAA,oBACpF,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,cAAA,EACZ,QAAA,EAAA;AAAA,MAAA,WAAA,oBACC,GAAA,CAAC,UAAK,SAAA,EAAU,2BAAA,EACd,8BAAC,QAAA,EAAA,EAAS,IAAA,EAAa,uBAAY,CAAA,EACrC,CAAA;AAAA,sBAEF,GAAA;AAAA,QAAC,OAAA;AAAA,QAAA;AAAA,UACC,GAAA,EAAK,QAAA;AAAA,UACL,SAAA,EAAU,YAAA;AAAA,UACV,KAAA;AAAA,UACA,cAAA,EAAc,QAAQ,IAAA,GAAO,MAAA;AAAA,UAC5B,GAAG,IAAA;AAAA,UACH,GAAG;AAAA;AAAA,OACN;AAAA,MACC,6BACC,GAAA,CAAC,QAAA,EAAA,EAAO,IAAA,EAAK,QAAA,EAAS,WAAU,aAAA,EAAc,YAAA,EAAW,OAAA,EAAQ,OAAA,EAAS,OACxE,QAAA,kBAAA,GAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAK,OAAA,EAAQ,MAAY,CAAA,EACjC;AAAA,KAAA,EAEJ,CAAA;AAAA,oBACA,GAAA,CAAC,YAAA,EAAA,EAAa,OAAA,EAAS,GAAA,EAAK,MAAM,OAAA,EAAS;AAAA,GAAA,EAC7C,CAAA;AAEJ","file":"text-field.js","sourcesContent":["'use client';\n\nimport './input.css';\nimport { useRef } from 'react';\nimport type { CSSProperties, InputHTMLAttributes, ReactNode } from 'react';\nimport { Icon } from '../../internal/icon/Icon';\nimport { IconSlot } from '../../internal/icon/IconSlot';\nimport { FieldLabel, FieldMessage, resolveFieldMessage, type FieldMessagingProps } from './field-chrome';\nimport type { DataAttributes } from '../../../dom-props';\nimport { cx } from '../../internal/utils/cx';\n\n/** The native <input> props TextField surfaces at the top level (the rest live in `htmlProps`). */\ntype TextFieldNative = Pick<\n InputHTMLAttributes<HTMLInputElement>,\n | 'placeholder'\n | 'value'\n | 'onChange'\n | 'disabled'\n | 'readOnly'\n | 'maxLength'\n | 'minLength'\n | 'hidden'\n | 'pattern'\n | 'onKeyDown'\n>;\n\ninterface TextFieldOwnProps extends FieldMessagingProps, TextFieldNative {\n /** Leading icon - your own icon node (sized to the control). Decorative. */\n leadingIcon?: ReactNode;\n /** Show a clear button when there's a value. */\n clearable?: boolean;\n /** Control height: sm 28 - md 36 (default) - lg 40. */\n size?: 'sm' | 'md' | 'lg';\n /** Extra class(es) merged onto the field root. */\n className?: string;\n /** Inline styles merged onto the field root. */\n style?: CSSProperties;\n /** Available text like types */\n type?: 'text' | 'search' | 'email' | 'url' | 'password';\n}\n\nexport interface TextFieldProps extends TextFieldOwnProps {\n /** Standard <input> attributes (name, autoComplete, maxLength, aria-*, ...) forwarded to the input. */\n htmlProps?: Omit<InputHTMLAttributes<HTMLInputElement>, keyof TextFieldOwnProps | 'size'> & DataAttributes;\n}\n\nexport function TextField({\n label,\n helper,\n error,\n warning,\n success,\n leadingIcon,\n clearable,\n size,\n value,\n htmlProps,\n className,\n style,\n optional,\n ...rest\n}: TextFieldProps) {\n const { state, msg, msgIcon } = resolveFieldMessage(error, warning, success, helper);\n const inputRef = useRef<HTMLInputElement>(null);\n const showClear = clearable && value && !rest.disabled && !rest.readOnly;\n\n function clear() {\n const el = inputRef.current;\n if (!el) return;\n const setValue = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value')!.set!;\n setValue.call(el, '');\n el.dispatchEvent(new Event('input', { bubbles: true }));\n el.focus();\n }\n const cls = cx(\n 'fld',\n size === 'sm' ? 'fld--sm' : size === 'lg' ? 'fld--lg' : '',\n leadingIcon && 'fld--has-lead',\n showClear && 'fld--has-action',\n state,\n className,\n );\n\n return (\n <div className={cls} style={style}>\n <FieldLabel id={rest.id} label={label} required={rest.required} optional={optional} />\n <div className=\"fld__control\">\n {leadingIcon && (\n <span className=\"fld__icon fld__icon--lead\">\n <IconSlot size={size}>{leadingIcon}</IconSlot>\n </span>\n )}\n <input\n ref={inputRef}\n className=\"fld__input\"\n value={value}\n aria-invalid={error ? true : undefined}\n {...rest}\n {...htmlProps}\n />\n {showClear && (\n <button type=\"button\" className=\"fld__action\" aria-label=\"Clear\" onClick={clear}>\n <Icon name=\"close\" size={size} />\n </button>\n )}\n </div>\n <FieldMessage message={msg} icon={msgIcon} />\n </div>\n );\n}\n"]}
@@ -0,0 +1,219 @@
1
+ /* textarea.css - Textarea (multiline composer): the .txa box over the .fld shell, auto-grow, char meter, over-limit highlight. */
2
+
3
+ .txa {
4
+ --txa-pad-y: var(--space-3);
5
+ --txa-pad-x: var(--space-4);
6
+ --txa-lh: var(--leading-body);
7
+ --txa-min-rows: 3;
8
+ --txa-max-rows: 10;
9
+ position: relative;
10
+ display: flex;
11
+ flex-direction: column;
12
+ background: var(--bg-inset);
13
+ border: var(--border-hairline) solid var(--border-default);
14
+ border-radius: var(--radius-lg);
15
+ transition: var(--transition-control);
16
+ }
17
+ .txa:hover:not(.is-disabled):not(.is-readonly):not(:focus-within) {
18
+ border-color: var(--border-strong);
19
+ }
20
+ .txa:focus-within {
21
+ border-color: var(--accent);
22
+ background: var(--bg-surface);
23
+ box-shadow: var(--ring-accent);
24
+ }
25
+ .txa.is-disabled {
26
+ background: var(--bg-muted);
27
+ }
28
+ .txa.is-readonly {
29
+ background: var(--bg-subtle);
30
+ }
31
+
32
+ /* The .txa__stack wrapper owns the height and is the only thing that animates; overflow:clip while growing (a clip box can't scroll to the caret - no jump), flipped to auto by JS only past max-rows. */
33
+ .txa__stack {
34
+ position: relative;
35
+ min-height: calc(var(--txa-min-rows) * var(--txa-lh) + 2 * var(--txa-pad-y));
36
+ max-height: calc(var(--txa-max-rows) * var(--txa-lh) + 2 * var(--txa-pad-y));
37
+ overflow: clip;
38
+ transition: height var(--duration-base) var(--ease-standard);
39
+ }
40
+ .txa__input,
41
+ .txa__mirror {
42
+ box-sizing: border-box;
43
+ width: 100%;
44
+ font: var(--type-body);
45
+ padding: var(--txa-pad-y) var(--txa-pad-x);
46
+ border-radius: inherit;
47
+ white-space: pre-wrap;
48
+ overflow-wrap: break-word;
49
+ word-break: break-word;
50
+ }
51
+ .txa__input {
52
+ position: relative;
53
+ z-index: 1;
54
+ display: block;
55
+ margin: 0;
56
+ border: 0;
57
+ background: transparent;
58
+ resize: none;
59
+ appearance: none;
60
+ -webkit-appearance: none;
61
+ outline: none;
62
+ color: var(--text-strong);
63
+ overflow: hidden;
64
+ }
65
+ .txa__input::placeholder {
66
+ color: var(--text-disabled);
67
+ }
68
+ .txa__input:disabled {
69
+ color: var(--text-disabled);
70
+ cursor: not-allowed;
71
+ }
72
+ .txa__input[readonly] {
73
+ color: var(--text-body);
74
+ }
75
+
76
+ /* over-limit highlight: faint tint + a danger underline on the excess chars */
77
+ .txa__mirror {
78
+ position: absolute;
79
+ top: 0;
80
+ left: 0;
81
+ right: 0;
82
+ z-index: 0;
83
+ color: transparent;
84
+ pointer-events: none;
85
+ user-select: none;
86
+ }
87
+ .txa__mirror mark {
88
+ color: transparent;
89
+ background: var(--danger-subtle);
90
+ border-radius: var(--radius-sm);
91
+ text-decoration: underline;
92
+ text-decoration-color: var(--danger);
93
+ text-decoration-thickness: 2px;
94
+ text-underline-offset: 3px;
95
+ -webkit-box-decoration-break: clone;
96
+ box-decoration-break: clone;
97
+ }
98
+
99
+ .txa__bar {
100
+ display: flex;
101
+ align-items: center;
102
+ gap: var(--space-3);
103
+ padding: var(--space-2) var(--space-3);
104
+ border-top: var(--border-hairline) solid var(--border-subtle);
105
+ transition: border-color var(--duration-fast) var(--ease-standard);
106
+ }
107
+ .txa:focus-within .txa__bar {
108
+ border-top-color: var(--border-default);
109
+ }
110
+ .txa__hint {
111
+ font: var(--type-micro);
112
+ color: var(--text-subtle);
113
+ display: inline-flex;
114
+ align-items: center;
115
+ gap: var(--space-1);
116
+ min-width: 0;
117
+ overflow: hidden;
118
+ text-overflow: ellipsis;
119
+ white-space: nowrap;
120
+ }
121
+ .txa__kbd {
122
+ font-family: var(--font-mono);
123
+ font-size: var(--size-micro);
124
+ line-height: 1;
125
+ color: var(--text-muted);
126
+ padding: var(--space-1);
127
+ border: var(--border-hairline) solid var(--border-default);
128
+ border-radius: var(--radius-sm);
129
+ background: var(--bg-surface);
130
+ }
131
+
132
+ .txa__meter {
133
+ margin-left: auto;
134
+ flex: none;
135
+ display: inline-flex;
136
+ align-items: center;
137
+ gap: var(--space-2);
138
+ }
139
+ .txa__count {
140
+ font-family: var(--font-mono);
141
+ font-size: var(--size-micro);
142
+ line-height: 1;
143
+ font-variant-numeric: tabular-nums;
144
+ color: var(--text-subtle);
145
+ white-space: nowrap;
146
+ transition: color var(--duration-fast) var(--ease-standard);
147
+ }
148
+ .txa__ring {
149
+ width: var(--icon-sm);
150
+ height: var(--icon-sm);
151
+ flex: none;
152
+ transform: rotate(-90deg);
153
+ }
154
+ .txa__ring circle {
155
+ fill: none;
156
+ stroke-width: 2;
157
+ }
158
+ .txa__ring .txa__ring-trk {
159
+ stroke: var(--border-default);
160
+ }
161
+ .txa__ring .txa__ring-prg {
162
+ stroke: var(--accent);
163
+ stroke-linecap: round;
164
+ stroke-dasharray: var(--txa-ring-c);
165
+ stroke-dashoffset: calc(var(--txa-ring-c) * (1 - var(--txa-ring-p, 0)));
166
+ transition:
167
+ stroke-dashoffset var(--duration-base) var(--ease-standard),
168
+ stroke var(--duration-fast) var(--ease-standard);
169
+ }
170
+ .txa__meter.is-near .txa__ring-prg {
171
+ stroke: var(--warning);
172
+ }
173
+ .txa__meter.is-near .txa__count {
174
+ color: var(--warning-text);
175
+ }
176
+ .txa__meter.is-over .txa__ring-prg {
177
+ stroke: var(--danger);
178
+ }
179
+ .txa__meter.is-over .txa__count {
180
+ color: var(--danger-text);
181
+ font-weight: var(--weight-medium);
182
+ }
183
+
184
+ .fld.is-error .txa {
185
+ border-color: var(--danger);
186
+ }
187
+ .fld.is-error .txa:hover:not(.is-disabled):not(.is-readonly):not(:focus-within) {
188
+ border-color: var(--danger-text);
189
+ }
190
+ .fld.is-error .txa:focus-within {
191
+ box-shadow: var(--ring-danger);
192
+ }
193
+ .fld.is-warning .txa {
194
+ border-color: var(--warning);
195
+ }
196
+ .fld.is-warning .txa:hover:not(.is-disabled):not(.is-readonly):not(:focus-within) {
197
+ border-color: var(--warning-text);
198
+ }
199
+ .fld.is-warning .txa:focus-within {
200
+ box-shadow: var(--ring-warning);
201
+ }
202
+ .fld.is-success .txa {
203
+ border-color: var(--success);
204
+ }
205
+ .fld.is-success .txa:hover:not(.is-disabled):not(.is-readonly):not(:focus-within) {
206
+ border-color: var(--success-text);
207
+ }
208
+ .fld.is-success .txa:focus-within {
209
+ box-shadow: var(--ring-success);
210
+ }
211
+
212
+ .fld--txa.fld--lg .txa {
213
+ --txa-pad-y: var(--space-4);
214
+ --txa-lh: var(--leading-body-lg);
215
+ }
216
+ .fld--txa.fld--lg .txa__input,
217
+ .fld--txa.fld--lg .txa__mirror {
218
+ font: var(--type-body-lg);
219
+ }
@@ -0,0 +1,38 @@
1
+ import * as react from 'react';
2
+ import { TextareaHTMLAttributes, ChangeEventHandler, ReactNode, CSSProperties } from 'react';
3
+ import { b as FieldMessagingProps } from './field-chrome-CMPOQSLs.js';
4
+ import { D as DataAttributes } from './dom-props-C0jrllBw.js';
5
+
6
+ /** The native <textarea> props Textarea surfaces at the top level (the rest live in `htmlProps`). */
7
+ type TextareaNative = Pick<TextareaHTMLAttributes<HTMLTextAreaElement>, 'placeholder' | 'disabled' | 'readOnly' | 'onKeyDown'>;
8
+ interface TextareaOwnProps extends FieldMessagingProps, TextareaNative {
9
+ /** Controlled text value. @default '' */
10
+ value?: string;
11
+ /** Change handler - fired on each edit with the textarea change event. */
12
+ onChange?: ChangeEventHandler<HTMLTextAreaElement>;
13
+ /** Fired on ⌘/Ctrl+Enter with the current text. */
14
+ onSubmit?: (value: string) => void;
15
+ /** Soft char limit: shows the meter + over-limit highlight. Does NOT truncate (use native maxLength for a hard stop). */
16
+ max?: number;
17
+ /** Rows shown before auto-grow kicks in. @default 3 */
18
+ minRows?: number;
19
+ /** Row cap - grows up to this, then the box scrolls. @default 10 */
20
+ maxRows?: number;
21
+ /** Remaining-chars threshold that flips the meter amber. Default 20. */
22
+ warnAt?: number;
23
+ /** Footer hint, left of the meter - e.g. a ⌘↵ affordance. */
24
+ hint?: ReactNode;
25
+ /** md (default) - lg (prominent composer). */
26
+ size?: 'md' | 'lg';
27
+ /** Extra class(es) merged onto the field root. */
28
+ className?: string;
29
+ /** Inline styles merged onto the field root. */
30
+ style?: CSSProperties;
31
+ }
32
+ interface TextareaProps extends TextareaOwnProps {
33
+ /** Standard <textarea> attributes (name, maxLength, aria-*, onKeyDown, ...) forwarded to the textarea. */
34
+ htmlProps?: Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, keyof TextareaOwnProps | 'rows'> & DataAttributes;
35
+ }
36
+ declare function Textarea({ id, label, required, optional, placeholder, helper, error, warning, success, value, onChange, onKeyDown, onSubmit, max, minRows, maxRows, warnAt, hint, size, disabled, readOnly, className, style, htmlProps, }: TextareaProps): react.JSX.Element;
37
+
38
+ export { Textarea, type TextareaProps };
@@ -0,0 +1,144 @@
1
+ 'use client';import { resolveFieldMessage, FieldLabel, FieldMessage } from './chunk-I4XQ4PV2.js';
2
+ import './chunk-3SBCBYB7.js';
3
+ import './chunk-7SZCJ7WI.js';
4
+ import './chunk-VTJTGVZZ.js';
5
+ import { cx } from './chunk-QGNC7LH5.js';
6
+ import './textarea.css';
7
+ import { useRef, useLayoutEffect, useEffect } from 'react';
8
+ import { jsxs, jsx } from 'react/jsx-runtime';
9
+
10
+ var RING_C = (2 * Math.PI * 7).toFixed(2);
11
+ function Textarea({
12
+ id,
13
+ label,
14
+ required,
15
+ optional,
16
+ placeholder,
17
+ helper,
18
+ error,
19
+ warning,
20
+ success,
21
+ value = "",
22
+ onChange,
23
+ onKeyDown,
24
+ onSubmit,
25
+ max,
26
+ minRows = 3,
27
+ maxRows = 10,
28
+ warnAt = 20,
29
+ hint,
30
+ size,
31
+ disabled,
32
+ readOnly,
33
+ className = "",
34
+ style,
35
+ htmlProps
36
+ }) {
37
+ const taRef = useRef(null);
38
+ const stackRef = useRef(null);
39
+ const mirrorRef = useRef(null);
40
+ const text = value ?? "";
41
+ const count = text.length;
42
+ const over = max ? Math.max(count - max, 0) : 0;
43
+ const remaining = max ? max - count : 0;
44
+ const meterState = over ? "is-over" : max && remaining <= warnAt ? "is-near" : "";
45
+ const { state, msg, msgIcon } = resolveFieldMessage(error, warning, success, helper);
46
+ const resize = () => {
47
+ const el = taRef.current, stack = stackRef.current;
48
+ if (!el || !stack) return;
49
+ const start = stack.offsetHeight;
50
+ el.style.height = "auto";
51
+ el.style.height = el.scrollHeight + "px";
52
+ const content = el.offsetHeight;
53
+ const maxPx = parseFloat(getComputedStyle(stack).maxHeight) || Infinity;
54
+ const target = Math.min(content, maxPx);
55
+ if (target === start) {
56
+ stack.style.overflowY = content > maxPx ? "auto" : "clip";
57
+ return;
58
+ }
59
+ stack.style.overflowY = "clip";
60
+ stack.style.height = start + "px";
61
+ void stack.offsetHeight;
62
+ stack.style.height = target + "px";
63
+ };
64
+ useLayoutEffect(resize, [text, size]);
65
+ useEffect(() => {
66
+ const stack = stackRef.current;
67
+ if (!stack) return void 0;
68
+ let w = stack.offsetWidth;
69
+ const ro = new ResizeObserver(() => {
70
+ if (stack.offsetWidth !== w) {
71
+ w = stack.offsetWidth;
72
+ resize();
73
+ }
74
+ });
75
+ ro.observe(stack);
76
+ return () => ro.disconnect();
77
+ }, []);
78
+ const handleKeyDown = (e) => {
79
+ if (onSubmit && (e.metaKey || e.ctrlKey) && e.key === "Enter") {
80
+ e.preventDefault();
81
+ onSubmit(text);
82
+ }
83
+ onKeyDown?.(e);
84
+ };
85
+ const cls = cx("fld", "fld--txa", size === "lg" && "fld--lg", state, className);
86
+ const boxCls = cx("txa", disabled && "is-disabled", readOnly && "is-readonly");
87
+ return /* @__PURE__ */ jsxs("div", { className: cls, style, children: [
88
+ /* @__PURE__ */ jsx(FieldLabel, { id, label, required, optional }),
89
+ /* @__PURE__ */ jsxs("div", { className: boxCls, style: { "--txa-min-rows": minRows, "--txa-max-rows": maxRows }, children: [
90
+ /* @__PURE__ */ jsxs("div", { className: "txa__stack", ref: stackRef, children: [
91
+ /* @__PURE__ */ jsxs("div", { className: "txa__mirror", ref: mirrorRef, "aria-hidden": "true", children: [
92
+ over ? text.slice(0, max) : text,
93
+ over ? /* @__PURE__ */ jsx("mark", { children: text.slice(max) }) : null,
94
+ "\n"
95
+ ] }),
96
+ /* @__PURE__ */ jsx(
97
+ "textarea",
98
+ {
99
+ id,
100
+ className: "txa__input",
101
+ ref: taRef,
102
+ rows: minRows,
103
+ value: text,
104
+ placeholder,
105
+ required,
106
+ disabled,
107
+ readOnly,
108
+ onChange,
109
+ onKeyDown: handleKeyDown,
110
+ onScroll: () => {
111
+ if (mirrorRef.current) mirrorRef.current.scrollTop = taRef.current.scrollTop;
112
+ },
113
+ "aria-invalid": error ? true : void 0,
114
+ ...htmlProps
115
+ }
116
+ )
117
+ ] }),
118
+ (max || hint) && /* @__PURE__ */ jsxs("div", { className: "txa__bar", children: [
119
+ hint && /* @__PURE__ */ jsx("span", { className: "txa__hint", children: hint }),
120
+ max && /* @__PURE__ */ jsxs("span", { className: cx("txa__meter", meterState), children: [
121
+ /* @__PURE__ */ jsx("span", { className: "txa__count", children: over || remaining <= warnAt ? remaining : `${count} / ${max}` }),
122
+ /* @__PURE__ */ jsxs(
123
+ "svg",
124
+ {
125
+ className: "txa__ring",
126
+ viewBox: "0 0 16 16",
127
+ "aria-hidden": "true",
128
+ style: { "--txa-ring-c": RING_C, "--txa-ring-p": Math.min(count / max, 1) },
129
+ children: [
130
+ /* @__PURE__ */ jsx("circle", { className: "txa__ring-trk", cx: "8", cy: "8", r: "7" }),
131
+ /* @__PURE__ */ jsx("circle", { className: "txa__ring-prg", cx: "8", cy: "8", r: "7" })
132
+ ]
133
+ }
134
+ )
135
+ ] })
136
+ ] })
137
+ ] }),
138
+ /* @__PURE__ */ jsx(FieldMessage, { message: msg, icon: msgIcon })
139
+ ] });
140
+ }
141
+
142
+ export { Textarea };
143
+ //# sourceMappingURL=textarea.js.map
144
+ //# sourceMappingURL=textarea.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/primitives/textarea/Textarea.tsx"],"names":[],"mappings":"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","file":"textarea.js","sourcesContent":["'use client';\n\nimport './textarea.css';\nimport {\n useEffect,\n useLayoutEffect,\n useRef,\n type ChangeEventHandler,\n type CSSProperties,\n type KeyboardEvent,\n type ReactNode,\n type TextareaHTMLAttributes,\n} from 'react';\nimport { FieldLabel, FieldMessage, resolveFieldMessage, type FieldMessagingProps } from '../input/field-chrome';\nimport type { DataAttributes } from '../../../dom-props';\nimport { cx } from '../../internal/utils/cx';\n\nconst RING_C = (2 * Math.PI * 7).toFixed(2);\n\n/** The native <textarea> props Textarea surfaces at the top level (the rest live in `htmlProps`). */\ntype TextareaNative = Pick<\n TextareaHTMLAttributes<HTMLTextAreaElement>,\n 'placeholder' | 'disabled' | 'readOnly' | 'onKeyDown'\n>;\n\ninterface TextareaOwnProps extends FieldMessagingProps, TextareaNative {\n /** Controlled text value. @default '' */\n value?: string;\n /** Change handler - fired on each edit with the textarea change event. */\n onChange?: ChangeEventHandler<HTMLTextAreaElement>;\n /** Fired on ⌘/Ctrl+Enter with the current text. */\n onSubmit?: (value: string) => void;\n /** Soft char limit: shows the meter + over-limit highlight. Does NOT truncate (use native maxLength for a hard stop). */\n max?: number;\n /** Rows shown before auto-grow kicks in. @default 3 */\n minRows?: number;\n /** Row cap - grows up to this, then the box scrolls. @default 10 */\n maxRows?: number;\n /** Remaining-chars threshold that flips the meter amber. Default 20. */\n warnAt?: number;\n /** Footer hint, left of the meter - e.g. a ⌘↵ affordance. */\n hint?: ReactNode;\n /** md (default) - lg (prominent composer). */\n size?: 'md' | 'lg';\n /** Extra class(es) merged onto the field root. */\n className?: string;\n /** Inline styles merged onto the field root. */\n style?: CSSProperties;\n}\n\nexport interface TextareaProps extends TextareaOwnProps {\n /** Standard <textarea> attributes (name, maxLength, aria-*, onKeyDown, ...) forwarded to the textarea. */\n htmlProps?: Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, keyof TextareaOwnProps | 'rows'> & DataAttributes;\n}\n\nexport function Textarea({\n id,\n label,\n required,\n optional,\n placeholder,\n helper,\n error,\n warning,\n success,\n value = '',\n onChange,\n onKeyDown,\n onSubmit,\n max,\n minRows = 3,\n maxRows = 10,\n warnAt = 20,\n hint,\n size,\n disabled,\n readOnly,\n className = '',\n style,\n htmlProps,\n}: TextareaProps) {\n const taRef = useRef<HTMLTextAreaElement>(null);\n const stackRef = useRef<HTMLDivElement>(null);\n const mirrorRef = useRef<HTMLDivElement>(null);\n const text = value ?? '';\n const count = text.length;\n const over = max ? Math.max(count - max, 0) : 0;\n const remaining = max ? max - count : 0;\n const meterState = over ? 'is-over' : max && remaining <= warnAt ? 'is-near' : '';\n\n const { state, msg, msgIcon } = resolveFieldMessage(error, warning, success, helper);\n\n const resize = () => {\n const el = taRef.current,\n stack = stackRef.current;\n if (!el || !stack) return;\n const start = stack.offsetHeight;\n el.style.height = 'auto';\n el.style.height = el.scrollHeight + 'px';\n const content = el.offsetHeight;\n const maxPx = parseFloat(getComputedStyle(stack).maxHeight) || Infinity;\n const target = Math.min(content, maxPx);\n if (target === start) {\n stack.style.overflowY = content > maxPx ? 'auto' : 'clip';\n return;\n }\n stack.style.overflowY = 'clip';\n stack.style.height = start + 'px';\n void stack.offsetHeight;\n stack.style.height = target + 'px';\n };\n useLayoutEffect(resize, [text, size]);\n useEffect(() => {\n const stack = stackRef.current;\n if (!stack) return undefined;\n let w = stack.offsetWidth;\n const ro = new ResizeObserver(() => {\n if (stack.offsetWidth !== w) {\n w = stack.offsetWidth;\n resize();\n }\n });\n ro.observe(stack);\n return () => ro.disconnect();\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n const handleKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {\n if (onSubmit && (e.metaKey || e.ctrlKey) && e.key === 'Enter') {\n e.preventDefault();\n onSubmit(text);\n }\n onKeyDown?.(e);\n };\n\n const cls = cx('fld', 'fld--txa', size === 'lg' && 'fld--lg', state, className);\n const boxCls = cx('txa', disabled && 'is-disabled', readOnly && 'is-readonly');\n\n return (\n <div className={cls} style={style}>\n <FieldLabel id={id} label={label} required={required} optional={optional} />\n <div className={boxCls} style={{ '--txa-min-rows': minRows, '--txa-max-rows': maxRows } as CSSProperties}>\n <div className=\"txa__stack\" ref={stackRef}>\n <div className=\"txa__mirror\" ref={mirrorRef} aria-hidden=\"true\">\n {over ? text.slice(0, max) : text}\n {over ? <mark>{text.slice(max)}</mark> : null}\n {'\\n'}\n </div>\n <textarea\n id={id}\n className=\"txa__input\"\n ref={taRef}\n rows={minRows}\n value={text}\n placeholder={placeholder}\n required={required}\n disabled={disabled}\n readOnly={readOnly}\n onChange={onChange}\n onKeyDown={handleKeyDown}\n onScroll={() => {\n if (mirrorRef.current) mirrorRef.current.scrollTop = taRef.current.scrollTop;\n }}\n aria-invalid={error ? true : undefined}\n {...htmlProps}\n />\n </div>\n {(max || hint) && (\n <div className=\"txa__bar\">\n {hint && <span className=\"txa__hint\">{hint}</span>}\n {max && (\n <span className={cx('txa__meter', meterState)}>\n <span className=\"txa__count\">{over || remaining <= warnAt ? remaining : `${count} / ${max}`}</span>\n <svg\n className=\"txa__ring\"\n viewBox=\"0 0 16 16\"\n aria-hidden=\"true\"\n style={{ '--txa-ring-c': RING_C, '--txa-ring-p': Math.min(count / max, 1) } as CSSProperties}\n >\n <circle className=\"txa__ring-trk\" cx=\"8\" cy=\"8\" r=\"7\" />\n <circle className=\"txa__ring-prg\" cx=\"8\" cy=\"8\" r=\"7\" />\n </svg>\n </span>\n )}\n </div>\n )}\n </div>\n <FieldMessage message={msg} icon={msgIcon} />\n </div>\n );\n}\n"]}
@@ -0,0 +1,28 @@
1
+ import * as react from 'react';
2
+ import { D as DateFieldBaseProps } from './field-shell-Cuda-feL.js';
3
+ import './timing-7JA_zQHP.js';
4
+ import './motion-scale-Canq4stZ.js';
5
+ import './dom-props-C0jrllBw.js';
6
+
7
+ interface TimeFieldProps extends DateFieldBaseProps {
8
+ /** Controlled value, canonical 'HH:mm' (24h). */
9
+ value?: string | null;
10
+ /** Uncontrolled initial value, 'HH:mm' (24h). Use instead of `value`. @default null */
11
+ defaultValue?: string | null;
12
+ /** Fires live - the instant both segments exist. */
13
+ onChange?: (value: string) => void;
14
+ /** Field label rendered above the box; also the segments' `aria-label` fallback. */
15
+ label?: string;
16
+ /** Display only; storage stays 24h. Default '24h'. */
17
+ format?: '24h' | '12h';
18
+ /** ↑/↓ step granularity in minutes (typing is exact). Default 5. */
19
+ minuteStep?: number;
20
+ /** Lower bound 'HH:mm' - saturates, never errors. */
21
+ min?: string;
22
+ /** Upper bound 'HH:mm' - saturates, never errors. */
23
+ max?: string;
24
+ }
25
+ declare function TimeField({ value, // controlled: 'HH:mm' | null
26
+ defaultValue, onChange, label, format, minuteStep, min, max, required, invalid, message, disabled, className, htmlProps, }: TimeFieldProps): react.JSX.Element;
27
+
28
+ export { TimeField, type TimeFieldProps };
@@ -0,0 +1,66 @@
1
+ 'use client';import { TimeSegments } from './chunk-64UU4LGU.js';
2
+ import { FieldShell } from './chunk-YGGCQNNU.js';
3
+ import './chunk-I4XQ4PV2.js';
4
+ import './chunk-3SBCBYB7.js';
5
+ import { useControllable } from './chunk-MMRIQNEN.js';
6
+ import './chunk-7SZCJ7WI.js';
7
+ import './chunk-VTJTGVZZ.js';
8
+ import './chunk-QGNC7LH5.js';
9
+ import './date-picker.css';
10
+ import { jsx } from 'react/jsx-runtime';
11
+
12
+ function TimeField({
13
+ value,
14
+ // controlled: 'HH:mm' | null
15
+ defaultValue = null,
16
+ onChange,
17
+ label,
18
+ format = "24h",
19
+ minuteStep = 5,
20
+ min,
21
+ max,
22
+ required = false,
23
+ invalid = false,
24
+ message,
25
+ disabled = false,
26
+ className = "",
27
+ htmlProps
28
+ }) {
29
+ const [val, commit] = useControllable(value, defaultValue, onChange);
30
+ function onBoxPointerDown(e) {
31
+ if (disabled || e.target.closest(".tsg__seg")) return;
32
+ e.preventDefault();
33
+ const seg = e.currentTarget.querySelector(".tsg__seg");
34
+ if (seg) seg.focus();
35
+ }
36
+ return /* @__PURE__ */ jsx(
37
+ FieldShell,
38
+ {
39
+ variant: "tfd",
40
+ label,
41
+ required,
42
+ invalid,
43
+ message,
44
+ icon: "clock",
45
+ className,
46
+ htmlProps,
47
+ children: /* @__PURE__ */ jsx("div", { className: "fld__input tfd__box" + (disabled ? " is-disabled" : ""), onPointerDown: onBoxPointerDown, children: /* @__PURE__ */ jsx(
48
+ TimeSegments,
49
+ {
50
+ value: val,
51
+ onCommit: commit,
52
+ format,
53
+ minuteStep,
54
+ min,
55
+ max,
56
+ disabled,
57
+ ariaLabel: label || "Time"
58
+ }
59
+ ) })
60
+ }
61
+ );
62
+ }
63
+
64
+ export { TimeField };
65
+ //# sourceMappingURL=time-field.js.map
66
+ //# sourceMappingURL=time-field.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/composites/date-picker/TimeField.tsx"],"names":[],"mappings":";;;;;;;;;;;AA2BO,SAAS,SAAA,CAAU;AAAA,EACxB,KAAA;AAAA;AAAA,EACA,YAAA,GAAe,IAAA;AAAA,EACf,QAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA,GAAS,KAAA;AAAA,EACT,UAAA,GAAa,CAAA;AAAA,EACb,GAAA;AAAA,EACA,GAAA;AAAA,EACA,QAAA,GAAW,KAAA;AAAA,EACX,OAAA,GAAU,KAAA;AAAA,EACV,OAAA;AAAA,EACA,QAAA,GAAW,KAAA;AAAA,EACX,SAAA,GAAY,EAAA;AAAA,EACZ;AACF,CAAA,EAAmB;AACjB,EAAA,MAAM,CAAC,GAAA,EAAK,MAAM,IAAI,eAAA,CAAgB,KAAA,EAAO,cAAc,QAAQ,CAAA;AAEnE,EAAA,SAAS,iBAAiB,CAAA,EAAiC;AACzD,IAAA,IAAI,QAAA,IAAa,CAAA,CAAE,MAAA,CAAuB,OAAA,CAAQ,WAAW,CAAA,EAAG;AAChE,IAAA,CAAA,CAAE,cAAA,EAAe;AACjB,IAAA,MAAM,GAAA,GAAM,CAAA,CAAE,aAAA,CAAc,aAAA,CAAc,WAAW,CAAA;AACrD,IAAA,IAAI,GAAA,MAAS,KAAA,EAAM;AAAA,EACrB;AAEA,EAAA,uBACE,GAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,OAAA,EAAQ,KAAA;AAAA,MACR,KAAA;AAAA,MACA,QAAA;AAAA,MACA,OAAA;AAAA,MACA,OAAA;AAAA,MACA,IAAA,EAAK,OAAA;AAAA,MACL,SAAA;AAAA,MACA,SAAA;AAAA,MAEA,QAAA,kBAAA,GAAA,CAAC,SAAI,SAAA,EAAW,qBAAA,IAAyB,WAAW,cAAA,GAAiB,EAAA,CAAA,EAAK,eAAe,gBAAA,EACvF,QAAA,kBAAA,GAAA;AAAA,QAAC,YAAA;AAAA,QAAA;AAAA,UACC,KAAA,EAAO,GAAA;AAAA,UACP,QAAA,EAAU,MAAA;AAAA,UACV,MAAA;AAAA,UACA,UAAA;AAAA,UACA,GAAA;AAAA,UACA,GAAA;AAAA,UACA,QAAA;AAAA,UACA,WAAW,KAAA,IAAS;AAAA;AAAA,OACtB,EACF;AAAA;AAAA,GACF;AAEJ","file":"time-field.js","sourcesContent":["'use client';\n\nimport './date-picker.css';\nimport type { PointerEvent } from 'react';\nimport { FieldShell, type DateFieldBaseProps } from './field-shell';\nimport { useControllable } from '../../internal/hooks/use-controllable';\nimport { TimeSegments } from './time-core';\n\nexport interface TimeFieldProps extends DateFieldBaseProps {\n /** Controlled value, canonical 'HH:mm' (24h). */\n value?: string | null;\n /** Uncontrolled initial value, 'HH:mm' (24h). Use instead of `value`. @default null */\n defaultValue?: string | null;\n /** Fires live - the instant both segments exist. */\n onChange?: (value: string) => void;\n /** Field label rendered above the box; also the segments' `aria-label` fallback. */\n label?: string;\n /** Display only; storage stays 24h. Default '24h'. */\n format?: '24h' | '12h';\n /** ↑/↓ step granularity in minutes (typing is exact). Default 5. */\n minuteStep?: number;\n /** Lower bound 'HH:mm' - saturates, never errors. */\n min?: string;\n /** Upper bound 'HH:mm' - saturates, never errors. */\n max?: string;\n}\n\nexport function TimeField({\n value, // controlled: 'HH:mm' | null\n defaultValue = null,\n onChange,\n label,\n format = '24h',\n minuteStep = 5,\n min,\n max,\n required = false,\n invalid = false,\n message,\n disabled = false,\n className = '',\n htmlProps,\n}: TimeFieldProps) {\n const [val, commit] = useControllable(value, defaultValue, onChange);\n\n function onBoxPointerDown(e: PointerEvent<HTMLDivElement>) {\n if (disabled || (e.target as HTMLElement).closest('.tsg__seg')) return;\n e.preventDefault();\n const seg = e.currentTarget.querySelector('.tsg__seg') as HTMLElement | null;\n if (seg) seg.focus();\n }\n\n return (\n <FieldShell\n variant=\"tfd\"\n label={label}\n required={required}\n invalid={invalid}\n message={message}\n icon=\"clock\"\n className={className}\n htmlProps={htmlProps}\n >\n <div className={'fld__input tfd__box' + (disabled ? ' is-disabled' : '')} onPointerDown={onBoxPointerDown}>\n <TimeSegments\n value={val}\n onCommit={commit}\n format={format}\n minuteStep={minuteStep}\n min={min}\n max={max}\n disabled={disabled}\n ariaLabel={label || 'Time'}\n />\n </div>\n </FieldShell>\n );\n}\n"]}
@@ -0,0 +1,27 @@
1
+ import { D as DurationToken, E as EaseToken } from './motion-scale-Canq4stZ.js';
2
+
3
+ type TimingDirection = 'open' | 'close';
4
+ /** One token for both directions, or split per direction; an omitted direction keeps its default. */
5
+ type DirectionalToken<Token extends string> = Token | {
6
+ [D in TimingDirection]?: Token;
7
+ };
8
+ /** Timing of an open/close transition, constrained to the motion token vocabulary -
9
+ * see DurationToken / EaseToken for what each token means. */
10
+ interface AnimationTiming {
11
+ /** Duration token(s); an omitted field or direction keeps the component's default. */
12
+ duration?: DirectionalToken<DurationToken>;
13
+ /** Ease token(s); an omitted field or direction keeps the component's default. */
14
+ ease?: DirectionalToken<EaseToken>;
15
+ }
16
+ /** The `animation` prop shape: tokens to retime, omit for the component's defaults, or
17
+ * `null` to disable the transition entirely (it plays instantly). */
18
+ type DisableableAnimation = AnimationTiming | null;
19
+ /** Extend this to expose the timing API on a component; redeclare `animation`
20
+ * to document the component's own default tokens. */
21
+ interface TimingProps {
22
+ /** Transition timing - motion tokens only, each field a single token or { open, close };
23
+ * `null` disables the transition (it plays instantly). */
24
+ animation?: DisableableAnimation;
25
+ }
26
+
27
+ export type { AnimationTiming as A, DisableableAnimation as D, TimingProps as T, DirectionalToken as a };