@astryxdesign/core 0.1.8-canary.0c4d8d7 → 0.1.8-canary.0db5dfd
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.
- package/dist/Avatar/AvatarStatusDot.d.ts +33 -5
- package/dist/Avatar/AvatarStatusDot.d.ts.map +1 -1
- package/dist/Avatar/AvatarStatusDot.js +144 -19
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +30 -2
- package/dist/Chat/useChatStreamScroll.d.ts +2 -1
- package/dist/Chat/useChatStreamScroll.d.ts.map +1 -1
- package/dist/Chat/useChatStreamScroll.js +22 -8
- package/dist/Chat/useSpeechRecognition.d.ts +0 -1
- package/dist/Chat/useSpeechRecognition.d.ts.map +1 -1
- package/dist/Chat/useSpeechRecognition.js +1 -1
- package/dist/CheckboxList/CheckboxListItem.d.ts +20 -1
- package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
- package/dist/CheckboxList/CheckboxListItem.js +18 -2
- package/dist/Dialog/Dialog.d.ts +3 -0
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +54 -5
- package/dist/Dialog/DialogContext.d.ts +7 -0
- package/dist/Dialog/DialogContext.d.ts.map +1 -1
- package/dist/Dialog/DialogContext.js +2 -2
- package/dist/Dialog/DialogHeader.d.ts +5 -2
- package/dist/Dialog/DialogHeader.d.ts.map +1 -1
- package/dist/Dialog/DialogHeader.js +6 -1
- package/dist/Icon/Icon.d.ts +7 -2
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Item/Item.d.ts +6 -1
- package/dist/Item/Item.d.ts.map +1 -1
- package/dist/Item/Item.js +22 -1
- package/dist/Stack/stack.stylex.d.ts +9 -9
- package/dist/Table/plugins/selection/useTableSelection.d.ts +2 -1
- package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
- package/dist/Thumbnail/Thumbnail.d.ts +8 -1
- package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
- package/dist/Thumbnail/Thumbnail.js +27 -1
- package/dist/ToggleButton/ToggleButtonGroup.d.ts +0 -1
- package/dist/ToggleButton/ToggleButtonGroup.d.ts.map +1 -1
- package/dist/ToggleButton/ToggleButtonGroup.js +1 -1
- package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts +9 -1
- package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts.map +1 -1
- package/dist/TopNav/TopNavMegaMenuFeaturedCard.js +8 -1
- package/dist/TreeList/TreeListBranches.d.ts +5 -0
- package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
- package/dist/TreeList/TreeListBranches.js +10 -4
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +25 -6
- package/dist/astryx.css +0 -1
- package/dist/astryx.umd.js +43 -43
- package/dist/astryx.umd.js.map +3 -3
- package/dist/docs-types.d.ts +8 -0
- package/dist/docs-types.d.ts.map +1 -1
- package/dist/theme/hct.d.ts +0 -1
- package/dist/theme/hct.d.ts.map +1 -1
- package/dist/theme/hct.js +1 -1
- package/locales/en.json +4 -0
- package/locales/fr-FR.json +4 -0
- package/locales/pseudo.json +3 -0
- package/package.json +1 -1
- package/src/Avatar/Avatar.doc.mjs +5 -3
- package/src/Avatar/AvatarStatusDot.doc.mjs +23 -12
- package/src/Avatar/AvatarStatusDot.test.tsx +284 -0
- package/src/Avatar/AvatarStatusDot.tsx +178 -21
- package/src/Calendar/Calendar.doc.mjs +12 -1
- package/src/Calendar/Calendar.test.tsx +193 -0
- package/src/Calendar/Calendar.tsx +38 -16
- package/src/Carousel/Carousel.doc.mjs +1 -0
- package/src/Chat/useChatStreamScroll.test.tsx +49 -0
- package/src/Chat/useChatStreamScroll.ts +27 -10
- package/src/Chat/useSpeechRecognition.ts +1 -1
- package/src/CheckboxList/CheckboxList.test.tsx +72 -2
- package/src/CheckboxList/CheckboxListItem.doc.mjs +33 -5
- package/src/CheckboxList/CheckboxListItem.tsx +50 -6
- package/src/ContextMenu/ContextMenu.test.tsx +193 -0
- package/src/Dialog/Dialog.doc.mjs +2 -2
- package/src/Dialog/Dialog.test.tsx +77 -4
- package/src/Dialog/Dialog.tsx +75 -3
- package/src/Dialog/DialogContext.ts +9 -2
- package/src/Dialog/DialogHeader.doc.mjs +2 -2
- package/src/Dialog/DialogHeader.tsx +9 -2
- package/src/DropdownMenu/DropdownMenu.test.tsx +169 -0
- package/src/Icon/Icon.doc.mjs +3 -2
- package/src/Icon/Icon.tsx +7 -2
- package/src/Item/Item.test.tsx +40 -18
- package/src/Item/Item.tsx +38 -2
- package/src/List/List.test.tsx +9 -8
- package/src/PowerSearch/PowerSearch.doc.mjs +14 -0
- package/src/PowerSearch/PowerSearch.test.tsx +20 -0
- package/src/Table/plugins/selection/useTableSelection.tsx +2 -1
- package/src/Thumbnail/Thumbnail.doc.mjs +3 -3
- package/src/Thumbnail/Thumbnail.test.tsx +35 -0
- package/src/Thumbnail/Thumbnail.tsx +52 -3
- package/src/ToggleButton/ToggleButtonGroup.tsx +1 -1
- package/src/Tokenizer/Tokenizer.doc.mjs +14 -0
- package/src/Tokenizer/Tokenizer.test.tsx +46 -0
- package/src/TopNav/TopNav.test.tsx +45 -0
- package/src/TopNav/TopNavMegaMenuFeaturedCard.doc.mjs +3 -3
- package/src/TopNav/TopNavMegaMenuFeaturedCard.tsx +19 -2
- package/src/TreeList/TreeList.doc.mjs +6 -0
- package/src/TreeList/TreeList.test.tsx +169 -0
- package/src/TreeList/TreeListBranches.tsx +16 -2
- package/src/TreeList/TreeListItem.tsx +34 -3
- package/src/docs-types.ts +5 -0
- package/src/i18n/InternationalizationProvider.doc.mjs +77 -2
- 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
|
|
41
|
-
* -
|
|
42
|
-
*
|
|
43
|
-
* - `
|
|
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;
|
|
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
|
-
*
|
|
27
|
-
*
|
|
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: "
|
|
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
|
-
|
|
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:
|
|
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,+
|
|
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
|
-
|
|
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
|
});
|
|
@@ -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":"
|
|
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;
|
|
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
|
-
|
|
138
|
+
function getDefaultAudioContext() {
|
|
139
139
|
if (!_sharedAudioCtx || _sharedAudioCtx.state === 'closed') {
|
|
140
140
|
_sharedAudioCtx = new AudioContext();
|
|
141
141
|
}
|
|
@@ -22,6 +22,25 @@ export interface CheckboxListItemProps extends BaseProps<HTMLLIElement> {
|
|
|
22
22
|
* child components control their own text behavior).
|
|
23
23
|
*/
|
|
24
24
|
label: ReactNode;
|
|
25
|
+
/**
|
|
26
|
+
* Plain-text accessible name for the checkbox when `label` is a ReactNode.
|
|
27
|
+
*
|
|
28
|
+
* A string `label` names the checkbox automatically. A rich (ReactNode)
|
|
29
|
+
* `label` cannot, so pass a concise string equivalent via the standard
|
|
30
|
+
* `aria-label` — otherwise the checkbox falls back to the generic name
|
|
31
|
+
* "Checkbox" and every rich-label item in a list announces identically to
|
|
32
|
+
* screen readers. Applied to the checkbox control, not the row.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```
|
|
36
|
+
* <CheckboxListItem
|
|
37
|
+
* label={<span>Pro plan <Badge label="Recommended" /></span>}
|
|
38
|
+
* aria-label="Pro plan"
|
|
39
|
+
* value="pro"
|
|
40
|
+
* />
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
'aria-label'?: string;
|
|
25
44
|
/**
|
|
26
45
|
* Identity key for collection mode (REQUIRED inside CheckboxList).
|
|
27
46
|
* Throws a runtime error if missing when used inside CheckboxList.
|
|
@@ -83,7 +102,7 @@ export interface CheckboxListItemProps extends BaseProps<HTMLLIElement> {
|
|
|
83
102
|
* />
|
|
84
103
|
* ```
|
|
85
104
|
*/
|
|
86
|
-
export declare function CheckboxListItem({ label, value, description, endContent, isDisabled: isItemDisabled, isLoading: isItemLoading, isChecked, onCheck, ref, xstyle, className, style, onClick: onClickProp, ...restProps }: CheckboxListItemProps): import("react").JSX.Element;
|
|
105
|
+
export declare function CheckboxListItem({ label, 'aria-label': ariaLabel, value, description, endContent, isDisabled: isItemDisabled, isLoading: isItemLoading, isChecked, onCheck, ref, xstyle, className, style, onClick: onClickProp, ...restProps }: CheckboxListItemProps): import("react").JSX.Element;
|
|
87
106
|
export declare namespace CheckboxListItem {
|
|
88
107
|
var displayName: string;
|
|
89
108
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CheckboxListItem.d.ts","sourceRoot":"","sources":["../../src/CheckboxList/CheckboxListItem.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"CheckboxListItem.d.ts","sourceRoot":"","sources":["../../src/CheckboxList/CheckboxListItem.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAA0C,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAI9E,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAsB5C,MAAM,WAAW,qBAAsB,SAAQ,SAAS,CAAC,aAAa,CAAC;IACrE;;;;;;OAMG;IACH,KAAK,EAAE,SAAS,CAAC;IACjB;;;;;;;;;;;;;;;;;OAiBG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,GAAG,eAAe,CAAC;IACtC;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACrC,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;CAChC;AAMD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,KAAK,EACL,YAAY,EAAE,SAAS,EACvB,KAAK,EACL,WAAW,EACX,UAAU,EACV,UAAU,EAAE,cAAsB,EAClC,SAAS,EAAE,aAAqB,EAChC,SAAS,EACT,OAAO,EACP,GAAG,EACH,MAAM,EACN,SAAS,EACT,KAAK,EACL,OAAO,EAAE,WAAW,EACpB,GAAG,SAAS,EACb,EAAE,qBAAqB,+BAsIvB;yBAtJe,gBAAgB"}
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* - /apps/storybook/stories/CheckboxList.stories.tsx
|
|
16
16
|
* - /packages/cli/templates/blocks/components/CheckboxList/ (showcase blocks)
|
|
17
17
|
*/
|
|
18
|
-
import { use } from 'react';
|
|
18
|
+
import { use, useEffect, useRef } from 'react';
|
|
19
19
|
import * as stylex from '@stylexjs/stylex';
|
|
20
20
|
import "../theme/tokens.stylex.js";
|
|
21
21
|
import { colorVars } from "../theme/tokens.stylex.js";
|
|
@@ -67,6 +67,7 @@ const styles = {
|
|
|
67
67
|
*/
|
|
68
68
|
export function CheckboxListItem({
|
|
69
69
|
label,
|
|
70
|
+
'aria-label': ariaLabel,
|
|
70
71
|
value,
|
|
71
72
|
description,
|
|
72
73
|
endContent,
|
|
@@ -87,6 +88,21 @@ export function CheckboxListItem({
|
|
|
87
88
|
throw new Error('CheckboxListItem requires a `value` prop when used inside CheckboxList with a value array.');
|
|
88
89
|
}
|
|
89
90
|
|
|
91
|
+
// Accessible name for the (visually hidden) checkbox label. A string
|
|
92
|
+
// `label` names it directly; a rich label needs `aria-label`.
|
|
93
|
+
const checkboxLabel = ariaLabel ?? (typeof label === 'string' ? label : t('@astryx.checkboxList.item.checkbox'));
|
|
94
|
+
|
|
95
|
+
// Dev-time guardrail: a rich label without `aria-label` leaves the
|
|
96
|
+
// checkbox with the generic name "Checkbox". Warn once per item instance
|
|
97
|
+
// (in an effect) rather than on every render.
|
|
98
|
+
const warnedUnnamedCheckboxRef = useRef(false);
|
|
99
|
+
useEffect(() => {
|
|
100
|
+
if (typeof label !== 'string' && ariaLabel == null && !warnedUnnamedCheckboxRef.current) {
|
|
101
|
+
warnedUnnamedCheckboxRef.current = true;
|
|
102
|
+
console.warn('CheckboxListItem: `label` is a ReactNode, so the checkbox falls ' + 'back to the generic accessible name "Checkbox". Pass ' + '`aria-label` with a concise string equivalent of the visible ' + 'label so screen readers can tell items apart.');
|
|
103
|
+
}
|
|
104
|
+
}, [label, ariaLabel]);
|
|
105
|
+
|
|
90
106
|
// Density from list context for checkbox sizing
|
|
91
107
|
const listCtx = use(ListContext);
|
|
92
108
|
const density = listCtx?.density ?? 'balanced';
|
|
@@ -144,7 +160,7 @@ export function CheckboxListItem({
|
|
|
144
160
|
className: className,
|
|
145
161
|
style: style,
|
|
146
162
|
startContent: /*#__PURE__*/_jsx(CheckboxInput, {
|
|
147
|
-
label:
|
|
163
|
+
label: checkboxLabel,
|
|
148
164
|
isLabelHidden: true,
|
|
149
165
|
value: resolvedChecked,
|
|
150
166
|
onChange: () => handleToggle(),
|
package/dist/Dialog/Dialog.d.ts
CHANGED
|
@@ -132,6 +132,9 @@ export interface DialogProps extends BaseProps<HTMLDialogElement> {
|
|
|
132
132
|
*
|
|
133
133
|
* Designed to be used with Layout as its child for structured content.
|
|
134
134
|
* Uses the browser's built-in modal behavior for optimal accessibility.
|
|
135
|
+
* When a DialogHeader is rendered inside, its title automatically names the
|
|
136
|
+
* dialog via aria-labelledby; pass `aria-label` or `aria-labelledby` to
|
|
137
|
+
* override.
|
|
135
138
|
*
|
|
136
139
|
* @example
|
|
137
140
|
* ```
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Dialog.d.ts","sourceRoot":"","sources":["../../src/Dialog/Dialog.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"Dialog.d.ts","sourceRoot":"","sources":["../../src/Dialog/Dialog.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAML,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAoB5C,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAwBhD;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,IAAI,CAAC;IACf,UAAU,EAAE,IAAI,CAAC;CAClB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,gBAAgB,CAAC;AAEnD;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;AAEzD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB;AA+HD,MAAM,WAAW,WAAY,SAAQ,SAAS,CAAC,iBAAiB,CAAC;IAC/D,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACnC;;OAEG;IACH,MAAM,EAAE,OAAO,CAAC;IAEhB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;;;;;OAOG;IACH,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC;IAE3C;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAExB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAE5B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;IAEpC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC;IAExB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC;IAExB;;;;OAIG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC;IAEtB;;;OAGG;IACH,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,MAAM,CAAC,EACrB,MAAM,EACN,QAAgB,EAChB,YAAY,EACZ,KAAW,EACX,SAAkB,EAClB,QAAQ,EACR,OAAoB,EACpB,OAAgB,EAChB,OAAO,EACP,QAAQ,EACR,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,GAAG,KAAK,EACT,EAAE,WAAW,sCAuSb;yBAvTe,MAAM"}
|