@astryxdesign/core 0.7.7-canary.bf14580 → 0.7.7-canary.c19ca12
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/AlertDialog/AlertDialog.d.ts +4 -1
- package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
- package/dist/AlertDialog/AlertDialog.js +36 -6
- package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheet.js +76 -6
- package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheetPanel.js +23 -4
- package/dist/BottomSheet/bottomSheetStack.d.ts.map +1 -1
- package/dist/BottomSheet/bottomSheetStack.js +5 -4
- package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
- package/dist/BottomSheet/useSheetGestures.js +3 -1
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +47 -3
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +13 -2
- package/dist/ComplexSelector/ComplexSelector.d.ts +4 -1
- package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
- package/dist/ComplexSelector/ComplexSelector.js +14 -4
- package/dist/ContextMenu/ContextMenu.js +2 -2
- package/dist/DateInput/MonthScroller.d.ts.map +1 -1
- package/dist/DateInput/MonthScroller.js +13 -27
- package/dist/DateInput/Wheel.d.ts.map +1 -1
- package/dist/DateInput/Wheel.js +22 -41
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +7 -31
- package/dist/Field/Field.js +2 -2
- package/dist/HoverCard/HoverCard.d.ts +4 -3
- package/dist/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/HoverCard/HoverCard.js +27 -2
- package/dist/HoverCard/useHoverCard.d.ts +5 -4
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +17 -31
- package/dist/Icon/Icon.d.ts +5 -1
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Icon/Icon.js +5 -2
- package/dist/Layer/layerAnimations.stylex.d.ts +7 -8
- package/dist/Layer/layerAnimations.stylex.d.ts.map +1 -1
- package/dist/Layer/layerAnimations.stylex.js +25 -20
- package/dist/Layer/usePressPin.d.ts +17 -5
- package/dist/Layer/usePressPin.d.ts.map +1 -1
- package/dist/Layer/usePressPin.js +62 -12
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +18 -0
- package/dist/PowerSearch/PowerSearch.d.ts +36 -3
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +522 -269
- package/dist/PowerSearch/PowerSearchBottomSheet.d.ts +100 -0
- package/dist/PowerSearch/PowerSearchBottomSheet.d.ts.map +1 -0
- package/dist/PowerSearch/PowerSearchBottomSheet.js +1913 -0
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts +32 -1
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchEditPopover.js +17 -6
- package/dist/PowerSearch/PowerSearchValueEditor.d.ts +38 -3
- package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchValueEditor.js +170 -61
- package/dist/PowerSearch/formatFilterValue.d.ts +7 -0
- package/dist/PowerSearch/formatFilterValue.d.ts.map +1 -1
- package/dist/PowerSearch/formatFilterValue.js +11 -1
- package/dist/PowerSearch/formatTokenValue.d.ts +28 -0
- package/dist/PowerSearch/formatTokenValue.d.ts.map +1 -0
- package/dist/PowerSearch/formatTokenValue.js +160 -0
- package/dist/PowerSearch/powerSearchSheetUtils.d.ts +65 -0
- package/dist/PowerSearch/powerSearchSheetUtils.d.ts.map +1 -0
- package/dist/PowerSearch/powerSearchSheetUtils.js +168 -0
- package/dist/RadioList/RadioList.d.ts.map +1 -1
- package/dist/RadioList/RadioList.js +3 -2
- package/dist/RadioList/RadioListItem.d.ts +1 -1
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +5 -3
- package/dist/SegmentedControl/useSegmentedSelectionMotion.d.ts.map +1 -1
- package/dist/SegmentedControl/useSegmentedSelectionMotion.js +3 -3
- package/dist/Slider/sliderTouchController.js +2 -2
- package/dist/Spinner/Spinner.d.ts +1 -1
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +60 -58
- package/dist/Switch/useSwitchTouch.js +4 -4
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +29 -8
- package/dist/TextInput/TextInput.d.ts +2 -2
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +10 -7
- package/dist/Toast/Toast.d.ts +11 -1
- package/dist/Toast/Toast.d.ts.map +1 -1
- package/dist/Toast/Toast.js +25 -15
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +94 -34
- package/dist/Toast/types.d.ts +9 -3
- package/dist/Toast/types.d.ts.map +1 -1
- package/dist/Token/Token.d.ts +2 -2
- package/dist/Token/Token.d.ts.map +1 -1
- package/dist/Token/Token.js +12 -4
- package/dist/Token/TokenNamingContext.d.ts +14 -0
- package/dist/Token/TokenNamingContext.d.ts.map +1 -0
- package/dist/Token/TokenNamingContext.js +23 -0
- package/dist/Tooltip/useTooltip.d.ts +19 -1
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +34 -53
- package/dist/Typeahead/TypeaheadItem.d.ts +2 -1
- package/dist/Typeahead/TypeaheadItem.d.ts.map +1 -1
- package/dist/animator/createAnimator.d.ts +98 -0
- package/dist/animator/createAnimator.d.ts.map +1 -0
- package/dist/animator/createAnimator.js +259 -0
- package/dist/astryx.css +22 -6
- package/dist/gestures/GestureHost.d.ts +27 -1
- package/dist/gestures/GestureHost.d.ts.map +1 -1
- package/dist/gestures/GestureHost.js +90 -8
- package/dist/gestures/PressTracker.d.ts.map +1 -1
- package/dist/gestures/PressTracker.js +4 -3
- package/dist/hooks/actionGroupTracker.d.ts +4 -1
- package/dist/hooks/actionGroupTracker.d.ts.map +1 -1
- package/dist/hooks/actionGroupTracker.js +13 -3
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/pressGroupContext.d.ts +6 -0
- package/dist/hooks/pressGroupContext.d.ts.map +1 -0
- package/dist/hooks/pressGroupContext.js +20 -0
- package/dist/hooks/useActionGroupTracking.d.ts +53 -0
- package/dist/hooks/useActionGroupTracking.d.ts.map +1 -0
- package/dist/hooks/useActionGroupTracking.js +174 -0
- package/dist/hooks/useAnimator.d.ts +41 -0
- package/dist/hooks/useAnimator.d.ts.map +1 -0
- package/dist/hooks/useAnimator.js +70 -0
- package/dist/hooks/useAttachment.d.ts +1 -1
- package/dist/hooks/useAttachment.js +1 -1
- package/dist/hooks/useInputStatusIcon.d.ts +1 -1
- package/dist/hooks/useInputStatusIcon.d.ts.map +1 -1
- package/dist/hooks/useInputStatusIcon.js +2 -2
- package/dist/hooks/useLongPress.d.ts +6 -2
- package/dist/hooks/useLongPress.d.ts.map +1 -1
- package/dist/hooks/useLongPress.js +95 -15
- package/dist/hooks/useMenuPress.d.ts.map +1 -1
- package/dist/hooks/useMenuPress.js +4 -2
- package/dist/i18n/generated-english/PowerSearch/PowerSearchBottomSheet.generated.d.ts +8 -0
- package/dist/i18n/generated-english/PowerSearch/PowerSearchBottomSheet.generated.d.ts.map +1 -0
- package/dist/i18n/generated-english/PowerSearch/PowerSearchBottomSheet.generated.js +42 -0
- package/dist/i18n/generated-english/PowerSearch/PowerSearchValueEditor.generated.d.ts.map +1 -1
- package/dist/i18n/generated-english/PowerSearch/PowerSearchValueEditor.generated.js +6 -0
- package/dist/i18n/generated-english/PowerSearch/formatTokenValue.generated.d.ts +8 -0
- package/dist/i18n/generated-english/PowerSearch/formatTokenValue.generated.d.ts.map +1 -0
- package/dist/i18n/generated-english/PowerSearch/formatTokenValue.generated.js +14 -0
- package/dist/i18n/generated-locales/en.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/en.generated.js +30 -0
- package/dist/i18n/generated-locales/pseudo.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/pseudo.generated.js +30 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/internal/indicatorPress.stylex.d.ts +20 -0
- package/dist/internal/indicatorPress.stylex.d.ts.map +1 -0
- package/dist/internal/indicatorPress.stylex.js +26 -0
- package/dist/motion/animator.d.ts +14 -14
- package/dist/motion/animator.d.ts.map +1 -1
- package/dist/motion/animator.js +41 -18
- package/dist/motion/reducedMotion.d.ts +24 -0
- package/dist/motion/reducedMotion.d.ts.map +1 -1
- package/dist/motion/reducedMotion.js +78 -1
- package/dist/motion/uikit/alert.d.ts +41 -0
- package/dist/motion/uikit/alert.d.ts.map +1 -0
- package/dist/motion/uikit/alert.js +43 -0
- package/dist/privateAttributes/pressGroupItem.stylex.d.ts +15 -0
- package/dist/privateAttributes/pressGroupItem.stylex.d.ts.map +1 -0
- package/dist/privateAttributes/pressGroupItem.stylex.js +23 -0
- package/dist/utils/clickGuard.d.ts +8 -1
- package/dist/utils/clickGuard.d.ts.map +1 -1
- package/dist/utils/clickGuard.js +24 -1
- package/dist/utils/dateParser.d.ts.map +1 -1
- package/dist/utils/dateParser.js +12 -0
- package/dist/utils/focusReturn.d.ts +15 -0
- package/dist/utils/focusReturn.d.ts.map +1 -1
- package/dist/utils/focusReturn.js +28 -0
- package/dist/utils/interactionOverlay.stylex.d.ts +3 -2
- package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -1
- package/dist/utils/interactionOverlay.stylex.js +3 -2
- package/dist/utils/pressFeedback.d.ts.map +1 -1
- package/dist/utils/pressFeedback.js +19 -6
- package/dist/utils/triggerFocus.d.ts +36 -0
- package/dist/utils/triggerFocus.d.ts.map +1 -0
- package/dist/utils/triggerFocus.js +65 -0
- package/locales/en.json +120 -0
- package/locales/pseudo.json +90 -0
- package/package.json +9 -4
- package/src/AlertDialog/AlertDialog.doc.mjs +2 -2
- package/src/AlertDialog/AlertDialog.tsx +37 -5
- package/src/BottomSheet/BottomSheet.tsx +85 -5
- package/src/BottomSheet/BottomSheetPanel.tsx +40 -5
- package/src/BottomSheet/bottomSheetStack.ts +8 -4
- package/src/BottomSheet/useSheetGestures.ts +3 -1
- package/src/Button/Button.tsx +63 -5
- package/src/CheckboxInput/CheckboxInput.doc.mjs +18 -0
- package/src/CheckboxInput/CheckboxInput.tsx +36 -9
- package/src/ComplexSelector/ComplexSelector.tsx +20 -5
- package/src/ContextMenu/ContextMenu.tsx +2 -2
- package/src/DateInput/MonthScroller.tsx +18 -22
- package/src/DateInput/Wheel.tsx +30 -32
- package/src/Dialog/Dialog.tsx +10 -31
- package/src/Field/Field.tsx +2 -2
- package/src/HoverCard/HoverCard.doc.mjs +4 -2
- package/src/HoverCard/HoverCard.tsx +35 -4
- package/src/HoverCard/useHoverCard.doc.mjs +178 -36
- package/src/HoverCard/useHoverCard.tsx +46 -52
- package/src/Icon/Icon.doc.mjs +49 -8
- package/src/Icon/Icon.tsx +15 -7
- package/src/Layer/layerAnimations.stylex.ts +24 -16
- package/src/Layer/usePressPin.ts +81 -15
- package/src/Lightbox/Lightbox.tsx +18 -0
- package/src/PowerSearch/PowerSearch.doc.mjs +54 -5
- package/src/PowerSearch/PowerSearch.tsx +734 -288
- package/src/PowerSearch/PowerSearchBottomSheet.tsx +2515 -0
- package/src/PowerSearch/PowerSearchEditPopover.tsx +28 -6
- package/src/PowerSearch/PowerSearchValueEditor.tsx +203 -38
- package/src/PowerSearch/formatFilterValue.ts +18 -1
- package/src/PowerSearch/formatTokenValue.ts +215 -0
- package/src/PowerSearch/powerSearchSheetUtils.ts +224 -0
- package/src/RadioList/RadioList.tsx +3 -2
- package/src/RadioList/RadioListItem.tsx +5 -3
- package/src/SegmentedControl/useSegmentedSelectionMotion.ts +6 -3
- package/src/Slider/sliderTouchController.ts +2 -2
- package/src/Spinner/Spinner.tsx +77 -63
- package/src/Switch/useSwitchTouch.ts +4 -4
- package/src/Table/BaseTable.tsx +46 -12
- package/src/TextInput/TextInput.tsx +11 -10
- package/src/Toast/Toast.doc.mjs +4 -3
- package/src/Toast/Toast.tsx +52 -32
- package/src/Toast/ToastViewport.tsx +121 -35
- package/src/Toast/types.ts +9 -3
- package/src/Token/Token.tsx +13 -4
- package/src/Token/TokenNamingContext.ts +28 -0
- package/src/Tooltip/useTooltip.doc.mjs +24 -0
- package/src/Tooltip/useTooltip.tsx +61 -56
- package/src/Typeahead/TypeaheadItem.doc.mjs +6 -3
- package/src/Typeahead/TypeaheadItem.tsx +2 -1
- package/src/animator/createAnimator.doc.mjs +153 -0
- package/src/animator/createAnimator.ts +324 -0
- package/src/gestures/GestureHost.ts +105 -10
- package/src/gestures/PressTracker.ts +4 -3
- package/src/gestures/README.md +7 -1
- package/src/hooks/actionGroupTracker.ts +20 -5
- package/src/hooks/index.ts +2 -0
- package/src/hooks/pressGroupContext.ts +21 -0
- package/src/hooks/useActionGroupTracking.ts +224 -0
- package/src/hooks/useAnimator.doc.mjs +109 -0
- package/src/hooks/useAnimator.ts +67 -0
- package/src/hooks/useAttachment.ts +1 -1
- package/src/hooks/useInputStatusIcon.tsx +3 -2
- package/src/hooks/useLongPress.doc.mjs +2 -2
- package/src/hooks/useLongPress.ts +136 -15
- package/src/hooks/useMenuPress.ts +8 -2
- package/src/i18n/generated-english/PowerSearch/PowerSearchBottomSheet.generated.ts +43 -0
- package/src/i18n/generated-english/PowerSearch/PowerSearchValueEditor.generated.ts +6 -0
- package/src/i18n/generated-english/PowerSearch/formatTokenValue.generated.ts +15 -0
- package/src/i18n/generated-locales/en.generated.ts +41 -0
- package/src/i18n/generated-locales/pseudo.generated.ts +42 -0
- package/src/index.ts +13 -0
- package/src/internal/indicatorPress.stylex.ts +24 -0
- package/src/motion/README.md +8 -5
- package/src/motion/animator.ts +61 -29
- package/src/motion/reducedMotion.ts +79 -1
- package/src/motion/uikit/alert.ts +43 -0
- package/src/privateAttributes/pressGroupItem.stylex.ts +23 -0
- package/src/utils/clickGuard.ts +37 -1
- package/src/utils/dateParser.ts +16 -0
- package/src/utils/focusReturn.ts +30 -0
- package/src/utils/interactionOverlay.stylex.ts +3 -2
- package/src/utils/pressFeedback.ts +19 -6
- package/src/utils/triggerFocus.ts +80 -0
package/src/Spinner/Spinner.tsx
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*
|
|
11
11
|
* SYNC: When modified, update these files to stay in sync:
|
|
12
12
|
* - /packages/core/src/Spinner/Spinner.doc.mjs
|
|
13
|
-
* - /packages/core/src/Spinner/Spinner.test.tsx
|
|
13
|
+
* - /packages/core/src/Spinner/Spinner.test.tsx and __tests__/SpinnerMotion.a11y.chromium.spec.ts (rotor timing)
|
|
14
14
|
* - /packages/core/src/Spinner/index.ts
|
|
15
15
|
* - /apps/storybook/stories/Spinner.stories.tsx
|
|
16
16
|
* - /packages/cli/assets/templates/blocks/components/Spinner/ (showcase blocks)
|
|
@@ -153,60 +153,57 @@ function registerSpinnerVars(): void {
|
|
|
153
153
|
registerSpinnerVars();
|
|
154
154
|
|
|
155
155
|
/**
|
|
156
|
-
* Pin every ring's
|
|
157
|
-
*
|
|
156
|
+
* Pin every ring's rotation to the document timeline's origin instead of its
|
|
157
|
+
* own start time, so spinners mounted seconds apart stay in phase.
|
|
158
158
|
*
|
|
159
|
-
* Setting `startTime` is exact where arithmetic on a clock read is not
|
|
159
|
+
* Setting `startTime` is exact where arithmetic on a clock read is not. A
|
|
160
160
|
* negative `animation-delay` computed at mount is only as good as the gap
|
|
161
|
-
* between
|
|
162
|
-
*
|
|
163
|
-
* literal rotation; the same drift risk applies to the dash offset now).
|
|
161
|
+
* between the clock read and the frame the animation starts in. At 10x CPU
|
|
162
|
+
* throttling that gap measured 116 degrees of drift.
|
|
164
163
|
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
164
|
+
* Rotors are collected and pinned in one frame. `getAnimations()` resolves
|
|
165
|
+
* style, and `startTime` dirties it again. So pinning them one at a time makes
|
|
166
|
+
* each mount re-force what the previous one invalidated: 53 style recalcs for
|
|
167
|
+
* 38 spinners, against 19 batched.
|
|
169
168
|
*/
|
|
170
|
-
const
|
|
169
|
+
const pendingRotors = new Set<HTMLSpanElement>();
|
|
171
170
|
let flushScheduled = false;
|
|
172
171
|
|
|
173
|
-
function
|
|
172
|
+
function pinRotorsToTimelineOrigin(): void {
|
|
174
173
|
flushScheduled = false;
|
|
175
174
|
const animations: Animation[] = [];
|
|
176
|
-
for (const
|
|
177
|
-
|
|
178
|
-
// this ref sits on (#6253), so it needs subtree:true to be found here.
|
|
179
|
-
animations.push(...svg.getAnimations({subtree: true}));
|
|
175
|
+
for (const rotor of pendingRotors) {
|
|
176
|
+
animations.push(...rotor.getAnimations());
|
|
180
177
|
}
|
|
181
|
-
|
|
178
|
+
pendingRotors.clear();
|
|
182
179
|
for (const animation of animations) {
|
|
183
180
|
animation.startTime = 0;
|
|
184
181
|
}
|
|
185
182
|
}
|
|
186
183
|
|
|
187
184
|
/**
|
|
188
|
-
* Ref callback for the
|
|
185
|
+
* Ref callback for the rotor: the one place a mounted ring touches the DOM.
|
|
189
186
|
*
|
|
190
187
|
* It reads nothing back — the geometry is resolved by the cascade, not in JS.
|
|
191
188
|
*/
|
|
192
189
|
function syncRotationPhase(
|
|
193
|
-
|
|
190
|
+
rotor: HTMLSpanElement | null,
|
|
194
191
|
): (() => void) | undefined {
|
|
195
|
-
if (
|
|
192
|
+
if (rotor == null) {
|
|
196
193
|
return undefined;
|
|
197
194
|
}
|
|
198
195
|
// jsdom implements no Web Animations, and this runs in every consumer's
|
|
199
196
|
// component tests.
|
|
200
|
-
if (typeof
|
|
197
|
+
if (typeof rotor.getAnimations !== 'function') {
|
|
201
198
|
return undefined;
|
|
202
199
|
}
|
|
203
|
-
|
|
200
|
+
pendingRotors.add(rotor);
|
|
204
201
|
if (!flushScheduled) {
|
|
205
202
|
flushScheduled = true;
|
|
206
|
-
requestAnimationFrame(
|
|
203
|
+
requestAnimationFrame(pinRotorsToTimelineOrigin);
|
|
207
204
|
}
|
|
208
205
|
return () => {
|
|
209
|
-
|
|
206
|
+
pendingRotors.delete(rotor);
|
|
210
207
|
};
|
|
211
208
|
}
|
|
212
209
|
|
|
@@ -215,19 +212,13 @@ function syncRotationPhase(
|
|
|
215
212
|
// =============================================================================
|
|
216
213
|
|
|
217
214
|
/**
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
*
|
|
221
|
-
* angle, which reads as a visible wobble on iOS Safari independent of
|
|
222
|
-
* compositing (#6253) — confirmed by a real-device test against this exact
|
|
223
|
-
* fix, since `willChange`/layer promotion alone (the earlier fix for #3617)
|
|
224
|
-
* only smooths the rotation's motion, not the per-frame stroke rasterization.
|
|
225
|
-
* A static circle with an animated `stroke-dashoffset` never rotates, so
|
|
226
|
-
* WebKit never re-rasterizes the cap at an intermediate angle at all.
|
|
215
|
+
* A `transform` animation runs on the compositor, so the ring keeps turning
|
|
216
|
+
* while a script runs. A `stroke-dashoffset` animation would repaint the arc
|
|
217
|
+
* on the main thread every frame, so it would stop while a script runs.
|
|
227
218
|
*/
|
|
228
|
-
const
|
|
229
|
-
'0%': {
|
|
230
|
-
'100%': {
|
|
219
|
+
const rotation = stylex.keyframes({
|
|
220
|
+
'0%': {transform: 'rotate(0deg)'},
|
|
221
|
+
'100%': {transform: 'rotate(360deg)'},
|
|
231
222
|
});
|
|
232
223
|
|
|
233
224
|
// =============================================================================
|
|
@@ -283,6 +274,8 @@ const styles = stylex.create({
|
|
|
283
274
|
ring: {
|
|
284
275
|
backfaceVisibility: 'hidden',
|
|
285
276
|
display: 'block',
|
|
277
|
+
// The track and the rotor share the one grid cell, stacked and centred.
|
|
278
|
+
gridArea: '1 / 1',
|
|
286
279
|
// The frame is the box, read from the same composed var the span is sized
|
|
287
280
|
// from — not from the size constant, which a theme cannot reach, and not
|
|
288
281
|
// from a percentage, which needs the grid area to be a definite size in
|
|
@@ -300,6 +293,27 @@ const styles = stylex.create({
|
|
|
300
293
|
// which put the ring 1.5-3.3px off across the four sizes.
|
|
301
294
|
overflow: 'visible',
|
|
302
295
|
},
|
|
296
|
+
// The rotor is the frame's size, so it turns about the ring's centre.
|
|
297
|
+
rotor: {
|
|
298
|
+
display: 'block',
|
|
299
|
+
gridArea: '1 / 1',
|
|
300
|
+
width: `var(${BOX_SIZE})`,
|
|
301
|
+
height: `var(${BOX_SIZE})`,
|
|
302
|
+
// Mobile Safari keeps a re-timed animation off the main thread only on an
|
|
303
|
+
// element with its own layer. So the rotor declares one before the start
|
|
304
|
+
// time is set (see `pinRotorsToTimelineOrigin`).
|
|
305
|
+
willChange: 'transform',
|
|
306
|
+
// Reduced motion slows the turn but never stops it: a still ring reads as
|
|
307
|
+
// broken. The status role and its name still say that work is busy.
|
|
308
|
+
animationDuration: {
|
|
309
|
+
// The loop reads the duration before a theme's tempo scales it.
|
|
310
|
+
default: `var(--_astryx-pre-tempo-duration-slow-min, ${durationVars['--duration-slow-min']})`,
|
|
311
|
+
'@media (prefers-reduced-motion: reduce)': '3s',
|
|
312
|
+
},
|
|
313
|
+
animationIterationCount: 'infinite',
|
|
314
|
+
animationName: rotation,
|
|
315
|
+
animationTimingFunction: 'linear',
|
|
316
|
+
},
|
|
303
317
|
circle: {
|
|
304
318
|
fill: 'none',
|
|
305
319
|
// The ring is centred on the box (cx/cy 50%), so the arc's start offset
|
|
@@ -336,18 +350,6 @@ const styles = stylex.create({
|
|
|
336
350
|
// `0` the way the registered length pair guards against, so it needs no
|
|
337
351
|
// registration.
|
|
338
352
|
arc: {
|
|
339
|
-
// Slow the motion dramatically under reduced-motion rather than freezing
|
|
340
|
-
// it (a frozen spinner reads as broken), matching ProgressBar's approach.
|
|
341
|
-
// The role="status" + "Loading" label still convey busy state (obs-6).
|
|
342
|
-
animationDuration: {
|
|
343
|
-
// The loop reads the duration before a theme's tempo scales it
|
|
344
|
-
// (spec:AST-108 FR4).
|
|
345
|
-
default: `var(--_astryx-pre-tempo-duration-slow-min, ${durationVars['--duration-slow-min']})`,
|
|
346
|
-
'@media (prefers-reduced-motion: reduce)': '3s',
|
|
347
|
-
},
|
|
348
|
-
animationIterationCount: 'infinite',
|
|
349
|
-
animationName: dashMotion,
|
|
350
|
-
animationTimingFunction: 'linear',
|
|
351
353
|
stroke: 'var(--spinner-color)',
|
|
352
354
|
transform: 'rotate(-90deg)',
|
|
353
355
|
strokeDasharray: `calc(var(${RESOLVED_DIAMETER}) * ${PI} * var(--spinner-arc-fraction)) calc(var(${RESOLVED_DIAMETER}) * ${PI} * (1 - var(--spinner-arc-fraction)))`,
|
|
@@ -569,10 +571,12 @@ export function Spinner({
|
|
|
569
571
|
height: `var(${BOX_SIZE}, ${frameSize}px)`,
|
|
570
572
|
},
|
|
571
573
|
)}>
|
|
574
|
+
{/* The track is zero-sized by attribute. With no stylesheet, the
|
|
575
|
+
rotor's arc alone fills the box, instead of two discs side by side.
|
|
576
|
+
`ring` sizes both to the box. */}
|
|
572
577
|
<svg
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
height={frameSize}
|
|
578
|
+
width={0}
|
|
579
|
+
height={0}
|
|
576
580
|
aria-hidden="true"
|
|
577
581
|
{...stylex.props(styles.ring)}>
|
|
578
582
|
<circle
|
|
@@ -586,18 +590,28 @@ export function Spinner({
|
|
|
586
590
|
trackOpacityStyles[shade],
|
|
587
591
|
)}
|
|
588
592
|
/>
|
|
589
|
-
<circle
|
|
590
|
-
cx="50%"
|
|
591
|
-
cy="50%"
|
|
592
|
-
r={diameter / 2}
|
|
593
|
-
strokeWidth={border}
|
|
594
|
-
// The size's own dash, for the render with no stylesheet. The rule
|
|
595
|
-
// above composes the same lengths from the resolved diameter, so a
|
|
596
|
-
// themed ring keeps this fraction of arc rather than this length.
|
|
597
|
-
strokeDasharray={`${arcLength} ${circumference - arcLength}`}
|
|
598
|
-
{...stylex.props(styles.circle, styles.arc)}
|
|
599
|
-
/>
|
|
600
593
|
</svg>
|
|
594
|
+
<span
|
|
595
|
+
ref={syncRotationPhase}
|
|
596
|
+
aria-hidden="true"
|
|
597
|
+
{...stylex.props(styles.rotor)}>
|
|
598
|
+
<svg
|
|
599
|
+
width={frameSize}
|
|
600
|
+
height={frameSize}
|
|
601
|
+
{...stylex.props(styles.ring)}>
|
|
602
|
+
<circle
|
|
603
|
+
cx="50%"
|
|
604
|
+
cy="50%"
|
|
605
|
+
r={diameter / 2}
|
|
606
|
+
strokeWidth={border}
|
|
607
|
+
// The size's own dash, for the render with no stylesheet. The rule
|
|
608
|
+
// above composes the same lengths from the resolved diameter, so a
|
|
609
|
+
// themed ring keeps this fraction of arc rather than this length.
|
|
610
|
+
strokeDasharray={`${arcLength} ${circumference - arcLength}`}
|
|
611
|
+
{...stylex.props(styles.circle, styles.arc)}
|
|
612
|
+
/>
|
|
613
|
+
</svg>
|
|
614
|
+
</span>
|
|
601
615
|
</span>
|
|
602
616
|
);
|
|
603
617
|
|
|
@@ -23,7 +23,7 @@ import type {GestureTouch} from '../gestures/types';
|
|
|
23
23
|
import {isRtlElement} from '../hooks/isRtlElement';
|
|
24
24
|
import {useIsomorphicLayoutEffect} from '../hooks/useIsomorphicLayoutEffect';
|
|
25
25
|
import {
|
|
26
|
-
|
|
26
|
+
createMotionAnimator,
|
|
27
27
|
type Animator,
|
|
28
28
|
type MotionCurve,
|
|
29
29
|
} from '../motion/animator';
|
|
@@ -282,15 +282,15 @@ export class SwitchTouchController {
|
|
|
282
282
|
return;
|
|
283
283
|
}
|
|
284
284
|
registerSwitchTable();
|
|
285
|
-
this.thumb =
|
|
285
|
+
this.thumb = createMotionAnimator(elements.thumb);
|
|
286
286
|
// The layer rests clear (its class's opacity 0) while the visuals show
|
|
287
287
|
// the value; from here its opacity is the animator's.
|
|
288
|
-
this.fade =
|
|
288
|
+
this.fade = createMotionAnimator(elements.track, {
|
|
289
289
|
pseudoElement: '::after',
|
|
290
290
|
initial: {opacity: 0},
|
|
291
291
|
});
|
|
292
292
|
this.fade.set({opacity: 0});
|
|
293
|
-
this.shadow =
|
|
293
|
+
this.shadow = createMotionAnimator(elements.thumb, {
|
|
294
294
|
pseudoElement: '::after',
|
|
295
295
|
initial: {opacity: 0},
|
|
296
296
|
});
|
package/src/Table/BaseTable.tsx
CHANGED
|
@@ -14,7 +14,14 @@
|
|
|
14
14
|
* - /packages/cli/assets/templates/blocks/components/Table/ (showcase blocks)
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
memo,
|
|
19
|
+
useId,
|
|
20
|
+
useRef,
|
|
21
|
+
type ReactElement,
|
|
22
|
+
type ReactNode,
|
|
23
|
+
type Ref,
|
|
24
|
+
} from 'react';
|
|
18
25
|
import {isRenderable} from '../utils/isRenderable';
|
|
19
26
|
import * as stylex from '@stylexjs/stylex';
|
|
20
27
|
import {spacingVars} from '../theme/tokens.stylex';
|
|
@@ -423,6 +430,7 @@ function BaseTableInner<T extends Record<string, unknown>>({
|
|
|
423
430
|
} satisfies TableRenderProps);
|
|
424
431
|
|
|
425
432
|
// --- Plugin pipeline: header cells ---
|
|
433
|
+
const headerLabelIdBase = useId();
|
|
426
434
|
const headerCells = resolvedColumns.map((col, columnIndex) => {
|
|
427
435
|
const headerContent = col.header ?? col.key;
|
|
428
436
|
|
|
@@ -477,28 +485,54 @@ function BaseTableInner<T extends Record<string, unknown>>({
|
|
|
477
485
|
const hasSlots =
|
|
478
486
|
before != null || after != null || overlay != null || below != null;
|
|
479
487
|
|
|
480
|
-
const
|
|
488
|
+
const labelRow = isRenderable(after) ? (
|
|
489
|
+
<div {...stylex.props(styles.headerLabelRow)}>
|
|
490
|
+
{resolvedContent}
|
|
491
|
+
{after}
|
|
492
|
+
</div>
|
|
493
|
+
) : (
|
|
494
|
+
resolvedContent
|
|
495
|
+
);
|
|
496
|
+
|
|
497
|
+
// The overlay is a control of its own. Keep its name and value out of the
|
|
498
|
+
// header's name.
|
|
499
|
+
const namesOwnHeader =
|
|
500
|
+
isRenderable(overlay) &&
|
|
501
|
+
mergedHtmlProps['aria-label'] == null &&
|
|
502
|
+
mergedHtmlProps['aria-labelledby'] == null;
|
|
503
|
+
const labelId = `${headerLabelIdBase}-label-${columnIndex}`;
|
|
504
|
+
const belowId = `${headerLabelIdBase}-below-${columnIndex}`;
|
|
505
|
+
const hasBelow = isRenderable(below);
|
|
506
|
+
|
|
507
|
+
const headerInner = !hasSlots ? (
|
|
508
|
+
resolvedContent
|
|
509
|
+
) : namesOwnHeader ? (
|
|
510
|
+
<>
|
|
511
|
+
{/* Inline, so the cell's text-overflow still reaches the label. */}
|
|
512
|
+
<span id={labelId}>
|
|
513
|
+
{before}
|
|
514
|
+
{labelRow}
|
|
515
|
+
</span>
|
|
516
|
+
{overlay}
|
|
517
|
+
{hasBelow && <div id={belowId}>{below}</div>}
|
|
518
|
+
</>
|
|
519
|
+
) : (
|
|
481
520
|
<>
|
|
482
521
|
{before}
|
|
483
|
-
{
|
|
484
|
-
<div {...stylex.props(styles.headerLabelRow)}>
|
|
485
|
-
{resolvedContent}
|
|
486
|
-
{after}
|
|
487
|
-
</div>
|
|
488
|
-
) : (
|
|
489
|
-
resolvedContent
|
|
490
|
-
)}
|
|
522
|
+
{labelRow}
|
|
491
523
|
{overlay}
|
|
492
524
|
{below}
|
|
493
525
|
</>
|
|
494
|
-
) : (
|
|
495
|
-
resolvedContent
|
|
496
526
|
);
|
|
527
|
+
const headerNameProps = namesOwnHeader
|
|
528
|
+
? {'aria-labelledby': hasBelow ? `${labelId} ${belowId}` : labelId}
|
|
529
|
+
: {};
|
|
497
530
|
|
|
498
531
|
return (
|
|
499
532
|
<HeaderCellComponent
|
|
500
533
|
key={col.key}
|
|
501
534
|
{...mergedHtmlProps}
|
|
535
|
+
{...headerNameProps}
|
|
502
536
|
{...headerTitleProp}
|
|
503
537
|
contextMenuActions={cellRenderProps.contextMenuActions}
|
|
504
538
|
xstyle={cellRenderProps.xstyle}>
|
|
@@ -35,21 +35,22 @@ import {
|
|
|
35
35
|
typographyVars,
|
|
36
36
|
typeScaleVars,
|
|
37
37
|
} from '../theme/tokens.stylex';
|
|
38
|
+
import {Field} from '../Field/Field';
|
|
39
|
+
import {InputClearButton} from '../Field/InputClearButton';
|
|
38
40
|
import {
|
|
39
|
-
Field,
|
|
40
|
-
InputClearButton,
|
|
41
|
-
type InputStatus,
|
|
42
41
|
inputWrapperStyles,
|
|
43
42
|
inputStatusBorderStyles,
|
|
44
43
|
inputStatusHoverShadowStyles,
|
|
45
44
|
inputStatusFocusWithinStyles,
|
|
46
|
-
} from '../Field';
|
|
47
|
-
import
|
|
45
|
+
} from '../Field/inputStyles.stylex';
|
|
46
|
+
import type {InputStatus} from '../Field/types';
|
|
47
|
+
import {renderIconSlot, type IconType} from '../Icon/Icon';
|
|
48
48
|
import {isRenderable} from '../utils/isRenderable';
|
|
49
|
-
import {Spinner} from '../Spinner';
|
|
50
|
-
import {useTooltip} from '../Tooltip';
|
|
51
|
-
import {VisuallyHidden} from '../VisuallyHidden';
|
|
52
|
-
import {getInputARIA
|
|
49
|
+
import {Spinner} from '../Spinner/Spinner';
|
|
50
|
+
import {useTooltip} from '../Tooltip/useTooltip';
|
|
51
|
+
import {VisuallyHidden} from '../VisuallyHidden/VisuallyHidden';
|
|
52
|
+
import {getInputARIA} from '../utils/inputAria';
|
|
53
|
+
import {isImeKeyEvent} from '../utils/ime';
|
|
53
54
|
import {
|
|
54
55
|
textEntryTraitAttributes,
|
|
55
56
|
type TextEntryTraitProps,
|
|
@@ -109,7 +110,7 @@ export type {
|
|
|
109
110
|
InputStatus as TextInputStatus,
|
|
110
111
|
InputStatusType as TextInputStatusType,
|
|
111
112
|
} from '../Field';
|
|
112
|
-
import {mergeProps} from '../utils';
|
|
113
|
+
import {mergeProps} from '../utils/mergeProps';
|
|
113
114
|
import {useSize} from '../SizeContext/SizeContext';
|
|
114
115
|
import {useInputContainer} from '../hooks/useInputContainer';
|
|
115
116
|
import {useInputStatusIcon} from '../hooks/useInputStatusIcon';
|
package/src/Toast/Toast.doc.mjs
CHANGED
|
@@ -89,7 +89,7 @@ export const docs = {
|
|
|
89
89
|
name: 'renderContent',
|
|
90
90
|
type: '(toast: ToastContentRenderProps) => ReactNode',
|
|
91
91
|
description:
|
|
92
|
-
"Replaces the content of this toast's card with your own layout. Astryx keeps the card, its astryx-toast theme target
|
|
92
|
+
"Replaces the content of this toast's card with your own layout. Astryx keeps the card, its astryx-toast theme target and auto-hide behavior (inside a ToastViewport the viewport announces the toast, and while a modal hosts the viewport the card announces itself), then hands the renderer the message, endContent, resolved toast settings and a dismiss callback. The custom renderer owns every control in its layout: compose the control you want and call dismiss from it. Astryx does not inject a fallback close into custom content. Per-toast: an app shares one layout by wrapping useToast and passing it on every call, while a toast raised by library code that never passes it renders as an ordinary Astryx toast. The argument is {body, endContent, type, isAutoHide, autoHideDuration, dismiss}, where type is 'info' | 'error'.",
|
|
93
93
|
},
|
|
94
94
|
],
|
|
95
95
|
theming: {
|
|
@@ -211,7 +211,7 @@ export const docsZh = {
|
|
|
211
211
|
collisionBehavior: '当已存在相同 uniqueID 的 toast 时的行为。',
|
|
212
212
|
onHide: '当 toast 被移除时触发的回调。',
|
|
213
213
|
renderContent:
|
|
214
|
-
"用你自己的布局替换该 toast 卡片内部的内容。Astryx 保留卡片本身、astryx-toast
|
|
214
|
+
"用你自己的布局替换该 toast 卡片内部的内容。Astryx 保留卡片本身、astryx-toast 主题目标和自动关闭行为(在 ToastViewport 中由视口播报该 toast;当模态框承载视口时由卡片自行播报),并把消息、endContent、解析后的 toast 设置和 dismiss 回调交给渲染函数。自定义渲染函数完全拥有布局中的控件:请组合所需的控件并通过它调用 dismiss。Astryx 不会向自定义内容注入后备关闭按钮。按 toast 单独设置:应用可通过封装 useToast 并在每次调用时传入来共享同一套布局;而由库代码发起、从不传入该参数的 toast 会渲染为普通的 Astryx toast。传入参数为 {body, endContent, type, isAutoHide, autoHideDuration, dismiss},其中 type 为 'info' | 'error'。",
|
|
215
215
|
},
|
|
216
216
|
usage: {
|
|
217
217
|
description:
|
|
@@ -328,6 +328,7 @@ export const docsDense = {
|
|
|
328
328
|
uniqueID: 'unique id for dedup',
|
|
329
329
|
collisionBehavior: 'behavior when matching uniqueID exists',
|
|
330
330
|
onHide: 'callback when toast removed',
|
|
331
|
-
renderContent:
|
|
331
|
+
renderContent:
|
|
332
|
+
'custom inner layout; receives content, resolved settings + dismiss callback; no injected fallback control',
|
|
332
333
|
},
|
|
333
334
|
};
|
package/src/Toast/Toast.tsx
CHANGED
|
@@ -154,6 +154,16 @@ export interface ToastProps {
|
|
|
154
154
|
|
|
155
155
|
interface ToastSurfaceProps extends ToastProps {
|
|
156
156
|
gestureDirection: ToastGestureDirection;
|
|
157
|
+
/**
|
|
158
|
+
* Changes when a uniqueID overwrite updates this card in place: the new
|
|
159
|
+
* toast's auto-hide timer starts over.
|
|
160
|
+
*/
|
|
161
|
+
timerKey?: string;
|
|
162
|
+
/**
|
|
163
|
+
* False when the viewport announces the toast: the card then carries no
|
|
164
|
+
* live region of its own, so an update in place is announced once.
|
|
165
|
+
*/
|
|
166
|
+
isLiveRegion?: boolean;
|
|
157
167
|
}
|
|
158
168
|
|
|
159
169
|
/**
|
|
@@ -193,6 +203,8 @@ export function ToastSurface({
|
|
|
193
203
|
onDismiss,
|
|
194
204
|
renderContent,
|
|
195
205
|
gestureDirection,
|
|
206
|
+
timerKey,
|
|
207
|
+
isLiveRegion = true,
|
|
196
208
|
}: ToastSurfaceProps) {
|
|
197
209
|
const t = useComponentTranslator();
|
|
198
210
|
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
@@ -226,34 +238,28 @@ export function ToastSurface({
|
|
|
226
238
|
}, remainingRef.current);
|
|
227
239
|
}, [isAutoHide]);
|
|
228
240
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
},
|
|
249
|
-
[isAutoHide],
|
|
250
|
-
);
|
|
241
|
+
// Pointer, focus and gesture holds are tracked whatever isAutoHide is: an
|
|
242
|
+
// overwrite can turn a toast that does not auto-hide into one that does
|
|
243
|
+
// while a hold is in place. The window hold leaves with its listeners.
|
|
244
|
+
const pauseTimer = useCallback((source: PauseSource) => {
|
|
245
|
+
const sources = pauseSourcesRef.current;
|
|
246
|
+
const wasRunning = sources.size === 0;
|
|
247
|
+
sources.add(source);
|
|
248
|
+
if (!wasRunning) {
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
if (timerRef.current) {
|
|
252
|
+
clearTimeout(timerRef.current);
|
|
253
|
+
timerRef.current = null;
|
|
254
|
+
}
|
|
255
|
+
if (startTimeRef.current != null) {
|
|
256
|
+
const elapsed = Date.now() - startTimeRef.current;
|
|
257
|
+
remainingRef.current = Math.max(remainingRef.current - elapsed, 1000);
|
|
258
|
+
}
|
|
259
|
+
}, []);
|
|
251
260
|
|
|
252
261
|
const resumeTimer = useCallback(
|
|
253
262
|
(source: PauseSource) => {
|
|
254
|
-
if (!isAutoHide) {
|
|
255
|
-
return;
|
|
256
|
-
}
|
|
257
263
|
const sources = pauseSourcesRef.current;
|
|
258
264
|
if (!sources.delete(source)) {
|
|
259
265
|
return;
|
|
@@ -271,20 +277,31 @@ export function ToastSurface({
|
|
|
271
277
|
}
|
|
272
278
|
startTimer();
|
|
273
279
|
},
|
|
274
|
-
[
|
|
280
|
+
[startTimer],
|
|
275
281
|
);
|
|
276
282
|
|
|
277
283
|
useEffect(() => {
|
|
278
284
|
remainingRef.current = autoHideDuration;
|
|
285
|
+
// An update in place can remove the focused control, which fires no blur:
|
|
286
|
+
// a focus hold whose focus has left the card is stale.
|
|
287
|
+
const root = cardRootRef.current?.current;
|
|
288
|
+
if (
|
|
289
|
+
pauseSourcesRef.current.has('focus') &&
|
|
290
|
+
root != null &&
|
|
291
|
+
!root.contains(root.ownerDocument.activeElement)
|
|
292
|
+
) {
|
|
293
|
+
pauseSourcesRef.current.delete('focus');
|
|
294
|
+
}
|
|
279
295
|
startTimer();
|
|
280
296
|
return () => {
|
|
281
297
|
if (timerRef.current) {
|
|
282
298
|
clearTimeout(timerRef.current);
|
|
283
299
|
}
|
|
284
300
|
};
|
|
285
|
-
// startTimer's identity is stable per isAutoHide, so this runs on mount
|
|
286
|
-
//
|
|
287
|
-
|
|
301
|
+
// startTimer's identity is stable per isAutoHide, so this runs on mount,
|
|
302
|
+
// on a genuine duration change and on an overwrite (timerKey), not on
|
|
303
|
+
// unrelated viewport renders.
|
|
304
|
+
}, [autoHideDuration, startTimer, timerKey]);
|
|
288
305
|
|
|
289
306
|
// Pause the auto-hide timer while the window is not focused, so a toast
|
|
290
307
|
// doesn't silently expire while the user is in another window or tab.
|
|
@@ -292,6 +309,7 @@ export function ToastSurface({
|
|
|
292
309
|
if (!isAutoHide) {
|
|
293
310
|
return;
|
|
294
311
|
}
|
|
312
|
+
const pauseSources = pauseSourcesRef.current;
|
|
295
313
|
const pauseForWindow = () => pauseTimer('window');
|
|
296
314
|
const resumeForWindow = () => resumeTimer('window');
|
|
297
315
|
window.addEventListener('blur', pauseForWindow);
|
|
@@ -304,6 +322,8 @@ export function ToastSurface({
|
|
|
304
322
|
return () => {
|
|
305
323
|
window.removeEventListener('blur', pauseForWindow);
|
|
306
324
|
window.removeEventListener('focus', resumeForWindow);
|
|
325
|
+
// With the listeners gone, no focus event would clear the window hold.
|
|
326
|
+
pauseSources.delete('window');
|
|
307
327
|
};
|
|
308
328
|
}, [isAutoHide, pauseTimer, resumeTimer]);
|
|
309
329
|
|
|
@@ -368,9 +388,9 @@ export function ToastSurface({
|
|
|
368
388
|
return (
|
|
369
389
|
<div
|
|
370
390
|
ref={rootRef}
|
|
371
|
-
role={isError ? 'alert' : 'status'}
|
|
372
|
-
aria-live={isError ? 'assertive' : 'polite'}
|
|
373
|
-
aria-atomic=
|
|
391
|
+
role={isLiveRegion ? (isError ? 'alert' : 'status') : undefined}
|
|
392
|
+
aria-live={isLiveRegion ? (isError ? 'assertive' : 'polite') : undefined}
|
|
393
|
+
aria-atomic={isLiveRegion ? 'true' : undefined}
|
|
374
394
|
onMouseEnter={pauseForPointer}
|
|
375
395
|
onMouseLeave={resumeForPointer}
|
|
376
396
|
onFocusCapture={pauseForFocus}
|