@astryxdesign/core 0.4.2 → 0.4.3-canary.551a8de

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 (98) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/README.md +79 -45
  3. package/dist/Avatar/Avatar.d.ts.map +1 -1
  4. package/dist/Avatar/Avatar.js +3 -19
  5. package/dist/Banner/Banner.d.ts +9 -2
  6. package/dist/Banner/Banner.d.ts.map +1 -1
  7. package/dist/Banner/Banner.js +84 -33
  8. package/dist/Banner/index.d.ts +14 -12
  9. package/dist/Banner/index.d.ts.map +1 -1
  10. package/dist/Banner/index.js +10 -8
  11. package/dist/Chat/ChatTokenizedText.js +1 -1
  12. package/dist/ComplexSelector/ComplexSelector.d.ts +38 -4
  13. package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
  14. package/dist/ComplexSelector/ComplexSelector.js +98 -31
  15. package/dist/ComplexSelector/index.d.ts +2 -2
  16. package/dist/ComplexSelector/index.d.ts.map +1 -1
  17. package/dist/ComplexSelector/index.js +1 -1
  18. package/dist/Markdown/parser.d.ts.map +1 -1
  19. package/dist/Markdown/parser.js +55 -12
  20. package/dist/MobileNav/MobileNav.d.ts +12 -0
  21. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  22. package/dist/MobileNav/MobileNav.js +102 -30
  23. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  24. package/dist/PowerSearch/PowerSearch.js +4 -1
  25. package/dist/PowerSearch/formatFilterValue.d.ts.map +1 -1
  26. package/dist/PowerSearch/formatFilterValue.js +2 -4
  27. package/dist/Switch/Switch.d.ts.map +1 -1
  28. package/dist/Switch/Switch.js +5 -1
  29. package/dist/Table/columnUtils.d.ts.map +1 -1
  30. package/dist/Table/columnUtils.js +4 -1
  31. package/dist/TextArea/TextArea.d.ts +6 -3
  32. package/dist/TextArea/TextArea.d.ts.map +1 -1
  33. package/dist/TextArea/TextArea.js +17 -6
  34. package/dist/TreeList/TreeList.js +2 -1
  35. package/dist/astryx.css +8 -4
  36. package/dist/theme/defineTheme.d.ts +30 -7
  37. package/dist/theme/defineTheme.d.ts.map +1 -1
  38. package/dist/theme/defineTheme.js +36 -47
  39. package/dist/theme/expandColorScale.d.ts +17 -2
  40. package/dist/theme/expandColorScale.d.ts.map +1 -1
  41. package/dist/theme/expandColorScale.js +63 -33
  42. package/dist/theme/mergeComponents.d.ts +20 -0
  43. package/dist/theme/mergeComponents.d.ts.map +1 -0
  44. package/dist/theme/mergeComponents.js +56 -0
  45. package/dist/theme/onMediaTokens.d.ts +6 -1
  46. package/dist/theme/onMediaTokens.d.ts.map +1 -1
  47. package/dist/theme/onMediaTokens.js +11 -3
  48. package/dist/utils/characters.d.ts +27 -0
  49. package/dist/utils/characters.d.ts.map +1 -0
  50. package/dist/utils/characters.js +83 -0
  51. package/dist/utils/index.d.ts +1 -0
  52. package/dist/utils/index.d.ts.map +1 -1
  53. package/dist/utils/index.js +1 -0
  54. package/package.json +4 -8
  55. package/src/Avatar/Avatar.test.tsx +6 -1
  56. package/src/Avatar/Avatar.tsx +3 -21
  57. package/src/Banner/Banner.doc.mjs +12 -10
  58. package/src/Banner/Banner.test.tsx +108 -0
  59. package/src/Banner/Banner.tsx +124 -38
  60. package/src/Banner/index.ts +15 -13
  61. package/src/Chat/ChatTokenizedText.tsx +1 -1
  62. package/src/ComplexSelector/ComplexSelector.doc.mjs +55 -6
  63. package/src/ComplexSelector/ComplexSelector.test.tsx +197 -6
  64. package/src/ComplexSelector/ComplexSelector.tsx +156 -28
  65. package/src/ComplexSelector/index.ts +3 -1
  66. package/src/Markdown/parser.test.ts +53 -0
  67. package/src/Markdown/parser.ts +53 -12
  68. package/src/MobileNav/MobileNav.tsx +128 -37
  69. package/src/MobileNav/MobileNavCloseEdgeCases.test.tsx +426 -0
  70. package/src/MobileNav/MobileNavCloseTiming.test.ts +58 -0
  71. package/src/MobileNav/MobileNavCloseVisibility.test.tsx +172 -0
  72. package/src/PowerSearch/PowerSearch.test.tsx +48 -3
  73. package/src/PowerSearch/PowerSearch.tsx +4 -1
  74. package/src/PowerSearch/formatFilterValue.test.ts +22 -0
  75. package/src/PowerSearch/formatFilterValue.ts +2 -4
  76. package/src/Switch/Switch.test.tsx +16 -0
  77. package/src/Switch/Switch.tsx +7 -0
  78. package/src/Table/Table.test.tsx +6 -0
  79. package/src/Table/columnUtils.ts +3 -1
  80. package/src/TextArea/TextArea.doc.mjs +1 -1
  81. package/src/TextArea/TextArea.test.tsx +72 -0
  82. package/src/TextArea/TextArea.tsx +26 -8
  83. package/src/TreeList/TreeList.doc.mjs +2 -2
  84. package/src/TreeList/TreeList.tsx +1 -1
  85. package/src/__tests__/stubMatchMedia.test.ts +79 -0
  86. package/src/__tests__/stubMatchMedia.ts +95 -0
  87. package/src/theme/defineTheme.test.ts +127 -0
  88. package/src/theme/defineTheme.ts +70 -55
  89. package/src/theme/expandColorScale.test.ts +138 -0
  90. package/src/theme/expandColorScale.ts +89 -44
  91. package/src/theme/extensibleAxes.test.ts +365 -0
  92. package/src/theme/mergeComponents.ts +59 -0
  93. package/src/theme/onMediaTokens.ts +9 -2
  94. package/src/utils/characters.test.ts +141 -0
  95. package/src/utils/characters.ts +88 -0
  96. package/src/utils/index.ts +2 -0
  97. package/dist/astryx.umd.js +0 -147
  98. package/dist/astryx.umd.js.map +0 -7
@@ -57,6 +57,9 @@ const styles = {
57
57
  kFalU9: "x5ve5x3",
58
58
  kI3sdo: "x1a2a7pz",
59
59
  k1xSpc: "x1s85apg",
60
+ k1ekBW: "xrgi2yo",
61
+ kIyJzY: "x80gvsz",
62
+ kzIqYQ: "xd00j3c",
60
63
  $$css: true
61
64
  },
62
65
  open: {
@@ -133,6 +136,61 @@ const dynamicStyles = {
133
136
  }]
134
137
  };
135
138
 
139
+ // =============================================================================
140
+ // Close timing
141
+ // =============================================================================
142
+
143
+ /** Longest the drawer will wait before closing, however long the hold is. */
144
+ const MAX_CLOSE_DELAY_MS = 250;
145
+ /** Fraction of the hold to close at, so the close never lands on its boundary. */
146
+ const CLOSE_WITHIN_HOLD = 0.6;
147
+
148
+ /**
149
+ * Shortest duration in a `transition-duration` list, in ms; null if unreadable.
150
+ *
151
+ * Browsers serialise computed `<time>` values in seconds — an authored `410ms`
152
+ * reads back as `"0.41s"` and a list as `"0.41s, 0.12s"` — so the seconds branch
153
+ * is the one that runs outside tests. jsdom echoes an inline `250ms` back as-is
154
+ * and never resolves `var()`, so both units and the unreadable case are covered
155
+ * directly in MobileNavCloseTiming.test.ts rather than through the component.
156
+ *
157
+ * @internal Exported for unit tests.
158
+ */
159
+ export function parseShortestDurationMs(value) {
160
+ const durations = value.split(',').map(part => {
161
+ const trimmed = part.trim();
162
+ const ms = Number.parseFloat(trimmed);
163
+ if (!Number.isFinite(ms)) {
164
+ return null;
165
+ }
166
+ return trimmed.endsWith('ms') ? ms : trimmed.endsWith('s') ? ms * 1000 : null;
167
+ }).filter(ms => ms !== null);
168
+ return durations.length ? Math.min(...durations) : null;
169
+ }
170
+
171
+ /**
172
+ * How long to wait before closing the native dialog.
173
+ *
174
+ * The drawer is only rendered for as long as its `display` transition runs, and
175
+ * closing an unrendered modal dialog is what leaves the page inert (#4290). So
176
+ * the close has to land inside that hold. The hold is `--duration-medium`,
177
+ * which themes rewrite — the shipped y2k theme sets it to exactly 250ms — so
178
+ * read the hold in effect rather than assuming it.
179
+ */
180
+ function resolveCloseDelay(dialog) {
181
+ // Reduced motion makes the close sooner; it must not make the hold shorter.
182
+ // Shrinking both leaves no slack — one slow frame between the commit and this
183
+ // macrotask and the drawer has already stopped being rendered.
184
+ const cap = window.matchMedia('(prefers-reduced-motion: reduce)').matches ? 0 : MAX_CLOSE_DELAY_MS;
185
+ const hold = parseShortestDurationMs(window.getComputedStyle(dialog).transitionDuration);
186
+
187
+ // The hold is unreadable — an unresolved var() outside a real browser.
188
+ if (hold === null) {
189
+ return cap;
190
+ }
191
+ return hold <= 0 ? 0 : Math.min(cap, hold * CLOSE_WITHIN_HOLD);
192
+ }
193
+
136
194
  // =============================================================================
137
195
  // Types
138
196
  // =============================================================================
@@ -203,6 +261,31 @@ export function MobileNav({
203
261
  // Resolved side — computed from trigger position when side='auto'
204
262
  const [resolvedSide, setResolvedSide] = useState(side === 'auto' ? 'end' : side);
205
263
 
264
+ // Resolve which edge the drawer slides from. Deliberately its own effect,
265
+ // declared before the open/close effect below so the trigger is still the
266
+ // active element when `side='auto'` reads it. Keeping it out of that effect
267
+ // is what stops a `side` change during a close from re-arming the delay: the
268
+ // CSS hold runs from the commit that started the slide-out and does not
269
+ // restart, so a fresh full delay could land after the drawer had already
270
+ // stopped being rendered — #4290 again.
271
+ useEffect(() => {
272
+ if (!isOpen) {
273
+ return;
274
+ }
275
+ if (side === 'auto') {
276
+ const trigger = document.activeElement;
277
+ if (trigger && trigger !== document.body) {
278
+ const rect = trigger.getBoundingClientRect();
279
+ const triggerCenter = rect.left + rect.width / 2;
280
+ // eslint-disable-next-line @eslint-react/set-state-in-effect -- side is resolved from trigger layout immediately before showModal()
281
+ setResolvedSide(triggerCenter < window.innerWidth / 2 ? 'start' : 'end');
282
+ }
283
+ } else {
284
+ // eslint-disable-next-line @eslint-react/set-state-in-effect -- side prop changes must update the open dialog placement
285
+ setResolvedSide(side);
286
+ }
287
+ }, [isOpen, side]);
288
+
206
289
  // Open/close the dialog via showModal()/close()
207
290
  // close() is delayed so the slide-out transition can play.
208
291
  useEffect(() => {
@@ -210,24 +293,7 @@ export function MobileNav({
210
293
  if (!dialog) {
211
294
  return;
212
295
  }
213
- if (closeTimeoutRef.current) {
214
- clearTimeout(closeTimeoutRef.current);
215
- closeTimeoutRef.current = null;
216
- }
217
296
  if (isOpen) {
218
- // Determine drawer side from trigger position when auto
219
- if (side === 'auto') {
220
- const trigger = document.activeElement;
221
- if (trigger && trigger !== document.body) {
222
- const rect = trigger.getBoundingClientRect();
223
- const triggerCenter = rect.left + rect.width / 2;
224
- // eslint-disable-next-line @eslint-react/set-state-in-effect -- side is resolved from trigger layout immediately before showModal()
225
- setResolvedSide(triggerCenter < window.innerWidth / 2 ? 'start' : 'end');
226
- }
227
- } else {
228
- // eslint-disable-next-line @eslint-react/set-state-in-effect -- side prop changes must update the open dialog placement
229
- setResolvedSide(side);
230
- }
231
297
  if (!dialog.open) {
232
298
  dialog.showModal();
233
299
  }
@@ -237,10 +303,9 @@ export function MobileNav({
237
303
  document.documentElement.style.overflow = 'clip';
238
304
  } else if (dialog.open) {
239
305
  document.documentElement.style.overflow = '';
240
- const duration = window.matchMedia('(prefers-reduced-motion: reduce)').matches ? 10 : 250;
241
306
  closeTimeoutRef.current = setTimeout(() => {
242
307
  dialog.close();
243
- }, duration);
308
+ }, resolveCloseDelay(dialog));
244
309
  }
245
310
  return () => {
246
311
  if (closeTimeoutRef.current) {
@@ -248,20 +313,27 @@ export function MobileNav({
248
313
  closeTimeoutRef.current = null;
249
314
  }
250
315
  document.documentElement.style.overflow = '';
251
- // Close the native dialog on teardown if it's still open. Inside AppShell
252
- // the drawer is mounted in an <Activity> that switches to mode="hidden"
253
- // when the drawer closes; React then runs this cleanup (with a stale
254
- // isOpen) instead of re-running the effect with isOpen=false, so the
255
- // close branch above never fires. If we leave the <dialog> `open` here,
256
- // showModal() is skipped on the next open (the dialog is already open in
257
- // the hidden tree) and the drawer can never be re-opened. Closing it
258
- // unconditionally on teardown keeps the native dialog state in sync so a
259
- // subsequent open cleanly calls showModal() again.
260
- if (dialog.open) {
316
+ };
317
+ }, [isOpen]);
318
+
319
+ // Close the native dialog on unmount if it's still open. Inside AppShell the
320
+ // drawer is mounted in an <Activity> that switches to mode="hidden" when the
321
+ // drawer closes; React then runs effect cleanups (with a stale isOpen)
322
+ // instead of re-running the effect with isOpen=false, so the close branch
323
+ // above never fires. If we leave the <dialog> `open` here, showModal() is
324
+ // skipped on the next open (the dialog is already open in the hidden tree)
325
+ // and the drawer can never be re-opened — see MobileNavReopen.test.tsx.
326
+ // This must be a separate unmount-only effect: putting it in the open/close
327
+ // effect above would close the dialog on every isOpen flip and cut off the
328
+ // delayed slide-out close.
329
+ useEffect(() => {
330
+ const dialog = dialogRef.current;
331
+ return () => {
332
+ if (dialog?.open) {
261
333
  dialog.close();
262
334
  }
263
335
  };
264
- }, [isOpen, side]);
336
+ }, []);
265
337
 
266
338
  // Handle native cancel event (Escape key) — prevent default and route through onOpenChange
267
339
  const handleCancel = useCallback(event => {
@@ -1 +1 @@
1
- {"version":3,"file":"PowerSearch.d.ts","sourceRoot":"","sources":["../../src/PowerSearch/PowerSearch.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PowerSearch.d.ts","sourceRoot":"","sources":["../../src/PowerSearch/PowerSearch.tsx"],"names":[],"mappings":"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"}
@@ -33,6 +33,7 @@ import { formatFilterValue } from "./formatFilterValue.js";
33
33
  import { PowerSearchEditPopover } from "./PowerSearchEditPopover.js";
34
34
  import { resolveOperatorLabel } from "./resolveOperatorLabel.js";
35
35
  import { themeProps } from "../utils/themeProps.js";
36
+ import { truncateCharacters } from "../utils/characters.js";
36
37
  import { useTranslator } from "../i18n/index.js";
37
38
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
38
39
  // =============================================================================
@@ -68,7 +69,9 @@ const popoverLayerStyles = {
68
69
  }
69
70
  };
70
71
  function truncateString(value, limit) {
71
- return value.length > limit + 3 ? value.slice(0, limit) + '...' : value;
72
+ // Same semantics as before — strings within limit + 3 pass through, longer
73
+ // ones cut to limit + '...' — but counted in characters, not code units.
74
+ return truncateCharacters(value, limit + 3, '...');
72
75
  }
73
76
  function getEnumLabel(values, value) {
74
77
  return values.find(v => v.value === value)?.label ?? value;
@@ -1 +1 @@
1
- {"version":3,"file":"formatFilterValue.d.ts","sourceRoot":"","sources":["../../src/PowerSearch/formatFilterValue.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,aAAa,EAAE,WAAW,EAAW,MAAM,SAAS,CAAC;AAClE,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,SAAS,CAAC;AA8C1C,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,cAAc,EACvB,aAAa,EAAE,aAAa,EAC5B,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,MAAM,EACjB,CAAC,EAAE,YAAY,EACf,UAAU,CAAC,EAAE,MAAM,GAClB,MAAM,CAsHR"}
1
+ {"version":3,"file":"formatFilterValue.d.ts","sourceRoot":"","sources":["../../src/PowerSearch/formatFilterValue.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,aAAa,EAAE,WAAW,EAAW,MAAM,SAAS,CAAC;AAClE,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,SAAS,CAAC;AA4C1C,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,cAAc,EACvB,aAAa,EAAE,aAAa,EAC5B,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,MAAM,EACjB,CAAC,EAAE,YAAY,EACf,UAAU,CAAC,EAAE,MAAM,GAClB,MAAM,CAsHR"}
@@ -10,11 +10,9 @@
10
10
  * - /packages/core/src/PowerSearch/index.ts
11
11
  */
12
12
 
13
+ import { truncateCharacters } from "../utils/characters.js";
13
14
  function truncate(str, maxLength) {
14
- if (str.length <= maxLength) {
15
- return str;
16
- }
17
- return str.slice(0, maxLength - 1) + '\u2026';
15
+ return truncateCharacters(str, maxLength);
18
16
  }
19
17
  function formatEnumLabel(value, enumValues) {
20
18
  const item = enumValues.find(v => v.value === value);
@@ -1 +1 @@
1
- {"version":3,"file":"Switch.d.ts","sourceRoot":"","sources":["../../src/Switch/Switch.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Switch.d.ts","sourceRoot":"","sources":["../../src/Switch/Switch.tsx"],"names":[],"mappings":"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"}
@@ -112,6 +112,10 @@ const styles = {
112
112
  kOIVth: "x1txdalj",
113
113
  $$css: true
114
114
  },
115
+ containerLabelHidden: {
116
+ kOIVth: "xxhr3t",
117
+ $$css: true
118
+ },
115
119
  containerSpread: {
116
120
  kjj79g: "x1qughib",
117
121
  kzqmXN: "xh8yej3",
@@ -396,7 +400,7 @@ export function Switch({
396
400
  // unconditionally is safe.
397
401
  disabledMessageTooltip.interactionRef(el);
398
402
  },
399
- ...stylex.props(styles.container, labelSpacing === 'spread' && styles.containerSpread, !isDisabled && switchScope),
403
+ ...stylex.props(styles.container, isLabelHidden && styles.containerLabelHidden, labelSpacing === 'spread' && styles.containerSpread, !isDisabled && switchScope),
400
404
  children: [' ', labelPosition === 'start' ? /*#__PURE__*/_jsxs(_Fragment, {
401
405
  children: [labelElement, switchElement]
402
406
  }) : /*#__PURE__*/_jsxs(_Fragment, {
@@ -1 +1 @@
1
- {"version":3,"file":"columnUtils.d.ts","sourceRoot":"","sources":["../../src/Table/columnUtils.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAC,aAAa,EAAE,SAAS,EAAC,MAAM,OAAO,CAAC;AACpD,OAAO,KAAK,EAAC,WAAW,EAAE,iBAAiB,EAAE,UAAU,EAAC,MAAM,SAAS,CAAC;AAExE,8DAA8D;AAC9D,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAM5C;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,2DAA2D;IAC3D,KAAK,EAAE,aAAa,CAAC;CACtB;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,sDAAsD;IACtD,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IAC1C,oGAAoG;IACpG,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnE,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,GACxB,oBAAoB,CAmEtB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAC1B,KAAK,GAAE,MAAU,EACjB,OAAO,CAAC,EAAE;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAC,GAC5B,iBAAiB,CAMnB;AAED;;;;;;;GAOG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAE/C;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAK9C;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnE,IAAI,EAAE,CAAC,EACP,GAAG,EAAE,MAAM,GACV,SAAS,CAiBX;AA+DD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/D,IAAI,EAAE,CAAC,EAAE,GACR,WAAW,CAAC,CAAC,CAAC,EAAE,CAmDlB"}
1
+ {"version":3,"file":"columnUtils.d.ts","sourceRoot":"","sources":["../../src/Table/columnUtils.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAC,aAAa,EAAE,SAAS,EAAC,MAAM,OAAO,CAAC;AACpD,OAAO,KAAK,EAAC,WAAW,EAAE,iBAAiB,EAAE,UAAU,EAAC,MAAM,SAAS,CAAC;AAGxE,8DAA8D;AAC9D,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAM5C;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,2DAA2D;IAC3D,KAAK,EAAE,aAAa,CAAC;CACtB;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,sDAAsD;IACtD,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IAC1C,oGAAoG;IACpG,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnE,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,GACxB,oBAAoB,CAmEtB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAC1B,KAAK,GAAE,MAAU,EACjB,OAAO,CAAC,EAAE;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAC,GAC5B,iBAAiB,CAMnB;AAED;;;;;;;GAOG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAE/C;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAM9C;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnE,IAAI,EAAE,CAAC,EACP,GAAG,EAAE,MAAM,GACV,SAAS,CAiBX;AA+DD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/D,IAAI,EAAE,CAAC,EAAE,GACR,WAAW,CAAC,CAAC,CAAC,EAAE,CAmDlB"}
@@ -11,6 +11,8 @@
11
11
  * - /packages/core/src/Table/index.ts (exports if functions change)
12
12
  */
13
13
 
14
+ import { firstCharacter } from "../utils/characters.js";
15
+
14
16
  /** Default minimum width (in px) for proportional columns. */
15
17
  export const DEFAULT_MIN_COLUMN_WIDTH = 120;
16
18
 
@@ -153,7 +155,8 @@ export function capitalize(str) {
153
155
  if (str.length === 0) {
154
156
  return str;
155
157
  }
156
- return str.charAt(0).toUpperCase() + str.slice(1);
158
+ const first = firstCharacter(str);
159
+ return first.toUpperCase() + str.slice(first.length);
157
160
  }
158
161
 
159
162
  /**
@@ -149,10 +149,13 @@ export interface TextAreaProps extends Omit<BaseProps, 'onChange' | 'defaultValu
149
149
  */
150
150
  onPaste?: (e: ClipboardEvent<HTMLTextAreaElement>) => void;
151
151
  /**
152
- * Maximum number of characters allowed.
153
- * When set, displays a character counter below the textarea.
152
+ * Maximum number of characters allowed, counted as user-perceived
153
+ * characters — an emoji or flag sequence counts as one. When set,
154
+ * displays a character counter below the textarea.
154
155
  * Does not enforce the limit natively — the counter shows error styling
155
- * when exceeded, and the consumer can validate via onChange.
156
+ * when exceeded, and the consumer can validate via onChange. Validate with
157
+ * `characterCount` (exported from this package) rather than `value.length`
158
+ * so enforcement matches the displayed count.
156
159
  */
157
160
  maxLength?: number;
158
161
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"TextArea.d.ts","sourceRoot":"","sources":["../../src/TextArea/TextArea.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TextArea.d.ts","sourceRoot":"","sources":["../../src/TextArea/TextArea.tsx"],"names":[],"mappings":"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"}
@@ -15,7 +15,7 @@
15
15
  * - /apps/storybook/stories/TextArea.stories.tsx (storybook stories)
16
16
  * - /packages/cli/assets/templates/blocks/components/TextArea/ (showcase blocks)
17
17
  */
18
- import { useId, useOptimistic, useTransition, useRef, useCallback } from 'react';
18
+ import { useId, useOptimistic, useTransition, useRef, useCallback, useMemo } from 'react';
19
19
  import * as stylex from '@stylexjs/stylex';
20
20
  import "../theme/tokens.stylex.js";
21
21
  import { colorVars, spacingVars, typographyVars, typeScaleVars } from "../theme/tokens.stylex.js";
@@ -29,6 +29,7 @@ import { useInputStatusIcon } from "../hooks/useInputStatusIcon.js";
29
29
  import { useAnnounce } from "../hooks/useAnnounce.js";
30
30
  import { useSize } from "../SizeContext/SizeContext.js";
31
31
  import { themeProps } from "../utils/themeProps.js";
32
+ import { characterCount } from "../utils/characters.js";
32
33
  import { useTranslator } from "../i18n/index.js";
33
34
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
34
35
  const COUNTER_WARNING_THRESHOLD = 0.8;
@@ -208,7 +209,11 @@ export function TextArea({
208
209
  return;
209
210
  }
210
211
  const newValue = e.target.value;
211
- announceCounter(newValue.length);
212
+ // Guarded here, not just inside announceCounter, so textareas without a
213
+ // maxLength never pay for segmenting the whole value on each keystroke.
214
+ if (maxLength != null) {
215
+ announceCounter(characterCount(newValue));
216
+ }
212
217
  onChange?.(newValue, e);
213
218
  if (changeAction && !e.defaultPrevented) {
214
219
  startTransition(async () => {
@@ -217,6 +222,12 @@ export function TextArea({
217
222
  });
218
223
  }
219
224
  };
225
+
226
+ // Counter semantics count user-perceived characters, so an emoji or flag
227
+ // sequence counts as one character, not its code units.
228
+ // Only measured when a counter exists — segmentation is O(value length),
229
+ // and memoized so re-renders that keep the same value skip it entirely.
230
+ const valueLength = useMemo(() => maxLength != null ? characterCount(optimisticValue) : 0, [maxLength, optimisticValue]);
220
231
  const effectivelyDisabled = isDisabled || isBusy;
221
232
 
222
233
  // Focus textarea when clicking anywhere on the wrapper (icons, padding, etc.)
@@ -293,7 +304,7 @@ export function TextArea({
293
304
  "data-autofocus": hasAutoFocus || undefined,
294
305
  "aria-describedby": ariaDescribedBy,
295
306
  "aria-required": isRequired && !isOptional ? 'true' : undefined,
296
- "aria-invalid": status?.type === 'error' || maxLength != null && optimisticValue.length > maxLength ? 'true' : undefined,
307
+ "aria-invalid": status?.type === 'error' || maxLength != null && valueLength > maxLength ? 'true' : undefined,
297
308
  "aria-busy": isBusy || undefined,
298
309
  ...stylex.props(styles.textarea, textareaSizeStyles[size], isDisabled && styles.textareaDisabled, Boolean(startIcon) && styles.textareaWithStartIcon,
299
310
  // Reserve trailing space only when the end slot actually renders
@@ -318,8 +329,8 @@ export function TextArea({
318
329
  1: {
319
330
  className: "x10l6tqk x112dmjn x13oyzgk x47corl x78zum5 x6s0dn4 xzye2dw x9ynric x141an7d x1ltkj2j xjt36v0"
320
331
  }
321
- }[!!(optimisticValue.length > maxLength) << 0],
322
- children: [optimisticValue.length > maxLength &&
332
+ }[!!(valueLength > maxLength) << 0],
333
+ children: [valueLength > maxLength &&
323
334
  /*#__PURE__*/
324
335
  // Non-color cue so the over-limit state isn't conveyed by the red
325
336
  // color alone (WCAG 1.4.1). Decorative — the count text and the
@@ -327,7 +338,7 @@ export function TextArea({
327
338
  _jsx(Icon, {
328
339
  icon: "warning",
329
340
  size: "sm"
330
- }), optimisticValue.length, "/", maxLength]
341
+ }), valueLength, "/", maxLength]
331
342
  })]
332
343
  }), showsDisabledMessage && disabledMessageTooltip.renderTooltip(disabledMessage)]
333
344
  });
@@ -226,7 +226,8 @@ export function TreeList({
226
226
  ref: ref,
227
227
  "data-testid": testId,
228
228
  ...mergeProps(themeProps('tree-list', {
229
- density
229
+ density,
230
+ variant
230
231
  }), stylex.props(styles.root, xstyle), className, style),
231
232
  children: [header != null && /*#__PURE__*/_jsx("div", {
232
233
  id: headerId,
package/dist/astryx.css CHANGED
@@ -378,6 +378,7 @@
378
378
  .x1pjcqnp:not(#\#):not(#\#){border-radius:inherit}
379
379
  .x1ws5lxm:not(#\#):not(#\#){border-radius:max(0px,calc(var(--_dropdown-menu-radius,var(--spacing-2)) - var(--_dropdown-menu-padding,var(--spacing-1))))}
380
380
  .xc910v0:not(#\#):not(#\#){border-radius:max(0px,calc(var(--_segmented-control-radius) - var(--_segmented-control-padding)))}
381
+ .x1vf2byn:not(#\#):not(#\#){border-radius:var(--_banner-radius,var(--radius-container))}
381
382
  .x1jxw6zd:not(#\#):not(#\#){border-radius:var(--_button-radius,var(--radius-element))}
382
383
  .xy0xnkn:not(#\#):not(#\#){border-radius:var(--_button-radius,var(--radius-full))}
383
384
  .x153u1i6:not(#\#):not(#\#){border-radius:var(--_card-radius)}
@@ -639,14 +640,14 @@
639
640
  .x18o3ruo:not(#\#):not(#\#):not(#\#){background-image:none}
640
641
  .x1mwwwfo:not(#\#):not(#\#):not(#\#){border-collapse:collapse}
641
642
  .x16uus16:not(#\#):not(#\#):not(#\#){border-end-end-radius:0}
643
+ .x1eprgri:not(#\#):not(#\#):not(#\#){border-end-end-radius:var(--_banner-radius,var(--radius-container))}
642
644
  .x6k0y1c:not(#\#):not(#\#):not(#\#){border-end-end-radius:var(--_chat-composer-radius)}
643
- .xiaxfje:not(#\#):not(#\#):not(#\#){border-end-end-radius:var(--radius-container)}
644
645
  .x14i3lts:not(#\#):not(#\#):not(#\#){border-end-end-radius:var(--radius-element)}
645
646
  .x1dgc8on:not(#\#):not(#\#):not(#\#){border-end-end-radius:var(--radius-full)}
646
647
  .x1whkvtz:not(#\#):not(#\#):not(#\#){border-end-end-radius:var(--radius-inner)}
647
648
  .xbiv7yw:not(#\#):not(#\#):not(#\#){border-end-start-radius:0}
649
+ .x1k5g1gk:not(#\#):not(#\#):not(#\#){border-end-start-radius:var(--_banner-radius,var(--radius-container))}
648
650
  .xkvxy4d:not(#\#):not(#\#):not(#\#){border-end-start-radius:var(--_chat-composer-radius)}
649
- .x14k8p9y:not(#\#):not(#\#):not(#\#){border-end-start-radius:var(--radius-container)}
650
651
  .xquck67:not(#\#):not(#\#):not(#\#){border-end-start-radius:var(--radius-element)}
651
652
  .x1wc3881:not(#\#):not(#\#):not(#\#){border-end-start-radius:var(--radius-full)}
652
653
  .xrfs2vl:not(#\#):not(#\#):not(#\#){border-end-start-radius:var(--radius-inner)}
@@ -664,16 +665,16 @@
664
665
  .xtpqe59:not(#\#):not(#\#):not(#\#){border-inline-start-width:var(--spacing-0-5)}
665
666
  .x1gukg7c:not(#\#):not(#\#):not(#\#){border-spacing:0}
666
667
  .x1ga7v0g:not(#\#):not(#\#):not(#\#){border-start-end-radius:0}
668
+ .x13nour3:not(#\#):not(#\#):not(#\#){border-start-end-radius:var(--_banner-radius,var(--radius-container))}
667
669
  .xzc3kxz:not(#\#):not(#\#):not(#\#){border-start-end-radius:var(--_chat-composer-radius)}
668
670
  .xg0tfu:not(#\#):not(#\#):not(#\#){border-start-end-radius:var(--radius-chat)}
669
- .x7hs6f1:not(#\#):not(#\#):not(#\#){border-start-end-radius:var(--radius-container)}
670
671
  .xxbepff:not(#\#):not(#\#):not(#\#){border-start-end-radius:var(--radius-element)}
671
672
  .x8agd5o:not(#\#):not(#\#):not(#\#){border-start-end-radius:var(--radius-full)}
672
673
  .x126per9:not(#\#):not(#\#):not(#\#){border-start-end-radius:var(--radius-inner)}
673
674
  .x15mokao:not(#\#):not(#\#):not(#\#){border-start-start-radius:0}
675
+ .xwxb7qi:not(#\#):not(#\#):not(#\#){border-start-start-radius:var(--_banner-radius,var(--radius-container))}
674
676
  .xy7p8pm:not(#\#):not(#\#):not(#\#){border-start-start-radius:var(--_chat-composer-radius)}
675
677
  .x1n70msy:not(#\#):not(#\#):not(#\#){border-start-start-radius:var(--radius-chat)}
676
- .x81l70g:not(#\#):not(#\#):not(#\#){border-start-start-radius:var(--radius-container)}
677
678
  .x19415el:not(#\#):not(#\#):not(#\#){border-start-start-radius:var(--radius-full)}
678
679
  .x3qb8m:not(#\#):not(#\#):not(#\#){border-start-start-radius:var(--radius-inner)}
679
680
  .x183tx6i:not(#\#):not(#\#):not(#\#){border-start-start-radius:var(--radius-page)}
@@ -780,6 +781,7 @@
780
781
  .x1r8uery:not(#\#):not(#\#):not(#\#){flex-basis:0}
781
782
  .xjpgo6f:not(#\#):not(#\#):not(#\#){flex-basis:200px}
782
783
  .xchdapg:not(#\#):not(#\#):not(#\#){flex-basis:300px}
784
+ .xgualba:not(#\#):not(#\#):not(#\#){flex-basis:8rem}
783
785
  .xdl72j9:not(#\#):not(#\#):not(#\#){flex-basis:auto}
784
786
  .x3ieub6:not(#\#):not(#\#):not(#\#){flex-direction:column-reverse}
785
787
  .xdt5ytf:not(#\#):not(#\#):not(#\#){flex-direction:column}
@@ -972,6 +974,7 @@
972
974
  .x1t137rt:not(#\#):not(#\#):not(#\#){outline-style:none}
973
975
  .x1k57tk5:not(#\#):not(#\#):not(#\#){outline-width:0}
974
976
  .x9y5y3v:not(#\#):not(#\#):not(#\#){overflow-clip-margin:1px}
977
+ .xj0a0fe:not(#\#):not(#\#):not(#\#){overflow-wrap:anywhere}
975
978
  .x1mzt3pk:not(#\#):not(#\#):not(#\#){overflow-wrap:break-word}
976
979
  .x1h4wwuj:not(#\#):not(#\#):not(#\#){overflow-wrap:normal}
977
980
  .xyri2b:not(#\#):not(#\#):not(#\#){padding-inline-end:0}
@@ -1123,6 +1126,7 @@
1123
1126
  .x1gbuem2:not(#\#):not(#\#):not(#\#){transition-property:color,background-color}
1124
1127
  .x1mpt4pi:not(#\#):not(#\#):not(#\#){transition-property:color,text-decoration}
1125
1128
  .xt3l3uh:not(#\#):not(#\#):not(#\#){transition-property:color}
1129
+ .xrgi2yo:not(#\#):not(#\#):not(#\#){transition-property:display}
1126
1130
  .xjshnde:not(#\#):not(#\#):not(#\#){transition-property:grid-template-rows,padding}
1127
1131
  .x1qn9uv2:not(#\#):not(#\#):not(#\#){transition-property:grid-template-rows}
1128
1132
  .x157bb6t:not(#\#):not(#\#):not(#\#){transition-property:mask-image}
@@ -112,9 +112,14 @@ export interface DefineThemeInput {
112
112
  /** Theme name — used for data-astryx-theme attribute and identification */
113
113
  name: string;
114
114
  /**
115
- * Base theme to extend. When provided, the new theme starts with the
116
- * base theme's tokens, components, and fonts, then applies overrides
117
- * from this input on top. The base theme's values have lowest precedence.
115
+ * Base theme to extend. When provided, the new theme starts with everything
116
+ * the base resolved to — tokens, component overrides, icons, indicators, and
117
+ * its `onDark`/`onLight` surfaces — then applies this input on top. The base
118
+ * theme's values have lowest precedence.
119
+ *
120
+ * The result is flat: an extended theme carries its inheritance in its own
121
+ * resolved output, so `astryx theme build` emits one self-contained
122
+ * stylesheet and the base's CSS does not need to be loaded alongside it.
118
123
  *
119
124
  * Use this to create variant themes that customize only a few aspects
120
125
  * (e.g. icons, accent color) without re-specifying the full theme.
@@ -189,20 +194,38 @@ export interface DefineThemeInput {
189
194
  */
190
195
  radius?: RadiusScaleConfig;
191
196
  /**
192
- * Color scale configuration. Generates color token overrides from a
193
- * single accent color using the HCT perceptual color model.
197
+ * Color scale configuration. Generates color token overrides from an
198
+ * accent seed using the HCT perceptual color model.
194
199
  *
195
200
  * Only generates tokens derivable from the accent — status colors,
196
201
  * categorical hues, and fixed tokens (on-dark/on-light) use defaults.
197
- * Explicit `tokens` entries always take precedence.
202
+ *
203
+ * `accent` accepts a single hex (same seed for both color schemes) or a
204
+ * `[light, dark]` tuple, matching `TokenValue`. With a tuple, the light
205
+ * scheme's full palette derives from the light seed and the dark
206
+ * scheme's from the dark seed.
198
207
  *
199
208
  * `accent` is optional — omit it for a neutral-only theme, which keeps
200
209
  * the default accent tokens and only themes the neutrals.
201
210
  *
211
+ * Precedence vs `tokens`: explicit `tokens` entries win over generated
212
+ * values, token by token. Because `--color-accent-muted`,
213
+ * `--color-text-accent` and `--color-icon-accent` are generated as
214
+ * `var(--color-accent)` references, a `tokens['--color-accent']`
215
+ * override re-points them at runtime. `--color-on-accent` does NOT
216
+ * follow: it is baked from the `color.accent` seed (a contrast
217
+ * computation CSS cannot express), so overriding the accent through
218
+ * `tokens` without also overriding `--color-on-accent` leaves the two
219
+ * out of sync. To re-seat the whole palette per scheme, prefer a tuple
220
+ * `color.accent` over the `tokens['--color-accent']` workaround.
221
+ *
202
222
  * @example
203
- * ```tsx
223
+ * ```
204
224
  * color: { accent: '#0064E0', neutralStyle: 'cool', contrast: 'standard' }
205
225
  *
226
+ * // Per-scheme accents — light palette from the first seed, dark from the second
227
+ * color: { accent: ['#0064E0', '#48CAE4'] }
228
+ *
206
229
  * // Neutral-only — accent tokens stay at their defaults
207
230
  * color: { neutralStyle: 'warm' }
208
231
  * ```
@@ -1 +1 @@
1
- {"version":3,"file":"defineTheme.d.ts","sourceRoot":"","sources":["../../src/theme/defineTheme.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"defineTheme.d.ts","sourceRoot":"","sources":["../../src/theme/defineTheme.ts"],"names":[],"mappings":"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"}