@astryxdesign/core 0.7.6-canary.0eb4eff → 0.7.6-canary.0fa0207
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/Resizable/useResizable.d.ts.map +1 -1
- package/dist/Resizable/useResizable.js +53 -10
- package/dist/Slider/Slider.d.ts.map +1 -1
- package/dist/Slider/Slider.js +8 -0
- package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
- package/dist/Tokenizer/Tokenizer.js +51 -47
- package/dist/Tokenizer/TokenizerBottomSheet.d.ts.map +1 -1
- package/dist/Tokenizer/TokenizerBottomSheet.js +8 -14
- package/package.json +4 -4
- package/src/Field/FieldLabel.spec.md +68 -60
- package/src/HoverCard/HoverCard.spec.md +96 -39
- package/src/InfoTip/InfoTip.spec.md +193 -0
- package/src/Layout/LayoutPanel.spec.md +60 -38
- package/src/Resizable/Resizable.spec.md +41 -33
- package/src/Resizable/useResizable.ts +50 -7
- package/src/SideNav/SideNav.spec.md +8 -8
- package/src/Slider/Slider.spec.md +18 -18
- package/src/Slider/Slider.tsx +8 -0
- package/src/StatusDot/StatusDot.spec.md +77 -54
- package/src/Tokenizer/Tokenizer.tsx +54 -48
- package/src/Tokenizer/TokenizerBottomSheet.tsx +8 -14
- package/src/Tooltip/Tooltip.spec.md +139 -41
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useResizable.d.ts","sourceRoot":"","sources":["../../src/Resizable/useResizable.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"useResizable.d.ts","sourceRoot":"","sources":["../../src/Resizable/useResizable.ts"],"names":[],"mappings":"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"}
|
|
@@ -487,10 +487,14 @@ function useSingleResizable(config) {
|
|
|
487
487
|
// otherwise move the bound under the pointer; the new basis applies once the
|
|
488
488
|
// gesture ends.
|
|
489
489
|
const gestureBasisRef = useRef(null);
|
|
490
|
-
// Only forces the render that releases the frozen basis
|
|
490
|
+
// Only forces the render that ends a gesture: it releases the frozen basis,
|
|
491
|
+
// and its commit writes the size the gesture settled on.
|
|
491
492
|
const [gestureTick, setGestureTick] = useState(0);
|
|
492
493
|
void gestureTick;
|
|
493
494
|
const basis = gestureBasisRef.current ?? liveBasis;
|
|
495
|
+
// The frozen basis also marks a gesture in flight, from `_onResizeStart`
|
|
496
|
+
// until `_onResizeEnd` or `_onResizeCancel`.
|
|
497
|
+
const isGestureActive = gestureBasisRef.current != null;
|
|
494
498
|
const didWarnMinRef = useRef(false);
|
|
495
499
|
const didWarnMaxRef = useRef(false);
|
|
496
500
|
const didWarnDefaultRef = useRef(false);
|
|
@@ -608,18 +612,55 @@ function useSingleResizable(config) {
|
|
|
608
612
|
devWarn('useResizable', `the resolved minimum (${resolvedMin}px) is above the resolved ` + `maximum (${resolvedMax}px). The maximum wins, as it always has.`);
|
|
609
613
|
}
|
|
610
614
|
}, [resolvedMin, resolvedMax]);
|
|
615
|
+
|
|
616
|
+
// The size a gesture in flight has reached, for a region that unmounts
|
|
617
|
+
// before the gesture ends.
|
|
618
|
+
const pendingWriteRef = useRef(null);
|
|
611
619
|
useEffect(() => {
|
|
620
|
+
// Synchronizes the `autoSaveId` entry in localStorage with the size.
|
|
612
621
|
// Nothing is written while the basis is still the temporary stand-in. The
|
|
613
622
|
// size on such a render is a placeholder, and persisting it overwrites the
|
|
614
623
|
// real saved size with a value derived from a basis that was never real
|
|
615
624
|
// (AST-010 Platform support, FR9).
|
|
616
|
-
if (autoSaveId
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
625
|
+
if (!autoSaveId || !isBasisMeasured) {
|
|
626
|
+
pendingWriteRef.current = null;
|
|
627
|
+
return;
|
|
628
|
+
}
|
|
629
|
+
// Nor while a gesture is in flight. A drag commits a new size on every
|
|
630
|
+
// pointer move, and each write reaches every other open document of the
|
|
631
|
+
// origin as a `storage` event.
|
|
632
|
+
if (isGestureActive) {
|
|
633
|
+
pendingWriteRef.current = {
|
|
634
|
+
key: autoSaveId,
|
|
635
|
+
state: {
|
|
636
|
+
size,
|
|
637
|
+
isCollapsed
|
|
638
|
+
}
|
|
639
|
+
};
|
|
640
|
+
return;
|
|
621
641
|
}
|
|
622
|
-
|
|
642
|
+
// A gesture's one write happens here, in the commit that applies its
|
|
643
|
+
// release, not in the handler that ended it: this render is the first to
|
|
644
|
+
// know the final size. A basis that changed mid-gesture applies only at
|
|
645
|
+
// the release and can re-clamp the size (AST-010 FR7), and a move the
|
|
646
|
+
// release arrived before renders together with it. The handler sees
|
|
647
|
+
// neither.
|
|
648
|
+
pendingWriteRef.current = null;
|
|
649
|
+
persistState(autoSaveId, {
|
|
650
|
+
size,
|
|
651
|
+
isCollapsed
|
|
652
|
+
});
|
|
653
|
+
}, [size, isCollapsed, autoSaveId, isBasisMeasured, isGestureActive]);
|
|
654
|
+
|
|
655
|
+
// A region that unmounts mid-gesture never commits a release, so the size
|
|
656
|
+
// the gesture reached is written on the way out.
|
|
657
|
+
useEffect(() => () => {
|
|
658
|
+
const pending = pendingWriteRef.current;
|
|
659
|
+
pendingWriteRef.current = null;
|
|
660
|
+
if (pending != null) {
|
|
661
|
+
persistState(pending.key, pending.state);
|
|
662
|
+
}
|
|
663
|
+
}, []);
|
|
623
664
|
const collapse = useCallback(() => {
|
|
624
665
|
// The already-collapsed guard keeps a repeated call from re-notifying a
|
|
625
666
|
// transition that already happened.
|
|
@@ -683,7 +724,7 @@ function useSingleResizable(config) {
|
|
|
683
724
|
}, [collapsible, collapsedSize, setCollapsed, resolvedMin, resolvedMax, snaps, onSizeChange, onCollapseChange]);
|
|
684
725
|
|
|
685
726
|
// Releasing the frozen basis needs a render to apply whatever the basis
|
|
686
|
-
// became during the gesture.
|
|
727
|
+
// became during the gesture; that render's commit writes the final size.
|
|
687
728
|
const releaseGestureBasis = useCallback(() => {
|
|
688
729
|
if (gestureBasisRef.current != null) {
|
|
689
730
|
gestureBasisRef.current = null;
|
|
@@ -691,7 +732,8 @@ function useSingleResizable(config) {
|
|
|
691
732
|
}
|
|
692
733
|
}, []);
|
|
693
734
|
const onResizeEnd = useCallback(() => {
|
|
694
|
-
// Sizes are already committed during move;
|
|
735
|
+
// Sizes are already committed during move; the basis is held, and the
|
|
736
|
+
// commit that releases it writes the final size to storage.
|
|
695
737
|
releaseGestureBasis();
|
|
696
738
|
}, [releaseGestureBasis]);
|
|
697
739
|
|
|
@@ -699,7 +741,8 @@ function useSingleResizable(config) {
|
|
|
699
741
|
// capture, a handle unmounted mid-drag — is still over. It does not signal a
|
|
700
742
|
// resize end (that is #5297's contract, and the sizes were committed during
|
|
701
743
|
// move anyway), but the basis it froze has to come back, or every later
|
|
702
|
-
// percentage bound stays pinned to the container size at grab time
|
|
744
|
+
// percentage bound stays pinned to the container size at grab time, and the
|
|
745
|
+
// size it reached has to reach storage.
|
|
703
746
|
const onResizeCancel = releaseGestureBasis;
|
|
704
747
|
|
|
705
748
|
// The maximum a handle REPORTS (End uses only a configured maximum). A
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Slider.d.ts","sourceRoot":"","sources":["../../src/Slider/Slider.tsx"],"names":[],"mappings":"AA2CA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAShD,OAAO,EACL,KAAK,mBAAmB,EAEzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AAU9C,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAC3C,mBAAmB,CAAC,cAAc,CAAC,EACnC,UAAU,CACX;IACC,mDAAmD;IACnD,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,8FAA8F;IAC9F,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kDAAkD;IAClD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qDAAqD;IACrD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oDAAoD;IACpD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,oDAAoD;IACpD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,uCAAuC;IACvC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;;OAIG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,uEAAuE;IACvE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gCAAgC;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;IACxC,uEAAuE;IACvE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACxC,6DAA6D;IAC7D,YAAY,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;IAC3C,8DAA8D;IAC9D,KAAK,CAAC,EAAE;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAC,EAAE,CAAC;IAC1C;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oCAAoC;IACpC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,iBAAkB,SAAQ,eAAe;IACxD,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,iEAAiE;IACjE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC;AAED,MAAM,WAAW,gBAAiB,SAAQ,eAAe;IACvD,8CAA8C;IAC9C,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;IAC7C,iEAAiE;IACjE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;IAChD,8CAA8C;IAC9C,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,MAAM,WAAW,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;AAmT/D;;;;;;;;GAQG;AACH,wBAAgB,MAAM,CAAC,EAAC,GAAG,EAAE,GAAG,KAAK,EAAC,EAAE,WAAW,+
|
|
1
|
+
{"version":3,"file":"Slider.d.ts","sourceRoot":"","sources":["../../src/Slider/Slider.tsx"],"names":[],"mappings":"AA2CA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAShD,OAAO,EACL,KAAK,mBAAmB,EAEzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AAU9C,MAAM,WAAW,eAAgB,SAAQ,IAAI,CAC3C,mBAAmB,CAAC,cAAc,CAAC,EACnC,UAAU,CACX;IACC,mDAAmD;IACnD,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd,8FAA8F;IAC9F,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kDAAkD;IAClD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qDAAqD;IACrD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oDAAoD;IACpD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,oDAAoD;IACpD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,uCAAuC;IACvC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;;OAIG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,uEAAuE;IACvE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gCAAgC;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;IACxC,uEAAuE;IACvE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACxC,6DAA6D;IAC7D,YAAY,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,MAAM,CAAC;IAC3C,8DAA8D;IAC9D,KAAK,CAAC,EAAE;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAC,EAAE,CAAC;IAC1C;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oCAAoC;IACpC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,iBAAkB,SAAQ,eAAe;IACxD,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,iEAAiE;IACjE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC;AAED,MAAM,WAAW,gBAAiB,SAAQ,eAAe;IACvD,8CAA8C;IAC9C,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;IAC7C,iEAAiE;IACjE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;IAChD,8CAA8C;IAC9C,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,MAAM,WAAW,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;AAmT/D;;;;;;;;GAQG;AACH,wBAAgB,MAAM,CAAC,EAAC,GAAG,EAAE,GAAG,KAAK,EAAC,EAAE,WAAW,+BAi6BlD;yBAj6Be,MAAM"}
|
package/dist/Slider/Slider.js
CHANGED
|
@@ -529,6 +529,14 @@ export function Slider({
|
|
|
529
529
|
const isCoincident = isRange && values[0] === values[1];
|
|
530
530
|
let thumbIndex = pressedThumbIndex >= 0 ? pressedThumbIndex : getClosestThumb(newVal);
|
|
531
531
|
const parks = isCoincident && (pressedThumbIndex >= 0 || newVal === values[0]);
|
|
532
|
+
// Until the first movement, a parked press is held by the upper thumb,
|
|
533
|
+
// the one drawn over the lower one, wherever it landed: on the thumbs
|
|
534
|
+
// (which the upper thumb covers) or on their shared value elsewhere,
|
|
535
|
+
// such as its mark label. So its pressed paint shows, and a press that
|
|
536
|
+
// never moves leaves focus on the same thumb.
|
|
537
|
+
if (parks && pressedThumbIndex < 0) {
|
|
538
|
+
thumbIndex = 1;
|
|
539
|
+
}
|
|
532
540
|
// The first movement is measured from the pointer itself, not from a
|
|
533
541
|
// mark it pressed (a wide label sits away from its mark's value).
|
|
534
542
|
coincidentDragRef.current = parks ? getValueFromPosition(e.clientX, e.clientY) : null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tokenizer.d.ts","sourceRoot":"","sources":["../../src/Tokenizer/Tokenizer.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,EAYZ,KAAK,SAAS,EAEf,MAAM,OAAO,CAAC;AASf,OAAO,EACL,KAAK,mBAAmB,EAEzB,MAAM,qBAAqB,CAAC;AAQ7B,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AAG9C,OAAO,EAGL,KAAK,WAAW,EAKhB,KAAK,kBAAkB,EACxB,MAAM,UAAU,CAAC;AAIlB,OAAO,EAAiB,KAAK,QAAQ,EAAC,MAAM,SAAS,CAAC;AAWtD,OAAO,KAAK,EAAC,cAAc,EAAE,YAAY,EAAC,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"Tokenizer.d.ts","sourceRoot":"","sources":["../../src/Tokenizer/Tokenizer.tsx"],"names":[],"mappings":"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"}
|
|
@@ -50,6 +50,7 @@ import "../theme/tokens.stylex.js";
|
|
|
50
50
|
import { colorVars, spacingVars, sizeVars, typeScaleVars } from "../theme/tokens.stylex.js";
|
|
51
51
|
import { composeEventHandlers, mergeProps } from "../utils/index.js";
|
|
52
52
|
import { joinAriaIDs } from "../utils/inputAria.js";
|
|
53
|
+
import { isFocusDetached } from "../utils/focusReturn.js";
|
|
53
54
|
import { themeProps } from "../utils/themeProps.js";
|
|
54
55
|
import { useTranslator } from "../i18n/index.js";
|
|
55
56
|
import { useResolvedRequired } from "../hooks/useResolvedRequired.js";
|
|
@@ -506,14 +507,6 @@ export function Tokenizer({
|
|
|
506
507
|
sheetQueryRef.current = query;
|
|
507
508
|
onChangeQuery?.(query);
|
|
508
509
|
}, [onChangeQuery]);
|
|
509
|
-
// Whether the field's control — the inline input or the trigger — holds
|
|
510
|
-
// focus. Kept in a ref by the focus and blur handlers of both, because a
|
|
511
|
-
// control unmounted while focused fires no blur: when a presentation swap
|
|
512
|
-
// removes the focused control (the latch releasing into the popover, or
|
|
513
|
-
// `adaptive` changing while the sheet is closed), the new presentation's
|
|
514
|
-
// control takes the focus over once it has mounted, so focus never lands on
|
|
515
|
-
// the page body (`component:Tokenizer` FR16, `spec:AST-085` FR4).
|
|
516
|
-
const isControlFocusedRef = useRef(false);
|
|
517
510
|
// Set around a focus move the field makes itself — a presentation swap
|
|
518
511
|
// handing focus from one control to the other — so the receiving control
|
|
519
512
|
// does not report it as focus entering from outside.
|
|
@@ -524,35 +517,33 @@ export function Tokenizer({
|
|
|
524
517
|
// entry, and the one focus the trigger then gets — BottomSheet's return
|
|
525
518
|
// focus — is the entry to report.
|
|
526
519
|
const hasReportedFocusRef = useRef(false);
|
|
527
|
-
//
|
|
528
|
-
//
|
|
529
|
-
//
|
|
530
|
-
//
|
|
531
|
-
//
|
|
532
|
-
//
|
|
533
|
-
//
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
if (active != null && (active === inputRef.current || active === triggerRef.current)) {
|
|
540
|
-
isControlFocusedRef.current = true;
|
|
541
|
-
}
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
useEffect(() => {
|
|
545
|
-
if (!isControlFocusedRef.current) {
|
|
520
|
+
// When a presentation swap removes the focused control (the latch
|
|
521
|
+
// releasing into the popover, or `adaptive` changing while the sheet is
|
|
522
|
+
// closed), the new presentation's control takes the focus over, so focus
|
|
523
|
+
// never lands on the page body (`component:Tokenizer` FR16, `spec:AST-085`
|
|
524
|
+
// FR4). Both controls' callback refs own the hand-off
|
|
525
|
+
// (`architecture:react-component-runtime` INV6): the detaching control
|
|
526
|
+
// notes that it held focus — it is still in the document then, so this also
|
|
527
|
+
// covers a control focused before hydration (`hasAutoFocus`), which no focus
|
|
528
|
+
// event reported — and the attaching control takes it.
|
|
529
|
+
const isFocusPendingHandOffRef = useRef(false);
|
|
530
|
+
const handOffFocusRef = useCallback(node => {
|
|
531
|
+
if (node == null) {
|
|
546
532
|
return;
|
|
547
533
|
}
|
|
548
|
-
const
|
|
549
|
-
|
|
550
|
-
|
|
534
|
+
const takesFocus = isFocusPendingHandOffRef.current;
|
|
535
|
+
isFocusPendingHandOffRef.current = false;
|
|
536
|
+
if (takesFocus && isFocusDetached(node.ownerDocument)) {
|
|
537
|
+
isHandingOffFocusRef.current = true;
|
|
538
|
+
node.focus();
|
|
539
|
+
isHandingOffFocusRef.current = false;
|
|
551
540
|
}
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
541
|
+
return () => {
|
|
542
|
+
if (node.ownerDocument.activeElement === node) {
|
|
543
|
+
isFocusPendingHandOffRef.current = true;
|
|
544
|
+
}
|
|
545
|
+
};
|
|
546
|
+
}, []);
|
|
556
547
|
// The trigger's accessible description names the selected tokens: the
|
|
557
548
|
// button's children are tokens whose own content assistive technology
|
|
558
549
|
// leaves out of a button's name (`spec:AST-020` FR1).
|
|
@@ -603,10 +594,30 @@ export function Tokenizer({
|
|
|
603
594
|
focusTrigger: 'always',
|
|
604
595
|
isEnabled: showsDisabledMessage
|
|
605
596
|
});
|
|
597
|
+
// The inline field's wrapper holds every control a swap removes with the
|
|
598
|
+
// input — a token's Remove button, the inline Clear all — so it notes focus
|
|
599
|
+
// anywhere inside it for the hand-off above. It also anchors the
|
|
600
|
+
// disabled-message tooltip, whose handlers are gated internally by
|
|
601
|
+
// isEnabled, so attaching unconditionally is safe.
|
|
602
|
+
const tooltipAnchorRef = disabledMessageTooltip.ref;
|
|
603
|
+
const wrapperCallbackRef = useCallback(el => {
|
|
604
|
+
wrapperRef.current = el;
|
|
605
|
+
tooltipAnchorRef(el);
|
|
606
|
+
if (el == null) {
|
|
607
|
+
return;
|
|
608
|
+
}
|
|
609
|
+
return () => {
|
|
610
|
+
if (el.contains(el.ownerDocument.activeElement)) {
|
|
611
|
+
isFocusPendingHandOffRef.current = true;
|
|
612
|
+
}
|
|
613
|
+
wrapperRef.current = null;
|
|
614
|
+
tooltipAnchorRef(null);
|
|
615
|
+
};
|
|
616
|
+
}, [tooltipAnchorRef]);
|
|
606
617
|
|
|
607
618
|
// The sheet presentation has no input; the public ref reaches the trigger,
|
|
608
619
|
// the control it stands for (`family:input-fields` FR10).
|
|
609
|
-
const triggerMergedRef = useMergedRefs(triggerRef, ref, disabledMessageTooltip.ref);
|
|
620
|
+
const triggerMergedRef = useMergedRefs(triggerRef, ref, disabledMessageTooltip.ref, handOffFocusRef);
|
|
610
621
|
useImperativeHandle(handleRef, () => ({
|
|
611
622
|
focus() {
|
|
612
623
|
(isSheetPresentation ? triggerRef : inputRef).current?.focus();
|
|
@@ -678,7 +689,6 @@ export function Tokenizer({
|
|
|
678
689
|
layer.show();
|
|
679
690
|
}
|
|
680
691
|
if (comingFromOutside) {
|
|
681
|
-
isControlFocusedRef.current = true;
|
|
682
692
|
if (!isHandingOffFocusRef.current) {
|
|
683
693
|
hasReportedFocusRef.current = true;
|
|
684
694
|
onFocus?.(e);
|
|
@@ -692,8 +702,9 @@ export function Tokenizer({
|
|
|
692
702
|
}, [isLayerMode, layer, isFocusInTokenizer, onFocus]);
|
|
693
703
|
const handleBlurCapture = useCallback(e => {
|
|
694
704
|
if (!isFocusInTokenizer(e.relatedTarget)) {
|
|
695
|
-
isControlFocusedRef.current = false;
|
|
696
705
|
hasReportedFocusRef.current = false;
|
|
706
|
+
// Focus left the field: no hand-off is owed any more.
|
|
707
|
+
isFocusPendingHandOffRef.current = false;
|
|
697
708
|
setIsFocusedWithin(false);
|
|
698
709
|
onBlur?.(e);
|
|
699
710
|
if (isLayerMode) {
|
|
@@ -915,13 +926,7 @@ export function Tokenizer({
|
|
|
915
926
|
left: 'anchor(start)'
|
|
916
927
|
};
|
|
917
928
|
const wrapperContent = /*#__PURE__*/_jsxs("div", {
|
|
918
|
-
ref:
|
|
919
|
-
wrapperRef.current = el;
|
|
920
|
-
// Anchor + hover/focus listeners for the disabled-message tooltip.
|
|
921
|
-
// Handlers are gated internally by isEnabled, so attaching
|
|
922
|
-
// unconditionally is safe.
|
|
923
|
-
disabledMessageTooltip.ref(el);
|
|
924
|
-
},
|
|
929
|
+
ref: wrapperCallbackRef,
|
|
925
930
|
role: "group",
|
|
926
931
|
"aria-label": label,
|
|
927
932
|
onClick: handleWrapperClick,
|
|
@@ -971,7 +976,7 @@ export function Tokenizer({
|
|
|
971
976
|
ref: useMergedRefs(inputRef,
|
|
972
977
|
// With `experimental`, the ref type admits the trigger too; in
|
|
973
978
|
// this presentation it receives the input.
|
|
974
|
-
ref),
|
|
979
|
+
ref, handOffFocusRef),
|
|
975
980
|
searchSource: isAtMax ? emptySource : filteredSource,
|
|
976
981
|
value: null,
|
|
977
982
|
onChange: handleAdd,
|
|
@@ -1079,7 +1084,6 @@ export function Tokenizer({
|
|
|
1079
1084
|
// trigger button, and the handler only reads the event.
|
|
1080
1085
|
callerOnClick),
|
|
1081
1086
|
onFocus: event => {
|
|
1082
|
-
isControlFocusedRef.current = true;
|
|
1083
1087
|
// BottomSheet focuses the trigger only after its exit completes;
|
|
1084
1088
|
// that focus is the signal that the retained sheet can leave. If
|
|
1085
1089
|
// the resolution moved to the popover meanwhile, the inline input
|
|
@@ -1106,8 +1110,8 @@ export function Tokenizer({
|
|
|
1106
1110
|
if (isSheetOpen) {
|
|
1107
1111
|
return;
|
|
1108
1112
|
}
|
|
1109
|
-
isControlFocusedRef.current = false;
|
|
1110
1113
|
hasReportedFocusRef.current = false;
|
|
1114
|
+
isFocusPendingHandOffRef.current = false;
|
|
1111
1115
|
onBlur?.(event);
|
|
1112
1116
|
},
|
|
1113
1117
|
onKeyDown: onKeyDown,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TokenizerBottomSheet.d.ts","sourceRoot":"","sources":["../../src/Tokenizer/TokenizerBottomSheet.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAML,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"TokenizerBottomSheet.d.ts","sourceRoot":"","sources":["../../src/Tokenizer/TokenizerBottomSheet.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAML,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAkBf,OAAO,KAAK,EAAC,cAAc,EAAE,YAAY,EAAC,MAAM,oBAAoB,CAAC;AASrE,sFAAsF;AACtF,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAyHzC,MAAM,WAAW,yBAAyB,CAAC,CAAC,SAAS,cAAc;IACjE,iCAAiC;IACjC,MAAM,EAAE,OAAO,CAAC;IAChB,uEAAuE;IACvE,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACxC,kEAAkE;IAClE,aAAa,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC7C;;;;;;;OAOG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;IAC9B,+BAA+B;IAC/B,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,uCAAuC;IACvC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,eAAe,EAAE,SAAS,CAAC;IAC3B;;;;;OAKG;IACH,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE;QAAC,MAAM,EAAE,IAAI,CAAA;KAAC,KAAK,OAAO,CAAC;IACrD,2DAA2D;IAC3D,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE;QAAC,MAAM,EAAE,IAAI,CAAA;KAAC,KAAK,OAAO,CAAC;IACxD,kCAAkC;IAClC,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAED;;;;;;;GAOG;AACH;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,cAAc,EAAE,EAC7D,MAAM,EACN,YAAY,EACZ,aAAa,EACb,KAAK,EACL,GAAG,OAAO,EACX,EAAE,yBAAyB,CAAC,CAAC,CAAC,+BAgC9B;yBAtCe,oBAAoB"}
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
* - /packages/core/src/Tokenizer/Tokenizer.spec.md (FR16–FR24, AR6, PR6)
|
|
27
27
|
*/
|
|
28
28
|
import { useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
|
|
29
|
+
import { flushSync } from 'react-dom';
|
|
29
30
|
import * as stylex from '@stylexjs/stylex';
|
|
30
31
|
import { AlertDialog } from "../AlertDialog/AlertDialog.js";
|
|
31
32
|
import { BottomSheet } from "../BottomSheet/BottomSheet.js";
|
|
@@ -176,8 +177,9 @@ function TokenizerSheetContent({
|
|
|
176
177
|
// trigger's press — so an open sheet with no confirmation pending carries
|
|
177
178
|
// no closed dialog (`architecture:component-style-authoring` INV7). Dialog
|
|
178
179
|
// has an entrance animation and no exit, so a close is its unmount; the
|
|
179
|
-
//
|
|
180
|
-
// gone and the sheet's content can take focus again
|
|
180
|
+
// close handler commits that unmount at once and then places focus itself,
|
|
181
|
+
// now that the modal is gone and the sheet's content can take focus again
|
|
182
|
+
// (`architecture:react-component-runtime` INV2): on the search field
|
|
181
183
|
// after a confirmed clear — the clear is spent, and the search field is
|
|
182
184
|
// where the next selection starts (FR24, `spec:AST-085` FR4) — and back on
|
|
183
185
|
// Clear all after a cancel. A confirmed clear is announced there too — a
|
|
@@ -189,25 +191,17 @@ function TokenizerSheetContent({
|
|
|
189
191
|
// dialog, so FR14 routes the words into it while the sheet is open.
|
|
190
192
|
const [isClearConfirmationOpen, setIsClearConfirmationOpen] = useState(false);
|
|
191
193
|
const clearAllRef = useRef(null);
|
|
192
|
-
const afterConfirmationRef = useRef(null);
|
|
193
194
|
const announce = useAnnounce();
|
|
194
195
|
const closeClearConfirmation = confirmed => {
|
|
195
|
-
|
|
196
|
-
setIsClearConfirmationOpen(false);
|
|
197
|
-
|
|
198
|
-
useEffect(() => {
|
|
199
|
-
if (isClearConfirmationOpen || afterConfirmationRef.current == null) {
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
const destination = afterConfirmationRef.current;
|
|
203
|
-
afterConfirmationRef.current = null;
|
|
204
|
-
if (destination === 'search') {
|
|
196
|
+
// eslint-disable-next-line @eslint-react/dom-no-flush-sync -- the confirmation must be gone before focus moves into the sheet and the words are routed into it
|
|
197
|
+
flushSync(() => setIsClearConfirmationOpen(false));
|
|
198
|
+
if (confirmed) {
|
|
205
199
|
searchRef.current?.focus();
|
|
206
200
|
announce(t('@astryx.tokenizer.allRemoved'));
|
|
207
201
|
} else {
|
|
208
202
|
clearAllRef.current?.focus();
|
|
209
203
|
}
|
|
210
|
-
}
|
|
204
|
+
};
|
|
211
205
|
const selectedIds = useMemo(() => new Set(value.map(v => v.id)), [value]);
|
|
212
206
|
|
|
213
207
|
// ---- sheet session ----
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astryxdesign/core",
|
|
3
|
-
"version": "0.7.6-canary.
|
|
3
|
+
"version": "0.7.6-canary.0fa0207",
|
|
4
4
|
"displayName": "Astryx Core",
|
|
5
5
|
"description": "The component library. Accessible, themeable React components with built-in spacing, dark mode, and StyleX styling.",
|
|
6
6
|
"author": "Meta Open Source",
|
|
@@ -860,9 +860,9 @@
|
|
|
860
860
|
"react-dom": ">=19.0.0"
|
|
861
861
|
},
|
|
862
862
|
"devDependencies": {
|
|
863
|
-
"@astryxdesign/a11y-spec": "0.7.6-canary.
|
|
864
|
-
"@astryxdesign/cli": "0.7.6-canary.
|
|
865
|
-
"@astryxdesign/interaction-harness": "0.7.6-canary.
|
|
863
|
+
"@astryxdesign/a11y-spec": "0.7.6-canary.0fa0207",
|
|
864
|
+
"@astryxdesign/cli": "0.7.6-canary.0fa0207",
|
|
865
|
+
"@astryxdesign/interaction-harness": "0.7.6-canary.0fa0207",
|
|
866
866
|
"@babel/cli": "^7.29.7",
|
|
867
867
|
"@babel/core": "^7.29.7",
|
|
868
868
|
"@babel/preset-react": "^7.29.7",
|