@astryxdesign/core 0.1.8-canary.dad941c → 0.1.8-canary.dd421ea

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 (128) hide show
  1. package/dist/Avatar/AvatarStatusDot.d.ts +33 -5
  2. package/dist/Avatar/AvatarStatusDot.d.ts.map +1 -1
  3. package/dist/Avatar/AvatarStatusDot.js +144 -19
  4. package/dist/Calendar/Calendar.d.ts.map +1 -1
  5. package/dist/Calendar/Calendar.js +30 -2
  6. package/dist/Chat/ChatComposerInput.d.ts +20 -3
  7. package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
  8. package/dist/Chat/ChatComposerInput.js +19 -3
  9. package/dist/Chat/useChatStreamScroll.d.ts +2 -1
  10. package/dist/Chat/useChatStreamScroll.d.ts.map +1 -1
  11. package/dist/Chat/useChatStreamScroll.js +22 -8
  12. package/dist/Chat/useSpeechRecognition.d.ts +0 -1
  13. package/dist/Chat/useSpeechRecognition.d.ts.map +1 -1
  14. package/dist/Chat/useSpeechRecognition.js +1 -1
  15. package/dist/CheckboxList/CheckboxListItem.d.ts +20 -1
  16. package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
  17. package/dist/CheckboxList/CheckboxListItem.js +18 -2
  18. package/dist/Dialog/Dialog.d.ts +3 -0
  19. package/dist/Dialog/Dialog.d.ts.map +1 -1
  20. package/dist/Dialog/Dialog.js +54 -5
  21. package/dist/Dialog/DialogContext.d.ts +7 -0
  22. package/dist/Dialog/DialogContext.d.ts.map +1 -1
  23. package/dist/Dialog/DialogContext.js +2 -2
  24. package/dist/Dialog/DialogHeader.d.ts +5 -2
  25. package/dist/Dialog/DialogHeader.d.ts.map +1 -1
  26. package/dist/Dialog/DialogHeader.js +6 -1
  27. package/dist/Icon/Icon.d.ts +7 -2
  28. package/dist/Icon/Icon.d.ts.map +1 -1
  29. package/dist/Item/Item.d.ts +6 -1
  30. package/dist/Item/Item.d.ts.map +1 -1
  31. package/dist/Item/Item.js +22 -1
  32. package/dist/OverflowList/OverflowList.d.ts +20 -3
  33. package/dist/OverflowList/OverflowList.d.ts.map +1 -1
  34. package/dist/OverflowList/OverflowList.js +29 -4
  35. package/dist/PowerSearch/PowerSearchEditPopover.js +1 -1
  36. package/dist/Stack/stack.stylex.d.ts +9 -9
  37. package/dist/Table/plugins/selection/useTableSelection.d.ts +2 -1
  38. package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
  39. package/dist/Thumbnail/Thumbnail.d.ts +8 -1
  40. package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
  41. package/dist/Thumbnail/Thumbnail.js +27 -1
  42. package/dist/ToggleButton/ToggleButtonGroup.d.ts +0 -1
  43. package/dist/ToggleButton/ToggleButtonGroup.d.ts.map +1 -1
  44. package/dist/ToggleButton/ToggleButtonGroup.js +1 -1
  45. package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts +9 -1
  46. package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts.map +1 -1
  47. package/dist/TopNav/TopNavMegaMenuFeaturedCard.js +8 -1
  48. package/dist/TreeList/TreeListBranches.d.ts +5 -0
  49. package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
  50. package/dist/TreeList/TreeListBranches.js +10 -4
  51. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  52. package/dist/TreeList/TreeListItem.js +25 -6
  53. package/dist/astryx.css +1 -1
  54. package/dist/astryx.umd.js +46 -46
  55. package/dist/astryx.umd.js.map +4 -4
  56. package/dist/docs-types.d.ts +8 -0
  57. package/dist/docs-types.d.ts.map +1 -1
  58. package/dist/hooks/computeOverflow.d.ts +47 -0
  59. package/dist/hooks/computeOverflow.d.ts.map +1 -0
  60. package/dist/hooks/computeOverflow.js +213 -0
  61. package/dist/hooks/useOverflow.d.ts +19 -0
  62. package/dist/hooks/useOverflow.d.ts.map +1 -1
  63. package/dist/hooks/useOverflow.js +37 -25
  64. package/dist/theme/hct.d.ts +0 -1
  65. package/dist/theme/hct.d.ts.map +1 -1
  66. package/dist/theme/hct.js +1 -1
  67. package/locales/en.json +4 -0
  68. package/locales/fr-FR.json +4 -0
  69. package/locales/pseudo.json +3 -0
  70. package/package.json +1 -1
  71. package/src/Avatar/Avatar.doc.mjs +5 -3
  72. package/src/Avatar/AvatarStatusDot.doc.mjs +23 -12
  73. package/src/Avatar/AvatarStatusDot.test.tsx +284 -0
  74. package/src/Avatar/AvatarStatusDot.tsx +178 -21
  75. package/src/Calendar/Calendar.doc.mjs +12 -1
  76. package/src/Calendar/Calendar.test.tsx +193 -0
  77. package/src/Calendar/Calendar.tsx +38 -16
  78. package/src/Carousel/Carousel.doc.mjs +1 -0
  79. package/src/Chat/ChatComposerInput.doc.mjs +7 -0
  80. package/src/Chat/ChatComposerInput.test.tsx +87 -0
  81. package/src/Chat/ChatComposerInput.tsx +35 -3
  82. package/src/Chat/useChatStreamScroll.test.tsx +49 -0
  83. package/src/Chat/useChatStreamScroll.ts +27 -10
  84. package/src/Chat/useSpeechRecognition.ts +1 -1
  85. package/src/CheckboxList/CheckboxList.test.tsx +72 -2
  86. package/src/CheckboxList/CheckboxListItem.doc.mjs +33 -5
  87. package/src/CheckboxList/CheckboxListItem.tsx +50 -6
  88. package/src/ContextMenu/ContextMenu.test.tsx +193 -0
  89. package/src/Dialog/Dialog.doc.mjs +2 -2
  90. package/src/Dialog/Dialog.test.tsx +77 -4
  91. package/src/Dialog/Dialog.tsx +75 -3
  92. package/src/Dialog/DialogContext.ts +9 -2
  93. package/src/Dialog/DialogHeader.doc.mjs +2 -2
  94. package/src/Dialog/DialogHeader.tsx +9 -2
  95. package/src/DropdownMenu/DropdownMenu.test.tsx +169 -0
  96. package/src/Icon/Icon.doc.mjs +3 -2
  97. package/src/Icon/Icon.tsx +7 -2
  98. package/src/Item/Item.test.tsx +40 -18
  99. package/src/Item/Item.tsx +38 -2
  100. package/src/List/List.test.tsx +9 -8
  101. package/src/OverflowList/OverflowList.doc.mjs +39 -6
  102. package/src/OverflowList/OverflowList.test.tsx +111 -0
  103. package/src/OverflowList/OverflowList.tsx +48 -8
  104. package/src/PowerSearch/PowerSearch.doc.mjs +14 -0
  105. package/src/PowerSearch/PowerSearch.test.tsx +20 -0
  106. package/src/PowerSearch/PowerSearchEditPopover.test.tsx +67 -0
  107. package/src/PowerSearch/PowerSearchEditPopover.tsx +1 -1
  108. package/src/Table/plugins/selection/useTableSelection.tsx +2 -1
  109. package/src/Thumbnail/Thumbnail.doc.mjs +3 -3
  110. package/src/Thumbnail/Thumbnail.test.tsx +35 -0
  111. package/src/Thumbnail/Thumbnail.tsx +52 -3
  112. package/src/ToggleButton/ToggleButtonGroup.tsx +1 -1
  113. package/src/Tokenizer/Tokenizer.doc.mjs +14 -0
  114. package/src/Tokenizer/Tokenizer.test.tsx +46 -0
  115. package/src/TopNav/TopNav.test.tsx +45 -0
  116. package/src/TopNav/TopNavMegaMenuFeaturedCard.doc.mjs +3 -3
  117. package/src/TopNav/TopNavMegaMenuFeaturedCard.tsx +19 -2
  118. package/src/TreeList/TreeList.doc.mjs +6 -0
  119. package/src/TreeList/TreeList.test.tsx +169 -0
  120. package/src/TreeList/TreeListBranches.tsx +16 -2
  121. package/src/TreeList/TreeListItem.tsx +34 -3
  122. package/src/docs-types.ts +5 -0
  123. package/src/hooks/computeOverflow.test.ts +422 -0
  124. package/src/hooks/computeOverflow.ts +290 -0
  125. package/src/hooks/useOverflow.test.ts +96 -4
  126. package/src/hooks/useOverflow.ts +77 -33
  127. package/src/i18n/InternationalizationProvider.doc.mjs +77 -2
  128. package/src/theme/hct.ts +1 -1
@@ -24,6 +24,13 @@ import type { BaseProps } from '../BaseProps';
24
24
  * }
25
25
  * }
26
26
  * ```
27
+ *
28
+ * Custom variants render no background fill, no ink colour, and no built-in
29
+ * shape glyph — the theme must supply the fill and, if it passes an `icon`,
30
+ * a `color` for it to paint with. It should also supply a non-colour mark
31
+ * so the status is not distinguishable by colour alone (a WCAG 1.4.1
32
+ * failure): pass `icon`, or theme a glyph onto the dot via
33
+ * `.astryx-avatar-status-dot[data-variant="..."]` (e.g. a `::before` mark).
27
34
  */
28
35
  export interface AvatarStatusDotVariantMap {
29
36
  success: true;
@@ -37,12 +44,14 @@ export type AvatarStatusDotVariant = keyof AvatarStatusDotVariantMap;
37
44
  export interface AvatarStatusDotProps extends BaseProps<HTMLDivElement> {
38
45
  ref?: React.Ref<HTMLDivElement>;
39
46
  /**
40
- * The semantic color variant of the dot.
41
- * - `success` — green dot (e.g. online, accepted)
42
- * - `neutral` — gray dot (e.g. offline, pending)
43
- * - `error` — red dot (e.g. busy, rejected)
47
+ * The semantic variant of the dot. Each variant pairs a colour with a
48
+ * distinct built-in shape so status is never conveyed by colour alone
49
+ * (WCAG 2.1 SC 1.4.1):
50
+ * - `success` — filled green dot (e.g. online, accepted)
51
+ * - `neutral` — grey ring (e.g. away, offline, pending)
52
+ * - `error` — red dot with a minus bar (e.g. busy, do not disturb)
44
53
  *
45
- * Matches the `variant` convention from `StatusDot`.
54
+ * Matches the `variant` naming convention from `StatusDot`.
46
55
  * @default 'success'
47
56
  */
48
57
  variant?: AvatarStatusDotVariant;
@@ -50,6 +59,11 @@ export interface AvatarStatusDotProps extends BaseProps<HTMLDivElement> {
50
59
  * Accessible label for the status dot.
51
60
  * Describes the meaning of the indicator for screen readers
52
61
  * (e.g. "Online", "Accepted", "John Doe is busy").
62
+ *
63
+ * Note: inside an Avatar the label is currently not announced — the
64
+ * Avatar root is `role="img"`, which prunes descendant semantics.
65
+ * Pass it anyway; composing status into the avatar's accessible name
66
+ * is a planned Avatar-level fix.
53
67
  */
54
68
  label?: string;
55
69
  /**
@@ -58,6 +72,14 @@ export interface AvatarStatusDotProps extends BaseProps<HTMLDivElement> {
58
72
  * The icon is automatically sized to fit the dot and hidden
59
73
  * at the smallest avatar sizes where there isn't enough room.
60
74
  *
75
+ * A rendered icon replaces the variant's built-in shape glyph, so use a
76
+ * different icon per status — the same icon on every variant leaves the
77
+ * statuses distinguishable by colour alone (WCAG 1.4.1). At the smallest
78
+ * avatar sizes the built-in glyph still shows instead of the icon.
79
+ * Booleans and empty strings are ignored (safe for `cond && <Icon />`),
80
+ * but a component that renders nothing still counts as an icon and
81
+ * suppresses the glyph.
82
+ *
61
83
  * @example
62
84
  * ```
63
85
  * <AvatarStatusDot variant="success" label="Verified" icon={<CheckIcon />} />
@@ -69,6 +91,12 @@ export interface AvatarStatusDotProps extends BaseProps<HTMLDivElement> {
69
91
  * A status indicator dot that automatically scales to match the parent
70
92
  * Avatar's size.
71
93
  *
94
+ * Each variant pairs a colour with a distinct built-in shape (filled dot,
95
+ * ring, minus bar) so status stays distinguishable without colour
96
+ * perception (WCAG 2.1 SC 1.4.1). Themes can target the shape glyph via
97
+ * the `astryx-avatar-status-dot-glyph` class and its `data-shape`
98
+ * attribute.
99
+ *
72
100
  * Must be used inside an Avatar's `status` prop so it can read
73
101
  * the avatar size from context.
74
102
  *
@@ -1 +1 @@
1
- {"version":3,"file":"AvatarStatusDot.d.ts","sourceRoot":"","sources":["../../src/Avatar/AvatarStatusDot.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,EAAM,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AACjD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAqC5C;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,IAAI,CAAC;IACd,OAAO,EAAE,IAAI,CAAC;IACd,KAAK,EAAE,IAAI,CAAC;CACb;AAED;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,MAAM,yBAAyB,CAAC;AAErE,MAAM,WAAW,oBAAqB,SAAQ,SAAS,CAAC,cAAc,CAAC;IACrE,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,sBAAsB,CAAC;IACjC;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;;;OAUG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAkDD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,eAAe,CAAC,EAC9B,GAAG,EACH,OAAmB,EACnB,KAAK,EACL,IAAI,EACJ,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,KAAK,EACT,EAAE,oBAAoB,qBA6BtB;yBAtCe,eAAe"}
1
+ {"version":3,"file":"AvatarStatusDot.d.ts","sourceRoot":"","sources":["../../src/Avatar/AvatarStatusDot.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,EAAM,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AACjD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAiD5C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,IAAI,CAAC;IACd,OAAO,EAAE,IAAI,CAAC;IACd,KAAK,EAAE,IAAI,CAAC;CACb;AAED;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,MAAM,yBAAyB,CAAC;AAErE,MAAM,WAAW,oBAAqB,SAAQ,SAAS,CAAC,cAAc,CAAC;IACrE,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC;;;;;;;;;;OAUG;IACH,OAAO,CAAC,EAAE,sBAAsB,CAAC;IACjC;;;;;;;;;OASG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;;;;;;;;OAkBG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AA2JD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,eAAe,CAAC,EAC9B,GAAG,EACH,OAAmB,EACnB,KAAK,EACL,IAAI,EACJ,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,KAAK,EACT,EAAE,oBAAoB,qBAyCtB;yBAlDe,eAAe"}
@@ -19,45 +19,57 @@ import * as stylex from '@stylexjs/stylex';
19
19
  import "../theme/tokens.stylex.js";
20
20
  import { colorVars, radiusVars } from "../theme/tokens.stylex.js";
21
21
  import { AvatarSizeContext } from "./AvatarSizeContext.js";
22
- import { mergeProps } from "../utils/index.js";
22
+ import { isRenderable, mergeProps } from "../utils/index.js";
23
23
  import { themeProps } from "../utils/themeProps.js";
24
24
 
25
25
  /**
26
- * Resolves the status dot size, border width, and icon size based on the
27
- * avatar size.
26
+ * Discrete size tier of the status dot, derived from the avatar size.
27
+ * Keys the built-in shape glyph's stroke weight — see `GLYPH_STROKE_WIDTH`.
28
+ */
29
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
30
+ /**
31
+ * Resolves the status dot size, border width, icon size, and size tier
32
+ * based on the avatar size.
28
33
  *
29
34
  * Uses discrete size tiers rather than a continuous ratio so the dot
30
35
  * looks intentional at every avatar size:
31
36
  *
32
- * | Avatar size | Dot | Border | Icon |
33
- * |--------------|------|--------|------|
34
- * | ≤ 36px | 10px | 1px | — |
35
- * | 40–72px | 20px | 2px | 12px |
36
- * | ≥ 96px | 32px | 4px | 18px |
37
+ * | Avatar size | Tier | Dot | Border | Icon | Field | Glyph stroke |
38
+ * |--------------|--------|------|--------|------|-------|--------------|
39
+ * | ≤ 36px | small | 10px | 1px | — | 8px | 1px |
40
+ * | 40–72px | medium | 20px | 2px | 12px | 16px | 1.5px |
41
+ * | ≥ 96px | large | 32px | 4px | 18px | 24px | 2px |
42
+ *
43
+ * "Field" is the dot's inner field — the dot minus both borders — that the
44
+ * shape glyph is drawn into; see `GLYPH_STROKE_WIDTH` for the stroke ladder.
37
45
  *
38
46
  * Icons are not rendered at the smallest tier — there isn't enough
39
- * room for them to be legible.
47
+ * room for them to be legible. The built-in shape glyphs (see
48
+ * `glyphShapeMap`) do render there, so status stays distinguishable
49
+ * without colour at every size.
40
50
  */
41
- import { jsx as _jsx } from "react/jsx-runtime";
42
51
  function resolveStatusDotSize(avatarSize) {
43
52
  if (avatarSize <= 36) {
44
53
  return {
45
54
  dotSize: 10,
46
55
  borderWidth: 1,
47
- iconSize: 0
56
+ iconSize: 0,
57
+ tier: 'small'
48
58
  };
49
59
  }
50
60
  if (avatarSize <= 72) {
51
61
  return {
52
62
  dotSize: 20,
53
63
  borderWidth: 2,
54
- iconSize: 12
64
+ iconSize: 12,
65
+ tier: 'medium'
55
66
  };
56
67
  }
57
68
  return {
58
69
  dotSize: 32,
59
70
  borderWidth: 4,
60
- iconSize: 18
71
+ iconSize: 18,
72
+ tier: 'large'
61
73
  };
62
74
  }
63
75
 
@@ -73,6 +85,13 @@ function resolveStatusDotSize(avatarSize) {
73
85
  * }
74
86
  * }
75
87
  * ```
88
+ *
89
+ * Custom variants render no background fill, no ink colour, and no built-in
90
+ * shape glyph — the theme must supply the fill and, if it passes an `icon`,
91
+ * a `color` for it to paint with. It should also supply a non-colour mark
92
+ * so the status is not distinguishable by colour alone (a WCAG 1.4.1
93
+ * failure): pass `icon`, or theme a glyph onto the dot via
94
+ * `.astryx-avatar-status-dot[data-variant="..."]` (e.g. a `::before` mark).
76
95
  */
77
96
 
78
97
  /**
@@ -92,21 +111,23 @@ const styles = {
92
111
  },
93
112
  success: {
94
113
  kWkggS: "xdsz4j9",
114
+ kMwMTN: "xrkvqaz",
95
115
  $$css: true
96
116
  },
97
117
  neutral: {
98
- kWkggS: "xdomwnj",
118
+ kWkggS: "x10xzikg",
119
+ kMwMTN: "xv1l7n4",
99
120
  $$css: true
100
121
  },
101
122
  error: {
102
123
  kWkggS: "x1pjz0fi",
124
+ kMwMTN: "xrkvqaz",
103
125
  $$css: true
104
126
  },
105
127
  icon: {
106
128
  k1xSpc: "x78zum5",
107
129
  kGNEyG: "x6s0dn4",
108
130
  kjj79g: "xl56j7k",
109
- kMwMTN: "xrkvqaz",
110
131
  kLWn49: "x14ju556",
111
132
  $$css: true
112
133
  }
@@ -137,10 +158,105 @@ const variantStyleMap = {
137
158
  error: styles.error
138
159
  };
139
160
 
161
+ /**
162
+ * Built-in shape glyph per variant, so each status differs by shape and not
163
+ * only by colour (WCAG 2.1 SC 1.4.1). The glyph is a stroked inline SVG
164
+ * painted in `currentColor`:
165
+ * - `ring` — a stroked circle on a surface plate; the dot reads as hollow
166
+ * (away/offline).
167
+ * - `minus` — a round-capped bar across the filled dot; the dot reads as
168
+ * "do not disturb" (busy).
169
+ *
170
+ * `success` stays the plain filled dot — filled, hollow, and barred are the
171
+ * three distinct fill topologies. Custom augmented variants have no entry
172
+ * and render no glyph; see the `AvatarStatusDotVariantMap` docs.
173
+ */
174
+
175
+ const glyphShapeMap = {
176
+ neutral: 'ring',
177
+ error: 'minus'
178
+ };
179
+
180
+ /**
181
+ * Glyph stroke weight per tier, in px of the dot's inner field.
182
+ *
183
+ * Roughly `field / 12`, floored at 1px so the smallest tier stays visible.
184
+ * That lands on the 1 / 1.5 / 2 ladder the rest of the system draws with —
185
+ * `Icon`'s default set strokes at 1.5 in a 24 viewBox, as does the
186
+ * `CheckboxInput` checkmark — rather than the 25% band a CSS box cutout
187
+ * produced, which was several times heavier than any other glyph we ship.
188
+ */
189
+ const GLYPH_STROKE_WIDTH = {
190
+ small: 1,
191
+ medium: 1.5,
192
+ large: 2
193
+ };
194
+
195
+ /** Fraction of the inner field the minus bar spans, cap to cap. */
196
+ const MINUS_BAR_SPAN = 0.75;
197
+
198
+ /**
199
+ * The built-in shape glyph, drawn as a stroked inline SVG in `currentColor`.
200
+ *
201
+ * Stroking (rather than a CSS box) is what buys sub-pixel control and round
202
+ * line caps, so the mark stays intentional at every tier — including the
203
+ * 10px dot, where a box cutout can only land on whole pixels.
204
+ *
205
+ * `viewBox` is one user unit per px of the inner field, so every value here
206
+ * is literal px.
207
+ */
208
+ function StatusDotGlyph({
209
+ shape,
210
+ field,
211
+ stroke
212
+ }) {
213
+ const center = field / 2;
214
+ return /*#__PURE__*/_jsx("svg", {
215
+ "aria-hidden": "true",
216
+ viewBox: `0 0 ${field} ${field}`,
217
+ width: field,
218
+ height: field,
219
+ fill: "none",
220
+ ...themeProps('avatar-status-dot-glyph', {
221
+ shape
222
+ }),
223
+ children: shape === 'ring' ?
224
+ /*#__PURE__*/
225
+ // Radius is to the stroke centreline, so the ring's outer edge lands
226
+ // exactly on the inner field and never clips against the border.
227
+ _jsx("circle", {
228
+ cx: center,
229
+ cy: center,
230
+ r: (field - stroke) / 2,
231
+ fill: "none",
232
+ stroke: "currentColor",
233
+ strokeWidth: stroke
234
+ }) :
235
+ /*#__PURE__*/
236
+ // Ends inset by half the stroke so the round caps land inside the
237
+ // span rather than overhanging it.
238
+ _jsx("line", {
239
+ x1: field * (1 - MINUS_BAR_SPAN) / 2 + stroke / 2,
240
+ y1: center,
241
+ x2: field * (1 + MINUS_BAR_SPAN) / 2 - stroke / 2,
242
+ y2: center,
243
+ stroke: "currentColor",
244
+ strokeWidth: stroke,
245
+ strokeLinecap: "round"
246
+ })
247
+ });
248
+ }
249
+
140
250
  /**
141
251
  * A status indicator dot that automatically scales to match the parent
142
252
  * Avatar's size.
143
253
  *
254
+ * Each variant pairs a colour with a distinct built-in shape (filled dot,
255
+ * ring, minus bar) so status stays distinguishable without colour
256
+ * perception (WCAG 2.1 SC 1.4.1). Themes can target the shape glyph via
257
+ * the `astryx-avatar-status-dot-glyph` class and its `data-shape`
258
+ * attribute.
259
+ *
144
260
  * Must be used inside an Avatar's `status` prop so it can read
145
261
  * the avatar size from context.
146
262
  *
@@ -172,9 +288,14 @@ export function AvatarStatusDot({
172
288
  const {
173
289
  dotSize,
174
290
  borderWidth,
175
- iconSize
291
+ iconSize,
292
+ tier
176
293
  } = resolveStatusDotSize(avatarSize);
177
- return /*#__PURE__*/_jsx("div", {
294
+ const showsIcon = isRenderable(icon) && iconSize > 0;
295
+ // A rendered icon is itself a non-colour mark; overlaying both cutouts in
296
+ // the dot's small inner field would make each illegible.
297
+ const glyphShape = showsIcon ? undefined : glyphShapeMap[variant];
298
+ return /*#__PURE__*/_jsxs("div", {
178
299
  ...props,
179
300
  ref: ref,
180
301
  ...(label ? {
@@ -184,11 +305,15 @@ export function AvatarStatusDot({
184
305
  ...mergeProps(themeProps('avatar-status-dot', {
185
306
  variant
186
307
  }), stylex.props(styles.dot, variantStyleMap[variant], dynamicStyles.size(dotSize, borderWidth), xstyle), className, style),
187
- children: icon && iconSize > 0 && /*#__PURE__*/_jsx("span", {
308
+ children: [showsIcon && /*#__PURE__*/_jsx("span", {
188
309
  "aria-hidden": "true",
189
310
  ...stylex.props(styles.icon, dynamicStyles.iconSize(iconSize)),
190
311
  children: icon
191
- })
312
+ }), glyphShape && /*#__PURE__*/_jsx(StatusDotGlyph, {
313
+ shape: glyphShape,
314
+ field: dotSize - borderWidth * 2,
315
+ stroke: GLYPH_STROKE_WIDTH[tier]
316
+ })]
192
317
  });
193
318
  }
194
319
  AvatarStatusDot.displayName = 'AvatarStatusDot';
@@ -1 +1 @@
1
- {"version":3,"file":"Calendar.d.ts","sourceRoot":"","sources":["../../src/Calendar/Calendar.tsx"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AA8C5C,YAAY,EACV,aAAa,EACb,SAAS,EACT,aAAa,EACb,SAAS,GACV,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EACV,aAAa,EACb,SAAS,EACT,aAAa,EACb,SAAS,EACV,MAAM,oBAAoB,CAAC;AAK5B,+CAA+C;AAE/C,MAAM,WAAW,cAAc;IAC7B,wEAAwE;IACxE,UAAU,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;CAC3C;AAID,UAAU,iBAAkB,SAAQ,IAAI,CACtC,SAAS,CAAC,cAAc,CAAC,EACzB,UAAU,GAAG,cAAc,CAC5B;IACC,kDAAkD;IAClD,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,qDAAqD;IACrD,SAAS,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACtC,+CAA+C;IAC/C,cAAc,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IAEvB,4CAA4C;IAC5C,GAAG,CAAC,EAAE,aAAa,CAAC;IAEpB,4CAA4C;IAC5C,GAAG,CAAC,EAAE,aAAa,CAAC;IAEpB;;;OAGG;IACH,eAAe,CAAC,EAAE,aAAa,CAAC,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC;IAEzD;;;OAGG;IACH,SAAS,CAAC,EAAE,aAAa,CAAC;IAE1B,yDAAyD;IACzD,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,aAAa,KAAK,IAAI,CAAC;IAEvD;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;OAGG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAE9B;;;;OAIG;IACH,YAAY,CAAC,EAAE,SAAS,GAAG,aAAa,CAAC;CAC1C;AAID,UAAU,mBAAoB,SAAQ,iBAAiB;IACrD,qBAAqB;IACrB,IAAI,CAAC,EAAE,QAAQ,CAAC;IAEhB,+CAA+C;IAC/C,KAAK,CAAC,EAAE,aAAa,CAAC;IAEtB,0CAA0C;IAC1C,YAAY,CAAC,EAAE,aAAa,CAAC;IAE7B,qCAAqC;IACrC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,IAAI,KAAK,IAAI,CAAC;CAC9D;AAED,UAAU,kBAAmB,SAAQ,iBAAiB;IACpD,qBAAqB;IACrB,IAAI,EAAE,OAAO,CAAC;IAEd,0BAA0B;IAC1B,KAAK,CAAC,EAAE,SAAS,CAAC;IAElB,0CAA0C;IAC1C,YAAY,CAAC,EAAE,SAAS,CAAC;IAEzB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;CACvC;AAED,MAAM,MAAM,aAAa,GAAG,mBAAmB,GAAG,kBAAkB,CAAC;AAMrE;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,EAAC,GAAG,EAAE,GAAG,KAAK,EAAC,EAAE,aAAa,+BAiUtD;yBAjUe,QAAQ"}
1
+ {"version":3,"file":"Calendar.d.ts","sourceRoot":"","sources":["../../src/Calendar/Calendar.tsx"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AA8C5C,YAAY,EACV,aAAa,EACb,SAAS,EACT,aAAa,EACb,SAAS,GACV,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EACV,aAAa,EACb,SAAS,EACT,aAAa,EACb,SAAS,EACV,MAAM,oBAAoB,CAAC;AAK5B,+CAA+C;AAE/C,MAAM,WAAW,cAAc;IAC7B,wEAAwE;IACxE,UAAU,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;CAC3C;AAID,UAAU,iBAAkB,SAAQ,IAAI,CACtC,SAAS,CAAC,cAAc,CAAC,EACzB,UAAU,GAAG,cAAc,CAC5B;IACC,kDAAkD;IAClD,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,qDAAqD;IACrD,SAAS,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACtC,+CAA+C;IAC/C,cAAc,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IAEvB,4CAA4C;IAC5C,GAAG,CAAC,EAAE,aAAa,CAAC;IAEpB,4CAA4C;IAC5C,GAAG,CAAC,EAAE,aAAa,CAAC;IAEpB;;;OAGG;IACH,eAAe,CAAC,EAAE,aAAa,CAAC,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC;IAEzD;;;OAGG;IACH,SAAS,CAAC,EAAE,aAAa,CAAC;IAE1B,yDAAyD;IACzD,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,aAAa,KAAK,IAAI,CAAC;IAEvD;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;OAGG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAE9B;;;;OAIG;IACH,YAAY,CAAC,EAAE,SAAS,GAAG,aAAa,CAAC;CAC1C;AAID,UAAU,mBAAoB,SAAQ,iBAAiB;IACrD,qBAAqB;IACrB,IAAI,CAAC,EAAE,QAAQ,CAAC;IAEhB,+CAA+C;IAC/C,KAAK,CAAC,EAAE,aAAa,CAAC;IAEtB,0CAA0C;IAC1C,YAAY,CAAC,EAAE,aAAa,CAAC;IAE7B,qCAAqC;IACrC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,IAAI,KAAK,IAAI,CAAC;CAC9D;AAED,UAAU,kBAAmB,SAAQ,iBAAiB;IACpD,qBAAqB;IACrB,IAAI,EAAE,OAAO,CAAC;IAEd,0BAA0B;IAC1B,KAAK,CAAC,EAAE,SAAS,CAAC;IAElB,0CAA0C;IAC1C,YAAY,CAAC,EAAE,SAAS,CAAC;IAEzB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;CACvC;AAED,MAAM,MAAM,aAAa,GAAG,mBAAmB,GAAG,kBAAkB,CAAC;AAMrE;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,EAAC,GAAG,EAAE,GAAG,KAAK,EAAC,EAAE,aAAa,+BAyUtD;yBAzUe,QAAQ"}
@@ -271,6 +271,10 @@ export function Calendar({
271
271
  children: [/*#__PURE__*/_jsxs("div", {
272
272
  ...stylex.props(calendarStyles.header),
273
273
  children: [/*#__PURE__*/_jsx(Button, {
274
+ ...themeProps('calendar-nav', {
275
+ nav: 'prev',
276
+ disabled: !canNavigatePrevious ? 'disabled' : null
277
+ }),
274
278
  label: t('@astryx.calendar.previousMonth'),
275
279
  variant: "ghost",
276
280
  icon:
@@ -293,6 +297,10 @@ export function Calendar({
293
297
  ...stylex.props(calendarStyles.monthYearLabel),
294
298
  children: monthYearLabel
295
299
  }), /*#__PURE__*/_jsx(Button, {
300
+ ...themeProps('calendar-nav', {
301
+ nav: 'next',
302
+ disabled: !canNavigateNext ? 'disabled' : null
303
+ }),
296
304
  label: t('@astryx.calendar.nextMonth'),
297
305
  variant: "ghost",
298
306
  icon: /*#__PURE__*/_jsx("span", {
@@ -662,6 +670,15 @@ function DayCell({
662
670
  isOutside
663
671
  });
664
672
  const endpoint = isEndpoint(state);
673
+
674
+ // The day's focus-ring treatment, derived once so the reflected `marker`
675
+ // theme state and the StyleX ring styles below share a single source of
676
+ // truth. `state.isSelected` is single-select only, so a range endpoint that
677
+ // is today still qualifies for the today-in-range ring (unchanged prior
678
+ // behavior).
679
+ const showsTodayRing = state.isToday && !state.isSelected && !state.isInRange;
680
+ const showsTodayInRangeRing = state.isToday && !state.isSelected && state.isInRange;
681
+ const markerState = showsTodayRing ? 'today-only' : showsTodayInRangeRing ? 'today-in-range' : null;
665
682
  const rangeRounding = computeRangeRounding(state, {
666
683
  prevInRange: neighbors.prevInRange,
667
684
  nextInRange: neighbors.nextInRange
@@ -698,8 +715,19 @@ function DayCell({
698
715
  selected: endpoint ? 'selected' : null,
699
716
  today: state.isToday ? 'today' : null,
700
717
  disabled: state.effectivelyDisabled ? 'disabled' : null,
701
- 'in-range': state.isInRange ? 'in-range' : null
702
- }), stylex.props(dayCellStyles.day, dayCellTheme.day, isOutside && dayCellStyles.dayOutside, isOutside && dayCellTheme.dayOutside, state.isToday && !state.isSelected && !state.isInRange && dayCellStyles.dayToday, state.isToday && !state.isSelected && !state.isInRange && dayCellTheme.dayToday, state.isToday && !state.isSelected && state.isInRange && dayCellStyles.dayTodayInRange, state.isToday && !state.isSelected && state.isInRange && dayCellTheme.dayTodayInRange, endpoint && dayCellStyles.daySelected, endpoint && dayCellTheme.daySelected, state.effectivelyDisabled && dayCellStyles.dayDisabled, state.effectivelyDisabled && dayCellTheme.dayDisabled)),
718
+ 'in-range': state.isInRange ? 'in-range' : null,
719
+ // `marker` reflects the day's *actual* focus-ring treatment as a
720
+ // single compound state, so a theme can target exactly the states
721
+ // the ring is drawn under without needing `:not()` in the theme
722
+ // key. It is null unless a ring is shown:
723
+ // 'today-only' → today, not single-selected, not in a range
724
+ // 'today-in-range' → today, not single-selected, inside a range
725
+ // `isSelected` here is single-select only (see computeDayCellState),
726
+ // so a today range endpoint still shows the today-in-range ring —
727
+ // `marker` mirrors the StyleX conditions below exactly, preserving
728
+ // the default rendering.
729
+ marker: markerState
730
+ }), stylex.props(dayCellStyles.day, dayCellTheme.day, isOutside && dayCellStyles.dayOutside, isOutside && dayCellTheme.dayOutside, showsTodayRing && dayCellStyles.dayToday, showsTodayRing && dayCellTheme.dayToday, showsTodayInRangeRing && dayCellStyles.dayTodayInRange, showsTodayInRangeRing && dayCellTheme.dayTodayInRange, endpoint && dayCellStyles.daySelected, endpoint && dayCellTheme.daySelected, state.effectivelyDisabled && dayCellStyles.dayDisabled, state.effectivelyDisabled && dayCellTheme.dayDisabled)),
703
731
  children: dayNumber
704
732
  })]
705
733
  });
@@ -7,8 +7,10 @@
7
7
  *
8
8
  * ContentEditable-based rich input for the chat composer.
9
9
  * Supports trigger menus (@ mentions, / commands) via SearchSource,
10
- * inline token rendering, serialization, Enter/Shift+Enter, message
11
- * history, paste/drop file handling, and mobile-safe touch typography.
10
+ * inline token rendering, serialization, Enter-to-submit with
11
+ * IME-composition guarding and an onKeyDown seam for platform-specific
12
+ * key handling, message history, paste/drop file handling, and
13
+ * mobile-safe touch typography.
12
14
  *
13
15
  *
14
16
  * SYNC: When modified, update:
@@ -16,7 +18,7 @@
16
18
  * - /apps/storybook/stories/ChatComposer.stories.tsx
17
19
  * - /packages/cli/templates/blocks/components/ChatComposerInput/ (block examples)
18
20
  */
19
- import { type ReactNode, type ClipboardEvent } from 'react';
21
+ import { type ReactNode, type KeyboardEvent, type ClipboardEvent } from 'react';
20
22
  import type { BaseProps } from '../BaseProps';
21
23
  import type { SearchableItem, SearchSource } from '../Typeahead/types';
22
24
  import { type UseChatPasteAsTokenReturn } from './useChatPasteAsToken';
@@ -137,6 +139,21 @@ export interface ChatComposerInputProps extends Omit<BaseProps<HTMLDivElement>,
137
139
  onFiles?: (files: File[]) => void;
138
140
  /** Submit handler (Enter without Shift) */
139
141
  onSubmit?: (value: string) => void;
142
+ /**
143
+ * Key-down handler invoked before the built-in Enter/history behavior
144
+ * (but after an open trigger menu consumes the event).
145
+ *
146
+ * This is the seam for platform- or app-specific key handling:
147
+ * - Call `event.preventDefault()` to suppress the default submit (e.g.
148
+ * let Enter insert a newline on a touch keyboard).
149
+ * - Add behavior by acting on the event yourself (e.g. submit on
150
+ * Cmd/Ctrl+Enter) without calling `preventDefault()`, so the default
151
+ * handling still runs for other keys.
152
+ *
153
+ * IME composition is always respected regardless of this handler: Enter
154
+ * never submits while a composition is in progress.
155
+ */
156
+ onKeyDown?: (event: KeyboardEvent<HTMLDivElement>) => void;
140
157
  }
141
158
  export declare function ChatComposerInput(props: ChatComposerInputProps): import("react").JSX.Element;
142
159
  export declare namespace ChatComposerInput {
@@ -1 +1 @@
1
- {"version":3,"file":"ChatComposerInput.d.ts","sourceRoot":"","sources":["../../src/Chat/ChatComposerInput.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ChatComposerInput.d.ts","sourceRoot":"","sources":["../../src/Chat/ChatComposerInput.tsx"],"names":[],"mappings":"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"}
@@ -11,8 +11,10 @@
11
11
  *
12
12
  * ContentEditable-based rich input for the chat composer.
13
13
  * Supports trigger menus (@ mentions, / commands) via SearchSource,
14
- * inline token rendering, serialization, Enter/Shift+Enter, message
15
- * history, paste/drop file handling, and mobile-safe touch typography.
14
+ * inline token rendering, serialization, Enter-to-submit with
15
+ * IME-composition guarding and an onKeyDown seam for platform-specific
16
+ * key handling, message history, paste/drop file handling, and
17
+ * mobile-safe touch typography.
16
18
  *
17
19
  *
18
20
  * SYNC: When modified, update:
@@ -133,6 +135,7 @@ export function ChatComposerInput(props) {
133
135
  pasteAsToken: pasteAsTokenProp,
134
136
  onFiles,
135
137
  onSubmit = composerCtx?.onSubmit,
138
+ onKeyDown: onKeyDownProp,
136
139
  xstyle,
137
140
  className,
138
141
  style,
@@ -289,6 +292,13 @@ export function ChatComposerInput(props) {
289
292
  return;
290
293
  }
291
294
 
295
+ // Consumer passthrough — runs before built-in Enter/history handling.
296
+ // A consumer can preventDefault() to fully own the keystroke.
297
+ onKeyDownProp?.(e);
298
+ if (e.defaultPrevented) {
299
+ return;
300
+ }
301
+
292
302
  // Handle Backspace near tokens — prevent browser from creating
293
303
  // stray <br> elements or moving the cursor unexpectedly.
294
304
  if (e.key === 'Backspace') {
@@ -322,6 +332,12 @@ export function ChatComposerInput(props) {
322
332
  }
323
333
  }
324
334
  if (e.key === 'Enter' && !e.shiftKey) {
335
+ // Never submit mid-composition — an IME uses Enter to commit a
336
+ // candidate (e.g. Japanese/Chinese/Korean input), and browsers may
337
+ // also surface the legacy keyCode 229 for composing keystrokes.
338
+ if (e.nativeEvent.isComposing || e.nativeEvent.keyCode === 229) {
339
+ return;
340
+ }
325
341
  e.preventDefault();
326
342
  if (!editableRef.current) {
327
343
  return;
@@ -379,7 +395,7 @@ export function ChatComposerInput(props) {
379
395
  e.preventDefault();
380
396
  }
381
397
  }
382
- }, [hasHistory, onSubmit, onChange, emitChange, triggerMenu]);
398
+ }, [hasHistory, onSubmit, onChange, emitChange, triggerMenu, onKeyDownProp]);
383
399
  const handlePaste = useCallback(e => {
384
400
  const editable = editableRef.current;
385
401
  if (!editable) {
@@ -4,7 +4,8 @@ export interface ChatScrollToBottomOptions {
4
4
  * the spring animation. Use for programmatic positioning (opening a
5
5
  * conversation, restoring a session) — keep the default `'spring'` for
6
6
  * user-initiated scrolls like the scroll-to-bottom button. Mirrors the
7
- * DOM's `scrollTo({behavior})`.
7
+ * DOM's `scrollTo({behavior})`. When the user prefers reduced motion,
8
+ * `'spring'` also jumps instantly.
8
9
  * @default 'spring'
9
10
  */
10
11
  behavior?: 'instant' | 'spring';
@@ -1 +1 @@
1
- {"version":3,"file":"useChatStreamScroll.d.ts","sourceRoot":"","sources":["../../src/Chat/useChatStreamScroll.ts"],"names":[],"mappings":"AAiCA,MAAM,WAAW,yBAAyB;IACxC;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;CACjC;AAED,MAAM,WAAW,0BAA0B;IACzC;;OAEG;IACH,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAE/C;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,yBAAyB;IACxC,6DAA6D;IAC7D,YAAY,EAAE,OAAO,CAAC;IAEtB,yDAAyD;IACzD,QAAQ,EAAE,OAAO,CAAC;IAElB,yDAAyD;IACzD,cAAc,EAAE,CAAC,OAAO,CAAC,EAAE,yBAAyB,KAAK,IAAI,CAAC;IAE9D,sFAAsF;IACtF,eAAe,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,IAAI,CAAC;IAE3C,6CAA6C;IAC7C,IAAI,EAAE,MAAM,IAAI,CAAC;IAEjB,0BAA0B;IAC1B,MAAM,EAAE,MAAM,IAAI,CAAC;IAEnB,oEAAoE;IACpE,cAAc,EAAE,MAAM,IAAI,CAAC;IAE3B,mDAAmD;IACnD,mBAAmB,EAAE,MAAM,IAAI,CAAC;CACjC;AAQD,wBAAgB,mBAAmB,CAAC,EAClC,SAAS,EACT,OAAc,EACd,aAAkB,EAClB,eAAqB,EACrB,OAAa,EACb,SAAgB,EAChB,IAAW,GACZ,EAAE,0BAA0B,GAAG,yBAAyB,CA4QxD"}
1
+ {"version":3,"file":"useChatStreamScroll.d.ts","sourceRoot":"","sources":["../../src/Chat/useChatStreamScroll.ts"],"names":[],"mappings":"AAoCA,MAAM,WAAW,yBAAyB;IACxC;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;CACjC;AAED,MAAM,WAAW,0BAA0B;IACzC;;OAEG;IACH,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAE/C;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,yBAAyB;IACxC,6DAA6D;IAC7D,YAAY,EAAE,OAAO,CAAC;IAEtB,yDAAyD;IACzD,QAAQ,EAAE,OAAO,CAAC;IAElB,yDAAyD;IACzD,cAAc,EAAE,CAAC,OAAO,CAAC,EAAE,yBAAyB,KAAK,IAAI,CAAC;IAE9D,sFAAsF;IACtF,eAAe,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,IAAI,CAAC;IAE3C,6CAA6C;IAC7C,IAAI,EAAE,MAAM,IAAI,CAAC;IAEjB,0BAA0B;IAC1B,MAAM,EAAE,MAAM,IAAI,CAAC;IAEnB,oEAAoE;IACpE,cAAc,EAAE,MAAM,IAAI,CAAC;IAE3B,mDAAmD;IACnD,mBAAmB,EAAE,MAAM,IAAI,CAAC;CACjC;AAQD,wBAAgB,mBAAmB,CAAC,EAClC,SAAS,EACT,OAAc,EACd,aAAkB,EAClB,eAAqB,EACrB,OAAa,EACb,SAAgB,EAChB,IAAW,GACZ,EAAE,0BAA0B,GAAG,yBAAyB,CAyRxD"}
@@ -4,7 +4,7 @@
4
4
 
5
5
  /**
6
6
  * @file useChatStreamScroll.ts
7
- * @input Uses React refs, state, callbacks
7
+ * @input Uses React refs, state, callbacks, useMediaQuery
8
8
  * @output Exports useChatStreamScroll hook for AI chat scroll behavior
9
9
  * @position Utility hook — used by ChatLayout, also usable standalone
10
10
  *
@@ -15,6 +15,8 @@
15
15
  * - The first fill positions instantly (whether content is present at
16
16
  * mount or arrives async); only subsequent growth springs
17
17
  * - `scrollToBottom({behavior: 'instant'})` jumps in one frame, no animation
18
+ * - Under `prefers-reduced-motion`, every spring path falls back to the
19
+ * same instant jump — following still works, it just doesn't animate
18
20
  *
19
21
  * Uses scroll direction (lastScrollTop comparison) to detect user
20
22
  * intent — works for wheel, touch, scrollbar drag, keyboard, everything.
@@ -25,6 +27,7 @@
25
27
  * - /packages/core/src/Chat/index.ts (exports)
26
28
  */
27
29
  import { useCallback, useEffect, useRef, useState } from 'react';
30
+ import { useMediaQuery } from "../hooks/useMediaQuery.js";
28
31
 
29
32
  // =============================================================================
30
33
  // Types
@@ -93,13 +96,6 @@ export function useChatStreamScroll({
93
96
  el.scrollTop += velocityRef.current * tickDelta;
94
97
  requestAnimationFrame(animate);
95
98
  }, [scrollRef, damping, stiffness, mass]);
96
- const startAnimation = useCallback(() => {
97
- if (!animatingRef.current && lockedRef.current) {
98
- animatingRef.current = true;
99
- lastTickRef.current = undefined;
100
- requestAnimationFrame(animate);
101
- }
102
- }, [animate]);
103
99
 
104
100
  // Jump to the bottom in a single frame — cancels any in-flight spring so
105
101
  // a later animation tick can't fight the assignment.
@@ -114,6 +110,24 @@ export function useChatStreamScroll({
114
110
  el.scrollTop = el.scrollHeight - el.clientHeight;
115
111
  lastScrollTopRef.current = el.scrollTop;
116
112
  }, [scrollRef]);
113
+ const prefersReducedMotion = useMediaQuery('(prefers-reduced-motion: reduce)');
114
+
115
+ // Every spring entry point (scrollToBottom, lock, scrollIfLocked growth
116
+ // follow) funnels through here, so this one branch covers them all.
117
+ const startAnimation = useCallback(() => {
118
+ if (!lockedRef.current) {
119
+ return;
120
+ }
121
+ if (prefersReducedMotion) {
122
+ jumpToBottom();
123
+ return;
124
+ }
125
+ if (!animatingRef.current) {
126
+ animatingRef.current = true;
127
+ lastTickRef.current = undefined;
128
+ requestAnimationFrame(animate);
129
+ }
130
+ }, [animate, jumpToBottom, prefersReducedMotion]);
117
131
 
118
132
  // --- Public API ---
119
133
 
@@ -47,6 +47,5 @@ export interface UseSpeechRecognitionReturn {
47
47
  /** Toggle between start and stop. */
48
48
  toggle: () => void;
49
49
  }
50
- export declare function getDefaultAudioContext(): AudioContext;
51
50
  export declare function useSpeechRecognition(options?: UseSpeechRecognitionOptions): UseSpeechRecognitionReturn;
52
51
  //# sourceMappingURL=useSpeechRecognition.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useSpeechRecognition.d.ts","sourceRoot":"","sources":["../../src/Chat/useSpeechRecognition.ts"],"names":[],"mappings":"AAsBA,MAAM,WAAW,2BAA2B;IAC1C,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4EAA4E;IAC5E,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,0DAA0D;IAC1D,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,wEAAwE;IACxE,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,kDAAkD;IAClD,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/C,2DAA2D;IAC3D,YAAY,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9D,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,8CAA8C;IAC9C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAC,KAAK,IAAI,CAAC;IAC7D,sCAAsC;IACtC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;CACpB;AAED,MAAM,WAAW,0BAA0B;IACzC,sDAAsD;IACtD,WAAW,EAAE,OAAO,CAAC;IACrB,+CAA+C;IAC/C,WAAW,EAAE,OAAO,CAAC;IACrB,kDAAkD;IAClD,UAAU,EAAE,OAAO,CAAC;IACpB,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,qDAAqD;IACrD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,oDAAoD;IACpD,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,2CAA2C;IAC3C,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gCAAgC;IAChC,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,0CAA0C;IAC1C,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,4CAA4C;IAC5C,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,qCAAqC;IACrC,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB;AAgLD,wBAAgB,sBAAsB,IAAI,YAAY,CAQrD;AAMD,wBAAgB,oBAAoB,CAClC,OAAO,GAAE,2BAAgC,GACxC,0BAA0B,CAqM5B"}
1
+ {"version":3,"file":"useSpeechRecognition.d.ts","sourceRoot":"","sources":["../../src/Chat/useSpeechRecognition.ts"],"names":[],"mappings":"AAsBA,MAAM,WAAW,2BAA2B;IAC1C,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4EAA4E;IAC5E,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,0DAA0D;IAC1D,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,wEAAwE;IACxE,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,kDAAkD;IAClD,mBAAmB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/C,2DAA2D;IAC3D,YAAY,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9D,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,8CAA8C;IAC9C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAC,KAAK,IAAI,CAAC;IAC7D,sCAAsC;IACtC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;CACpB;AAED,MAAM,WAAW,0BAA0B;IACzC,sDAAsD;IACtD,WAAW,EAAE,OAAO,CAAC;IACrB,+CAA+C;IAC/C,WAAW,EAAE,OAAO,CAAC;IACrB,kDAAkD;IAClD,UAAU,EAAE,OAAO,CAAC;IACpB,iDAAiD;IACjD,MAAM,EAAE,MAAM,CAAC;IACf,qDAAqD;IACrD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,oDAAoD;IACpD,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,2CAA2C;IAC3C,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gCAAgC;IAChC,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,0CAA0C;IAC1C,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,4CAA4C;IAC5C,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,qCAAqC;IACrC,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB;AA8LD,wBAAgB,oBAAoB,CAClC,OAAO,GAAE,2BAAgC,GACxC,0BAA0B,CAqM5B"}
@@ -135,7 +135,7 @@ async function createVolumeAnalyser(getCtx) {
135
135
  // =============================================================================
136
136
 
137
137
  let _sharedAudioCtx = null;
138
- export function getDefaultAudioContext() {
138
+ function getDefaultAudioContext() {
139
139
  if (!_sharedAudioCtx || _sharedAudioCtx.state === 'closed') {
140
140
  _sharedAudioCtx = new AudioContext();
141
141
  }