@jsenv/navi 0.27.62 → 0.27.64
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/jsenv_navi.js +305 -291
- package/dist/jsenv_navi.js.map +41 -36
- package/package.json +1 -1
package/dist/jsenv_navi.js
CHANGED
|
@@ -6494,9 +6494,6 @@ const DIMENSION_PROPS = {
|
|
|
6494
6494
|
if (parentBoxFlow === "flex-y" || parentBoxFlow === "inline-flex-y") {
|
|
6495
6495
|
return {
|
|
6496
6496
|
alignSelf: "stretch",
|
|
6497
|
-
// ensure we override any with: 'fit-content' for instance
|
|
6498
|
-
// also useful for ".navi_text_sizer" to inherit the full size
|
|
6499
|
-
width: "100%",
|
|
6500
6497
|
};
|
|
6501
6498
|
}
|
|
6502
6499
|
// Can't use flexGrow — parent is not flex-x
|
|
@@ -6515,9 +6512,6 @@ const DIMENSION_PROPS = {
|
|
|
6515
6512
|
if (parentBoxFlow === "flex-x" || parentBoxFlow === "inline-flex-x") {
|
|
6516
6513
|
return {
|
|
6517
6514
|
alignSelf: "stretch",
|
|
6518
|
-
// ensure we override any with: 'fit-content' for instance
|
|
6519
|
-
// also useful for ".navi_text_sizer" to inherit the full size
|
|
6520
|
-
height: "100%",
|
|
6521
6515
|
};
|
|
6522
6516
|
}
|
|
6523
6517
|
// Can't use flexGrow — parent is not flex-y
|
|
@@ -28315,6 +28309,7 @@ installImportMetaCssBuild(import.meta);const css$J = /* css */`
|
|
|
28315
28309
|
--button-color-disabled: var(--button-color-readonly);
|
|
28316
28310
|
|
|
28317
28311
|
/* Here to be easy to override */
|
|
28312
|
+
display: inline-block; /* So box css can override when wanting to put button inline flex */
|
|
28318
28313
|
font-size: var(--button-font-size);
|
|
28319
28314
|
font-family: var(--button-font-family);
|
|
28320
28315
|
}
|
|
@@ -28347,7 +28342,6 @@ installImportMetaCssBuild(import.meta);const css$J = /* css */`
|
|
|
28347
28342
|
touch-action: manipulation;
|
|
28348
28343
|
user-select: none;
|
|
28349
28344
|
-webkit-tap-highlight-color: var(--navi-control-tap-highlight-color);
|
|
28350
|
-
display: inline-flex;
|
|
28351
28345
|
|
|
28352
28346
|
.navi_button_content {
|
|
28353
28347
|
position: relative;
|
|
@@ -28535,6 +28529,7 @@ installImportMetaCssBuild(import.meta);const css$J = /* css */`
|
|
|
28535
28529
|
}
|
|
28536
28530
|
&[data-icon] {
|
|
28537
28531
|
--button-padding: 0;
|
|
28532
|
+
display: inline-flex;
|
|
28538
28533
|
}
|
|
28539
28534
|
/* cta: call-to-action — special background, border matches background */
|
|
28540
28535
|
&[data-cta] {
|
|
@@ -28623,7 +28618,7 @@ const ButtonUI = props => {
|
|
|
28623
28618
|
});
|
|
28624
28619
|
return jsxs(Box, {
|
|
28625
28620
|
inline: true,
|
|
28626
|
-
|
|
28621
|
+
block: true,
|
|
28627
28622
|
...buttonControlRootProps,
|
|
28628
28623
|
...buttonControlHostProps,
|
|
28629
28624
|
// eslint-disable-next-line react/no-children-prop
|
|
@@ -33658,13 +33653,16 @@ const css$x = /* css */`
|
|
|
33658
33653
|
&::placeholder {
|
|
33659
33654
|
color: var(--x-placeholder-color);
|
|
33660
33655
|
}
|
|
33656
|
+
/* Webkit is putting a slight blue bckground on autofilled input */
|
|
33657
|
+
/* For now we override with out custom background color */
|
|
33658
|
+
/* Ideally we'll later provide a custom data attribute with ability to see styles when autofilled */
|
|
33661
33659
|
&:-webkit-autofill {
|
|
33662
33660
|
-webkit-box-shadow: 0 0 0 1000px var(--x-background-color) inset;
|
|
33663
33661
|
}
|
|
33662
|
+
/* Webkit is putting some nasty styles after automplete that look as follow */
|
|
33663
|
+
/* input:-internal-autofill-selected { color: FieldText !important; } */
|
|
33664
|
+
/* Fortunately we can override it as follow */
|
|
33664
33665
|
&:-internal-autofill-selected {
|
|
33665
|
-
/* Webkit is putting some nasty styles after automplete that look as follow */
|
|
33666
|
-
/* input:-internal-autofill-selected { color: FieldText !important; } */
|
|
33667
|
-
/* Fortunately we can override it as follow */
|
|
33668
33666
|
-webkit-text-fill-color: var(--x-color) !important;
|
|
33669
33667
|
}
|
|
33670
33668
|
|
|
@@ -35123,7 +35121,10 @@ const useClipboardProps = groupRef => {
|
|
|
35123
35121
|
if (!target.matches) {
|
|
35124
35122
|
return false;
|
|
35125
35123
|
}
|
|
35126
|
-
if (!target.matches("
|
|
35124
|
+
if (!target.matches(`[navi-control-host="input"`)) {
|
|
35125
|
+
return false;
|
|
35126
|
+
}
|
|
35127
|
+
if (!target.closest(".navi_duration_part")) {
|
|
35127
35128
|
return false;
|
|
35128
35129
|
}
|
|
35129
35130
|
return true;
|
|
@@ -35541,29 +35542,6 @@ const transferFocus = (containerEl, debugFocus, e, fallback) => {
|
|
|
35541
35542
|
}
|
|
35542
35543
|
};
|
|
35543
35544
|
|
|
35544
|
-
const useCleanup = () => {
|
|
35545
|
-
const cleanupMethodsRef = useRef(null);
|
|
35546
|
-
let cleanupMethods = cleanupMethodsRef.current;
|
|
35547
|
-
if (!cleanupMethods) {
|
|
35548
|
-
const [publish, subscribe, clear] = createPubSub();
|
|
35549
|
-
const cleanup = () => {
|
|
35550
|
-
publish();
|
|
35551
|
-
clear();
|
|
35552
|
-
};
|
|
35553
|
-
const registerCleanup = (cb) => {
|
|
35554
|
-
subscribe(cb);
|
|
35555
|
-
};
|
|
35556
|
-
cleanupMethodsRef.current = cleanupMethods = [registerCleanup, cleanup];
|
|
35557
|
-
}
|
|
35558
|
-
useLayoutEffect(() => {
|
|
35559
|
-
return () => {
|
|
35560
|
-
const [, cleanup] = cleanupMethods;
|
|
35561
|
-
cleanup();
|
|
35562
|
-
};
|
|
35563
|
-
}, []);
|
|
35564
|
-
return cleanupMethods;
|
|
35565
|
-
};
|
|
35566
|
-
|
|
35567
35545
|
installImportMetaCssBuild(import.meta);const css$r = /* css */`
|
|
35568
35546
|
.navi_dialog {
|
|
35569
35547
|
&[open] {
|
|
@@ -35585,14 +35563,12 @@ installImportMetaCssBuild(import.meta);const css$r = /* css */`
|
|
|
35585
35563
|
const Dialog = props => {
|
|
35586
35564
|
import.meta.css = [css$r, "@jsenv/navi/src/popup/dialog.jsx"];
|
|
35587
35565
|
const {
|
|
35588
|
-
|
|
35589
|
-
requestClose,
|
|
35566
|
+
openController,
|
|
35590
35567
|
anchorRef,
|
|
35591
35568
|
children,
|
|
35592
35569
|
scrollTrap,
|
|
35593
35570
|
pointerTrap,
|
|
35594
35571
|
centerInVisualViewport: centerInVisualViewportProp,
|
|
35595
|
-
closeRequestHandler,
|
|
35596
35572
|
...rest
|
|
35597
35573
|
} = props;
|
|
35598
35574
|
const defaultRef = useRef();
|
|
@@ -35601,16 +35577,20 @@ const Dialog = props => {
|
|
|
35601
35577
|
const debugFocus = useDebugFocus();
|
|
35602
35578
|
const autoFocusProps = useAutoFocus(ref, props.autoFocus);
|
|
35603
35579
|
|
|
35604
|
-
//
|
|
35605
|
-
//
|
|
35606
|
-
//
|
|
35607
|
-
|
|
35608
|
-
|
|
35609
|
-
|
|
35580
|
+
// Sync the DOM open and return how to sync it back closed, fresh on every
|
|
35581
|
+
// render so it closes over the latest props (scrollTrap, etc.). The
|
|
35582
|
+
// controller (owned by picker_custom.jsx) decides *when* this runs.
|
|
35583
|
+
// openEffect runs outside of render (triggered by openController.open()), so
|
|
35584
|
+
// it cannot call hooks — cleanup is a plain pub/sub.
|
|
35585
|
+
openController.openEffect = e => {
|
|
35586
|
+
const dialogEl = ref.current;
|
|
35587
|
+
if (!dialogEl) {
|
|
35588
|
+
return undefined;
|
|
35589
|
+
}
|
|
35590
|
+
const [cleanup, addCleanup] = createPubSub(true);
|
|
35610
35591
|
const anchor = anchorRef?.current ?? null;
|
|
35611
35592
|
const effectiveAnchor = anchor || document.documentElement;
|
|
35612
35593
|
debugPopup(`"${e.type}" on ${getElementSignature(e.target)} -> openDialog`);
|
|
35613
|
-
const dialogEl = ref.current;
|
|
35614
35594
|
const {
|
|
35615
35595
|
width,
|
|
35616
35596
|
height
|
|
@@ -35658,22 +35638,15 @@ const Dialog = props => {
|
|
|
35658
35638
|
dialogEl.style.removeProperty("--dialog-top-inset");
|
|
35659
35639
|
});
|
|
35660
35640
|
}
|
|
35661
|
-
|
|
35662
|
-
|
|
35663
|
-
|
|
35664
|
-
|
|
35665
|
-
|
|
35666
|
-
|
|
35667
|
-
|
|
35668
|
-
|
|
35669
|
-
|
|
35670
|
-
markAutofocusRestoreOnClose(dialogEl);
|
|
35671
|
-
dialogEl.close();
|
|
35672
|
-
cleanup();
|
|
35673
|
-
openedRef.current = false;
|
|
35674
|
-
dispatchCustomEvent(dialogEl, "navi_close", {
|
|
35675
|
-
event: e
|
|
35676
|
-
});
|
|
35641
|
+
// Picker's openController.open() reads this back synchronously right
|
|
35642
|
+
// after openEffect() returns (see picker_custom.jsx useOpenController).
|
|
35643
|
+
e.detail.focusedBeforeOpen = focusedBeforeOpen;
|
|
35644
|
+
return () => {
|
|
35645
|
+
debugPopup(`"${e.type}" on ${getElementSignature(e.target)} -> closeDialog`);
|
|
35646
|
+
markAutofocusRestoreOnClose(dialogEl);
|
|
35647
|
+
dialogEl.close();
|
|
35648
|
+
cleanup();
|
|
35649
|
+
};
|
|
35677
35650
|
};
|
|
35678
35651
|
return jsx(Box, {
|
|
35679
35652
|
...rest,
|
|
@@ -35691,58 +35664,17 @@ const Dialog = props => {
|
|
|
35691
35664
|
const rect = ref.current.getBoundingClientRect();
|
|
35692
35665
|
const isBackdrop = e.clientX < rect.left || e.clientX > rect.right || e.clientY < rect.top || e.clientY > rect.bottom;
|
|
35693
35666
|
if (isBackdrop) {
|
|
35694
|
-
requestClose(e, {
|
|
35667
|
+
openController.requestClose(e, {
|
|
35695
35668
|
isCancel: true
|
|
35696
35669
|
});
|
|
35697
35670
|
}
|
|
35698
35671
|
}
|
|
35699
35672
|
},
|
|
35700
35673
|
onCancel: e => {
|
|
35701
|
-
requestClose(e, {
|
|
35674
|
+
openController.requestClose(e, {
|
|
35702
35675
|
isCancel: true
|
|
35703
35676
|
});
|
|
35704
35677
|
},
|
|
35705
|
-
onnavi_request_open: e => {
|
|
35706
|
-
const dialogEl = ref.current;
|
|
35707
|
-
if (!dialogEl) {
|
|
35708
|
-
return;
|
|
35709
|
-
}
|
|
35710
|
-
if (openedRef.current) {
|
|
35711
|
-
return;
|
|
35712
|
-
}
|
|
35713
|
-
open(e);
|
|
35714
|
-
},
|
|
35715
|
-
onnavi_request_close: e => {
|
|
35716
|
-
const dialogEl = ref.current;
|
|
35717
|
-
if (!dialogEl) {
|
|
35718
|
-
return;
|
|
35719
|
-
}
|
|
35720
|
-
if (!openedRef.current) {
|
|
35721
|
-
return;
|
|
35722
|
-
}
|
|
35723
|
-
if (closeRequestHandler) {
|
|
35724
|
-
let denied = false;
|
|
35725
|
-
const closePermission = {
|
|
35726
|
-
deny: () => {
|
|
35727
|
-
denied = true;
|
|
35728
|
-
},
|
|
35729
|
-
allow: () => {
|
|
35730
|
-
denied = false;
|
|
35731
|
-
}
|
|
35732
|
-
};
|
|
35733
|
-
closeRequestHandler(e, closePermission);
|
|
35734
|
-
if (denied) {
|
|
35735
|
-
if (e.type === "cancel") {
|
|
35736
|
-
e.preventDefault();
|
|
35737
|
-
}
|
|
35738
|
-
closePermission.allow = () => {
|
|
35739
|
-
close(e);
|
|
35740
|
-
};
|
|
35741
|
-
return;
|
|
35742
|
-
}
|
|
35743
|
-
}
|
|
35744
|
-
close(e);
|
|
35745
|
-
},
|
|
35746
35678
|
children: children
|
|
35747
35679
|
});
|
|
35748
35680
|
};
|
|
@@ -35773,7 +35705,7 @@ installImportMetaCssBuild(import.meta);const css$q = /* css */`
|
|
|
35773
35705
|
const Popover = props => {
|
|
35774
35706
|
import.meta.css = [css$q, "@jsenv/navi/src/popup/popover.jsx"];
|
|
35775
35707
|
const {
|
|
35776
|
-
|
|
35708
|
+
openController,
|
|
35777
35709
|
anchorRef,
|
|
35778
35710
|
scrollTrap,
|
|
35779
35711
|
pointerTrap,
|
|
@@ -35785,7 +35717,6 @@ const Popover = props => {
|
|
|
35785
35717
|
positionYFixed,
|
|
35786
35718
|
spacing = 0,
|
|
35787
35719
|
viewportSpacing = 0,
|
|
35788
|
-
closeRequestHandler,
|
|
35789
35720
|
...rest
|
|
35790
35721
|
} = props;
|
|
35791
35722
|
const defaultRef = useRef();
|
|
@@ -35796,14 +35727,18 @@ const Popover = props => {
|
|
|
35796
35727
|
const debugFocus = useDebugFocus();
|
|
35797
35728
|
const autoFocusProps = useAutoFocus(ref, props.autoFocus);
|
|
35798
35729
|
|
|
35799
|
-
//
|
|
35800
|
-
//
|
|
35801
|
-
//
|
|
35802
|
-
|
|
35803
|
-
|
|
35804
|
-
|
|
35805
|
-
debugPopup(e, `openPopover()`);
|
|
35730
|
+
// Sync the DOM open and return how to sync it back closed, fresh on every
|
|
35731
|
+
// render so it closes over the latest props (scrollTrap, etc.). The
|
|
35732
|
+
// controller (owned by picker_custom.jsx) decides *when* this runs.
|
|
35733
|
+
// openEffect runs outside of render (triggered by openController.open()), so
|
|
35734
|
+
// it cannot call hooks — cleanup is a plain pub/sub.
|
|
35735
|
+
openController.openEffect = e => {
|
|
35806
35736
|
const popoverEl = ref.current;
|
|
35737
|
+
if (!popoverEl) {
|
|
35738
|
+
return undefined;
|
|
35739
|
+
}
|
|
35740
|
+
const [cleanup, addCleanup] = createPubSub(true);
|
|
35741
|
+
debugPopup(e, `openPopover()`);
|
|
35807
35742
|
const focusedBeforeOpen = getFocusedBeforeTransfer(e);
|
|
35808
35743
|
popoverEl.showPopover();
|
|
35809
35744
|
transferFocus(popoverEl, debugFocus, e, focusedBeforeOpen);
|
|
@@ -35879,22 +35814,15 @@ const Popover = props => {
|
|
|
35879
35814
|
addCleanup(() => {
|
|
35880
35815
|
rectEffect.disconnect();
|
|
35881
35816
|
});
|
|
35882
|
-
|
|
35883
|
-
|
|
35884
|
-
|
|
35885
|
-
|
|
35886
|
-
|
|
35887
|
-
|
|
35888
|
-
|
|
35889
|
-
|
|
35890
|
-
|
|
35891
|
-
markAutofocusRestoreOnClose(popoverEl);
|
|
35892
|
-
popoverEl.hidePopover();
|
|
35893
|
-
cleanup();
|
|
35894
|
-
openedRef.current = false;
|
|
35895
|
-
dispatchCustomEvent(popoverEl, "navi_close", {
|
|
35896
|
-
event: e
|
|
35897
|
-
});
|
|
35817
|
+
// Picker's openController.open() reads this back synchronously right
|
|
35818
|
+
// after openEffect() returns (see picker_custom.jsx useOpenController).
|
|
35819
|
+
e.detail.focusedBeforeOpen = focusedBeforeOpen;
|
|
35820
|
+
return () => {
|
|
35821
|
+
debugPopup(e, `closePopover()`);
|
|
35822
|
+
markAutofocusRestoreOnClose(popoverEl);
|
|
35823
|
+
popoverEl.hidePopover();
|
|
35824
|
+
cleanup();
|
|
35825
|
+
};
|
|
35898
35826
|
};
|
|
35899
35827
|
return jsxs(Box, {
|
|
35900
35828
|
id: id,
|
|
@@ -35904,44 +35832,6 @@ const Popover = props => {
|
|
|
35904
35832
|
ref: ref,
|
|
35905
35833
|
baseClassName: "navi_popover",
|
|
35906
35834
|
pseudoClasses: POPOVER_PSEUDO_CLASSES,
|
|
35907
|
-
onnavi_request_open: e => {
|
|
35908
|
-
const popoverEl = ref.current;
|
|
35909
|
-
if (!popoverEl) {
|
|
35910
|
-
return;
|
|
35911
|
-
}
|
|
35912
|
-
if (openedRef.current) {
|
|
35913
|
-
return;
|
|
35914
|
-
}
|
|
35915
|
-
open(e);
|
|
35916
|
-
},
|
|
35917
|
-
onnavi_request_close: e => {
|
|
35918
|
-
const popoverEl = ref.current;
|
|
35919
|
-
if (!popoverEl) {
|
|
35920
|
-
return;
|
|
35921
|
-
}
|
|
35922
|
-
if (!openedRef.current) {
|
|
35923
|
-
return;
|
|
35924
|
-
}
|
|
35925
|
-
if (closeRequestHandler) {
|
|
35926
|
-
let denied = false;
|
|
35927
|
-
const closePermission = {
|
|
35928
|
-
deny: () => {
|
|
35929
|
-
denied = true;
|
|
35930
|
-
},
|
|
35931
|
-
allow: () => {
|
|
35932
|
-
denied = false;
|
|
35933
|
-
}
|
|
35934
|
-
};
|
|
35935
|
-
closeRequestHandler(e, closePermission);
|
|
35936
|
-
if (denied) {
|
|
35937
|
-
closePermission.allow = () => {
|
|
35938
|
-
close(e);
|
|
35939
|
-
};
|
|
35940
|
-
return;
|
|
35941
|
-
}
|
|
35942
|
-
}
|
|
35943
|
-
close(e);
|
|
35944
|
-
},
|
|
35945
35835
|
children: [jsx("div", {
|
|
35946
35836
|
className: "navi_popover_backdrop",
|
|
35947
35837
|
"aria-hidden": "true",
|
|
@@ -35953,7 +35843,7 @@ const Popover = props => {
|
|
|
35953
35843
|
e.preventDefault();
|
|
35954
35844
|
return;
|
|
35955
35845
|
}
|
|
35956
|
-
requestClose(e, {
|
|
35846
|
+
openController.requestClose(e, {
|
|
35957
35847
|
isCancel: true
|
|
35958
35848
|
});
|
|
35959
35849
|
}
|
|
@@ -36220,6 +36110,11 @@ const PickerCustom = props => {
|
|
|
36220
36110
|
ref,
|
|
36221
36111
|
mode: modeProp
|
|
36222
36112
|
} = props;
|
|
36113
|
+
// Resolve the id the same way useControlProps does (own id > Field's id > generated id)
|
|
36114
|
+
// before computing popupId below, so two Pickers without an explicit id never collide.
|
|
36115
|
+
const idDefault = useId();
|
|
36116
|
+
const controlId = useContext(ControlIdContext);
|
|
36117
|
+
props.id = props.id || controlId || idDefault;
|
|
36223
36118
|
// Freeze the mode for the lifetime of an opening: compute it when closed,
|
|
36224
36119
|
// keep it stable while open so a screen resize mid-session doesn't switch
|
|
36225
36120
|
// between Popover and Dialog.
|
|
@@ -36259,7 +36154,6 @@ const PickerCustom = props => {
|
|
|
36259
36154
|
// In "dialog" mode, enterExpanded() pushes a history entry so the back button closes.
|
|
36260
36155
|
// In "popover" mode, it replaces the current history state (no history entry added).
|
|
36261
36156
|
const pickerNavType = mode === "dialog" ? "push" : "replace";
|
|
36262
|
-
const expandedRef = useRef(false);
|
|
36263
36157
|
const [expanded, enterExpanded, leaveExpanded] = useNavState(popupId, {
|
|
36264
36158
|
type: pickerNavType,
|
|
36265
36159
|
// onLeave fires only when the state key disappears externally (back button/gesture most of the time).
|
|
@@ -36271,95 +36165,108 @@ const PickerCustom = props => {
|
|
|
36271
36165
|
});
|
|
36272
36166
|
}
|
|
36273
36167
|
});
|
|
36274
|
-
// expandedRef tracks actual open/close state, updated only by onOpen/onClose.
|
|
36275
|
-
// NOT synced to expanded on every render so the useLayoutEffect guard below works.
|
|
36276
|
-
const valueAtOpenRef = useRef(null);
|
|
36277
|
-
const activeElementAtOpenRef = useRef(null);
|
|
36278
|
-
const onOpen = e => {
|
|
36279
|
-
expandedRef.current = true;
|
|
36280
|
-
enterExpanded();
|
|
36281
|
-
const focusedBeforeOpen = e.detail.focusedBeforeOpen;
|
|
36282
|
-
activeElementAtOpenRef.current = focusedBeforeOpen;
|
|
36283
|
-
debugFocus(e, "picked opened, store element focused", focusedBeforeOpen);
|
|
36284
|
-
const valueAtOpen = getPickerInputUIState(ref.current);
|
|
36285
|
-
valueAtOpenRef.current = valueAtOpen;
|
|
36286
|
-
debugPopup(e, `picker opened, store value at open`, valueAtOpen);
|
|
36287
|
-
};
|
|
36288
|
-
const restoreFocus = e => {
|
|
36289
|
-
const activeElementAtOpen = activeElementAtOpenRef.current;
|
|
36290
|
-
activeElementAtOpenRef.current = null;
|
|
36291
|
-
const focusoutEvent = findEvent(e, "focusout");
|
|
36292
|
-
if (focusoutEvent) {
|
|
36293
|
-
debugFocus(e, `closed by focusout -> let focus go away`);
|
|
36294
|
-
return;
|
|
36295
|
-
}
|
|
36296
|
-
const mousedownEvent = findEvent(e, "mousedown");
|
|
36297
|
-
if (mousedownEvent) {
|
|
36298
|
-
debugFocus(e, "closed by mousedown -> prevent browser focus (mousedown.preventDefault())");
|
|
36299
|
-
mousedownEvent.preventDefault();
|
|
36300
|
-
}
|
|
36301
|
-
debugFocus(e, `restore focus to previously focused element`, activeElementAtOpen);
|
|
36302
|
-
activeElementAtOpen.focus({
|
|
36303
|
-
preventScroll: true
|
|
36304
|
-
});
|
|
36305
|
-
return;
|
|
36306
|
-
};
|
|
36307
|
-
const onClose = e => {
|
|
36308
|
-
const mousedownEvent = findEvent(e, "mousedown");
|
|
36309
|
-
if (mousedownEvent) {
|
|
36310
|
-
debugPopup(e, `closed by mousedown -> disable next click`);
|
|
36311
|
-
disableClickFor();
|
|
36312
|
-
} else {
|
|
36313
|
-
const spaceEvent = findEvent(e, e => e.type === "keydown" && e.key === " ");
|
|
36314
|
-
if (spaceEvent) {
|
|
36315
|
-
// space would trigger a click on the picker button causing it to re-open immediatly after closing
|
|
36316
|
-
debugPopup(e, `closed by space key -> prevent browser click`);
|
|
36317
|
-
// browser won't try to dispatch click
|
|
36318
|
-
// and our "space_to_open" will see e.defaultPrevented too and won't try to open picker
|
|
36319
|
-
spaceEvent.preventDefault();
|
|
36320
|
-
}
|
|
36321
|
-
}
|
|
36322
|
-
expandedRef.current = false;
|
|
36323
|
-
leaveExpanded({
|
|
36324
|
-
isBack: e.detail.isCancel
|
|
36325
|
-
});
|
|
36326
|
-
// Reset so the next opening re-evaluates screen size
|
|
36327
|
-
defaultModeRef.current = null;
|
|
36328
|
-
restoreFocus(e);
|
|
36329
|
-
};
|
|
36330
36168
|
const disableClickFor = useIgnoreClickForMousedown(ref, e => {
|
|
36331
36169
|
debugPopup(e, `click ignored`);
|
|
36332
36170
|
});
|
|
36171
|
+
// openController centralizes open/close decision-making (validation,
|
|
36172
|
+
// focus and value bookkeeping) for the picker. The returned
|
|
36173
|
+
// { onRequestClose, onClose } pair is the picker's reaction to close
|
|
36174
|
+
// requests — see createOpenController below for the full contract.
|
|
36175
|
+
const openController = useOpenController(openEvent => {
|
|
36176
|
+
enterExpanded();
|
|
36177
|
+
const focusedBeforeOpen = openEvent.detail.focusedBeforeOpen;
|
|
36178
|
+
debugFocus(openEvent, "picked opened, store element focused", focusedBeforeOpen);
|
|
36179
|
+
const valueAtOpen = getPickerInputUIState(ref.current);
|
|
36180
|
+
debugPopup(openEvent, `picker opened, store value at open`, valueAtOpen);
|
|
36181
|
+
return {
|
|
36182
|
+
onRequestClose: requestCloseEvent => {
|
|
36183
|
+
if (requestCloseEvent.detail.isCancel) {
|
|
36184
|
+
// Cancelling always succeeds — nothing to validate.
|
|
36185
|
+
return;
|
|
36186
|
+
}
|
|
36187
|
+
const pickerEl = ref.current;
|
|
36188
|
+
const inputEl = getPickerInput(pickerEl);
|
|
36189
|
+
dispatchRequestAction(inputEl, {
|
|
36190
|
+
event: requestCloseEvent,
|
|
36191
|
+
name: "picker request close",
|
|
36192
|
+
prevented: () => {
|
|
36193
|
+
requestCloseEvent.preventDefault();
|
|
36194
|
+
},
|
|
36195
|
+
// Always report validation when the picker tries to close so the
|
|
36196
|
+
// user sees what is wrong, even if the picker has no action prop.
|
|
36197
|
+
reportOnInvalid: true,
|
|
36198
|
+
onInvalid: () => {
|
|
36199
|
+
requestCloseEvent.preventDefault();
|
|
36200
|
+
}
|
|
36201
|
+
});
|
|
36202
|
+
},
|
|
36203
|
+
onClose: closeEvent => {
|
|
36204
|
+
if (closeEvent.detail.isCancel) {
|
|
36205
|
+
const pickerEl = ref.current;
|
|
36206
|
+
const inputEl = getPickerInput(pickerEl);
|
|
36207
|
+
debugPopup(closeEvent, `picker cancel, restoring value at open ${JSON.stringify(valueAtOpen)}`);
|
|
36208
|
+
dispatchRequestSetUIState(inputEl, valueAtOpen, {
|
|
36209
|
+
event: closeEvent
|
|
36210
|
+
});
|
|
36211
|
+
}
|
|
36212
|
+
{
|
|
36213
|
+
const mousedownEvent = findEvent(closeEvent, "mousedown");
|
|
36214
|
+
if (mousedownEvent) {
|
|
36215
|
+
debugPopup(closeEvent, `closed by mousedown -> disable next click`);
|
|
36216
|
+
disableClickFor();
|
|
36217
|
+
} else {
|
|
36218
|
+
const spaceEvent = findEvent(closeEvent, e => e.type === "keydown" && e.key === " ");
|
|
36219
|
+
if (spaceEvent) {
|
|
36220
|
+
// space would trigger a click on the picker button causing it to re-open immediatly after closing
|
|
36221
|
+
debugPopup(closeEvent, `closed by space key -> prevent browser click`);
|
|
36222
|
+
// browser won't try to dispatch click
|
|
36223
|
+
// and our "space_to_open" will see e.defaultPrevented too and won't try to open picker
|
|
36224
|
+
spaceEvent.preventDefault();
|
|
36225
|
+
}
|
|
36226
|
+
}
|
|
36227
|
+
}
|
|
36228
|
+
{
|
|
36229
|
+
const focusoutEvent = findEvent(closeEvent, "focusout");
|
|
36230
|
+
if (focusoutEvent) {
|
|
36231
|
+
debugFocus(closeEvent, `closed by focusout -> let focus go away`);
|
|
36232
|
+
} else {
|
|
36233
|
+
const mousedownEvent = findEvent(closeEvent, "mousedown");
|
|
36234
|
+
if (mousedownEvent) {
|
|
36235
|
+
debugFocus(closeEvent, "closed by mousedown -> prevent browser focus (mousedown.preventDefault())");
|
|
36236
|
+
mousedownEvent.preventDefault();
|
|
36237
|
+
}
|
|
36238
|
+
debugFocus(closeEvent, `restore focus to previously focused element`, focusedBeforeOpen);
|
|
36239
|
+
focusedBeforeOpen.focus({
|
|
36240
|
+
preventScroll: true
|
|
36241
|
+
});
|
|
36242
|
+
}
|
|
36243
|
+
}
|
|
36244
|
+
leaveExpanded({
|
|
36245
|
+
isBack: closeEvent.detail.isCancel
|
|
36246
|
+
});
|
|
36247
|
+
// Reset so the next opening re-evaluates screen size
|
|
36248
|
+
defaultModeRef.current = null;
|
|
36249
|
+
}
|
|
36250
|
+
};
|
|
36251
|
+
});
|
|
36333
36252
|
const requestOpen = (e, detail) => {
|
|
36334
36253
|
// scroll <button> of the picker into view when opening it
|
|
36335
36254
|
const pickerEl = ref.current;
|
|
36336
36255
|
pickerEl.scrollIntoView({
|
|
36337
36256
|
block: "nearest"
|
|
36338
36257
|
});
|
|
36339
|
-
|
|
36340
|
-
return dispatchCustomEvent(popupEl, "navi_request_open", {
|
|
36341
|
-
event: e,
|
|
36342
|
-
...detail
|
|
36343
|
-
});
|
|
36344
|
-
};
|
|
36345
|
-
const requestClose = (e = new CustomEvent("programmatic", {
|
|
36346
|
-
detail: {}
|
|
36347
|
-
}), detail) => {
|
|
36348
|
-
const popupEl = popupRef.current;
|
|
36349
|
-
return dispatchCustomEvent(popupEl, "navi_request_close", {
|
|
36350
|
-
event: e,
|
|
36351
|
-
...detail
|
|
36352
|
-
});
|
|
36258
|
+
openController.open(e, detail);
|
|
36353
36259
|
};
|
|
36260
|
+
const requestClose = openController.requestClose;
|
|
36354
36261
|
const open = Boolean(expanded);
|
|
36355
36262
|
useLayoutEffect(() => {
|
|
36356
36263
|
if (open === undefined) {
|
|
36357
36264
|
return;
|
|
36358
36265
|
}
|
|
36359
36266
|
// Skip when the popup is already in the desired state.
|
|
36360
|
-
//
|
|
36361
|
-
// so it is the authoritative check against feedback loops.
|
|
36362
|
-
if (open ===
|
|
36267
|
+
// openController.opened tracks actual open/close (updated by onopen/onclose,
|
|
36268
|
+
// not by renders) so it is the authoritative check against feedback loops.
|
|
36269
|
+
if (open === openController.opened) {
|
|
36363
36270
|
return;
|
|
36364
36271
|
}
|
|
36365
36272
|
// open_prop_change means the parent is driving the open state directly
|
|
@@ -36394,7 +36301,7 @@ const PickerCustom = props => {
|
|
|
36394
36301
|
// requestClose(e);
|
|
36395
36302
|
},
|
|
36396
36303
|
"onnavi_request_open": e => {
|
|
36397
|
-
if (
|
|
36304
|
+
if (openController.opened) {
|
|
36398
36305
|
return;
|
|
36399
36306
|
}
|
|
36400
36307
|
requestInteraction({
|
|
@@ -36409,7 +36316,9 @@ const PickerCustom = props => {
|
|
|
36409
36316
|
requestInteraction({
|
|
36410
36317
|
event: e,
|
|
36411
36318
|
allowed: () => {
|
|
36412
|
-
requestClose(e
|
|
36319
|
+
requestClose(e, {
|
|
36320
|
+
isCancel: e.detail.isCancel
|
|
36321
|
+
});
|
|
36413
36322
|
}
|
|
36414
36323
|
});
|
|
36415
36324
|
},
|
|
@@ -36420,41 +36329,7 @@ const PickerCustom = props => {
|
|
|
36420
36329
|
});
|
|
36421
36330
|
Object.assign(popupProps, {
|
|
36422
36331
|
anchorRef: props.ref,
|
|
36423
|
-
|
|
36424
|
-
closeRequestHandler: (requestCloseEvent, closePermission) => {
|
|
36425
|
-
const isCancel = requestCloseEvent.detail.isCancel;
|
|
36426
|
-
if (isCancel) {
|
|
36427
|
-
const pickerEl = ref.current;
|
|
36428
|
-
const inputEl = getPickerInput(pickerEl);
|
|
36429
|
-
const valueAtOpen = valueAtOpenRef.current;
|
|
36430
|
-
debugPopup(requestCloseEvent, `picker cancel, restoring value at open ${JSON.stringify(valueAtOpen)}`);
|
|
36431
|
-
dispatchRequestSetUIState(inputEl, valueAtOpen, {
|
|
36432
|
-
event: requestCloseEvent
|
|
36433
|
-
});
|
|
36434
|
-
return;
|
|
36435
|
-
}
|
|
36436
|
-
const pickerEl = ref.current;
|
|
36437
|
-
const inputEl = getPickerInput(pickerEl);
|
|
36438
|
-
dispatchRequestAction(inputEl, {
|
|
36439
|
-
event: requestCloseEvent,
|
|
36440
|
-
name: "picker close",
|
|
36441
|
-
prevented: () => {
|
|
36442
|
-
closePermission.deny();
|
|
36443
|
-
},
|
|
36444
|
-
// Always report validation when the picker tries to close so the
|
|
36445
|
-
// user sees what is wrong, even if the picker has no action prop.
|
|
36446
|
-
reportOnInvalid: true,
|
|
36447
|
-
onInvalid: () => {
|
|
36448
|
-
closePermission.deny();
|
|
36449
|
-
}
|
|
36450
|
-
});
|
|
36451
|
-
},
|
|
36452
|
-
onnavi_open: e => {
|
|
36453
|
-
onOpen(e);
|
|
36454
|
-
},
|
|
36455
|
-
onnavi_close: e => {
|
|
36456
|
-
onClose(e);
|
|
36457
|
-
}
|
|
36332
|
+
openController
|
|
36458
36333
|
});
|
|
36459
36334
|
{
|
|
36460
36335
|
const onKeyDownShortcuts = createOnKeyDownForShortcuts({
|
|
@@ -36511,7 +36386,7 @@ const PickerCustom = props => {
|
|
|
36511
36386
|
};
|
|
36512
36387
|
},
|
|
36513
36388
|
"escape": e => {
|
|
36514
|
-
if (!
|
|
36389
|
+
if (!openController.opened) {
|
|
36515
36390
|
return null;
|
|
36516
36391
|
}
|
|
36517
36392
|
return {
|
|
@@ -36535,7 +36410,7 @@ const PickerCustom = props => {
|
|
|
36535
36410
|
if (isWithinPopup(e.target)) {
|
|
36536
36411
|
return null;
|
|
36537
36412
|
}
|
|
36538
|
-
if (
|
|
36413
|
+
if (openController.opened) {
|
|
36539
36414
|
return {
|
|
36540
36415
|
name: "mousedown to close picker",
|
|
36541
36416
|
allowed: () => requestClose(e, {
|
|
@@ -36631,8 +36506,7 @@ const PickerContentInsidePopover = props => {
|
|
|
36631
36506
|
name: "blur",
|
|
36632
36507
|
category: "interaction",
|
|
36633
36508
|
allowed: () => {
|
|
36634
|
-
|
|
36635
|
-
event: e,
|
|
36509
|
+
popupProps.openController.requestClose(e, {
|
|
36636
36510
|
isCancel: true
|
|
36637
36511
|
});
|
|
36638
36512
|
}
|
|
@@ -36657,9 +36531,7 @@ const PickerContentInsidePopover = props => {
|
|
|
36657
36531
|
if (e.button !== 0) {
|
|
36658
36532
|
return;
|
|
36659
36533
|
}
|
|
36660
|
-
|
|
36661
|
-
dispatchCustomEvent(popupEl, "navi_request_close", {
|
|
36662
|
-
event: e,
|
|
36534
|
+
popupProps.openController.requestClose(e, {
|
|
36663
36535
|
isCancel: true
|
|
36664
36536
|
});
|
|
36665
36537
|
},
|
|
@@ -36744,6 +36616,142 @@ const useIgnoreClickForMousedown = (elementRef, onIgnore) => {
|
|
|
36744
36616
|
return disableClickFor;
|
|
36745
36617
|
};
|
|
36746
36618
|
|
|
36619
|
+
// Created once per picker instance: openHandler is wrapped in a stable callback
|
|
36620
|
+
// so the controller identity never changes across renders, even though
|
|
36621
|
+
// Dialog/Popover read fresh closures (scrollTrap, etc.) via
|
|
36622
|
+
// openController.openEffect on every render.
|
|
36623
|
+
const useOpenController = openHandler => {
|
|
36624
|
+
const stableOpenHandler = useStableCallback(openHandler);
|
|
36625
|
+
const controllerRef = useRef(null);
|
|
36626
|
+
if (!controllerRef.current) {
|
|
36627
|
+
controllerRef.current = createOpenController(stableOpenHandler);
|
|
36628
|
+
}
|
|
36629
|
+
// Unmount safety net: if Dialog/Popover unmounts while still open (parent
|
|
36630
|
+
// removes it from the tree without going through requestClose()), there is
|
|
36631
|
+
// no choice to leave open — close it for real.
|
|
36632
|
+
useLayoutEffect(() => {
|
|
36633
|
+
return () => {
|
|
36634
|
+
controllerRef.current.close();
|
|
36635
|
+
};
|
|
36636
|
+
}, []);
|
|
36637
|
+
return controllerRef.current;
|
|
36638
|
+
};
|
|
36639
|
+
|
|
36640
|
+
/**
|
|
36641
|
+
* Owns open/close decision-making for a picker popup (Dialog or Popover):
|
|
36642
|
+
* guards against duplicate requests and notifies the picker's own reactions.
|
|
36643
|
+
*
|
|
36644
|
+
* `controller.openEffect` is implemented by the controlled element (Dialog or
|
|
36645
|
+
* Popover), reassigned on every render so it always closes over the latest
|
|
36646
|
+
* props (scrollTrap, anchorRef, etc.). It performs whatever DOM side effects
|
|
36647
|
+
* are needed to make the element actually open (`showModal()`/`showPopover()`,
|
|
36648
|
+
* focus transfer, positioning, traps...) and returns its cleanup —
|
|
36649
|
+
* the matching side effects to sync back to closed (`close()`/
|
|
36650
|
+
* `hidePopover()`, releasing traps...). That cleanup is kept private to the
|
|
36651
|
+
* controller (not exposed as a property) and invoked when the popup actually
|
|
36652
|
+
* closes, however that happens.
|
|
36653
|
+
*
|
|
36654
|
+
* Dialog/Popover also call `openController.requestClose(e, { isCancel })` for
|
|
36655
|
+
* their own internal triggers (backdrop click, Escape).
|
|
36656
|
+
*
|
|
36657
|
+
* `openHandler` is the picker's own business logic, passed once to
|
|
36658
|
+
* `createOpenController`. Its return value is `{ onRequestClose, onClose }`,
|
|
36659
|
+
* in the spirit of CloseWatcher
|
|
36660
|
+
* (https://developer.mozilla.org/en-US/docs/Web/API/CloseWatcher) but with
|
|
36661
|
+
* clearer naming than its cancel/close pair:
|
|
36662
|
+
* - `onRequestClose(e)`: about to close — call `e.preventDefault()` to stay
|
|
36663
|
+
* open. Validation lives here.
|
|
36664
|
+
* - `onClose(e)`: actually closing, not preventable — final reactions live here.
|
|
36665
|
+
*
|
|
36666
|
+
* The controller exposes matching action methods:
|
|
36667
|
+
* - `open()`: requests opening — runs `openEffect`, then `openHandler`.
|
|
36668
|
+
* - `requestClose()`: requests closing — calls `onRequestClose` then `onClose`,
|
|
36669
|
+
* stopping after the first if denied. The popup may choose to stay open.
|
|
36670
|
+
* - `close()`: closes for real — calls only `onClose`, skipping
|
|
36671
|
+
* `onRequestClose` entirely. Used when there really is no choice (e.g. the
|
|
36672
|
+
* popup unmounting).
|
|
36673
|
+
*/
|
|
36674
|
+
const createOpenController = openHandler => {
|
|
36675
|
+
let closeHandlers = null; // { onRequestClose, onClose } returned by openHandler
|
|
36676
|
+
let openEffectCleanup = null; // function returned by openEffect, undoes its DOM side effects
|
|
36677
|
+
const performClose = closeEvent => {
|
|
36678
|
+
controller.opened = false;
|
|
36679
|
+
// Sync the DOM closed first (releasing the focus trap) — only then run
|
|
36680
|
+
// the picker's own reaction (onClose may restore focus to an element
|
|
36681
|
+
// outside the popup, which the focus trap would otherwise fight while
|
|
36682
|
+
// still active).
|
|
36683
|
+
openEffectCleanup?.(closeEvent);
|
|
36684
|
+
openEffectCleanup = null;
|
|
36685
|
+
closeHandlers?.onClose?.(closeEvent);
|
|
36686
|
+
closeHandlers = null;
|
|
36687
|
+
};
|
|
36688
|
+
const controller = {
|
|
36689
|
+
opened: false,
|
|
36690
|
+
openEffect: null,
|
|
36691
|
+
open: (e, detail) => {
|
|
36692
|
+
if (controller.opened || !controller.openEffect) {
|
|
36693
|
+
return;
|
|
36694
|
+
}
|
|
36695
|
+
const requestOpenEvent = new CustomEvent("navi_request_open", {
|
|
36696
|
+
detail: {
|
|
36697
|
+
event: e,
|
|
36698
|
+
...detail
|
|
36699
|
+
},
|
|
36700
|
+
cancelable: true
|
|
36701
|
+
});
|
|
36702
|
+
chainEvent(requestOpenEvent, e);
|
|
36703
|
+
controller.opened = true;
|
|
36704
|
+
// openEffect may populate requestOpenEvent.detail (e.g. focusedBeforeOpen)
|
|
36705
|
+
// by mutating it — openHandler reads it right after, synchronously.
|
|
36706
|
+
openEffectCleanup = controller.openEffect(requestOpenEvent) || null;
|
|
36707
|
+
closeHandlers = openHandler(requestOpenEvent) || null;
|
|
36708
|
+
},
|
|
36709
|
+
requestClose: (e = new CustomEvent("programmatic", {
|
|
36710
|
+
detail: {}
|
|
36711
|
+
}), detail) => {
|
|
36712
|
+
if (!controller.opened) {
|
|
36713
|
+
return;
|
|
36714
|
+
}
|
|
36715
|
+
const requestCloseEvent = new CustomEvent("navi_request_close", {
|
|
36716
|
+
detail: {
|
|
36717
|
+
event: e,
|
|
36718
|
+
...detail
|
|
36719
|
+
},
|
|
36720
|
+
cancelable: true
|
|
36721
|
+
});
|
|
36722
|
+
chainEvent(requestCloseEvent, e);
|
|
36723
|
+
closeHandlers?.onRequestClose?.(requestCloseEvent);
|
|
36724
|
+
if (requestCloseEvent.defaultPrevented) {
|
|
36725
|
+
// The native <dialog> "cancel" event (Escape key) closes the dialog
|
|
36726
|
+
// by default; prevent that default so denial actually keeps it open.
|
|
36727
|
+
const nativeCancelEvent = findEvent(requestCloseEvent, "cancel");
|
|
36728
|
+
if (nativeCancelEvent) {
|
|
36729
|
+
nativeCancelEvent.preventDefault();
|
|
36730
|
+
}
|
|
36731
|
+
return;
|
|
36732
|
+
}
|
|
36733
|
+
performClose(requestCloseEvent);
|
|
36734
|
+
},
|
|
36735
|
+
close: (e = new CustomEvent("programmatic", {
|
|
36736
|
+
detail: {}
|
|
36737
|
+
}), detail) => {
|
|
36738
|
+
if (!controller.opened) {
|
|
36739
|
+
return;
|
|
36740
|
+
}
|
|
36741
|
+
const closeEvent = new CustomEvent("navi_close", {
|
|
36742
|
+
detail: {
|
|
36743
|
+
event: e,
|
|
36744
|
+
...detail
|
|
36745
|
+
}
|
|
36746
|
+
});
|
|
36747
|
+
chainEvent(closeEvent, e);
|
|
36748
|
+
// Skips onRequestClose entirely — there is no choice here.
|
|
36749
|
+
performClose(closeEvent);
|
|
36750
|
+
}
|
|
36751
|
+
};
|
|
36752
|
+
return controller;
|
|
36753
|
+
};
|
|
36754
|
+
|
|
36747
36755
|
const PickerNaviMinute = props => {
|
|
36748
36756
|
const Next = useNextResolver();
|
|
36749
36757
|
const {
|
|
@@ -39954,7 +39962,7 @@ installImportMetaCssBuild(import.meta);const css$l = /* css */`
|
|
|
39954
39962
|
--x-color: var(--color, white);
|
|
39955
39963
|
|
|
39956
39964
|
position: relative;
|
|
39957
|
-
display: inline
|
|
39965
|
+
display: inline;
|
|
39958
39966
|
max-width: 200px;
|
|
39959
39967
|
padding-top: var(--padding-y);
|
|
39960
39968
|
padding-right: var(--padding-x);
|
|
@@ -39963,7 +39971,6 @@ installImportMetaCssBuild(import.meta);const css$l = /* css */`
|
|
|
39963
39971
|
align-items: stretch;
|
|
39964
39972
|
color: var(--x-color);
|
|
39965
39973
|
font-size: var(--font-size);
|
|
39966
|
-
line-height: normal;
|
|
39967
39974
|
background: var(--x-background);
|
|
39968
39975
|
background-color: var(--x-background-color);
|
|
39969
39976
|
border-radius: 1em;
|
|
@@ -39974,7 +39981,7 @@ installImportMetaCssBuild(import.meta);const css$l = /* css */`
|
|
|
39974
39981
|
}
|
|
39975
39982
|
|
|
39976
39983
|
&[data-text-overflow] {
|
|
39977
|
-
display:
|
|
39984
|
+
display: inline;
|
|
39978
39985
|
|
|
39979
39986
|
.navi_text_overflow_wrapper {
|
|
39980
39987
|
/* Keep badge text and button together */
|
|
@@ -39986,10 +39993,13 @@ installImportMetaCssBuild(import.meta);const css$l = /* css */`
|
|
|
39986
39993
|
display: inline-flex;
|
|
39987
39994
|
margin-top: calc(-1 * var(--padding-y));
|
|
39988
39995
|
margin-bottom: calc(-1 * var(--padding-y));
|
|
39996
|
+
padding-top: var(--padding-y);
|
|
39989
39997
|
padding-right: calc(var(--padding-x) / 2);
|
|
39998
|
+
padding-bottom: var(--padding-y);
|
|
39990
39999
|
padding-left: calc(var(--padding-x) / 2);
|
|
39991
40000
|
align-items: center;
|
|
39992
40001
|
cursor: pointer;
|
|
40002
|
+
pointer-events: auto;
|
|
39993
40003
|
user-select: none;
|
|
39994
40004
|
|
|
39995
40005
|
&:first-child {
|
|
@@ -40101,6 +40111,11 @@ const BadgeList = ({
|
|
|
40101
40111
|
const measure = () => {
|
|
40102
40112
|
visibleEl.style.width = "";
|
|
40103
40113
|
if (shrinkWrap) {
|
|
40114
|
+
// Clone the already-rendered DOM nodes instead of letting React/Preact
|
|
40115
|
+
// render the children a second time into the ghost: re-rendering would
|
|
40116
|
+
// instantiate Badge/Badge.Button a second time, double-registering
|
|
40117
|
+
// their controllers (and any other mount side effect) under the same id.
|
|
40118
|
+
measureEl.replaceChildren(...Array.from(visibleEl.children, child => child.cloneNode(true)));
|
|
40104
40119
|
const optimalWidth = measureWidestChildRow(measureEl);
|
|
40105
40120
|
if (optimalWidth !== null) {
|
|
40106
40121
|
visibleEl.style.width = `${Math.ceil(optimalWidth)}px`;
|
|
@@ -40142,8 +40157,7 @@ const BadgeList = ({
|
|
|
40142
40157
|
...sharedProps,
|
|
40143
40158
|
ref: measureRef,
|
|
40144
40159
|
"aria-hidden": "true",
|
|
40145
|
-
"navi-badge-list-clone": ""
|
|
40146
|
-
children: childArray
|
|
40160
|
+
"navi-badge-list-clone": ""
|
|
40147
40161
|
}), jsxs(Box, {
|
|
40148
40162
|
baseClassName: "navi_badge_list",
|
|
40149
40163
|
...sharedProps,
|