@agent-ui-kit/components 0.0.3

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 (271) hide show
  1. package/dist/base-styles.css +8 -0
  2. package/dist/component-styles.css +147 -0
  3. package/dist/controls/_base/index.d.ts +3 -0
  4. package/dist/controls/_base/index.js +9 -0
  5. package/dist/controls/_base/indicator-element.d.ts +132 -0
  6. package/dist/controls/_base/indicator-element.js +158 -0
  7. package/dist/controls/_base/listbox-element.d.ts +70 -0
  8. package/dist/controls/_base/listbox-element.js +74 -0
  9. package/dist/controls/_base/range-element.d.ts +120 -0
  10. package/dist/controls/_base/range-element.js +158 -0
  11. package/dist/controls/_surface/container-box.css +301 -0
  12. package/dist/controls/_surface/container.css +156 -0
  13. package/dist/controls/_token-surface/token-surface.d.ts +35 -0
  14. package/dist/controls/_token-surface/token-surface.js +97 -0
  15. package/dist/controls/attachment/attachment-meta.d.ts +8 -0
  16. package/dist/controls/attachment/attachment-meta.js +84 -0
  17. package/dist/controls/attachment/attachment.css +91 -0
  18. package/dist/controls/attachment/attachment.d.ts +40 -0
  19. package/dist/controls/attachment/attachment.js +70 -0
  20. package/dist/controls/avatar/avatar-initials.d.ts +4 -0
  21. package/dist/controls/avatar/avatar-initials.js +30 -0
  22. package/dist/controls/avatar/avatar.css +87 -0
  23. package/dist/controls/avatar/avatar.d.ts +40 -0
  24. package/dist/controls/avatar/avatar.js +77 -0
  25. package/dist/controls/badge/badge.css +175 -0
  26. package/dist/controls/badge/badge.d.ts +36 -0
  27. package/dist/controls/badge/badge.js +71 -0
  28. package/dist/controls/bar-chart/bar-chart.css +110 -0
  29. package/dist/controls/bar-chart/bar-chart.d.ts +26 -0
  30. package/dist/controls/bar-chart/bar-chart.js +80 -0
  31. package/dist/controls/bar-chart/bar-math.d.ts +31 -0
  32. package/dist/controls/bar-chart/bar-math.js +106 -0
  33. package/dist/controls/button/button.css +263 -0
  34. package/dist/controls/button/button.d.ts +61 -0
  35. package/dist/controls/button/button.js +115 -0
  36. package/dist/controls/calendar/calendar.css +495 -0
  37. package/dist/controls/calendar/calendar.d.ts +161 -0
  38. package/dist/controls/calendar/calendar.js +1004 -0
  39. package/dist/controls/card/card-content.d.ts +24 -0
  40. package/dist/controls/card/card-content.js +133 -0
  41. package/dist/controls/card/card-footer.d.ts +3 -0
  42. package/dist/controls/card/card-footer.js +16 -0
  43. package/dist/controls/card/card-header.d.ts +3 -0
  44. package/dist/controls/card/card-header.js +18 -0
  45. package/dist/controls/card/card.css +445 -0
  46. package/dist/controls/card/card.d.ts +51 -0
  47. package/dist/controls/card/card.js +61 -0
  48. package/dist/controls/checkbox/checkbox.css +204 -0
  49. package/dist/controls/checkbox/checkbox.d.ts +114 -0
  50. package/dist/controls/checkbox/checkbox.js +130 -0
  51. package/dist/controls/code/code.css +72 -0
  52. package/dist/controls/code/code.d.ts +23 -0
  53. package/dist/controls/code/code.js +40 -0
  54. package/dist/controls/color-picker/color-picker.css +209 -0
  55. package/dist/controls/color-picker/color-picker.d.ts +84 -0
  56. package/dist/controls/color-picker/color-picker.js +545 -0
  57. package/dist/controls/color-picker/color.d.ts +40 -0
  58. package/dist/controls/color-picker/color.js +159 -0
  59. package/dist/controls/column/column.css +151 -0
  60. package/dist/controls/column/column.d.ts +107 -0
  61. package/dist/controls/column/column.js +57 -0
  62. package/dist/controls/combo-box/combo-box.css +397 -0
  63. package/dist/controls/combo-box/combo-box.d.ts +133 -0
  64. package/dist/controls/combo-box/combo-box.js +680 -0
  65. package/dist/controls/command-modal/command-modal.css +226 -0
  66. package/dist/controls/command-modal/command-modal.d.ts +42 -0
  67. package/dist/controls/command-modal/command-modal.js +315 -0
  68. package/dist/controls/disclosure/disclosure.css +162 -0
  69. package/dist/controls/disclosure/disclosure.d.ts +37 -0
  70. package/dist/controls/disclosure/disclosure.js +207 -0
  71. package/dist/controls/field/field.css +140 -0
  72. package/dist/controls/field/field.d.ts +27 -0
  73. package/dist/controls/field/field.js +228 -0
  74. package/dist/controls/form-provider/form-provider.css +40 -0
  75. package/dist/controls/form-provider/form-provider.d.ts +42 -0
  76. package/dist/controls/form-provider/form-provider.js +105 -0
  77. package/dist/controls/grid/grid.css +72 -0
  78. package/dist/controls/grid/grid.d.ts +60 -0
  79. package/dist/controls/grid/grid.js +56 -0
  80. package/dist/controls/icon/icon.css +37 -0
  81. package/dist/controls/icon/icon.d.ts +25 -0
  82. package/dist/controls/icon/icon.js +55 -0
  83. package/dist/controls/index.d.ts +57 -0
  84. package/dist/controls/index.js +136 -0
  85. package/dist/controls/ladder/ladder.css +89 -0
  86. package/dist/controls/ladder/ladder.d.ts +27 -0
  87. package/dist/controls/ladder/ladder.js +78 -0
  88. package/dist/controls/list/list.css +118 -0
  89. package/dist/controls/list/list.d.ts +84 -0
  90. package/dist/controls/list/list.js +48 -0
  91. package/dist/controls/menu/menu.css +195 -0
  92. package/dist/controls/menu/menu.d.ts +44 -0
  93. package/dist/controls/menu/menu.js +248 -0
  94. package/dist/controls/modal/modal.css +99 -0
  95. package/dist/controls/modal/modal.d.ts +61 -0
  96. package/dist/controls/modal/modal.js +155 -0
  97. package/dist/controls/popover/popover.css +83 -0
  98. package/dist/controls/popover/popover.d.ts +44 -0
  99. package/dist/controls/popover/popover.js +164 -0
  100. package/dist/controls/progress/progress.css +106 -0
  101. package/dist/controls/progress/progress.d.ts +28 -0
  102. package/dist/controls/progress/progress.js +80 -0
  103. package/dist/controls/radio/radio-group.css +84 -0
  104. package/dist/controls/radio/radio-group.d.ts +152 -0
  105. package/dist/controls/radio/radio-group.js +350 -0
  106. package/dist/controls/radio/radio.css +219 -0
  107. package/dist/controls/radio/radio.d.ts +19 -0
  108. package/dist/controls/radio/radio.js +75 -0
  109. package/dist/controls/ramp/ramp.css +75 -0
  110. package/dist/controls/ramp/ramp.d.ts +29 -0
  111. package/dist/controls/ramp/ramp.js +72 -0
  112. package/dist/controls/row/row.css +152 -0
  113. package/dist/controls/row/row.d.ts +95 -0
  114. package/dist/controls/row/row.js +45 -0
  115. package/dist/controls/segment/segment.css +66 -0
  116. package/dist/controls/segment/segment.d.ts +3 -0
  117. package/dist/controls/segment/segment.js +26 -0
  118. package/dist/controls/segmented-control/segmented-control.css +189 -0
  119. package/dist/controls/segmented-control/segmented-control.d.ts +20 -0
  120. package/dist/controls/segmented-control/segmented-control.js +64 -0
  121. package/dist/controls/select/select.css +467 -0
  122. package/dist/controls/select/select.d.ts +147 -0
  123. package/dist/controls/select/select.js +538 -0
  124. package/dist/controls/slider/slider.css +231 -0
  125. package/dist/controls/slider/slider.d.ts +111 -0
  126. package/dist/controls/slider/slider.js +60 -0
  127. package/dist/controls/slider-multi/slider-multi.css +197 -0
  128. package/dist/controls/slider-multi/slider-multi.d.ts +149 -0
  129. package/dist/controls/slider-multi/slider-multi.js +380 -0
  130. package/dist/controls/sparkline/sparkline-math.d.ts +23 -0
  131. package/dist/controls/sparkline/sparkline-math.js +79 -0
  132. package/dist/controls/sparkline/sparkline.css +61 -0
  133. package/dist/controls/sparkline/sparkline.d.ts +27 -0
  134. package/dist/controls/sparkline/sparkline.js +74 -0
  135. package/dist/controls/split/constrain.d.ts +44 -0
  136. package/dist/controls/split/constrain.js +126 -0
  137. package/dist/controls/split/split-pane.css +63 -0
  138. package/dist/controls/split/split-pane.d.ts +49 -0
  139. package/dist/controls/split/split-pane.js +42 -0
  140. package/dist/controls/split/split.css +127 -0
  141. package/dist/controls/split/split.d.ts +42 -0
  142. package/dist/controls/split/split.js +364 -0
  143. package/dist/controls/stat/stat-model.d.ts +22 -0
  144. package/dist/controls/stat/stat-model.js +69 -0
  145. package/dist/controls/stat/stat.css +101 -0
  146. package/dist/controls/stat/stat.d.ts +30 -0
  147. package/dist/controls/stat/stat.js +73 -0
  148. package/dist/controls/status-stream/status-stream.css +151 -0
  149. package/dist/controls/status-stream/status-stream.d.ts +108 -0
  150. package/dist/controls/status-stream/status-stream.js +417 -0
  151. package/dist/controls/swatch/swatch.css +66 -0
  152. package/dist/controls/swatch/swatch.d.ts +28 -0
  153. package/dist/controls/swatch/swatch.js +74 -0
  154. package/dist/controls/swiper/swiper-item.css +17 -0
  155. package/dist/controls/swiper/swiper-item.d.ts +31 -0
  156. package/dist/controls/swiper/swiper-item.js +47 -0
  157. package/dist/controls/swiper/swiper-label.css +10 -0
  158. package/dist/controls/swiper/swiper-label.d.ts +4 -0
  159. package/dist/controls/swiper/swiper-label.js +20 -0
  160. package/dist/controls/swiper/swiper-paddles.css +26 -0
  161. package/dist/controls/swiper/swiper-paddles.d.ts +10 -0
  162. package/dist/controls/swiper/swiper-paddles.js +62 -0
  163. package/dist/controls/swiper/swiper-pagination.css +60 -0
  164. package/dist/controls/swiper/swiper-pagination.d.ts +31 -0
  165. package/dist/controls/swiper/swiper-pagination.js +78 -0
  166. package/dist/controls/swiper/swiper.css +153 -0
  167. package/dist/controls/swiper/swiper.d.ts +158 -0
  168. package/dist/controls/swiper/swiper.js +659 -0
  169. package/dist/controls/switch/switch.css +194 -0
  170. package/dist/controls/switch/switch.d.ts +5 -0
  171. package/dist/controls/switch/switch.js +18 -0
  172. package/dist/controls/table/table-model.d.ts +43 -0
  173. package/dist/controls/table/table-model.js +124 -0
  174. package/dist/controls/table/table.css +90 -0
  175. package/dist/controls/table/table.d.ts +29 -0
  176. package/dist/controls/table/table.js +178 -0
  177. package/dist/controls/tabs/tab-panel.d.ts +10 -0
  178. package/dist/controls/tabs/tab-panel.js +89 -0
  179. package/dist/controls/tabs/tab.d.ts +26 -0
  180. package/dist/controls/tabs/tab.js +67 -0
  181. package/dist/controls/tabs/tabs.css +181 -0
  182. package/dist/controls/tabs/tabs.d.ts +61 -0
  183. package/dist/controls/tabs/tabs.js +176 -0
  184. package/dist/controls/text/href.d.ts +26 -0
  185. package/dist/controls/text/href.js +48 -0
  186. package/dist/controls/text/text.css +328 -0
  187. package/dist/controls/text/text.d.ts +85 -0
  188. package/dist/controls/text/text.js +273 -0
  189. package/dist/controls/text-field/text-field.css +498 -0
  190. package/dist/controls/text-field/text-field.d.ts +226 -0
  191. package/dist/controls/text-field/text-field.js +905 -0
  192. package/dist/controls/textarea/textarea.css +251 -0
  193. package/dist/controls/textarea/textarea.d.ts +136 -0
  194. package/dist/controls/textarea/textarea.js +312 -0
  195. package/dist/controls/theme-provider/theme-provider.css +48 -0
  196. package/dist/controls/theme-provider/theme-provider.d.ts +59 -0
  197. package/dist/controls/theme-provider/theme-provider.js +40 -0
  198. package/dist/controls/timeline/timeline.css +33 -0
  199. package/dist/controls/timeline/timeline.d.ts +39 -0
  200. package/dist/controls/timeline/timeline.js +52 -0
  201. package/dist/controls/timeline-item/timeline-item.css +495 -0
  202. package/dist/controls/timeline-item/timeline-item.d.ts +79 -0
  203. package/dist/controls/timeline-item/timeline-item.js +360 -0
  204. package/dist/controls/toast/toast-region.css +56 -0
  205. package/dist/controls/toast/toast-region.d.ts +20 -0
  206. package/dist/controls/toast/toast-region.js +113 -0
  207. package/dist/controls/toast/toast.css +96 -0
  208. package/dist/controls/toast/toast.d.ts +28 -0
  209. package/dist/controls/toast/toast.js +191 -0
  210. package/dist/controls/toolbar/toolbar.css +125 -0
  211. package/dist/controls/toolbar/toolbar.d.ts +108 -0
  212. package/dist/controls/toolbar/toolbar.js +68 -0
  213. package/dist/controls/tooltip/tooltip.css +80 -0
  214. package/dist/controls/tooltip/tooltip.d.ts +57 -0
  215. package/dist/controls/tooltip/tooltip.js +205 -0
  216. package/dist/descriptor/component-descriptor.d.ts +112 -0
  217. package/dist/descriptor/component-descriptor.js +492 -0
  218. package/dist/descriptor/index.d.ts +1 -0
  219. package/dist/descriptor/index.js +5 -0
  220. package/dist/dom/container.d.ts +45 -0
  221. package/dist/dom/container.js +60 -0
  222. package/dist/dom/element.d.ts +98 -0
  223. package/dist/dom/element.js +221 -0
  224. package/dist/dom/form.d.ts +240 -0
  225. package/dist/dom/form.js +399 -0
  226. package/dist/dom/index.d.ts +10 -0
  227. package/dist/dom/index.js +31 -0
  228. package/dist/dom/props.d.ts +56 -0
  229. package/dist/dom/props.js +231 -0
  230. package/dist/dom/repeat.d.ts +10 -0
  231. package/dist/dom/repeat.js +202 -0
  232. package/dist/dom/template.d.ts +161 -0
  233. package/dist/dom/template.js +634 -0
  234. package/dist/dom/watch.d.ts +11 -0
  235. package/dist/dom/watch.js +82 -0
  236. package/dist/foundation-styles.css +9 -0
  237. package/dist/index.d.ts +2 -0
  238. package/dist/index.js +3 -0
  239. package/dist/reactive/graph.d.ts +65 -0
  240. package/dist/reactive/graph.js +310 -0
  241. package/dist/reactive/index.d.ts +3 -0
  242. package/dist/reactive/index.js +4 -0
  243. package/dist/reactive/scheduler.d.ts +13 -0
  244. package/dist/reactive/scheduler.js +49 -0
  245. package/dist/traits/area-drag.d.ts +12 -0
  246. package/dist/traits/area-drag.js +70 -0
  247. package/dist/traits/form-registry.d.ts +36 -0
  248. package/dist/traits/form-registry.js +108 -0
  249. package/dist/traits/index.d.ts +24 -0
  250. package/dist/traits/index.js +19 -0
  251. package/dist/traits/overlay.d.ts +50 -0
  252. package/dist/traits/overlay.js +277 -0
  253. package/dist/traits/pane-resize.d.ts +26 -0
  254. package/dist/traits/pane-resize.js +103 -0
  255. package/dist/traits/press-activation.d.ts +11 -0
  256. package/dist/traits/press-activation.js +55 -0
  257. package/dist/traits/roving-focus.d.ts +52 -0
  258. package/dist/traits/roving-focus.js +214 -0
  259. package/dist/traits/scroll-fade.d.ts +28 -0
  260. package/dist/traits/scroll-fade.js +120 -0
  261. package/dist/traits/selection-commit.d.ts +30 -0
  262. package/dist/traits/selection-commit.js +146 -0
  263. package/dist/traits/tabbable.d.ts +12 -0
  264. package/dist/traits/tabbable.js +59 -0
  265. package/dist/traits/track-user-invalid.d.ts +36 -0
  266. package/dist/traits/track-user-invalid.js +52 -0
  267. package/dist/traits/value-codec.d.ts +120 -0
  268. package/dist/traits/value-codec.js +497 -0
  269. package/dist/traits/value-drag.d.ts +18 -0
  270. package/dist/traits/value-drag.js +84 -0
  271. package/package.json +263 -0
@@ -0,0 +1,251 @@
1
+ /* textarea.css — ui-textarea, the single-file component stylesheet (ADR-0003). Two clearly-SECTIONED
2
+ * blocks, mirroring text-field.css:
3
+ *
4
+ * [1] TOKEN BLOCK — `:where(ui-textarea)` (specificity 0,0,0) DECLARES the `--ui-textarea-*` chain from the
5
+ * colour roles (`--md-sys-color-{family}-{role}`; family = neutral, the text-field field-frame map reused
6
+ * verbatim) and the `--md-sys-font-{size}` dimensional ramp. The state channel is Kim's filled/container
7
+ * state law (TKT-0062) — THREE channels repoint per state (background, border, text-ink), keyed off
8
+ * five states (default/filled/hover/focus/disabled), the text-field precedent reused verbatim. `[size]`
9
+ * repoints ONLY the font — padding-block/padding-inline/the per-row line-box all DERIVE from font via
10
+ * calc(), so one repoint cascades through all three (ADR-0134's "[size] repoints font + block-padding +
11
+ * per-row line-box").
12
+ * [2] STYLES BLOCK — `@scope (ui-textarea)` CONSUMES only `--ui-textarea-*` for its OWN tokens (the one
13
+ * fleet exception: the shared focus-ring + motion constants, read DIRECTLY, the text-field precedent).
14
+ * ui-textarea declares its OWN multi-line geometry law (ADR-0134) — NOT the single-line Control-class
15
+ * `(scale × size) → §1-row` lookup ui-text-field rides (geometry.md / ADR-0038/0036): `min-block-size`
16
+ * is a GROWABLE minimum (`rows × line-box + 2·block-padding`), never a fixed height; real
17
+ * `padding-block` (never 0); top-left text placement via normal BLOCK flow — `display: block`, no
18
+ * `align-items` rule at all, deliberately (textarea-geometry.test.ts documents the choice; simpler
19
+ * than a flex `align-items: start` for a single block-axis child, same visual result); a prose
20
+ * `line-height` (never the single-line `line-height: 1`); `resize: vertical` (native `<textarea>`
21
+ * parity) + `overflow-y: auto`. The filled/container state ladder, `:focus-within` ring, forced-colors,
22
+ * and reduced-motion are inherited verbatim from the text-field precedent (the field-frame pattern is
23
+ * shape-independent — ADR-0134 "The multi-line geometry law").
24
+ *
25
+ * Standalone stylesheet — linked via the host page / component-styles barrel; NEVER injected from textarea.ts
26
+ * (behaviour-only `.ts`, no runtime style injection — plan §2).
27
+ */
28
+
29
+ /* ════════════════ [1] TOKEN BLOCK — :where(ui-textarea) declares --ui-textarea-* ════════════════ */
30
+
31
+ :where(ui-textarea) {
32
+ /* Field-frame colour channel (family = neutral) — Kim's filled/container state law (TKT-0062),
33
+ SUPERSEDING the old border-only channel: THREE channels now repoint per state (background, border,
34
+ text-ink), keyed off five states — default (empty, idle) / filled (has a value, idle) / hover / focus /
35
+ disabled. user-invalid is UNCHANGED — its own border-only danger channel (below) layers on top of
36
+ whichever bg/ink this table already picked; it never touches bg. The text-field precedent reused
37
+ verbatim (a multi-line surface is the SAME entry-control kin as a single-line one, only the box shape
38
+ differs):
39
+ state | bg | border | ink
40
+ default | container-low | transparent | neutral
41
+ filled | container | transparent | on-surface-variant
42
+ hover | container | outline-variant | on-surface-variant
43
+ focus | container-low | transparent (ring)| on-surface
44
+ disabled | container-low | transparent | neutral-low
45
+ "filled" reads `[data-part='editor']:not([data-empty])` (the SAME emptiness signal the placeholder
46
+ ::before already keys off) — see @scope's `:has()` selector below. Declared here, consumed at the
47
+ matching pseudo-/state selector in @scope (so @scope reads only --ui-textarea-*, never a role). */
48
+ --ui-textarea-bg: var(--md-sys-color-neutral-container-low); /* default */
49
+ --ui-textarea-bg-filled: var(--md-sys-color-neutral-container);
50
+ --ui-textarea-bg-hover: var(--md-sys-color-neutral-container);
51
+ --ui-textarea-bg-focus: var(--md-sys-color-neutral-container-low);
52
+ --ui-textarea-border: transparent; /* default — the ring is the interactive indicator, not the border */
53
+ --ui-textarea-border-hover: var(--md-sys-color-neutral-outline-variant); /* :hover — the ONE visible-border state */
54
+ --ui-textarea-border-focus: transparent; /* :focus-within — TRANSPARENT: the shared outline ring is the SOLE focus indicator (a --md-sys-color-focus-ring border-color step doubled with the ring into a visible double border; text-field ADR-0014 dev#1 precedent). Transparent holds the box geometry (the 1px frame still occupies its track — no layout shift). */
55
+ --ui-textarea-border-invalid: var(--md-sys-color-danger); /* :state(user-invalid) — UNCHANGED, orthogonal to the table above */
56
+ --ui-textarea-border-invalid-hover: var(--md-sys-color-danger-high); /* user-invalid + :hover — UNCHANGED */
57
+ --ui-textarea-ink: var(--md-sys-color-neutral); /* default — empty, idle (== the placeholder ink, below) */
58
+ --ui-textarea-ink-filled: var(--md-sys-color-neutral-on-surface-variant);
59
+ --ui-textarea-ink-hover: var(--md-sys-color-neutral-on-surface-variant);
60
+ --ui-textarea-ink-focus: var(--md-sys-color-neutral-on-surface);
61
+ --ui-textarea-placeholder: var(--ui-textarea-ink); /* tracks the SAME default-state ink role (Kim's table has no separate placeholder row) — re-resolves live off whatever --ui-textarea-ink cascades to for this element, so the disabled repoint below reaches it for free */
62
+
63
+ /* Geometry — the MULTI-LINE law (ADR-0134), not the single-line ramp. Font is the ONE sizing lever that
64
+ [size] repoints; padding-block/padding-inline/line-box all DERIVE from it via calc() below, so a single
65
+ repoint cascades through all three — the growable box has no fixed §1 height row. */
66
+ --ui-textarea-font: var(--md-sys-font-md);
67
+ --ui-textarea-line-height: 1.5; /* prose line-height — NEVER the single-line control's line-height:1 (geometry.md) */
68
+ --ui-textarea-line-box: calc(var(--ui-textarea-font) * var(--ui-textarea-line-height)); /* one rendered text row */
69
+ --ui-textarea-padding-block: calc(var(--ui-textarea-font) * 0.5); /* a comfortable text inset (ADR-0134) — never 0 */
70
+ --ui-textarea-padding-inline: calc(var(--ui-textarea-font) * 0.75);
71
+ --ui-textarea-rows: 3; /* the JS-set --ui-textarea-rows inline custom property overrides this per-instance (textarea.ts) */
72
+ --ui-textarea-min-block-size: calc(var(--ui-textarea-rows) * var(--ui-textarea-line-box) + 2 * var(--ui-textarea-padding-block));
73
+
74
+ /* Size-INVARIANT frame quantities — the entry-control class referents (geometry.md "Frame quantities that
75
+ split by control class"), the SAME fleet tokens ui-text-field's #71/#21 amendments introduced. */
76
+ --ui-textarea-radius: var(--md-sys-shape-corner-base); /* fixed rounded-rect — the container-fleet referent, not the action h/2 pill */
77
+ --ui-textarea-min-inline-size: 20ch; /* the entry-control typing-width floor (ADR-0021), native <textarea> parity */
78
+
79
+ /* Visible inline-validation message tokens (ADR-0029 A1, the text-field precedent) — the .ui-textarea-message
80
+ node (control-managed, aria-describedby target) becomes VISIBLE when non-empty under :state(user-invalid). */
81
+ --ui-textarea-message-font: var(--md-sys-font-sm);
82
+ --ui-textarea-message-ink: var(--md-sys-color-danger-on-surface-variant); /* AA-gated on-surface danger text ink */
83
+ }
84
+
85
+ /* size → the ONE sizing lever (font); padding-block/padding-inline/line-box all derive from it via calc() above. */
86
+ :where(ui-textarea[size='sm']) {
87
+ --ui-textarea-font: var(--md-sys-font-sm);
88
+ }
89
+ :where(ui-textarea[size='lg']) {
90
+ --ui-textarea-font: var(--md-sys-font-lg);
91
+ }
92
+
93
+ /* disabled → a role-REPOINT (NOT opacity, tokens.md canon; TKT-0062's disabled row). Matches BOTH the
94
+ own/reflected [disabled] AND the effective :state(disabled) (own || form-disabled). Declared LAST so it
95
+ wins the specificity-0 cascade for the BASE `--ui-textarea-{bg,border,ink}` tokens the unconditional
96
+ `:scope` rule reads. Only the base trio needs repointing — @scope's `filled`/`hover` selectors are
97
+ explicitly guarded with `:not(:is([disabled], :state(disabled)))` (a genuinely new hazard the old
98
+ border-only law never had: "filled" is a content-based `:has()` selector, not an interaction
99
+ pseudo-class, so it WOULD still match a disabled-but-non-empty field without that guard — unlike
100
+ `:hover`/`:focus-within`, which a pointer-inert, non-focusable disabled host can never really trigger).
101
+ user-invalid cannot co-occur (a disabled textarea does not willValidate — textarea.ts gates it), so the
102
+ danger border is left untouched. The text-field precedent reused verbatim. */
103
+ :where(ui-textarea:is([disabled], :state(disabled))) {
104
+ --ui-textarea-bg: var(--md-sys-color-neutral-container-low);
105
+ --ui-textarea-border: transparent;
106
+ --ui-textarea-ink: var(--md-sys-color-neutral-low);
107
+ }
108
+
109
+ /* ════════════════ [2] STYLES BLOCK — @scope (ui-textarea) consumes ONLY --ui-textarea-* ════════════════ */
110
+
111
+ @scope (ui-textarea) {
112
+ :scope {
113
+ display: block; /* no adornment slots (ADR-0134: no leading/trailing machinery) — the host IS the resizable box */
114
+ box-sizing: border-box;
115
+
116
+ /* the MULTI-LINE geometry law (ADR-0134) — a GROWABLE minimum, never a fixed §1-row height. */
117
+ min-block-size: var(--ui-textarea-min-block-size);
118
+ min-inline-size: var(--ui-textarea-min-inline-size); /* the entry-control typing-width floor (ADR-0021 parity) */
119
+ padding-block: var(--ui-textarea-padding-block); /* REAL block padding — the inversion of the single-line law's 0 */
120
+ padding-inline: var(--ui-textarea-padding-inline);
121
+ overflow-y: auto; /* content past min-block-size scrolls rather than growing the box unbounded */
122
+ resize: vertical; /* native <textarea> parity — user-draggable (requires overflow != visible, satisfied above) */
123
+
124
+ font-size: var(--ui-textarea-font);
125
+ line-height: var(--ui-textarea-line-height); /* prose line-height — NEVER the single-line control's line-height:1 */
126
+ background: var(--ui-textarea-bg);
127
+ color: var(--ui-textarea-ink);
128
+
129
+ border: 1px solid var(--ui-textarea-border);
130
+ border-radius: var(--ui-textarea-radius);
131
+ cursor: text;
132
+ }
133
+
134
+ :scope > [data-part='editor'] {
135
+ display: block;
136
+ min-inline-size: 0;
137
+ min-block-size: 100%;
138
+ font-size: var(--ui-textarea-font);
139
+ line-height: var(--ui-textarea-line-height);
140
+ color: var(--ui-textarea-ink);
141
+ outline: none; /* the focus ring is on the HOST frame, never the editor child */
142
+ white-space: pre-wrap; /* multi-line — newlines + wrapping both render (the ADR-0134 inversion of nowrap) */
143
+ overflow-wrap: break-word;
144
+ }
145
+
146
+ /* the placeholder — a control-toggled `data-empty` attr keys generated content (the text-field precedent
147
+ verbatim; NOT `:empty` — a cleared contenteditable can carry a bogus trailing <br>, ADR-0014). */
148
+ :scope > [data-part='editor'][data-empty]::before {
149
+ content: attr(data-placeholder);
150
+ color: var(--ui-textarea-placeholder);
151
+ pointer-events: none;
152
+ }
153
+
154
+ /* The filled/container state ladder (TKT-0062, Kim's ruling — supersedes the old border-only channel,
155
+ the text-field precedent reused verbatim) — repoints `background`/`border-color`/`color` together
156
+ from the per-state tokens declared in the :where() block (the geometry law is untouched). "filled" =
157
+ the editor carries a value (`:not([data-empty])`, the SAME emptiness signal the placeholder ::before
158
+ already keys off) — a CONTENT-based selector, not an interaction pseudo-class, so unlike :hover/
159
+ :focus-within it WOULD still match a disabled-but-non-empty field.
160
+
161
+ Precedence is enforced by MUTUAL EXCLUSION (`:not()`), not source-order/specificity: `:has()`/
162
+ `:not()` combinators contribute REAL specificity in a plain (non-:where()) selector — unlike the old
163
+ border-only law's bare single-pseudo-class rules, source order alone can no longer be trusted to pick
164
+ a winner (a `:not(:is(disabled))`-guarded `:hover` was measured to OUTRANK an unguarded
165
+ `:focus-within` by specificity in ui-text-field, so clicking to focus — which also leaves the pointer
166
+ hovering — kept the hover border instead of stepping transparent; a live regression this exact history
167
+ was caught fixing). Making each rule EXPLICITLY exclude every state that should outrank it removes the
168
+ ambiguity regardless of computed specificity: filled excludes hover/focus/disabled; hover excludes
169
+ focus/disabled; focus is checked last and excludes nothing (a disabled field is never focusable, so no
170
+ guard is needed there, matching the old law). user-invalid's border-only override still layers on top
171
+ of whichever bg/ink row above resolved, untouched. */
172
+ /* NOTE (code-reviewer HIGH finding, fixed — the text-field.css precedent): repointing the
173
+ --ui-textarea-ink TOKEN itself here, NOT a direct color: declaration on :scope — the editor part
174
+ carries its own color declaration reading that same token, so a host-only color: override never
175
+ reached the visible typed text or the placeholder (proven red in a real browser gate before this
176
+ fix). Repointing the token cascades to every consumer for free. */
177
+ :scope:not(:hover):not(:focus-within):not(:is([disabled], :state(disabled))):has(> [data-part='editor']:not([data-empty])) {
178
+ background: var(--ui-textarea-bg-filled);
179
+ --ui-textarea-ink: var(--ui-textarea-ink-filled);
180
+ }
181
+ :scope:not(:focus-within):not(:is([disabled], :state(disabled))):hover {
182
+ background: var(--ui-textarea-bg-hover);
183
+ border-color: var(--ui-textarea-border-hover);
184
+ --ui-textarea-ink: var(--ui-textarea-ink-hover);
185
+ }
186
+
187
+ /* Focus (the text-field ADR-0014 dev#1 precedent, reused verbatim) — the shared `outline` ring is the
188
+ SOLE interactive-frame indicator; the frame border steps to TRANSPARENT (a colour-step border here
189
+ would double with the ring). :focus-within (ALL focus, native text-input parity), not :focus-visible —
190
+ the focusable element is the editor child. Focus's bg/ink (TKT-0062) override filled/hover
191
+ unconditionally — a focused-and-filled field still shows the FOCUS row (container-low bg, on-surface
192
+ ink), not filled's. A disabled field is never focusable, so no guard is needed here (matching the old
193
+ law). */
194
+ :scope:focus-within {
195
+ background: var(--ui-textarea-bg-focus);
196
+ border-color: var(--ui-textarea-border-focus);
197
+ --ui-textarea-ink: var(--ui-textarea-ink-focus);
198
+ outline: var(--md-sys-state-focus-ring-width) solid var(--md-sys-color-focus-ring);
199
+ outline-offset: var(--md-sys-state-focus-ring-offset);
200
+ }
201
+
202
+ :scope:state(user-invalid) {
203
+ border-color: var(--ui-textarea-border-invalid);
204
+ }
205
+ :scope:state(user-invalid):hover {
206
+ border-color: var(--ui-textarea-border-invalid-hover);
207
+ }
208
+
209
+ /* Visible inline-validation message (ADR-0029 A1, the text-field precedent verbatim). */
210
+ :scope:state(user-invalid) > .ui-textarea-message {
211
+ display: block;
212
+ font-size: var(--ui-textarea-message-font);
213
+ color: var(--ui-textarea-message-ink);
214
+ }
215
+
216
+ :scope:is([disabled], :state(disabled)) {
217
+ pointer-events: none;
218
+ cursor: default;
219
+ resize: none; /* a disabled surface is not user-resizable */
220
+ }
221
+
222
+ /* Motion (ADR-0008 / interaction-states standard, reused verbatim) — state-PAINT properties only, never
223
+ geometry (a resize/rows change must SNAP). Gated behind :state(ready), zeroed under reduced-motion. */
224
+ :scope:state(ready) {
225
+ transition:
226
+ border-color var(--md-sys-motion-duration-fast) var(--md-sys-motion-easing-standard),
227
+ background-color var(--md-sys-motion-duration-fast) var(--md-sys-motion-easing-standard),
228
+ color var(--md-sys-motion-duration-fast) var(--md-sys-motion-easing-standard);
229
+ }
230
+ @media (prefers-reduced-motion: reduce) {
231
+ :scope:state(ready) {
232
+ transition: none;
233
+ }
234
+ }
235
+
236
+ /* forced-colors — keep the frame border + ink + placeholder VISIBLE (the text-field precedent verbatim).
237
+ The focus ring survives for free via --md-sys-color-focus-ring → Highlight. */
238
+ @media (forced-colors: active) {
239
+ :scope {
240
+ border-color: CanvasText;
241
+ color: CanvasText;
242
+ }
243
+ :scope > [data-part='editor'][data-empty]::before {
244
+ color: CanvasText;
245
+ }
246
+ :scope:is([disabled], :state(disabled)) {
247
+ border-color: GrayText;
248
+ color: GrayText;
249
+ }
250
+ }
251
+ }
@@ -0,0 +1,136 @@
1
+ import { type ReactiveProps } from '../../dom/index.js';
2
+ import { UIFormElement, type FormValue, type ValidityResult, type FieldLabelling } from '../../dom/form.js';
3
+ declare const props: {
4
+ value: import("../../index.js").PropConfig<string>;
5
+ label: {
6
+ reflect: true;
7
+ type: import("../../index.js").PropType<string>;
8
+ default: string;
9
+ attribute?: string | false;
10
+ };
11
+ placeholder: import("../../index.js").PropConfig<string>;
12
+ rows: {
13
+ reflect: true;
14
+ type: import("../../index.js").PropType<number | null>;
15
+ default: number | null;
16
+ attribute?: string | false;
17
+ };
18
+ size: {
19
+ reflect: true;
20
+ type: import("../../index.js").PropType<"sm" | "md" | "lg">;
21
+ default: "sm" | "md" | "lg";
22
+ attribute?: string | false;
23
+ };
24
+ readonly: {
25
+ reflect: true;
26
+ type: import("../../index.js").PropType<boolean>;
27
+ default: boolean;
28
+ attribute?: string | false;
29
+ };
30
+ name: {
31
+ reflect: true;
32
+ type: import("../../index.js").PropType<string>;
33
+ default: string;
34
+ attribute?: string | false;
35
+ };
36
+ disabled: {
37
+ reflect: true;
38
+ type: import("../../index.js").PropType<boolean>;
39
+ default: boolean;
40
+ attribute?: string | false;
41
+ };
42
+ required: {
43
+ reflect: true;
44
+ type: import("../../index.js").PropType<boolean>;
45
+ default: boolean;
46
+ attribute?: string | false;
47
+ };
48
+ };
49
+ export interface UITextareaElement extends ReactiveProps<typeof props> {
50
+ }
51
+ export declare class UITextareaElement extends UIFormElement {
52
+ #private;
53
+ static props: {
54
+ value: import("../../index.js").PropConfig<string>;
55
+ label: {
56
+ reflect: true;
57
+ type: import("../../index.js").PropType<string>;
58
+ default: string;
59
+ attribute?: string | false;
60
+ };
61
+ placeholder: import("../../index.js").PropConfig<string>;
62
+ rows: {
63
+ reflect: true;
64
+ type: import("../../index.js").PropType<number | null>;
65
+ default: number | null;
66
+ attribute?: string | false;
67
+ };
68
+ size: {
69
+ reflect: true;
70
+ type: import("../../index.js").PropType<"sm" | "md" | "lg">;
71
+ default: "sm" | "md" | "lg";
72
+ attribute?: string | false;
73
+ };
74
+ readonly: {
75
+ reflect: true;
76
+ type: import("../../index.js").PropType<boolean>;
77
+ default: boolean;
78
+ attribute?: string | false;
79
+ };
80
+ name: {
81
+ reflect: true;
82
+ type: import("../../index.js").PropType<string>;
83
+ default: string;
84
+ attribute?: string | false;
85
+ };
86
+ disabled: {
87
+ reflect: true;
88
+ type: import("../../index.js").PropType<boolean>;
89
+ default: boolean;
90
+ attribute?: string | false;
91
+ };
92
+ required: {
93
+ reflect: true;
94
+ type: import("../../index.js").PropType<boolean>;
95
+ default: boolean;
96
+ attribute?: string | false;
97
+ };
98
+ };
99
+ protected connected(): void;
100
+ protected disconnected(): void;
101
+ /** Forward host focus to the editor PART (label-association + native `.focus()` parity). */
102
+ focus(options?: FocusOptions): void;
103
+ /**
104
+ * Focus the editor and move the caret to the END of its text (a `ui-textarea`-friendly equivalent of the
105
+ * native `<textarea>.setSelectionRange(len, len)` a contenteditable host does not expose — the ADR-0134
106
+ * migration seam `entry-list.ts` uses to restore an in-progress edit after a re-render). A no-op before
107
+ * the editor part exists (guards a not-yet-connected control, mirroring `focus()`'s own guard above).
108
+ */
109
+ selectToEnd(): void;
110
+ /** The value contributed to the owning form (FACE — the base publishes it via internals.setFormValue). */
111
+ protected formValue(): FormValue;
112
+ /**
113
+ * The validity verdict: `required && value === ''` → `valueMissing`; valid otherwise. No codec/type
114
+ * validation — plain multi-line text has no value-shape to mismatch (ADR-0134). A disabled field is barred
115
+ * from constraint validation (native parity).
116
+ */
117
+ protected formValidity(): ValidityResult;
118
+ /**
119
+ * Form reset → value ← the initial `value` attribute (native-parity defaultValue) + clear the touched
120
+ * state (so a required-empty field does not show `:state(user-invalid)` until the user re-interacts).
121
+ */
122
+ protected formReset(): void;
123
+ /** Restore the value after navigation/autofill (FACE state restore). */
124
+ protected formStateRestore(state: File | string | FormData | null): void;
125
+ /**
126
+ * The part-role override (ADR-0051 cl.2) — the editor's `role=textbox` rides a light-DOM PART, not
127
+ * `internals.role`, so the base's guarded internals-reflection default never fires here; id-reference the
128
+ * editor directly instead. See text-field.ts's own doc for the full ordering rationale (reused verbatim —
129
+ * `aria-describedby` is only WRITTEN here on association; on dissociation the user-invalid/message effect
130
+ * above stays the exclusive owner, avoiding a two-effect write race).
131
+ */
132
+ protected applyFieldLabelling(refs: FieldLabelling | null): void;
133
+ /** Feeds `FormConnectDetail.userInvalid` (ADR-0050) — the `trackUserInvalid` tracker IS the timing source. */
134
+ protected formUserInvalid(): boolean;
135
+ }
136
+ export {};