@astryxdesign/core 0.1.0 → 0.1.1-canary.a514b99

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 (78) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
  3. package/dist/Chat/ChatLayoutScrollButton.js +5 -1
  4. package/dist/ContextMenu/ContextMenu.js +2 -2
  5. package/dist/DropdownMenu/DropdownMenu.js +2 -2
  6. package/dist/DropdownMenu/{renderXDSDropdownItems.d.ts → renderDropdownItems.d.ts} +3 -3
  7. package/dist/DropdownMenu/renderDropdownItems.d.ts.map +1 -0
  8. package/dist/DropdownMenu/{renderXDSDropdownItems.js → renderDropdownItems.js} +2 -2
  9. package/dist/Layout/Layout.d.ts +10 -1
  10. package/dist/Layout/Layout.d.ts.map +1 -1
  11. package/dist/Layout/Layout.js +5 -1
  12. package/dist/Outline/Outline.d.ts +3 -2
  13. package/dist/Outline/Outline.d.ts.map +1 -1
  14. package/dist/Outline/Outline.js +23 -4
  15. package/dist/Outline/useScrollSpy.d.ts +14 -1
  16. package/dist/Outline/useScrollSpy.d.ts.map +1 -1
  17. package/dist/Outline/useScrollSpy.js +161 -50
  18. package/dist/Resizable/useResizable.d.ts.map +1 -1
  19. package/dist/Resizable/useResizable.js +1 -5
  20. package/dist/Selector/Selector.d.ts.map +1 -1
  21. package/dist/Selector/Selector.js +1 -1
  22. package/dist/ToggleButton/ToggleButton.d.ts +10 -3
  23. package/dist/ToggleButton/ToggleButton.d.ts.map +1 -1
  24. package/dist/ToggleButton/ToggleButton.js +64 -18
  25. package/dist/theme/Theme.js +1 -1
  26. package/dist/theme/defineTheme.d.ts +1 -1
  27. package/dist/theme/defineTheme.d.ts.map +1 -1
  28. package/dist/theme/defineTheme.js +1 -1
  29. package/dist/theme/index.d.ts +1 -1
  30. package/dist/theme/index.d.ts.map +1 -1
  31. package/dist/theme/index.js +1 -1
  32. package/dist/theme/syntax/defineSyntaxTheme.js +1 -1
  33. package/dist/theme/tokens.d.ts +1 -1
  34. package/dist/theme/tokens.js +4 -4
  35. package/dist/theme/useTheme.d.ts +2 -2
  36. package/dist/utils/dateParser.d.ts.map +1 -1
  37. package/dist/utils/dateParser.js +15 -2
  38. package/package.json +2 -2
  39. package/src/Chat/ChatLayoutScrollButton.tsx +7 -1
  40. package/src/Collapsible/useCollapsible.doc.mjs +2 -2
  41. package/src/ContextMenu/ContextMenu.tsx +2 -2
  42. package/src/DateInput/DateInput.test.tsx +68 -20
  43. package/src/Divider/Divider.doc.mjs +1 -1
  44. package/src/DropdownMenu/DropdownMenu.tsx +2 -2
  45. package/src/DropdownMenu/{renderXDSDropdownItems.tsx → renderDropdownItems.tsx} +2 -2
  46. package/src/FormLayout/FormLayout.doc.mjs +3 -3
  47. package/src/Icon/Icon.doc.mjs +4 -4
  48. package/src/Item/Item.doc.mjs +2 -2
  49. package/src/Layout/Layout.doc.mjs +2 -1
  50. package/src/Layout/Layout.tsx +15 -1
  51. package/src/Layout/__tests__/childrenAsContent.test.tsx +59 -0
  52. package/src/Link/Link.doc.mjs +3 -3
  53. package/src/Link/LinkProvider.doc.mjs +3 -3
  54. package/src/Markdown/Markdown.doc.mjs +4 -4
  55. package/src/Outline/Outline.doc.mjs +1 -1
  56. package/src/Outline/Outline.test.tsx +76 -38
  57. package/src/Outline/Outline.tsx +23 -4
  58. package/src/Outline/useScrollSpy.ts +196 -63
  59. package/src/Resizable/Resizable.doc.mjs +2 -2
  60. package/src/Resizable/useResizable.ts +1 -7
  61. package/src/Selector/Selector.tsx +5 -6
  62. package/src/Table/Table.doc.mjs +3 -3
  63. package/src/ToggleButton/ToggleButton.doc.mjs +2 -2
  64. package/src/ToggleButton/ToggleButton.test.tsx +148 -6
  65. package/src/ToggleButton/ToggleButton.tsx +83 -20
  66. package/src/hooks/useEntryAnimation.doc.mjs +3 -3
  67. package/src/hooks/useMediaQuery.doc.mjs +2 -2
  68. package/src/hooks/useStreamingText.doc.mjs +3 -3
  69. package/src/theme/Theme.doc.mjs +2 -2
  70. package/src/theme/Theme.tsx +1 -1
  71. package/src/theme/defineTheme.ts +1 -1
  72. package/src/theme/index.ts +1 -1
  73. package/src/theme/syntax/defineSyntaxTheme.ts +1 -1
  74. package/src/theme/tokens.ts +4 -4
  75. package/src/theme/useTheme.ts +2 -2
  76. package/src/utils/dateParser.test.ts +26 -0
  77. package/src/utils/dateParser.ts +16 -2
  78. package/dist/DropdownMenu/renderXDSDropdownItems.d.ts.map +0 -1
@@ -486,7 +486,7 @@ export function Selector(props) {
486
486
  onKeyDown: onKeyDown,
487
487
  tabIndex: -1,
488
488
  ...{
489
- className: "x78zum5 x6s0dn4 x1qughib x1txdalj x1iyjqo2 xs83m0k x1r8uery xeuugli x1717udv x1ghz6dp xc342km xng3xce xjbqb8w xjb2p0i x1qlqyl8 x15bjb6t x1heor9g x1ypdohk x1a2a7pz x1p25gnr x1wfwxd8 xh6dtrn"
489
+ className: "x78zum5 x6s0dn4 x1qughib x1txdalj x1iyjqo2 xs83m0k x1r8uery xeuugli x1717udv x1ghz6dp xc342km xng3xce xjbqb8w xjb2p0i x1qlqyl8 x15bjb6t x1heor9g x1ypdohk x1a2a7pz"
490
490
  },
491
491
  children: /*#__PURE__*/_jsx("span", {
492
492
  ...{
@@ -38,8 +38,15 @@ export interface ToggleButtonProps extends BaseProps<HTMLButtonElement> {
38
38
  */
39
39
  onPressedChange?: (isPressed: boolean) => void;
40
40
  /**
41
- * Async action handler for API-backed toggles.
42
- * The button shows a loading spinner while the promise is pending.
41
+ * Action handler for API- or navigation-backed toggles, run inside a
42
+ * transition. The button shows a loading spinner while the action is
43
+ * pending — whether it returns a promise or synchronously triggers a
44
+ * suspending update (e.g. a router navigation that suspends on data).
45
+ *
46
+ * Because it runs in a transition, the toggle is *interruptible*: clicking
47
+ * again while an action is pending starts a new transition with the next
48
+ * optimistic state, so the action reflects the latest intent rather than
49
+ * being dropped.
43
50
  *
44
51
  * @example
45
52
  * ```
@@ -53,7 +60,7 @@ export interface ToggleButtonProps extends BaseProps<HTMLButtonElement> {
53
60
  * />
54
61
  * ```
55
62
  */
56
- pressedChangeAction?: (isPressed: boolean) => Promise<void>;
63
+ pressedChangeAction?: (isPressed: boolean) => void | Promise<void>;
57
64
  /**
58
65
  * The size of the toggle button.
59
66
  * When used inside ToggleButtonGroup, defaults to the group's size.
@@ -1 +1 @@
1
- {"version":3,"file":"ToggleButton.d.ts","sourceRoot":"","sources":["../../src/ToggleButton/ToggleButton.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,EAAc,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAIzD,OAAO,EAAS,KAAK,UAAU,EAAC,MAAM,WAAW,CAAC;AAElD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AA0C5C,MAAM,WAAW,iBAAkB,SAAQ,SAAS,CAAC,iBAAiB,CAAC;IACrE,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACnC;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;IAE/C;;;;;;;;;;;;;;;OAeG;IACH,mBAAmB,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5D;;;;OAIG;IACH,IAAI,CAAC,EAAE,UAAU,CAAC;IAElB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;OAEG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IAEjB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;;;;;;;;OAUG;IACH,WAAW,CAAC,EAAE,SAAS,CAAC;IAExB;;;OAGG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IAErB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAMD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,YAAY,CAAC,EAC3B,GAAG,EACH,KAAK,EACL,SAAS,EAAE,aAAa,EACxB,eAAe,EAAE,mBAAmB,EACpC,mBAAmB,EACnB,IAAI,EAAE,QAAQ,EACd,UAAU,EAAE,cAAsB,EAClC,SAAiB,EACjB,IAAI,EACJ,UAAkB,EAClB,WAAW,EACX,QAAQ,EACR,OAAO,EACP,KAAK,EACL,MAAM,EACN,SAAS,EAAE,UAAU,EACrB,KAAK,EACL,GAAG,KAAK,EACT,EAAE,iBAAiB,GAAG,SAAS,CAuF/B;yBA1Ge,YAAY"}
1
+ {"version":3,"file":"ToggleButton.d.ts","sourceRoot":"","sources":["../../src/ToggleButton/ToggleButton.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,EAMZ,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAIf,OAAO,EAAS,KAAK,UAAU,EAAC,MAAM,WAAW,CAAC;AAElD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAyE5C,MAAM,WAAW,iBAAkB,SAAQ,SAAS,CAAC,iBAAiB,CAAC;IACrE,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACnC;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;IAE/C;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,mBAAmB,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnE;;;;OAIG;IACH,IAAI,CAAC,EAAE,UAAU,CAAC;IAElB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;OAEG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IAEjB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;;;;;;;;OAUG;IACH,WAAW,CAAC,EAAE,SAAS,CAAC;IAExB;;;OAGG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IAErB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAMD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,YAAY,CAAC,EAC3B,GAAG,EACH,KAAK,EACL,SAAS,EAAE,aAAa,EACxB,eAAe,EAAE,mBAAmB,EACpC,mBAAmB,EACnB,IAAI,EAAE,QAAQ,EACd,UAAU,EAAE,cAAsB,EAClC,SAAiB,EACjB,IAAI,EACJ,UAAkB,EAClB,WAAW,EACX,QAAQ,EACR,OAAO,EACP,KAAK,EACL,MAAM,EACN,SAAS,EAAE,UAAU,EACrB,KAAK,EACL,GAAG,KAAK,EACT,EAAE,iBAAiB,GAAG,SAAS,CAyG/B;yBA5He,YAAY"}
@@ -19,7 +19,7 @@
19
19
  * - /apps/storybook/stories/ToggleButton.stories.tsx
20
20
  * - /packages/cli/templates/blocks/components/ToggleButton/ (showcase blocks)
21
21
  */
22
- import React, { useCallback } from 'react';
22
+ import React, { useCallback, useEffect, useOptimistic, useState, useTransition } from 'react';
23
23
  import * as stylex from '@stylexjs/stylex';
24
24
  import "../theme/tokens.stylex.js";
25
25
  import { colorVars, fontWeightVars } from "../theme/tokens.stylex.js";
@@ -27,6 +27,38 @@ import { Button } from "../Button/index.js";
27
27
  import { useToggleButtonGroup } from "./ToggleButtonGroup.js";
28
28
  import { themeProps } from "../utils/themeProps.js";
29
29
 
30
+ // =============================================================================
31
+ // Constants & helpers
32
+ // =============================================================================
33
+
34
+ /**
35
+ * The spinner only appears once the action has been pending for this long.
36
+ * A fast action shows the optimistic pressed state immediately with no spinner
37
+ * flash, and rapid re-clicks can interrupt the in-flight action before the
38
+ * button locks behind the spinner.
39
+ */
40
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
41
+ const PENDING_SPINNER_DELAY_MS = 150;
42
+
43
+ /**
44
+ * Returns `true` only once `active` has stayed `true` for `delayMs`.
45
+ * Used to debounce the loading spinner so the optimistic state shows first.
46
+ */
47
+ function useDelayed(active, delayMs) {
48
+ const [delayed, setDelayed] = useState(false);
49
+ useEffect(() => {
50
+ if (!active) {
51
+ return undefined;
52
+ }
53
+ const timer = setTimeout(() => setDelayed(true), delayMs);
54
+ return () => {
55
+ clearTimeout(timer);
56
+ setDelayed(false);
57
+ };
58
+ }, [active, delayMs]);
59
+ return active && delayed;
60
+ }
61
+
30
62
  // =============================================================================
31
63
  // Styles
32
64
  // =============================================================================
@@ -36,7 +68,6 @@ import { themeProps } from "../utils/themeProps.js";
36
68
  * A hidden span renders the same text at semibold weight to reserve
37
69
  * the wider width, preventing layout shift when toggling.
38
70
  */
39
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
40
71
  const pressedStyles = {
41
72
  background: {
42
73
  kWkggS: "xi89dp7",
@@ -93,32 +124,47 @@ export function ToggleButton({
93
124
  style,
94
125
  ...props
95
126
  }) {
96
- // Read group context if inside a group
97
127
  const group = useToggleButtonGroup();
98
-
99
- // Resolve state from group or props
100
- const isPressed = group && value != null ? group.selectedValues.has(value) : isPressedProp ?? false;
128
+ const committedPressed = group && value != null ? group.selectedValues.has(value) : isPressedProp ?? false;
101
129
  const size = sizeProp ?? group?.size ?? 'md';
102
130
  const isDisabled = group?.isDisabled ?? isDisabledProp;
131
+
132
+ // Track the pressed state optimistically. While an action is pending, the
133
+ // button reflects the intended (optimistic) state immediately, and a click
134
+ // mid-flight derives its next state from this value — so rapid toggles read
135
+ // true -> false -> true rather than stalling on the last committed value.
136
+ const [optimisticPressed, setOptimisticPressed] = useOptimistic(committedPressed);
137
+ const isPressed = optimisticPressed;
103
138
  const resolvedIcon = isPressed && pressedIcon ? pressedIcon : icon;
139
+
140
+ // Run the toggle inside a transition. The action is interruptible: clicking
141
+ // again while it is pending starts a fresh transition with the next
142
+ // optimistic state instead of being dropped, so there is no re-entry guard.
143
+ // Both onPressedChange and pressedChangeAction run inside the transition,
144
+ // which means a synchronous-but-suspending handler (e.g. a router navigation
145
+ // that suspends on data) also drives the pending state — not just promises.
146
+ const [isPending, startTransition] = useTransition();
147
+ // Debounce the spinner so a fast action shows the optimistic state without a
148
+ // spinner flash, and rapid re-clicks can interrupt before the button locks.
149
+ const showSpinner = useDelayed(isPending, PENDING_SPINNER_DELAY_MS);
150
+ const isLoadingState = isLoading || showSpinner;
104
151
  const handleClick = useCallback(() => {
105
- if (isDisabled || isLoading) {
152
+ if (isDisabled) {
106
153
  return;
107
154
  }
108
155
  if (group && value != null) {
109
- // Delegate to group context
156
+ // Group mode delegates selection to the group; no async-action path.
110
157
  group.toggle(value);
111
- } else if (onPressedChangeProp) {
112
- // Standalone toggle
113
- const newState = !isPressed;
114
- onPressedChangeProp(newState);
115
- if (pressedChangeAction) {
116
- void pressedChangeAction(newState);
117
- }
158
+ return;
118
159
  }
119
- }, [isDisabled, isLoading, group, value, onPressedChangeProp, pressedChangeAction, isPressed]);
160
+ const newState = !optimisticPressed;
161
+ startTransition(async () => {
162
+ setOptimisticPressed(newState);
163
+ onPressedChangeProp?.(newState);
164
+ await pressedChangeAction?.(newState);
165
+ });
166
+ }, [isDisabled, group, value, optimisticPressed, onPressedChangeProp, pressedChangeAction, setOptimisticPressed]);
120
167
 
121
- // Label with font weight shift and width reservation
122
168
  // isIconOnly prop is the source of truth for icon-only rendering.
123
169
  const labelContent = children != null ? /*#__PURE__*/_jsxs("span", {
124
170
  ...{
@@ -165,7 +211,7 @@ export function ToggleButton({
165
211
  variant: "ghost",
166
212
  size: size,
167
213
  isDisabled: isDisabled,
168
- isLoading: isLoading,
214
+ isLoading: isLoadingState,
169
215
  isIconOnly: isIconOnly,
170
216
  "aria-pressed": isPressed,
171
217
  icon: resolvedIcon,
@@ -115,7 +115,7 @@ function useThemeStyleInjection(theme) {
115
115
  // One-time perf hint per theme
116
116
  if (!warnedThemes.has(theme.name)) {
117
117
  warnedThemes.add(theme.name);
118
- console.warn(`[XDS] Theme "${theme.name}" is using runtime style injection. ` + `For better performance, use the pre-built theme:\n\n` + ` import {${theme.name}Theme} from '@astryxdesign/theme-${theme.name}/built';\n` + ` import '@astryxdesign/theme-${theme.name}/theme.css';\n\n` + `For custom themes, run \`npx astryx theme build <file>\` to generate ` + `the built artifacts.`);
118
+ console.warn(`[Astryx] Theme "${theme.name}" is using runtime style injection. ` + `For better performance, use the pre-built theme:\n\n` + ` import {${theme.name}Theme} from '@astryxdesign/theme-${theme.name}/built';\n` + ` import '@astryxdesign/theme-${theme.name}/theme.css';\n\n` + `For custom themes, run \`npx astryx theme build <file>\` to generate ` + `the built artifacts.`);
119
119
  }
120
120
  const {
121
121
  prose,
@@ -296,7 +296,7 @@ export interface DefinedTheme {
296
296
  __onLight?: ResolvedOnMedia;
297
297
  }
298
298
  /** All Astryx token defaults as a flat map. Useful for resolving full token sets. */
299
- export declare const xdsTokenDefaults: Record<string, string>;
299
+ export declare const tokenDefaults: Record<string, string>;
300
300
  /**
301
301
  * Create an Astryx theme.
302
302
  *
@@ -1 +1 @@
1
- {"version":3,"file":"defineTheme.d.ts","sourceRoot":"","sources":["../../src/theme/defineTheme.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,4BAA4B,CAAC;AAC7D,OAAO,KAAK,EAAC,gBAAgB,EAAa,MAAM,SAAS,CAAC;AAC1D,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACrB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,aAAa,EACb,eAAe,EACf,YAAY,EACZ,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EAClB,MAAM,iBAAiB,CAAC;AAMzB,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAmB,KAAK,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AAE3E,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,gBAAgB,CAAC;AAEpD,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,UAAU,CAAC;AAMpD,wCAAwC;AACxC,MAAM,MAAM,aAAa,GACrB,MAAM,OAAO,aAAa,GAC1B,MAAM,OAAO,eAAe,GAC5B,MAAM,OAAO,YAAY,GACzB,MAAM,OAAO,cAAc,GAC3B,MAAM,OAAO,cAAc,GAC3B,MAAM,OAAO,gBAAgB,GAC7B,MAAM,OAAO,YAAY,GACzB,MAAM,OAAO,kBAAkB,GAC/B,MAAM,OAAO,kBAAkB,GAC/B,MAAM,OAAO,gBAAgB,GAC7B,MAAM,OAAO,kBAAkB,GAC/B,MAAM,OAAO,iBAAiB,CAAC;AAEnC,0DAA0D;AAC1D,MAAM,MAAM,SAAS,GAAG,aAAa,GAAG,eAAe,CAAC;AAExD;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;AAEhE;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAE7E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,CACpC,MAAM,EACN,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAC/B,CAAC;AAEF,2BAA2B;AAC3B,MAAM,WAAW,gBAAgB;IAC/B,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;IAEb;;;;;;;;;;;;;;;;;;;OAmBG;IACH,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB;;;;;;;;;;;;;;;;;;OAkBG;IACH,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B;;;;;;;;;;;;;;;;;OAiBG;IACH,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB;;4EAEwE;IACxE,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;IAChD;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,8DAA8D;IAC9D,KAAK,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAC9B;;;;;;;;;;OAUG;IACH,MAAM,CAAC,EAAE,qBAAqB,CAAC;IAC/B;;;;;;;;;;;;;;;;;;OAkBG;IACH,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B;;;OAGG;IACH,OAAO,CAAC,EAAE,gBAAgB,CAAC;CAC5B;AAED,iDAAiD;AACjD,MAAM,WAAW,YAAY;IAC3B,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,gCAAgC;IAChC,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,oBAAoB;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAC9B,kEAAkE;IAClE,OAAO,CAAC,EAAE,IAAI,CAAC;IACf;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IACpD;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B;;;OAGG;IACH,SAAS,CAAC,EAAE,eAAe,CAAC;CAC7B;AAMD,qFAAqF;AACrF,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAcnD,CAAC;AA6FF;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,YAAY,CA8JjE;AAMD,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACvB,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,KAAK,eAAe,EACpB,KAAK,cAAc,GACpB,MAAM,sBAAsB,CAAC;AAM9B,2DAA2D;AAC3D,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,YAAY,CAQpE"}
1
+ {"version":3,"file":"defineTheme.d.ts","sourceRoot":"","sources":["../../src/theme/defineTheme.ts"],"names":[],"mappings":"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"}
@@ -115,7 +115,7 @@ import { domainTokenDefaults } from "./domainTokens/index.js";
115
115
  // =============================================================================
116
116
 
117
117
  /** All Astryx token defaults as a flat map. Useful for resolving full token sets. */
118
- export const xdsTokenDefaults = {
118
+ export const tokenDefaults = {
119
119
  ...colorDefaults,
120
120
  ...spacingDefaults,
121
121
  ...sizeDefaults,
@@ -13,7 +13,7 @@
13
13
  export { Theme } from './Theme';
14
14
  export { MediaTheme } from './MediaTheme';
15
15
  export type { MediaThemeProps } from './MediaTheme';
16
- export { defineTheme, generateThemeCSS, generateThemeCSSFlat, generateOnMediaCSS, generateThemeRules, generateThemeRulesSplit, type ThemeCSSOutput, type ThemeRulesSplit, isDefinedTheme, xdsTokenDefaults, } from './defineTheme';
16
+ export { defineTheme, generateThemeCSS, generateThemeCSSFlat, generateOnMediaCSS, generateThemeRules, generateThemeRulesSplit, type ThemeCSSOutput, type ThemeRulesSplit, isDefinedTheme, tokenDefaults, } from './defineTheme';
17
17
  export type { DefineThemeInput, DefinedTheme, CoreTokenName, TokenName, TokenValue, ComponentStyleMap, StyleOverrides, } from './defineTheme';
18
18
  export type { SyntaxTokenName, DomainTokenName, DataTokenName, } from './domainTokens';
19
19
  export { syntaxTokenDefaults, domainTokenDefaults, dataTokenDefaults, } from './domainTokens';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/theme/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/theme/index.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAC,KAAK,EAAC,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAC,UAAU,EAAC,MAAM,cAAc,CAAC;AACxC,YAAY,EAAC,eAAe,EAAC,MAAM,cAAc,CAAC;AAClD,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,uBAAuB,EACvB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,cAAc,EACd,aAAa,GACd,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,SAAS,EACT,UAAU,EACV,iBAAiB,EACjB,cAAc,GACf,MAAM,eAAe,CAAC;AAEvB,YAAY,EACV,eAAe,EACf,eAAe,EACf,aAAa,GACd,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAC,iBAAiB,EAAC,MAAM,UAAU,CAAC;AAC3C,YAAY,EACV,qBAAqB,EACrB,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,gBAAgB,GACjB,MAAM,UAAU,CAAC;AAGlB,OAAO,EAAC,WAAW,EAAE,cAAc,EAAC,MAAM,UAAU,CAAC;AACrD,YAAY,EAAC,oBAAoB,EAAC,MAAM,UAAU,CAAC;AAEnD,OAAO,EAAC,eAAe,EAAE,2BAA2B,EAAC,MAAM,mBAAmB,CAAC;AAC/E,YAAY,EAAC,eAAe,EAAE,eAAe,EAAC,MAAM,mBAAmB,CAAC;AAExE,OAAO,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAC;AACtD,YAAY,EACV,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AACpD,YAAY,EAAC,gBAAgB,EAAE,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AAE3E,OAAO,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAC;AACtD,YAAY,EACV,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,aAAa,EACb,eAAe,EACf,YAAY,EACZ,cAAc,EACd,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,SAAS,EACT,WAAW,EACX,QAAQ,EACR,UAAU,EACV,UAAU,EACV,UAAU,EACV,YAAY,EACZ,QAAQ,EACR,cAAc,EACd,cAAc,EACd,YAAY,EACZ,cAAc,EACd,aAAa,GACd,MAAM,iBAAiB,CAAC;AAGzB,YAAY,EACV,YAAY,EACZ,cAAc,EACd,WAAW,EACX,aAAa,EACb,aAAa,EACb,aAAa,EACb,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAC,QAAQ,EAAE,YAAY,EAAC,MAAM,YAAY,CAAC;AAClD,YAAY,EAAC,cAAc,EAAE,iBAAiB,EAAC,MAAM,YAAY,CAAC;AAClE,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,QAAQ,EACR,SAAS,GACV,MAAM,UAAU,CAAC;AAClB,YAAY,EACV,wBAAwB,EACxB,yBAAyB,EACzB,iBAAiB,GAClB,MAAM,UAAU,CAAC;AAElB,YAAY,EACV,SAAS,EACT,UAAU,EACV,QAAQ,EACR,eAAe,EACf,eAAe,EACf,QAAQ,EACR,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,cAAc,EACd,UAAU,GACX,MAAM,SAAS,CAAC"}
@@ -16,7 +16,7 @@
16
16
  */
17
17
  export { Theme } from "./Theme.js";
18
18
  export { MediaTheme } from "./MediaTheme.js";
19
- export { defineTheme, generateThemeCSS, generateThemeCSSFlat, generateOnMediaCSS, generateThemeRules, generateThemeRulesSplit, isDefinedTheme, xdsTokenDefaults } from "./defineTheme.js";
19
+ export { defineTheme, generateThemeCSS, generateThemeCSSFlat, generateOnMediaCSS, generateThemeRules, generateThemeRulesSplit, isDefinedTheme, tokenDefaults } from "./defineTheme.js";
20
20
  export { syntaxTokenDefaults, domainTokenDefaults, dataTokenDefaults } from "./domainTokens/index.js";
21
21
 
22
22
  // Syntax theme API
@@ -97,7 +97,7 @@ export function resolveSyntaxTokenForMode(value, mode) {
97
97
  export function defineSyntaxTheme(input) {
98
98
  const missing = ALL_SYNTAX_KEYS.filter(key => !(key in input.tokens));
99
99
  if (missing.length > 0) {
100
- console.warn('[XDS] defineSyntaxTheme("' + input.name + '"): missing tokens: ' + missing.join(', ') + '. All 14 syntax tokens are required.');
100
+ console.warn('[Astryx] defineSyntaxTheme("' + input.name + '"): missing tokens: ' + missing.join(', ') + '. All 14 syntax tokens are required.');
101
101
  }
102
102
 
103
103
  // Resolve tuples to light-dark() CSS strings
@@ -48,7 +48,7 @@ export declare const tokenVars: Record<TokenName, string>;
48
48
  /**
49
49
  * Resolve all Astryx token values for a theme and effective color mode.
50
50
  *
51
- * The result starts with `xdsTokenDefaults`, applies `theme.tokens`, then
51
+ * The result starts with `tokenDefaults`, applies `theme.tokens`, then
52
52
  * reapplies `theme.__inputTokens` when available so explicit tuple overrides
53
53
  * retain their original light/dark sides instead of relying on CSS parsing.
54
54
  * This mirrors the token resolution used by `useTheme()` but does not need
@@ -15,7 +15,7 @@
15
15
  * - /packages/core/src/theme/index.ts
16
16
  */
17
17
 
18
- import { xdsTokenDefaults } from "./defineTheme.js";
18
+ import { tokenDefaults } from "./defineTheme.js";
19
19
 
20
20
  /** Resolved color mode used when choosing the side of light/dark token values. */
21
21
 
@@ -45,7 +45,7 @@ export function tokenVar(name) {
45
45
  }
46
46
 
47
47
  /** Flat map of every known Astryx token name to its `var(--token-name)` reference. */
48
- export const tokenVars = Object.fromEntries(Object.keys(xdsTokenDefaults).map(name => [name, tokenVar(name)]));
48
+ export const tokenVars = Object.fromEntries(Object.keys(tokenDefaults).map(name => [name, tokenVar(name)]));
49
49
 
50
50
  /**
51
51
  * Split the arguments of a CSS function body on the first top-level comma.
@@ -118,7 +118,7 @@ function resolveXDSTokenValue(value, mode) {
118
118
  /**
119
119
  * Resolve all Astryx token values for a theme and effective color mode.
120
120
  *
121
- * The result starts with `xdsTokenDefaults`, applies `theme.tokens`, then
121
+ * The result starts with `tokenDefaults`, applies `theme.tokens`, then
122
122
  * reapplies `theme.__inputTokens` when available so explicit tuple overrides
123
123
  * retain their original light/dark sides instead of relying on CSS parsing.
124
124
  * This mirrors the token resolution used by `useTheme()` but does not need
@@ -131,7 +131,7 @@ export function resolveThemeTokens(theme, options) {
131
131
  mode
132
132
  } = options;
133
133
  const resolved = {};
134
- for (const [key, value] of Object.entries(xdsTokenDefaults)) {
134
+ for (const [key, value] of Object.entries(tokenDefaults)) {
135
135
  resolved[key] = resolveXDSTokenValue(value, mode);
136
136
  }
137
137
  if (theme == null) {
@@ -30,7 +30,7 @@ export interface UseThemeReturn {
30
30
  * For tokens with [light, dark] tuples, returns the value matching
31
31
  * the current mode. For single-value tokens, returns the value as-is.
32
32
  *
33
- * Falls back to xdsTokenDefaults if the token isn't overridden by the theme.
33
+ * Falls back to tokenDefaults if the token isn't overridden by the theme.
34
34
  *
35
35
  * @example
36
36
  * ```
@@ -42,7 +42,7 @@ export interface UseThemeReturn {
42
42
  /**
43
43
  * All tokens resolved for the current color mode.
44
44
  *
45
- * Merges xdsTokenDefaults with the theme's overrides, resolving
45
+ * Merges tokenDefaults with the theme's overrides, resolving
46
46
  * light-dark() values based on the effective color mode.
47
47
  *
48
48
  * Memoized — stable reference unless theme or mode changes.
@@ -1 +1 @@
1
- {"version":3,"file":"dateParser.d.ts","sourceRoot":"","sources":["../../src/utils/dateParser.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AAEH,OAAO,EAAC,KAAK,SAAS,EAAqC,MAAM,aAAa,CAAC;AAE/E,OAAO,EACL,gBAAgB,IAAI,QAAQ,EAC5B,cAAc,IAAI,SAAS,GAC5B,MAAM,aAAa,CAAC;AAErB;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAK1C;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAwF9D"}
1
+ {"version":3,"file":"dateParser.d.ts","sourceRoot":"","sources":["../../src/utils/dateParser.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AAEH,OAAO,EAAC,KAAK,SAAS,EAAqC,MAAM,aAAa,CAAC;AAE/E,OAAO,EACL,gBAAgB,IAAI,QAAQ,EAC5B,cAAc,IAAI,SAAS,GAC5B,MAAM,aAAa,CAAC;AAErB;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAK1C;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAsG9D"}
@@ -112,10 +112,23 @@ export function parseDateInput(input) {
112
112
  return parseNumericDate(+first, +second, currentYear);
113
113
  }
114
114
 
115
- // 6. Fall back to native Date parsing for other formats
115
+ // 6. Fall back to native Date parsing for other formats.
116
+ //
117
+ // Skip bare numeric input (e.g. "0", "1", "01", "2026"). These are
118
+ // in-progress values a user is still typing, not complete dates. Native
119
+ // `Date` parsing coerces them into arbitrary dates ("0" -> year 2000 in V8,
120
+ // year 0 in some engines), which is both surprising and — when the year
121
+ // resolves to 0 — produces an out-of-range date that throws downstream.
122
+ // Treat them as not-yet-a-valid-date instead.
123
+ if (/^\d+$/.test(trimmed)) {
124
+ return null;
125
+ }
116
126
  const parsed = new Date(trimmed);
117
127
  if (!isNaN(parsed.getTime())) {
118
- return plainDateFromDate(parsed);
128
+ const fromDate = plainDateFromDate(parsed);
129
+ // Validate the result so we never return an out-of-range date (e.g. a
130
+ // year of 0), which would throw when later re-parsed.
131
+ return tryCreatePlainDate(fromDate.year, fromDate.month, fromDate.day);
119
132
  }
120
133
  return null;
121
134
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astryxdesign/core",
3
- "version": "0.1.0",
3
+ "version": "0.1.1-canary.a514b99",
4
4
  "displayName": "XDS Core",
5
5
  "description": "The component library. Accessible, themeable React components with built-in spacing, dark mode, and StyleX styling.",
6
6
  "author": "Meta Open Source",
@@ -15,7 +15,7 @@
15
15
  "url": "https://github.com/facebook/astryx/issues"
16
16
  },
17
17
  "keywords": [
18
- "xds",
18
+ "astryx",
19
19
  "design-system",
20
20
  "react",
21
21
  "components",
@@ -90,6 +90,12 @@ const styles = stylex.create({
90
90
  whiteSpace: 'nowrap',
91
91
  paddingInline: spacingVars['--spacing-2'],
92
92
  },
93
+ // When a label is shown, the icon sits on the leading edge and the text on
94
+ // the trailing edge. Symmetric padding leaves the text cramped against the
95
+ // pill's rounded edge, so give the trailing side extra breathing room.
96
+ buttonWithLabel: {
97
+ paddingInlineEnd: spacingVars['--spacing-3'],
98
+ },
93
99
  });
94
100
 
95
101
  // =============================================================================
@@ -130,7 +136,7 @@ export function ChatLayoutScrollButton({
130
136
  variant="ghost"
131
137
  size="md"
132
138
  onClick={onClick}
133
- xstyle={styles.button}>
139
+ xstyle={[styles.button, label ? styles.buttonWithLabel : null]}>
134
140
  {label ?? undefined}
135
141
  </Button>
136
142
  </div>
@@ -38,7 +38,7 @@ export const docs = {
38
38
  usage: {
39
39
  description: 'Reusable hook that encapsulates the collapsible state machine. Supports three modes: group-controlled (inside CollapsibleGroup), controlled (isOpen + onOpenChange), and uncontrolled (self-managed with defaultIsOpen). Used internally by Card and Section.',
40
40
  bestPractices: [
41
- {guidance: true, description: 'Use the hook directly when building custom collapsible components that need XDS collapsible behavior without Collapsible wrapper.'},
41
+ {guidance: true, description: 'Use the hook directly when building custom collapsible components that need Astryx collapsible behavior without Collapsible wrapper.'},
42
42
  {guidance: true, description: 'For accordion behavior, wrap items in CollapsibleGroup and pass unique value props.'},
43
43
  {guidance: false, description: 'Implement your own open/close state when useCollapsible already provides it; the hook handles group coordination automatically.'},
44
44
  ],
@@ -64,7 +64,7 @@ export const docsDense = {
64
64
  usage: {
65
65
  description: 'Encapsulates collapsible state machine. 3 modes: group-controlled (inside CollapsibleGroup), controlled (isOpen + onOpenChange), uncontrolled (self-managed w/ defaultIsOpen). Used internally by Card + Section.',
66
66
  bestPractices: [
67
- {guidance: true, description: 'Use directly when building custom collapsible components needing XDS collapsible behavior w/o Collapsible wrapper.'},
67
+ {guidance: true, description: 'Use directly when building custom collapsible components needing Astryx collapsible behavior w/o Collapsible wrapper.'},
68
68
  {guidance: true, description: 'For accordion behavior, wrap items in CollapsibleGroup + pass unique value props.'},
69
69
  {guidance: false, description: 'Implement your own open/close state when useCollapsible already provides it; hook handles group coordination automatically.'},
70
70
  ],
@@ -36,7 +36,7 @@ import React, {
36
36
  import type {ReactNode} from 'react';
37
37
  import * as stylex from '@stylexjs/stylex';
38
38
  import {useLayer} from '../Layer/useLayer';
39
- import {renderXDSDropdownItems} from '../DropdownMenu/renderXDSDropdownItems';
39
+ import {renderDropdownItems} from '../DropdownMenu/renderDropdownItems';
40
40
  import {
41
41
  DropdownMenuContext,
42
42
  type DropdownMenuContextValue,
@@ -278,7 +278,7 @@ export function ContextMenu({
278
278
  );
279
279
 
280
280
  const resolvedMenuContent =
281
- props.items !== undefined ? renderXDSDropdownItems(items) : menuContent;
281
+ props.items !== undefined ? renderDropdownItems(items) : menuContent;
282
282
 
283
283
  return (
284
284
  <>
@@ -21,19 +21,13 @@ describe('DateInput', () => {
21
21
 
22
22
  it('renders with placeholder', () => {
23
23
  render(
24
- <DateInput
25
- label="Date"
26
- onChange={() => {}}
27
- placeholder="Pick a date"
28
- />,
24
+ <DateInput label="Date" onChange={() => {}} placeholder="Pick a date" />,
29
25
  );
30
26
  expect(screen.getByPlaceholderText('Pick a date')).toBeInTheDocument();
31
27
  });
32
28
 
33
29
  it('displays formatted date when value is provided', () => {
34
- render(
35
- <DateInput label="Date" value="2026-01-25" onChange={() => {}} />,
36
- );
30
+ render(<DateInput label="Date" value="2026-01-25" onChange={() => {}} />);
37
31
  expect(screen.getByDisplayValue('January 25, 2026')).toBeInTheDocument();
38
32
  });
39
33
 
@@ -118,9 +112,7 @@ describe('DateInput', () => {
118
112
 
119
113
  it('reverts to previous value on blur when input is invalid', async () => {
120
114
  const onChange = vi.fn();
121
- render(
122
- <DateInput label="Date" value="2026-01-25" onChange={onChange} />,
123
- );
115
+ render(<DateInput label="Date" value="2026-01-25" onChange={onChange} />);
124
116
 
125
117
  const input = screen.getByRole('combobox');
126
118
  fireEvent.change(input, {target: {value: 'not a date'}});
@@ -299,9 +291,7 @@ describe('DateInput', () => {
299
291
  // --- P1: Tab order: calendar button first, then input ---
300
292
 
301
293
  it('renders calendar button before input in DOM order', () => {
302
- const {container} = render(
303
- <DateInput label="Date" onChange={() => {}} />,
304
- );
294
+ const {container} = render(<DateInput label="Date" onChange={() => {}} />);
305
295
  const input = container.querySelector('input');
306
296
  const button = container.querySelector('button');
307
297
  // Calendar button should come before input in the DOM
@@ -389,9 +379,7 @@ describe('DateInput', () => {
389
379
 
390
380
  it('calls onChange with undefined when input is cleared and blurred', () => {
391
381
  const onChange = vi.fn();
392
- render(
393
- <DateInput label="Date" value="2026-01-25" onChange={onChange} />,
394
- );
382
+ render(<DateInput label="Date" value="2026-01-25" onChange={onChange} />);
395
383
 
396
384
  const input = screen.getByRole('combobox');
397
385
  fireEvent.change(input, {target: {value: ''}});
@@ -476,9 +464,7 @@ describe('DateInput', () => {
476
464
  });
477
465
 
478
466
  it('does not show clear button when hasClear is false', () => {
479
- render(
480
- <DateInput label="Date" value="2026-01-15" onChange={() => {}} />,
481
- );
467
+ render(<DateInput label="Date" value="2026-01-15" onChange={() => {}} />);
482
468
  expect(
483
469
  screen.queryByRole('button', {name: 'Clear Date'}),
484
470
  ).not.toBeInTheDocument();
@@ -514,6 +500,68 @@ describe('DateInput', () => {
514
500
  });
515
501
  });
516
502
 
503
+ // --- Regression: in-progress / leading-zero input must not crash ---
504
+
505
+ describe('incomplete typed input', () => {
506
+ it('does not crash or fire onChange when first digit typed is 0', () => {
507
+ const onChange = vi.fn();
508
+ render(<DateInput label="Date" onChange={onChange} />);
509
+
510
+ const input = screen.getByRole('combobox');
511
+ // Typing a leading "0" (e.g. starting "01" for January) must be treated
512
+ // as incomplete input, not coerced into an (invalid) date that crashes.
513
+ expect(() =>
514
+ fireEvent.change(input, {target: {value: '0'}}),
515
+ ).not.toThrow();
516
+
517
+ expect(onChange).not.toHaveBeenCalled();
518
+ expect(input).toHaveValue('0');
519
+ });
520
+
521
+ it('does not crash or fire onChange when first digit typed is 1', () => {
522
+ const onChange = vi.fn();
523
+ render(<DateInput label="Date" onChange={onChange} />);
524
+
525
+ const input = screen.getByRole('combobox');
526
+ expect(() =>
527
+ fireEvent.change(input, {target: {value: '1'}}),
528
+ ).not.toThrow();
529
+
530
+ expect(onChange).not.toHaveBeenCalled();
531
+ expect(input).toHaveValue('1');
532
+ });
533
+
534
+ it('does not crash while progressively typing a numeric date', () => {
535
+ const onChange = vi.fn();
536
+ render(<DateInput label="Date" onChange={onChange} />);
537
+
538
+ const input = screen.getByRole('combobox');
539
+ // Simulate keystroke-by-keystroke entry of "01/15/2026". The leading
540
+ // single-digit keystrokes must not crash (the original bug).
541
+ for (const partial of ['0', '01', '01/', '01/1', '01/15', '01/15/']) {
542
+ expect(() =>
543
+ fireEvent.change(input, {target: {value: partial}}),
544
+ ).not.toThrow();
545
+ }
546
+
547
+ // Completing the date commits it without error.
548
+ expect(() =>
549
+ fireEvent.change(input, {target: {value: '01/15/2026'}}),
550
+ ).not.toThrow();
551
+ expect(onChange).toHaveBeenCalledWith('2026-01-15');
552
+ });
553
+
554
+ it('does not crash on blur after typing an incomplete value', () => {
555
+ const onChange = vi.fn();
556
+ render(<DateInput label="Date" onChange={onChange} />);
557
+
558
+ const input = screen.getByRole('combobox');
559
+ fireEvent.change(input, {target: {value: '0'}});
560
+ expect(() => fireEvent.blur(input)).not.toThrow();
561
+ expect(onChange).not.toHaveBeenCalled();
562
+ });
563
+ });
564
+
517
565
  describe('external value changes', () => {
518
566
  it('clears pending input when value changes externally', () => {
519
567
  const onChange = vi.fn();
@@ -108,7 +108,7 @@ export const docsZh = {
108
108
 
109
109
  /** @type {import('../docs-types').TranslationDoc} */
110
110
  export const docsDense = {
111
- description: 'visual separator w/ optional label, using XDS design tokens',
111
+ description: 'visual separator w/ optional label, using Astryx design tokens',
112
112
  usage: {
113
113
  description: 'A visual separator that divides content into distinct sections. Use to create clear boundaries between groups of related content, or to demarcate interactive regions within a layout.',
114
114
  bestPractices: [
@@ -37,7 +37,7 @@ import {Button, type ButtonProps} from '../Button';
37
37
  import {Icon} from '../Icon';
38
38
  import type {IconType} from '../Icon';
39
39
 
40
- import {renderXDSDropdownItems} from './renderXDSDropdownItems';
40
+ import {renderDropdownItems} from './renderDropdownItems';
41
41
  import {
42
42
  DropdownMenuContext,
43
43
  type DropdownMenuContextValue,
@@ -366,7 +366,7 @@ export function DropdownMenu({
366
366
 
367
367
  // Resolve menu content: data-driven items become components
368
368
  const menuContent =
369
- props.items !== undefined ? renderXDSDropdownItems(items) : children;
369
+ props.items !== undefined ? renderDropdownItems(items) : children;
370
370
 
371
371
  return (
372
372
  <>
@@ -1,7 +1,7 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
2
 
3
3
  /**
4
- * @file renderXDSDropdownItems.tsx
4
+ * @file renderDropdownItems.tsx
5
5
  * @output Converts data-driven menu items into DropdownMenuItem components
6
6
  * @position Utility; used by DropdownMenu to unify data-driven and compound paths
7
7
  */
@@ -49,7 +49,7 @@ function getSectionKey(section: DropdownMenuSection, index: number): string {
49
49
  * Converts data-driven items into DropdownMenuItem components,
50
50
  * so both modes share the same rendering and keyboard navigation path.
51
51
  */
52
- export function renderXDSDropdownItems(
52
+ export function renderDropdownItems(
53
53
  items: DropdownMenuOption[],
54
54
  ): ReactNode {
55
55
  const elements: ReactNode[] = [];