@astryxdesign/core 0.4.3 → 0.4.4-canary.0e8af82
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/CHANGELOG.md +60 -0
- package/README.md +79 -45
- package/dist/Banner/Banner.d.ts +3 -0
- package/dist/Banner/Banner.d.ts.map +1 -1
- package/dist/Banner/Banner.js +13 -3
- package/dist/BottomSheet/BottomSheet.d.ts +75 -0
- package/dist/BottomSheet/BottomSheet.d.ts.map +1 -0
- package/dist/BottomSheet/BottomSheet.js +396 -0
- package/dist/BottomSheet/BottomSheetPanel.d.ts +63 -0
- package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -0
- package/dist/BottomSheet/BottomSheetPanel.js +441 -0
- package/dist/BottomSheet/BottomSheetSwitcher.d.ts +61 -0
- package/dist/BottomSheet/BottomSheetSwitcher.d.ts.map +1 -0
- package/dist/BottomSheet/BottomSheetSwitcher.js +410 -0
- package/dist/BottomSheet/BottomSheetSwitcherContext.d.ts +21 -0
- package/dist/BottomSheet/BottomSheetSwitcherContext.d.ts.map +1 -0
- package/dist/BottomSheet/BottomSheetSwitcherContext.js +13 -0
- package/dist/BottomSheet/index.d.ts +11 -0
- package/dist/BottomSheet/index.d.ts.map +1 -0
- package/dist/BottomSheet/index.js +12 -0
- package/dist/BottomSheet/snapOffsets.d.ts +109 -0
- package/dist/BottomSheet/snapOffsets.d.ts.map +1 -0
- package/dist/BottomSheet/snapOffsets.js +206 -0
- package/dist/BottomSheet/useMobileKeyboard.d.ts +35 -0
- package/dist/BottomSheet/useMobileKeyboard.d.ts.map +1 -0
- package/dist/BottomSheet/useMobileKeyboard.js +373 -0
- package/dist/BottomSheet/useSheetGestures.d.ts +185 -0
- package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -0
- package/dist/BottomSheet/useSheetGestures.js +1038 -0
- package/dist/Calendar/Calendar.d.ts +17 -0
- package/dist/Calendar/Calendar.d.ts.map +1 -1
- package/dist/Calendar/Calendar.js +25 -1
- package/dist/Calendar/hooks/useCalendarConstraints.d.ts +22 -1
- package/dist/Calendar/hooks/useCalendarConstraints.d.ts.map +1 -1
- package/dist/Calendar/hooks/useCalendarConstraints.js +26 -4
- package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
- package/dist/Chat/ChatComposerInput.js +3 -4
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +9 -0
- package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
- package/dist/ComplexSelector/ComplexSelector.js +18 -7
- package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
- package/dist/ContextMenu/ContextMenu.js +4 -2
- package/dist/DateInput/DateInput.d.ts.map +1 -1
- package/dist/DateInput/DateInput.js +15 -2
- package/dist/DateRangeInput/DateRangeInput.d.ts +23 -1
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +38 -3
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +38 -3
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +2 -1
- package/dist/Field/FieldLabel.d.ts +2 -1
- package/dist/Field/FieldLabel.d.ts.map +1 -1
- package/dist/Field/FieldLabel.js +21 -3
- package/dist/Field/InputClearButton.d.ts +2 -1
- package/dist/Field/InputClearButton.d.ts.map +1 -1
- package/dist/Field/InputClearButton.js +6 -1
- package/dist/FormLayout/FormLayout.d.ts +24 -2
- package/dist/FormLayout/FormLayout.d.ts.map +1 -1
- package/dist/FormLayout/FormLayout.js +7 -2
- package/dist/FormLayout/FormLayoutContext.d.ts +15 -2
- package/dist/FormLayout/FormLayoutContext.d.ts.map +1 -1
- package/dist/FormLayout/FormLayoutContext.js +19 -4
- package/dist/FormLayout/index.d.ts +1 -1
- package/dist/FormLayout/index.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +9 -3
- package/dist/MobileNav/MobileNav.d.ts +12 -0
- package/dist/MobileNav/MobileNav.d.ts.map +1 -1
- package/dist/MobileNav/MobileNav.js +102 -30
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.js +27 -8
- package/dist/NumberInput/NumberInput.d.ts.map +1 -1
- package/dist/NumberInput/NumberInput.js +15 -2
- package/dist/PowerSearch/PowerSearchEditPopover.js +1 -1
- package/dist/RadioList/RadioList.d.ts.map +1 -1
- package/dist/RadioList/RadioList.js +12 -1
- package/dist/Selector/Selector.d.ts.map +1 -1
- package/dist/Selector/Selector.js +20 -4
- package/dist/StatusDot/StatusDot.d.ts +43 -3
- package/dist/StatusDot/StatusDot.d.ts.map +1 -1
- package/dist/StatusDot/StatusDot.js +42 -5
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +14 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +7 -2
- package/dist/TextArea/TextArea.d.ts.map +1 -1
- package/dist/TextArea/TextArea.js +6 -1
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +6 -1
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +14 -2
- package/dist/Tokenizer/Tokenizer.js +11 -5
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +4 -1
- package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
- package/dist/Typeahead/BaseTypeahead.js +5 -3
- package/dist/Typeahead/Typeahead.d.ts.map +1 -1
- package/dist/Typeahead/Typeahead.js +10 -1
- package/dist/astryx.css +21 -0
- package/dist/hooks/index.d.ts +8 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +8 -1
- package/dist/hooks/useFocusTrap.d.ts +0 -11
- package/dist/hooks/useFocusTrap.d.ts.map +1 -1
- package/dist/hooks/useFocusTrap.js +1 -11
- package/dist/hooks/useInputStatusIcon.d.ts.map +1 -1
- package/dist/hooks/useInputStatusIcon.js +1 -0
- package/dist/hooks/useResolvedRequired.d.ts +19 -0
- package/dist/hooks/useResolvedRequired.d.ts.map +1 -0
- package/dist/hooks/useResolvedRequired.js +40 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/theme/defineTheme.d.ts +22 -4
- package/dist/theme/defineTheme.d.ts.map +1 -1
- package/dist/theme/expandColorScale.d.ts +17 -2
- package/dist/theme/expandColorScale.d.ts.map +1 -1
- package/dist/theme/expandColorScale.js +63 -33
- package/dist/utils/ime.d.ts +5 -0
- package/dist/utils/ime.d.ts.map +1 -0
- package/dist/utils/ime.js +63 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2 -1
- package/dist/utils/plainDate.d.ts +6 -0
- package/dist/utils/plainDate.d.ts.map +1 -1
- package/dist/utils/plainDate.js +12 -0
- package/locales/af-ZA.json +958 -0
- package/locales/ar-SA.json +998 -0
- package/locales/ca-ES.json +974 -0
- package/locales/cs-CZ.json +990 -0
- package/locales/da-DK.json +966 -0
- package/locales/de-DE.json +966 -0
- package/locales/el-GR.json +990 -0
- package/locales/en.json +52 -0
- package/locales/es-ES.json +978 -0
- package/locales/fi-FI.json +990 -0
- package/locales/fr-FR.json +928 -0
- package/locales/he-IL.json +990 -0
- package/locales/hu-HU.json +990 -0
- package/locales/it-IT.json +978 -0
- package/locales/ja-JP.json +998 -0
- package/locales/ko-KR.json +990 -0
- package/locales/nl-NL.json +954 -0
- package/locales/no-NO.json +978 -0
- package/locales/pl-PL.json +982 -0
- package/locales/pseudo.json +39 -0
- package/locales/pt-BR.json +982 -0
- package/locales/pt-PT.json +982 -0
- package/locales/ro-RO.json +982 -0
- package/locales/ru-RU.json +990 -0
- package/locales/sr-SP.json +990 -0
- package/locales/sv-SE.json +986 -0
- package/locales/tr-TR.json +990 -0
- package/locales/uk-UA.json +990 -0
- package/locales/vi-VN.json +986 -0
- package/locales/zh-CN.json +998 -0
- package/locales/zh-TW.json +998 -0
- package/package.json +9 -8
- package/src/Banner/Banner.doc.mjs +3 -3
- package/src/Banner/Banner.test.tsx +40 -0
- package/src/Banner/Banner.tsx +27 -2
- package/src/BottomSheet/BottomSheet.doc.mjs +299 -0
- package/src/BottomSheet/BottomSheet.test.tsx +2265 -0
- package/src/BottomSheet/BottomSheet.tsx +559 -0
- package/src/BottomSheet/BottomSheetPanel.test.tsx +240 -0
- package/src/BottomSheet/BottomSheetPanel.tsx +601 -0
- package/src/BottomSheet/BottomSheetSwitcher.doc.mjs +219 -0
- package/src/BottomSheet/BottomSheetSwitcher.test.tsx +850 -0
- package/src/BottomSheet/BottomSheetSwitcher.tsx +628 -0
- package/src/BottomSheet/BottomSheetSwitcherContext.ts +51 -0
- package/src/BottomSheet/index.ts +19 -0
- package/src/BottomSheet/snapOffsets.test.ts +254 -0
- package/src/BottomSheet/snapOffsets.ts +245 -0
- package/src/BottomSheet/useMobileKeyboard.ts +499 -0
- package/src/BottomSheet/useSheetGestures.test.ts +1112 -0
- package/src/BottomSheet/useSheetGestures.ts +1503 -0
- package/src/Calendar/Calendar.doc.mjs +16 -0
- package/src/Calendar/Calendar.test.tsx +96 -0
- package/src/Calendar/Calendar.tsx +55 -0
- package/src/Calendar/hooks/useCalendarConstraints.ts +54 -3
- package/src/Chat/ChatComposerInput.tsx +3 -4
- package/src/CheckboxInput/CheckboxInput.tsx +6 -0
- package/src/ComplexSelector/ComplexSelector.tsx +15 -6
- package/src/ContextMenu/ContextMenu.tsx +4 -2
- package/src/DateInput/DateInput.test.tsx +21 -0
- package/src/DateInput/DateInput.tsx +12 -2
- package/src/DateRangeInput/DateRangeInput.doc.mjs +16 -0
- package/src/DateRangeInput/DateRangeInput.test.tsx +81 -1
- package/src/DateRangeInput/DateRangeInput.tsx +72 -1
- package/src/DateTimeInput/DateTimeInput.doc.mjs +4 -0
- package/src/DateTimeInput/DateTimeInput.test.tsx +137 -0
- package/src/DateTimeInput/DateTimeInput.tsx +43 -4
- package/src/Dialog/Dialog.tsx +2 -1
- package/src/Field/Field.doc.mjs +1 -0
- package/src/Field/FieldLabel.tsx +20 -4
- package/src/Field/InputClearButton.test.tsx +25 -0
- package/src/Field/InputClearButton.tsx +4 -1
- package/src/FileInput/FileInput.test.tsx +53 -9
- package/src/FormLayout/FormLayout.doc.mjs +13 -0
- package/src/FormLayout/FormLayout.test.tsx +181 -4
- package/src/FormLayout/FormLayout.tsx +33 -2
- package/src/FormLayout/FormLayoutContext.ts +22 -7
- package/src/FormLayout/index.ts +1 -1
- package/src/Lightbox/Lightbox.test.tsx +49 -28
- package/src/Lightbox/Lightbox.tsx +7 -3
- package/src/MobileNav/MobileNav.tsx +128 -37
- package/src/MobileNav/MobileNavCloseEdgeCases.test.tsx +426 -0
- package/src/MobileNav/MobileNavCloseTiming.test.ts +58 -0
- package/src/MobileNav/MobileNavCloseVisibility.test.tsx +172 -0
- package/src/MultiSelector/MultiSelector.test.tsx +195 -51
- package/src/MultiSelector/MultiSelector.tsx +25 -9
- package/src/NumberInput/NumberInput.test.tsx +18 -0
- package/src/NumberInput/NumberInput.tsx +12 -2
- package/src/PowerSearch/PowerSearchEditPopover.tsx +1 -1
- package/src/RadioList/RadioList.tsx +9 -1
- package/src/Selector/Selector.test.tsx +85 -26
- package/src/Selector/Selector.tsx +16 -5
- package/src/StatusDot/StatusDot.doc.mjs +13 -0
- package/src/StatusDot/StatusDot.test.tsx +115 -8
- package/src/StatusDot/StatusDot.tsx +74 -9
- package/src/Switch/Switch.test.tsx +16 -0
- package/src/Switch/Switch.tsx +13 -0
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +20 -2
- package/src/TextArea/TextArea.tsx +3 -1
- package/src/TextInput/TextInput.tsx +3 -1
- package/src/TimeInput/TimeInput.test.tsx +23 -0
- package/src/TimeInput/TimeInput.tsx +11 -1
- package/src/Tokenizer/Tokenizer.test.tsx +50 -32
- package/src/Tokenizer/Tokenizer.tsx +5 -5
- package/src/Tooltip/useTooltip.tsx +4 -1
- package/src/Typeahead/BaseTypeahead.tsx +10 -3
- package/src/Typeahead/Typeahead.test.tsx +116 -7
- package/src/Typeahead/Typeahead.tsx +10 -1
- package/src/__tests__/stubMatchMedia.test.ts +79 -0
- package/src/__tests__/stubMatchMedia.ts +95 -0
- package/src/hooks/index.ts +9 -5
- package/src/hooks/useFocusTrap.ts +1 -14
- package/src/hooks/useInputStatusIcon.test.tsx +19 -0
- package/src/hooks/useInputStatusIcon.tsx +7 -0
- package/src/hooks/useResolvedRequired.ts +42 -0
- package/src/index.ts +1 -0
- package/src/theme/defineTheme.ts +22 -4
- package/src/theme/expandColorScale.test.ts +138 -0
- package/src/theme/expandColorScale.ts +89 -44
- package/src/utils/ime.test.ts +32 -0
- package/src/utils/ime.ts +69 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/plainDate.test.ts +50 -0
- package/src/utils/plainDate.ts +12 -0
- package/dist/astryx.umd.js +0 -147
- package/dist/astryx.umd.js.map +0 -7
|
@@ -57,6 +57,9 @@ const styles = {
|
|
|
57
57
|
kFalU9: "x5ve5x3",
|
|
58
58
|
kI3sdo: "x1a2a7pz",
|
|
59
59
|
k1xSpc: "x1s85apg",
|
|
60
|
+
k1ekBW: "xrgi2yo",
|
|
61
|
+
kIyJzY: "x80gvsz",
|
|
62
|
+
kzIqYQ: "xd00j3c",
|
|
60
63
|
$$css: true
|
|
61
64
|
},
|
|
62
65
|
open: {
|
|
@@ -133,6 +136,61 @@ const dynamicStyles = {
|
|
|
133
136
|
}]
|
|
134
137
|
};
|
|
135
138
|
|
|
139
|
+
// =============================================================================
|
|
140
|
+
// Close timing
|
|
141
|
+
// =============================================================================
|
|
142
|
+
|
|
143
|
+
/** Longest the drawer will wait before closing, however long the hold is. */
|
|
144
|
+
const MAX_CLOSE_DELAY_MS = 250;
|
|
145
|
+
/** Fraction of the hold to close at, so the close never lands on its boundary. */
|
|
146
|
+
const CLOSE_WITHIN_HOLD = 0.6;
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Shortest duration in a `transition-duration` list, in ms; null if unreadable.
|
|
150
|
+
*
|
|
151
|
+
* Browsers serialise computed `<time>` values in seconds — an authored `410ms`
|
|
152
|
+
* reads back as `"0.41s"` and a list as `"0.41s, 0.12s"` — so the seconds branch
|
|
153
|
+
* is the one that runs outside tests. jsdom echoes an inline `250ms` back as-is
|
|
154
|
+
* and never resolves `var()`, so both units and the unreadable case are covered
|
|
155
|
+
* directly in MobileNavCloseTiming.test.ts rather than through the component.
|
|
156
|
+
*
|
|
157
|
+
* @internal Exported for unit tests.
|
|
158
|
+
*/
|
|
159
|
+
export function parseShortestDurationMs(value) {
|
|
160
|
+
const durations = value.split(',').map(part => {
|
|
161
|
+
const trimmed = part.trim();
|
|
162
|
+
const ms = Number.parseFloat(trimmed);
|
|
163
|
+
if (!Number.isFinite(ms)) {
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
return trimmed.endsWith('ms') ? ms : trimmed.endsWith('s') ? ms * 1000 : null;
|
|
167
|
+
}).filter(ms => ms !== null);
|
|
168
|
+
return durations.length ? Math.min(...durations) : null;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* How long to wait before closing the native dialog.
|
|
173
|
+
*
|
|
174
|
+
* The drawer is only rendered for as long as its `display` transition runs, and
|
|
175
|
+
* closing an unrendered modal dialog is what leaves the page inert (#4290). So
|
|
176
|
+
* the close has to land inside that hold. The hold is `--duration-medium`,
|
|
177
|
+
* which themes rewrite — the shipped y2k theme sets it to exactly 250ms — so
|
|
178
|
+
* read the hold in effect rather than assuming it.
|
|
179
|
+
*/
|
|
180
|
+
function resolveCloseDelay(dialog) {
|
|
181
|
+
// Reduced motion makes the close sooner; it must not make the hold shorter.
|
|
182
|
+
// Shrinking both leaves no slack — one slow frame between the commit and this
|
|
183
|
+
// macrotask and the drawer has already stopped being rendered.
|
|
184
|
+
const cap = window.matchMedia('(prefers-reduced-motion: reduce)').matches ? 0 : MAX_CLOSE_DELAY_MS;
|
|
185
|
+
const hold = parseShortestDurationMs(window.getComputedStyle(dialog).transitionDuration);
|
|
186
|
+
|
|
187
|
+
// The hold is unreadable — an unresolved var() outside a real browser.
|
|
188
|
+
if (hold === null) {
|
|
189
|
+
return cap;
|
|
190
|
+
}
|
|
191
|
+
return hold <= 0 ? 0 : Math.min(cap, hold * CLOSE_WITHIN_HOLD);
|
|
192
|
+
}
|
|
193
|
+
|
|
136
194
|
// =============================================================================
|
|
137
195
|
// Types
|
|
138
196
|
// =============================================================================
|
|
@@ -203,6 +261,31 @@ export function MobileNav({
|
|
|
203
261
|
// Resolved side — computed from trigger position when side='auto'
|
|
204
262
|
const [resolvedSide, setResolvedSide] = useState(side === 'auto' ? 'end' : side);
|
|
205
263
|
|
|
264
|
+
// Resolve which edge the drawer slides from. Deliberately its own effect,
|
|
265
|
+
// declared before the open/close effect below so the trigger is still the
|
|
266
|
+
// active element when `side='auto'` reads it. Keeping it out of that effect
|
|
267
|
+
// is what stops a `side` change during a close from re-arming the delay: the
|
|
268
|
+
// CSS hold runs from the commit that started the slide-out and does not
|
|
269
|
+
// restart, so a fresh full delay could land after the drawer had already
|
|
270
|
+
// stopped being rendered — #4290 again.
|
|
271
|
+
useEffect(() => {
|
|
272
|
+
if (!isOpen) {
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
if (side === 'auto') {
|
|
276
|
+
const trigger = document.activeElement;
|
|
277
|
+
if (trigger && trigger !== document.body) {
|
|
278
|
+
const rect = trigger.getBoundingClientRect();
|
|
279
|
+
const triggerCenter = rect.left + rect.width / 2;
|
|
280
|
+
// eslint-disable-next-line @eslint-react/set-state-in-effect -- side is resolved from trigger layout immediately before showModal()
|
|
281
|
+
setResolvedSide(triggerCenter < window.innerWidth / 2 ? 'start' : 'end');
|
|
282
|
+
}
|
|
283
|
+
} else {
|
|
284
|
+
// eslint-disable-next-line @eslint-react/set-state-in-effect -- side prop changes must update the open dialog placement
|
|
285
|
+
setResolvedSide(side);
|
|
286
|
+
}
|
|
287
|
+
}, [isOpen, side]);
|
|
288
|
+
|
|
206
289
|
// Open/close the dialog via showModal()/close()
|
|
207
290
|
// close() is delayed so the slide-out transition can play.
|
|
208
291
|
useEffect(() => {
|
|
@@ -210,24 +293,7 @@ export function MobileNav({
|
|
|
210
293
|
if (!dialog) {
|
|
211
294
|
return;
|
|
212
295
|
}
|
|
213
|
-
if (closeTimeoutRef.current) {
|
|
214
|
-
clearTimeout(closeTimeoutRef.current);
|
|
215
|
-
closeTimeoutRef.current = null;
|
|
216
|
-
}
|
|
217
296
|
if (isOpen) {
|
|
218
|
-
// Determine drawer side from trigger position when auto
|
|
219
|
-
if (side === 'auto') {
|
|
220
|
-
const trigger = document.activeElement;
|
|
221
|
-
if (trigger && trigger !== document.body) {
|
|
222
|
-
const rect = trigger.getBoundingClientRect();
|
|
223
|
-
const triggerCenter = rect.left + rect.width / 2;
|
|
224
|
-
// eslint-disable-next-line @eslint-react/set-state-in-effect -- side is resolved from trigger layout immediately before showModal()
|
|
225
|
-
setResolvedSide(triggerCenter < window.innerWidth / 2 ? 'start' : 'end');
|
|
226
|
-
}
|
|
227
|
-
} else {
|
|
228
|
-
// eslint-disable-next-line @eslint-react/set-state-in-effect -- side prop changes must update the open dialog placement
|
|
229
|
-
setResolvedSide(side);
|
|
230
|
-
}
|
|
231
297
|
if (!dialog.open) {
|
|
232
298
|
dialog.showModal();
|
|
233
299
|
}
|
|
@@ -237,10 +303,9 @@ export function MobileNav({
|
|
|
237
303
|
document.documentElement.style.overflow = 'clip';
|
|
238
304
|
} else if (dialog.open) {
|
|
239
305
|
document.documentElement.style.overflow = '';
|
|
240
|
-
const duration = window.matchMedia('(prefers-reduced-motion: reduce)').matches ? 10 : 250;
|
|
241
306
|
closeTimeoutRef.current = setTimeout(() => {
|
|
242
307
|
dialog.close();
|
|
243
|
-
},
|
|
308
|
+
}, resolveCloseDelay(dialog));
|
|
244
309
|
}
|
|
245
310
|
return () => {
|
|
246
311
|
if (closeTimeoutRef.current) {
|
|
@@ -248,20 +313,27 @@ export function MobileNav({
|
|
|
248
313
|
closeTimeoutRef.current = null;
|
|
249
314
|
}
|
|
250
315
|
document.documentElement.style.overflow = '';
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
316
|
+
};
|
|
317
|
+
}, [isOpen]);
|
|
318
|
+
|
|
319
|
+
// Close the native dialog on unmount if it's still open. Inside AppShell the
|
|
320
|
+
// drawer is mounted in an <Activity> that switches to mode="hidden" when the
|
|
321
|
+
// drawer closes; React then runs effect cleanups (with a stale isOpen)
|
|
322
|
+
// instead of re-running the effect with isOpen=false, so the close branch
|
|
323
|
+
// above never fires. If we leave the <dialog> `open` here, showModal() is
|
|
324
|
+
// skipped on the next open (the dialog is already open in the hidden tree)
|
|
325
|
+
// and the drawer can never be re-opened — see MobileNavReopen.test.tsx.
|
|
326
|
+
// This must be a separate unmount-only effect: putting it in the open/close
|
|
327
|
+
// effect above would close the dialog on every isOpen flip and cut off the
|
|
328
|
+
// delayed slide-out close.
|
|
329
|
+
useEffect(() => {
|
|
330
|
+
const dialog = dialogRef.current;
|
|
331
|
+
return () => {
|
|
332
|
+
if (dialog?.open) {
|
|
261
333
|
dialog.close();
|
|
262
334
|
}
|
|
263
335
|
};
|
|
264
|
-
}, [
|
|
336
|
+
}, []);
|
|
265
337
|
|
|
266
338
|
// Handle native cancel event (Escape key) — prevent default and route through onOpenChange
|
|
267
339
|
const handleCancel = useCallback(event => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MultiSelector.d.ts","sourceRoot":"","sources":["../../src/MultiSelector/MultiSelector.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,EASZ,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAIf,OAAO,EAAuB,KAAK,QAAQ,EAAC,MAAM,SAAS,CAAC;AAE5D,OAAO,EAML,KAAK,kBAAkB,EACxB,MAAM,UAAU,CAAC;AAKlB,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,cAAc,CAAC;AAcpD,OAAO,KAAK,EACV,uBAAuB,EACvB,uBAAuB,EACvB,mBAAmB,EACpB,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"MultiSelector.d.ts","sourceRoot":"","sources":["../../src/MultiSelector/MultiSelector.tsx"],"names":[],"mappings":"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"}
|
|
@@ -30,8 +30,9 @@ import "../theme/tokens.stylex.js";
|
|
|
30
30
|
import { colorVars, sizeVars, spacingVars, radiusVars, durationVars, easeVars, typographyVars, fontWeightVars, typeScaleVars } from "../theme/tokens.stylex.js";
|
|
31
31
|
import { isOptionData, isDivider, isSection, normalizeOption, getSelectableOptions } from "../Selector/utils.js";
|
|
32
32
|
import { useMultiCombobox } from "./hooks.js";
|
|
33
|
-
import { getInputARIA, mergeProps } from "../utils/index.js";
|
|
33
|
+
import { getInputARIA, isImeKeyEvent, mergeProps } from "../utils/index.js";
|
|
34
34
|
import { useAnnounce } from "../hooks/useAnnounce.js";
|
|
35
|
+
import { useResolvedRequired } from "../hooks/useResolvedRequired.js";
|
|
35
36
|
import { useSize } from "../SizeContext/SizeContext.js";
|
|
36
37
|
import { themeProps } from "../utils/themeProps.js";
|
|
37
38
|
import { focusOutlineStyles } from "../utils/focusOutline.stylex.js";
|
|
@@ -287,6 +288,10 @@ export function MultiSelector({
|
|
|
287
288
|
style
|
|
288
289
|
}) {
|
|
289
290
|
const t = useTranslator();
|
|
291
|
+
const isEffectivelyRequired = useResolvedRequired({
|
|
292
|
+
isRequired,
|
|
293
|
+
isOptional
|
|
294
|
+
});
|
|
290
295
|
const placeholder = placeholderFromProps ?? t('@astryx.multiSelector.selectPlaceholder');
|
|
291
296
|
const selectAllLabel = selectAllLabelFromProps ?? t('@astryx.multiSelector.selectAll');
|
|
292
297
|
const searchPlaceholder = searchPlaceholderFromProps ?? t('@astryx.multiSelector.searchPlaceholder');
|
|
@@ -347,13 +352,16 @@ export function MultiSelector({
|
|
|
347
352
|
const selectableSet = new Set(selectableItems.map(item => item.value));
|
|
348
353
|
const selectedCount = nextValue.filter(v => selectableSet.has(v)).length;
|
|
349
354
|
if (selectedCount === 0) {
|
|
350
|
-
announce('
|
|
355
|
+
announce(t('@astryx.multiSelector.selectionCleared'));
|
|
351
356
|
} else if (total > 0 && selectedCount === total) {
|
|
352
|
-
announce('
|
|
357
|
+
announce(t('@astryx.multiSelector.allSelected'));
|
|
353
358
|
} else {
|
|
354
|
-
announce(
|
|
359
|
+
announce(t('@astryx.multiSelector.selectionCount', {
|
|
360
|
+
count: selectedCount,
|
|
361
|
+
total
|
|
362
|
+
}));
|
|
355
363
|
}
|
|
356
|
-
}, [announce, selectableItems]);
|
|
364
|
+
}, [announce, selectableItems, t]);
|
|
357
365
|
|
|
358
366
|
// Filter items by search query
|
|
359
367
|
const filteredItems = useMemo(() => filterOptionsByQuery(selectableItems, searchQuery), [selectableItems, searchQuery]);
|
|
@@ -446,8 +454,10 @@ export function MultiSelector({
|
|
|
446
454
|
return;
|
|
447
455
|
}
|
|
448
456
|
const count = filterOptionsByQuery(selectableItems, nextQuery).length;
|
|
449
|
-
announce(count === 0 ? '
|
|
450
|
-
|
|
457
|
+
announce(count === 0 ? t('@astryx.multiSelector.emptySearchResults') : t('@astryx.multiSelector.resultCount', {
|
|
458
|
+
count
|
|
459
|
+
}));
|
|
460
|
+
}, [announce, selectableItems, t]);
|
|
451
461
|
|
|
452
462
|
// Handle toggle
|
|
453
463
|
// Clear all selected values. Shared by the clear button and the keyboard
|
|
@@ -669,6 +679,15 @@ export function MultiSelector({
|
|
|
669
679
|
}
|
|
670
680
|
},
|
|
671
681
|
onKeyDown: e => {
|
|
682
|
+
// An in-progress IME composition uses these same keys (Enter to
|
|
683
|
+
// commit the candidate, Escape/Arrows to navigate the candidate
|
|
684
|
+
// window); the composing keydown fires before compositionend, so
|
|
685
|
+
// without this guard a Korean/Japanese/Chinese user committing a
|
|
686
|
+
// syllable with Enter would instead toggle the highlighted option.
|
|
687
|
+
// See utils/ime.ts.
|
|
688
|
+
if (isImeKeyEvent(e.nativeEvent)) {
|
|
689
|
+
return;
|
|
690
|
+
}
|
|
672
691
|
// Arrow keys navigate options; Enter toggles; Escape closes.
|
|
673
692
|
// Space and Home/End are left to the input (type a space / move
|
|
674
693
|
// the caret) per the APG editable combobox; PageUp/PageDown are
|
|
@@ -891,7 +910,7 @@ export function MultiSelector({
|
|
|
891
910
|
"aria-activedescendant": !hasSearch && popover.isOpen && highlightedIndex >= 0 ? getItemId(highlightedIndex) : undefined,
|
|
892
911
|
"aria-describedby": ariaDescribedBy,
|
|
893
912
|
"aria-labelledby": ariaLabelledBy,
|
|
894
|
-
"aria-required":
|
|
913
|
+
"aria-required": isEffectivelyRequired ? 'true' : undefined,
|
|
895
914
|
"aria-invalid": status?.type === 'error' ? 'true' : undefined,
|
|
896
915
|
"aria-busy": isBusy || undefined
|
|
897
916
|
// With a disabledMessage the trigger keeps focusability via
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NumberInput.d.ts","sourceRoot":"","sources":["../../src/NumberInput/NumberInput.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAML,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,MAAM,MAAM,kBAAkB,CAAC;AAU3C,OAAO,EAGL,KAAK,WAAW,EAKhB,KAAK,kBAAkB,EACxB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAuB,KAAK,QAAQ,EAAC,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"NumberInput.d.ts","sourceRoot":"","sources":["../../src/NumberInput/NumberInput.tsx"],"names":[],"mappings":"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"}
|
|
@@ -27,6 +27,7 @@ import { getInputARIA } from "../utils/index.js";
|
|
|
27
27
|
import { useSize } from "../SizeContext/SizeContext.js";
|
|
28
28
|
import { useInputContainer } from "../hooks/useInputContainer.js";
|
|
29
29
|
import { useInputStatusIcon } from "../hooks/useInputStatusIcon.js";
|
|
30
|
+
import { useResolvedRequired } from "../hooks/useResolvedRequired.js";
|
|
30
31
|
import { useInputGroup } from "../InputGroup/InputGroupContext.js";
|
|
31
32
|
const styles = {
|
|
32
33
|
wrapper: {
|
|
@@ -60,7 +61,7 @@ import { groupStyles } from "../InputGroup/groupStyles.js";
|
|
|
60
61
|
|
|
61
62
|
// Re-export shared types for convenience
|
|
62
63
|
|
|
63
|
-
import { mergeProps, mergeRefs } from "../utils/index.js";
|
|
64
|
+
import { isImeKeyEvent, mergeProps, mergeRefs } from "../utils/index.js";
|
|
64
65
|
import { themeProps } from "../utils/themeProps.js";
|
|
65
66
|
import { useTranslator } from "../i18n/index.js";
|
|
66
67
|
|
|
@@ -202,6 +203,10 @@ export function NumberInput({
|
|
|
202
203
|
...rest
|
|
203
204
|
}) {
|
|
204
205
|
const t = useTranslator();
|
|
206
|
+
const isEffectivelyRequired = useResolvedRequired({
|
|
207
|
+
isRequired,
|
|
208
|
+
isOptional
|
|
209
|
+
});
|
|
205
210
|
const size = useSize(sizeProp, 'md');
|
|
206
211
|
const id = useId();
|
|
207
212
|
const inputLabelID = useId();
|
|
@@ -371,6 +376,14 @@ export function NumberInput({
|
|
|
371
376
|
|
|
372
377
|
// Handle keyboard events
|
|
373
378
|
const handleKeyDown = useCallback(e => {
|
|
379
|
+
// The field is type="text" for formatted display, so an IME can compose
|
|
380
|
+
// into it: Enter commits the candidate and the arrows walk the candidate
|
|
381
|
+
// window. The composing keydown fires before compositionend, so without
|
|
382
|
+
// this guard those keystrokes would commit or step the value instead.
|
|
383
|
+
// See utils/ime.ts.
|
|
384
|
+
if (isImeKeyEvent(e.nativeEvent)) {
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
374
387
|
const hasModifier = e.altKey || e.ctrlKey || e.metaKey || e.shiftKey;
|
|
375
388
|
if (!hasModifier && (e.key === 'ArrowUp' || e.key === 'ArrowDown')) {
|
|
376
389
|
onKeyDown?.(e);
|
|
@@ -501,7 +514,7 @@ export function NumberInput({
|
|
|
501
514
|
"aria-valuenow": value ?? undefined,
|
|
502
515
|
"aria-valuetext": value == null || !formatValue ? undefined : formattedValue,
|
|
503
516
|
"aria-describedby": ariaDescribedBy,
|
|
504
|
-
"aria-required":
|
|
517
|
+
"aria-required": isEffectivelyRequired ? 'true' : undefined,
|
|
505
518
|
"aria-invalid": status?.type === 'error' || !isInputValid ? 'true' : undefined,
|
|
506
519
|
"aria-labelledby": ariaLabelledBy,
|
|
507
520
|
...{
|
|
@@ -19,7 +19,7 @@ import { HStack, VStack } from "../Stack/index.js";
|
|
|
19
19
|
import { Icon } from "../Icon/index.js";
|
|
20
20
|
import { TreeList } from "../TreeList/index.js";
|
|
21
21
|
import { useTranslator } from "../i18n/index.js";
|
|
22
|
-
import { isImeKeyEvent } from "../
|
|
22
|
+
import { isImeKeyEvent } from "../utils/ime.js";
|
|
23
23
|
import "../theme/tokens.stylex.js";
|
|
24
24
|
import { spacingVars, typeScaleVars } from "../theme/tokens.stylex.js";
|
|
25
25
|
import { PowerSearchValueEditor } from "./PowerSearchValueEditor.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RadioList.d.ts","sourceRoot":"","sources":["../../src/RadioList/RadioList.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,EAMZ,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAIf,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"RadioList.d.ts","sourceRoot":"","sources":["../../src/RadioList/RadioList.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,EAMZ,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAIf,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAIhD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AAG9C;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,IAAI,GAAG,IAAI,CAAC;AAExC,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,UAAU,EAAE,OAAO,CAAC;IACpB;;;;;OAKG;IACH,kBAAkB,EAAE,OAAO,CAAC;IAC5B,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,EAAE,aAAa,CAAC;IACpB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,eAAO,MAAM,gBAAgB,6CAE5B,CAAC;AAiBF,MAAM,WAAW,cAAe,SAAQ,IAAI,CAC1C,SAAS,CAAC,WAAW,CAAC,EACtB,UAAU,CACX;IACC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC;;;OAGG;IACH,WAAW,CAAC,EAAE,UAAU,GAAG,YAAY,CAAC;IACxC;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;;;;OASG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB;;;;OAIG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,SAAS,CAAC,EACxB,GAAG,EACH,KAAK,EACL,aAAqB,EACrB,WAAW,EACX,KAAK,EACL,QAAQ,EACR,WAAwB,EACxB,UAAkB,EAClB,eAAe,EACf,UAAkB,EAClB,UAAkB,EAClB,IAAW,EACX,MAAM,EACN,YAAY,EACZ,KAAK,EACL,MAAM,EACN,SAAS,EACT,KAAK,EACL,aAAa,EAAE,UAAU,EACzB,QAAQ,EACR,QAAQ,GACT,EAAE,cAAc,qBAwMhB;yBA9Ne,SAAS"}
|
|
@@ -21,6 +21,7 @@ import "../theme/tokens.stylex.js";
|
|
|
21
21
|
import { spacingVars } from "../theme/tokens.stylex.js";
|
|
22
22
|
import { Field } from "../Field/Field.js";
|
|
23
23
|
import { useTooltip } from "../Tooltip/index.js";
|
|
24
|
+
import { useResolvedRequired } from "../hooks/useResolvedRequired.js";
|
|
24
25
|
import { mergeProps } from "../utils/index.js";
|
|
25
26
|
import { themeProps } from "../utils/themeProps.js";
|
|
26
27
|
|
|
@@ -76,6 +77,16 @@ export function RadioList({
|
|
|
76
77
|
const statusMessageID = useId();
|
|
77
78
|
const groupRef = useRef(null);
|
|
78
79
|
|
|
80
|
+
// The radiogroup exposes the *effective* required state so a form-wide
|
|
81
|
+
// `defaultOptionality="required"` is announced even when the group carries no
|
|
82
|
+
// visible indicator. Individual radios keep their native `required` bound to
|
|
83
|
+
// the explicit `isRequired` (via context), so a layout default never switches
|
|
84
|
+
// on browser validation for the group.
|
|
85
|
+
const isEffectivelyRequired = useResolvedRequired({
|
|
86
|
+
isRequired,
|
|
87
|
+
isOptional
|
|
88
|
+
});
|
|
89
|
+
|
|
79
90
|
// Disabled-reason tooltip. Applies to the whole-group disabled state. Disabled
|
|
80
91
|
// controls swallow pointer events, so the tooltip listeners attach to the
|
|
81
92
|
// radiogroup container and the radios stay perceivable via aria-disabled
|
|
@@ -203,7 +214,7 @@ export function RadioList({
|
|
|
203
214
|
onFocus: handleFocus,
|
|
204
215
|
"aria-describedby": [description ? descriptionID : null, status?.message ? statusMessageID : null, showsDisabledMessage ? disabledMessageTooltip.describedBy : null].filter(Boolean).join(' ') || undefined,
|
|
205
216
|
"aria-invalid": status?.type === 'error' ? true : undefined,
|
|
206
|
-
"aria-required":
|
|
217
|
+
"aria-required": isEffectivelyRequired || undefined,
|
|
207
218
|
...mergeProps(themeProps('radio-list', {
|
|
208
219
|
orientation,
|
|
209
220
|
size
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Selector.d.ts","sourceRoot":"","sources":["../../src/Selector/Selector.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,EASZ,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAIf,OAAO,EAAuB,KAAK,QAAQ,EAAC,MAAM,SAAS,CAAC;AAE5D,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,cAAc,CAAC;AAEpD,OAAO,EAML,KAAK,kBAAkB,EACxB,MAAM,UAAU,CAAC;AAGlB,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,mBAAmB,CAAC;AAgBtD,OAAO,KAAK,EAAC,kBAAkB,EAAE,kBAAkB,EAAC,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"Selector.d.ts","sourceRoot":"","sources":["../../src/Selector/Selector.tsx"],"names":[],"mappings":"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"}
|
|
@@ -33,8 +33,9 @@ import { colorVars, sizeVars, spacingVars, radiusVars, durationVars, easeVars, t
|
|
|
33
33
|
import { isOptionData, isDivider, isSection, normalizeOption, getSelectableOptions } from "./utils.js";
|
|
34
34
|
import { useCombobox, useSelectedItemOffset } from "./hooks.js";
|
|
35
35
|
import { useTypeahead } from "../hooks/useTypeahead.js";
|
|
36
|
+
import { useResolvedRequired } from "../hooks/useResolvedRequired.js";
|
|
36
37
|
import { SelectorOption } from "./SelectorOption.js";
|
|
37
|
-
import { getInputARIA, mergeProps } from "../utils/index.js";
|
|
38
|
+
import { getInputARIA, isImeKeyEvent, mergeProps } from "../utils/index.js";
|
|
38
39
|
import { useSize } from "../SizeContext/SizeContext.js";
|
|
39
40
|
import { themeProps } from "../utils/themeProps.js";
|
|
40
41
|
import { focusOutlineStyles } from "../utils/focusOutline.stylex.js";
|
|
@@ -294,6 +295,10 @@ export function Selector(props) {
|
|
|
294
295
|
hasClear: hasClearProp,
|
|
295
296
|
...rest
|
|
296
297
|
} = props;
|
|
298
|
+
const isEffectivelyRequired = useResolvedRequired({
|
|
299
|
+
isRequired,
|
|
300
|
+
isOptional
|
|
301
|
+
});
|
|
297
302
|
const placeholder = placeholderFromProps ?? t('@astryx.selector.placeholder');
|
|
298
303
|
const searchPlaceholder = searchPlaceholderFromProps ?? t('@astryx.selector.searchPlaceholder');
|
|
299
304
|
const hasClear = hasClearProp === true;
|
|
@@ -409,8 +414,10 @@ export function Selector(props) {
|
|
|
409
414
|
return;
|
|
410
415
|
}
|
|
411
416
|
const count = filterOptionsByQuery(selectableItems, nextQuery).length;
|
|
412
|
-
announce(count === 0 ? '
|
|
413
|
-
|
|
417
|
+
announce(count === 0 ? t('@astryx.selector.emptySearchResults') : t('@astryx.selector.resultCount', {
|
|
418
|
+
count
|
|
419
|
+
}));
|
|
420
|
+
}, [announce, selectableItems, t]);
|
|
414
421
|
|
|
415
422
|
// Calculate offset to position selected item over trigger. Explicit
|
|
416
423
|
// placement opts out of the selector-specific overlay behavior and uses the
|
|
@@ -602,6 +609,15 @@ export function Selector(props) {
|
|
|
602
609
|
}
|
|
603
610
|
},
|
|
604
611
|
onKeyDown: e => {
|
|
612
|
+
// An in-progress IME composition uses these same keys (Enter to
|
|
613
|
+
// commit the candidate, Escape/Arrows to navigate the candidate
|
|
614
|
+
// window); the composing keydown fires before compositionend, so
|
|
615
|
+
// without this guard a Korean/Japanese/Chinese user committing a
|
|
616
|
+
// syllable with Enter would instead select the highlighted option.
|
|
617
|
+
// See utils/ime.ts.
|
|
618
|
+
if (isImeKeyEvent(e.nativeEvent)) {
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
605
621
|
// Arrow keys navigate options; Enter selects; Escape closes.
|
|
606
622
|
// Home/End are left to the input for caret movement (APG editable
|
|
607
623
|
// combobox); PageUp/PageDown are the sanctioned substitute for
|
|
@@ -794,7 +810,7 @@ export function Selector(props) {
|
|
|
794
810
|
"aria-activedescendant": !hasSearch && popover.isOpen && highlightedIndex >= 0 ? getItemId(highlightedIndex) : undefined,
|
|
795
811
|
"aria-describedby": ariaDescribedBy,
|
|
796
812
|
"aria-labelledby": ariaLabelledBy,
|
|
797
|
-
"aria-required":
|
|
813
|
+
"aria-required": isEffectivelyRequired ? 'true' : undefined,
|
|
798
814
|
"aria-invalid": status?.type === 'error' ? 'true' : undefined,
|
|
799
815
|
"aria-busy": isBusy || undefined
|
|
800
816
|
// With a disabledMessage the trigger keeps focusability via
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file StatusDot.tsx
|
|
3
|
+
* @input Uses React
|
|
4
|
+
* @output Exports StatusDot component, StatusDotProps, StatusDotVariant types
|
|
5
|
+
* @position Core implementation; consumed by index.ts
|
|
6
|
+
*
|
|
7
|
+
* SYNC: When modified, update these files to stay in sync:
|
|
8
|
+
* - /packages/core/src/StatusDot/StatusDot.doc.mjs (props table, features, implementation notes)
|
|
9
|
+
* - /packages/core/src/StatusDot/StatusDot.test.tsx (tests for new/changed behavior)
|
|
10
|
+
* - /packages/core/src/StatusDot/index.ts (exports if types change)
|
|
11
|
+
* - /apps/storybook/stories/StatusDot.stories.tsx (storybook stories)
|
|
12
|
+
* - /packages/cli/assets/templates/blocks/components/StatusDot/ (showcase blocks)
|
|
13
|
+
*/
|
|
14
|
+
import type { ReactNode } from 'react';
|
|
1
15
|
import type { BaseProps } from '../BaseProps';
|
|
2
16
|
import type { StatusDotVariantMap } from './index';
|
|
3
17
|
/**
|
|
@@ -13,7 +27,8 @@ export interface StatusDotProps extends BaseProps<HTMLSpanElement> {
|
|
|
13
27
|
*/
|
|
14
28
|
variant: StatusDotVariant;
|
|
15
29
|
/**
|
|
16
|
-
* Accessible label describing the status. Required for a11y
|
|
30
|
+
* Accessible label describing the status. Required for a11y — it is the
|
|
31
|
+
* dot's `aria-label`, so the status reaches screen readers without hover.
|
|
17
32
|
*/
|
|
18
33
|
label: string;
|
|
19
34
|
/**
|
|
@@ -27,11 +42,35 @@ export interface StatusDotProps extends BaseProps<HTMLSpanElement> {
|
|
|
27
42
|
* When omitted, no tooltip is rendered.
|
|
28
43
|
*/
|
|
29
44
|
tooltip?: string;
|
|
45
|
+
/**
|
|
46
|
+
* Optional icon to render centered inside the dot. Accepts any ReactNode
|
|
47
|
+
* (typically an SVG icon), painted in the dot's `currentColor` ink. Same
|
|
48
|
+
* contract as `AvatarStatusDot`'s `icon`.
|
|
49
|
+
*
|
|
50
|
+
* By default the dot is a colour-only signal; an icon gives the status a
|
|
51
|
+
* non-colour mark, so use a different icon per status — the same icon on
|
|
52
|
+
* every variant leaves the statuses distinguishable by colour alone
|
|
53
|
+
* (WCAG 2.1 SC 1.4.1). Booleans and empty strings are ignored (safe for
|
|
54
|
+
* `cond && <Icon />`).
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```
|
|
58
|
+
* <StatusDot variant="success" label="Verified" icon={<CheckIcon />} />
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
icon?: ReactNode;
|
|
30
62
|
}
|
|
31
63
|
/**
|
|
32
64
|
* A small colored dot indicator for status display (online/offline, severity, etc).
|
|
33
65
|
*
|
|
34
|
-
* Fixed 8px size.
|
|
66
|
+
* Fixed 8px size. By default the dot conveys status by colour only, which is
|
|
67
|
+
* not accessible in isolation (WCAG 2.1 SC 1.4.1) — treat it as a signal the
|
|
68
|
+
* surrounding UI must make accessible: use it as a binary present/absent
|
|
69
|
+
* signal, pair it with a visible label, pass `icon` so the status carries a
|
|
70
|
+
* non-colour mark, or convey the status accessibly elsewhere. See the usage
|
|
71
|
+
* guidance in the component docs.
|
|
72
|
+
*
|
|
73
|
+
* Renders as a non-focusable `<span>` with `role="img"` and
|
|
35
74
|
* `aria-label` for accessibility. Styles use Astryx theme tokens via StyleX.
|
|
36
75
|
* Wrap your app in `<Theme>` to apply a theme.
|
|
37
76
|
*
|
|
@@ -41,9 +80,10 @@ export interface StatusDotProps extends BaseProps<HTMLSpanElement> {
|
|
|
41
80
|
* <StatusDot variant="error" label="Offline" />
|
|
42
81
|
* <StatusDot variant="success" label="Live" isPulsing />
|
|
43
82
|
* <StatusDot variant="success" label="Online" tooltip="Online" />
|
|
83
|
+
* <StatusDot variant="success" label="Verified" icon={<CheckIcon />} />
|
|
44
84
|
* ```
|
|
45
85
|
*/
|
|
46
|
-
export declare function StatusDot({ variant, label, isPulsing, tooltip, xstyle, className, style, ref, ...props }: StatusDotProps): import("react").JSX.Element;
|
|
86
|
+
export declare function StatusDot({ variant, label, isPulsing, tooltip, icon, xstyle, className, style, ref, ...props }: StatusDotProps): import("react").JSX.Element;
|
|
47
87
|
export declare namespace StatusDot {
|
|
48
88
|
var displayName: string;
|
|
49
89
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StatusDot.d.ts","sourceRoot":"","sources":["../../src/StatusDot/StatusDot.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"StatusDot.d.ts","sourceRoot":"","sources":["../../src/StatusDot/StatusDot.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AAIrC,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAI5C,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,SAAS,CAAC;AAoFjD;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,mBAAmB,CAAC;AAEzD,MAAM,WAAW,cAAe,SAAQ,SAAS,CAAC,eAAe,CAAC;IAChE,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACjC;;OAEG;IACH,OAAO,EAAE,gBAAgB,CAAC;IAC1B;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;;;;;;;;;OAeG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,SAAS,CAAC,EACxB,OAAO,EACP,KAAK,EACL,SAAiB,EACjB,OAAO,EACP,IAAI,EACJ,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,GAAG,KAAK,EACT,EAAE,cAAc,+BAmChB;yBA9Ce,SAAS"}
|