@jsenv/navi 0.24.0 → 0.24.1
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 +874 -291
- package/dist/jsenv_navi.js.map +94 -50
- package/package.json +2 -2
package/dist/jsenv_navi.js
CHANGED
|
@@ -7226,6 +7226,12 @@ const PSEUDO_CLASSES = {
|
|
|
7226
7226
|
attribute: "data-invalid",
|
|
7227
7227
|
test: (el) => el.matches(":invalid"),
|
|
7228
7228
|
},
|
|
7229
|
+
":-navi-highlighted": {
|
|
7230
|
+
attribute: "data-highlighted",
|
|
7231
|
+
},
|
|
7232
|
+
":-navi-selected": {
|
|
7233
|
+
attribute: "data-selected",
|
|
7234
|
+
},
|
|
7229
7235
|
":-navi-loading": {
|
|
7230
7236
|
attribute: "data-loading",
|
|
7231
7237
|
},
|
|
@@ -15782,7 +15788,7 @@ installImportMetaCssBuild(import.meta);
|
|
|
15782
15788
|
* - Centers in viewport when no anchor element provided or anchor is too big
|
|
15783
15789
|
*/
|
|
15784
15790
|
|
|
15785
|
-
|
|
15791
|
+
const css$w = /* css */`
|
|
15786
15792
|
@layer navi {
|
|
15787
15793
|
.navi_callout {
|
|
15788
15794
|
--callout-success-color: #4caf50;
|
|
@@ -15924,7 +15930,7 @@ import.meta.css = [/* css */`
|
|
|
15924
15930
|
}
|
|
15925
15931
|
}
|
|
15926
15932
|
}
|
|
15927
|
-
|
|
15933
|
+
`;
|
|
15928
15934
|
|
|
15929
15935
|
/**
|
|
15930
15936
|
* Shows a callout attached to the specified element
|
|
@@ -15956,6 +15962,7 @@ const openCallout = (message, {
|
|
|
15956
15962
|
showErrorStack,
|
|
15957
15963
|
debug = false
|
|
15958
15964
|
} = {}) => {
|
|
15965
|
+
import.meta.css = [css$w, "@jsenv/navi/src/field/validation/callout/callout.js"];
|
|
15959
15966
|
const callout = {
|
|
15960
15967
|
opened: true,
|
|
15961
15968
|
close: null,
|
|
@@ -16115,8 +16122,14 @@ const openCallout = (message, {
|
|
|
16115
16122
|
}
|
|
16116
16123
|
allowWheelThrough(calloutElement, anchorElement);
|
|
16117
16124
|
anchorElement.setAttribute("data-callout", calloutId);
|
|
16125
|
+
dispatchCalloutCustomElement(anchorElement, new CustomEvent("navi_callout_open", {
|
|
16126
|
+
bubbles: true
|
|
16127
|
+
}));
|
|
16118
16128
|
addTeardown(() => {
|
|
16119
16129
|
anchorElement.removeAttribute("data-callout");
|
|
16130
|
+
dispatchCalloutCustomElement(anchorElement, new CustomEvent("navi_callout_close", {
|
|
16131
|
+
bubbles: true
|
|
16132
|
+
}));
|
|
16120
16133
|
});
|
|
16121
16134
|
addStatusEffect(status => {
|
|
16122
16135
|
if (!status) {
|
|
@@ -16747,6 +16760,20 @@ const generateSvgWithoutArrow = (width, height) => {
|
|
|
16747
16760
|
/>
|
|
16748
16761
|
</svg>`;
|
|
16749
16762
|
};
|
|
16763
|
+
const dispatchCalloutCustomElement = (anchorElement, customEvent) => {
|
|
16764
|
+
let targetElement;
|
|
16765
|
+
const visualSelector = anchorElement.getAttribute("data-visual-selector");
|
|
16766
|
+
if (visualSelector) {
|
|
16767
|
+
const visualElement = anchorElement.querySelector(visualSelector);
|
|
16768
|
+
if (visualElement) {
|
|
16769
|
+
targetElement = visualElement;
|
|
16770
|
+
}
|
|
16771
|
+
} else {
|
|
16772
|
+
targetElement = anchorElement;
|
|
16773
|
+
}
|
|
16774
|
+
console.log("dispatch on", targetElement, "event", customEvent);
|
|
16775
|
+
targetElement.dispatchEvent(customEvent);
|
|
16776
|
+
};
|
|
16750
16777
|
|
|
16751
16778
|
/**
|
|
16752
16779
|
* Creates a live mirror of a source DOM element that automatically stays in sync.
|
|
@@ -17122,6 +17149,56 @@ CONSTRAINT_ATTRIBUTE_SET.add("data-special-charset");
|
|
|
17122
17149
|
CONSTRAINT_ATTRIBUTE_SET.add("data-min-special-char");
|
|
17123
17150
|
CONSTRAINT_ATTRIBUTE_SET.add("data-min-special-char-message");
|
|
17124
17151
|
|
|
17152
|
+
const ONE_OF_CONSTRAINT = {
|
|
17153
|
+
name: "one_of",
|
|
17154
|
+
messageAttribute: "data-one-of-message",
|
|
17155
|
+
check: (field) => {
|
|
17156
|
+
const oneOf = field.getAttribute("data-one-of");
|
|
17157
|
+
if (!oneOf) {
|
|
17158
|
+
return null;
|
|
17159
|
+
}
|
|
17160
|
+
const fieldValue = field.value;
|
|
17161
|
+
if (!fieldValue) {
|
|
17162
|
+
return null;
|
|
17163
|
+
}
|
|
17164
|
+
const listEl = document.querySelector(oneOf);
|
|
17165
|
+
if (!listEl) {
|
|
17166
|
+
console.warn(
|
|
17167
|
+
`One of constraint: could not find element for selector "${oneOf}"`,
|
|
17168
|
+
);
|
|
17169
|
+
return null;
|
|
17170
|
+
}
|
|
17171
|
+
const allowedValues = collectAllowedValues(listEl);
|
|
17172
|
+
if (allowedValues.size === 0) {
|
|
17173
|
+
return null;
|
|
17174
|
+
}
|
|
17175
|
+
if (allowedValues.has(fieldValue)) {
|
|
17176
|
+
return null;
|
|
17177
|
+
}
|
|
17178
|
+
const message = field.getAttribute("data-one-of-message");
|
|
17179
|
+
if (message) {
|
|
17180
|
+
return message;
|
|
17181
|
+
}
|
|
17182
|
+
return `Veuillez choisir une valeur parmi les suggestions.`;
|
|
17183
|
+
},
|
|
17184
|
+
};
|
|
17185
|
+
CONSTRAINT_ATTRIBUTE_SET.add("data-one-of");
|
|
17186
|
+
CONSTRAINT_ATTRIBUTE_SET.add("data-one-of-message");
|
|
17187
|
+
|
|
17188
|
+
const collectAllowedValues = (listEl) => {
|
|
17189
|
+
const values = new Set();
|
|
17190
|
+
for (const optionEl of listEl.querySelectorAll("[role='option']")) {
|
|
17191
|
+
const value =
|
|
17192
|
+
optionEl.dataset.value ??
|
|
17193
|
+
optionEl.getAttribute("value") ??
|
|
17194
|
+
optionEl.textContent.trim();
|
|
17195
|
+
if (value) {
|
|
17196
|
+
values.add(value);
|
|
17197
|
+
}
|
|
17198
|
+
}
|
|
17199
|
+
return values;
|
|
17200
|
+
};
|
|
17201
|
+
|
|
17125
17202
|
const READONLY_CONSTRAINT = {
|
|
17126
17203
|
name: "readonly",
|
|
17127
17204
|
messageAttribute: "data-readonly-message",
|
|
@@ -17874,6 +17951,7 @@ const NAVI_CONSTRAINT_SET = new Set([
|
|
|
17874
17951
|
MIN_UPPER_LETTER_CONSTRAINT,
|
|
17875
17952
|
MIN_LOWER_LETTER_CONSTRAINT,
|
|
17876
17953
|
SAME_AS_CONSTRAINT,
|
|
17954
|
+
ONE_OF_CONSTRAINT,
|
|
17877
17955
|
READONLY_CONSTRAINT,
|
|
17878
17956
|
]);
|
|
17879
17957
|
const DEFAULT_CONSTRAINT_SET = new Set([
|
|
@@ -20292,7 +20370,7 @@ const selectByTextStrings = (element, range, startText, endText) => {
|
|
|
20292
20370
|
};
|
|
20293
20371
|
|
|
20294
20372
|
installImportMetaCssBuild(import.meta);/* eslint-disable jsenv/no-unknown-params */
|
|
20295
|
-
const css$
|
|
20373
|
+
const css$v = /* css */`
|
|
20296
20374
|
@layer navi {
|
|
20297
20375
|
.navi_text {
|
|
20298
20376
|
&[data-skeleton] {
|
|
@@ -20601,7 +20679,7 @@ const shouldInjectSpacingBetween = (left, right) => {
|
|
|
20601
20679
|
};
|
|
20602
20680
|
const OverflowPinnedElementContext = createContext(null);
|
|
20603
20681
|
const Text = props => {
|
|
20604
|
-
import.meta.css = [css$
|
|
20682
|
+
import.meta.css = [css$v, "@jsenv/navi/src/text/text.jsx"];
|
|
20605
20683
|
if (props.loading || props.skeleton) {
|
|
20606
20684
|
return jsx(TextSkeleton, {
|
|
20607
20685
|
...props
|
|
@@ -20797,7 +20875,7 @@ const TextBasic = ({
|
|
|
20797
20875
|
});
|
|
20798
20876
|
};
|
|
20799
20877
|
|
|
20800
|
-
installImportMetaCssBuild(import.meta);const css$
|
|
20878
|
+
installImportMetaCssBuild(import.meta);const css$u = /* css */`
|
|
20801
20879
|
.navi_text_anchor {
|
|
20802
20880
|
vertical-align: baseline;
|
|
20803
20881
|
user-select: none;
|
|
@@ -20832,7 +20910,7 @@ const TextAnchor = ({
|
|
|
20832
20910
|
textSize,
|
|
20833
20911
|
lineLayout
|
|
20834
20912
|
}) => {
|
|
20835
|
-
import.meta.css = [css$
|
|
20913
|
+
import.meta.css = [css$u, "@jsenv/navi/src/text/text_anchor.jsx"];
|
|
20836
20914
|
const anchorRef = useRef();
|
|
20837
20915
|
useLayoutEffect(() => {
|
|
20838
20916
|
const anchorEl = anchorRef.current;
|
|
@@ -20927,7 +21005,7 @@ const computeTopOffset = ({
|
|
|
20927
21005
|
};
|
|
20928
21006
|
const charTopCanvas = document.createElement("canvas");
|
|
20929
21007
|
|
|
20930
|
-
installImportMetaCssBuild(import.meta);const css$
|
|
21008
|
+
installImportMetaCssBuild(import.meta);const css$t = /* css */`
|
|
20931
21009
|
@layer navi {
|
|
20932
21010
|
/* Ensure data attributes from box.jsx can win to update display */
|
|
20933
21011
|
.navi_icon {
|
|
@@ -21000,7 +21078,7 @@ const Icon = ({
|
|
|
21000
21078
|
lineLayout,
|
|
21001
21079
|
...props
|
|
21002
21080
|
}) => {
|
|
21003
|
-
import.meta.css = [css$
|
|
21081
|
+
import.meta.css = [css$t, "@jsenv/navi/src/text/icon.jsx"];
|
|
21004
21082
|
const innerChildren = href ? jsx("svg", {
|
|
21005
21083
|
width: "100%",
|
|
21006
21084
|
height: "100%",
|
|
@@ -21706,7 +21784,7 @@ const useUIState = (uiStateController) => {
|
|
|
21706
21784
|
};
|
|
21707
21785
|
|
|
21708
21786
|
installImportMetaCssBuild(import.meta);/* eslint-disable jsenv/no-unknown-params */
|
|
21709
|
-
const css$
|
|
21787
|
+
const css$s = /* css */`
|
|
21710
21788
|
@layer navi {
|
|
21711
21789
|
.navi_button {
|
|
21712
21790
|
--button-outline-width: 1px;
|
|
@@ -21972,7 +22050,7 @@ const css$r = /* css */`
|
|
|
21972
22050
|
}
|
|
21973
22051
|
`;
|
|
21974
22052
|
const Button = props => {
|
|
21975
|
-
import.meta.css = [css$
|
|
22053
|
+
import.meta.css = [css$s, "@jsenv/navi/src/field/button.jsx"];
|
|
21976
22054
|
return renderActionableComponent(props, {
|
|
21977
22055
|
Basic: ButtonBasicDispatch,
|
|
21978
22056
|
WithAction: ButtonWithAction,
|
|
@@ -22504,7 +22582,7 @@ const useDimColorWhen = (elementRef, shouldDim) => {
|
|
|
22504
22582
|
};
|
|
22505
22583
|
|
|
22506
22584
|
installImportMetaCssBuild(import.meta);/* eslint-disable jsenv/no-unknown-params */
|
|
22507
|
-
const css$
|
|
22585
|
+
const css$r = /* css */`
|
|
22508
22586
|
@layer navi {
|
|
22509
22587
|
.navi_link {
|
|
22510
22588
|
--link-border-radius: unset;
|
|
@@ -22576,10 +22654,22 @@ const css$q = /* css */`
|
|
|
22576
22654
|
|
|
22577
22655
|
position: relative;
|
|
22578
22656
|
aspect-ratio: inherit;
|
|
22579
|
-
padding-top: max(
|
|
22580
|
-
|
|
22581
|
-
|
|
22582
|
-
|
|
22657
|
+
padding-top: max(
|
|
22658
|
+
var(--x-link-padding-top),
|
|
22659
|
+
var(--link-loading-outline-size)
|
|
22660
|
+
);
|
|
22661
|
+
padding-right: max(
|
|
22662
|
+
var(--x-link-padding-right),
|
|
22663
|
+
var(--link-loading-outline-size)
|
|
22664
|
+
);
|
|
22665
|
+
padding-bottom: max(
|
|
22666
|
+
var(--x-link-padding-bottom),
|
|
22667
|
+
var(--link-loading-outline-size)
|
|
22668
|
+
);
|
|
22669
|
+
padding-left: max(
|
|
22670
|
+
var(--x-link-padding-left),
|
|
22671
|
+
var(--link-loading-outline-size)
|
|
22672
|
+
);
|
|
22583
22673
|
color: var(--x-link-color);
|
|
22584
22674
|
text-decoration: var(--x-link-text-decoration);
|
|
22585
22675
|
background: var(--x-link-background);
|
|
@@ -22846,13 +22936,10 @@ Object.assign(PSEUDO_CLASSES, {
|
|
|
22846
22936
|
},
|
|
22847
22937
|
":-navi-href-current": {
|
|
22848
22938
|
attribute: "data-href-current"
|
|
22849
|
-
},
|
|
22850
|
-
":-navi-selected": {
|
|
22851
|
-
attribute: "data-selected"
|
|
22852
22939
|
}
|
|
22853
22940
|
});
|
|
22854
22941
|
const Link = props => {
|
|
22855
|
-
import.meta.css = [css$
|
|
22942
|
+
import.meta.css = [css$r, "@jsenv/navi/src/nav/link/link.jsx"];
|
|
22856
22943
|
return renderActionableComponent(props, {
|
|
22857
22944
|
Basic: LinkBasic,
|
|
22858
22945
|
WithAction: LinkWithAction
|
|
@@ -23114,7 +23201,7 @@ installImportMetaCssBuild(import.meta);/**
|
|
|
23114
23201
|
* TabList component with support for horizontal and vertical layouts
|
|
23115
23202
|
* https://dribbble.com/search/tabs
|
|
23116
23203
|
*/
|
|
23117
|
-
const css$
|
|
23204
|
+
const css$q = /* css */`
|
|
23118
23205
|
@layer navi {
|
|
23119
23206
|
.navi_nav {
|
|
23120
23207
|
--nav-border: none;
|
|
@@ -23250,7 +23337,7 @@ const Nav = ({
|
|
|
23250
23337
|
panelBorderConnection,
|
|
23251
23338
|
...props
|
|
23252
23339
|
}) => {
|
|
23253
|
-
import.meta.css = [css$
|
|
23340
|
+
import.meta.css = [css$q, "@jsenv/navi/src/nav/link/nav.jsx"];
|
|
23254
23341
|
children = toChildArray(children);
|
|
23255
23342
|
return jsx(Box, {
|
|
23256
23343
|
as: "nav",
|
|
@@ -23298,7 +23385,7 @@ const useFocusGroup = (
|
|
|
23298
23385
|
|
|
23299
23386
|
installImportMetaCssBuild(import.meta);const rightArrowPath = "M680-480L360-160l-80-80 240-240-240-240 80-80 320 320z";
|
|
23300
23387
|
const downArrowPath = "M480-280L160-600l80-80 240 240 240-240 80 80-320 320z";
|
|
23301
|
-
const css$
|
|
23388
|
+
const css$p = /* css */`
|
|
23302
23389
|
.navi_summary_marker {
|
|
23303
23390
|
width: 1em;
|
|
23304
23391
|
height: 1em;
|
|
@@ -23383,7 +23470,7 @@ const SummaryMarker = ({
|
|
|
23383
23470
|
open,
|
|
23384
23471
|
loading
|
|
23385
23472
|
}) => {
|
|
23386
|
-
import.meta.css = [css$
|
|
23473
|
+
import.meta.css = [css$p, "@jsenv/navi/src/field/details/summary_marker.jsx"];
|
|
23387
23474
|
const showLoading = useDebounceTrue(loading, 300);
|
|
23388
23475
|
const mountedRef = useRef(false);
|
|
23389
23476
|
const prevOpenRef = useRef(open);
|
|
@@ -23437,7 +23524,7 @@ const SummaryMarker = ({
|
|
|
23437
23524
|
});
|
|
23438
23525
|
};
|
|
23439
23526
|
|
|
23440
|
-
installImportMetaCssBuild(import.meta);const css$
|
|
23527
|
+
installImportMetaCssBuild(import.meta);const css$o = /* css */`
|
|
23441
23528
|
.navi_details {
|
|
23442
23529
|
position: relative;
|
|
23443
23530
|
z-index: 1;
|
|
@@ -23474,7 +23561,7 @@ installImportMetaCssBuild(import.meta);const css$n = /* css */`
|
|
|
23474
23561
|
}
|
|
23475
23562
|
`;
|
|
23476
23563
|
const Details = props => {
|
|
23477
|
-
import.meta.css = [css$
|
|
23564
|
+
import.meta.css = [css$o, "@jsenv/navi/src/field/details/details.jsx"];
|
|
23478
23565
|
const {
|
|
23479
23566
|
value = "on",
|
|
23480
23567
|
persists
|
|
@@ -23789,7 +23876,7 @@ const fieldPropSet = new Set([
|
|
|
23789
23876
|
"data-testid",
|
|
23790
23877
|
]);
|
|
23791
23878
|
|
|
23792
|
-
installImportMetaCssBuild(import.meta);const css$
|
|
23879
|
+
installImportMetaCssBuild(import.meta);const css$n = /* css */`
|
|
23793
23880
|
@layer navi {
|
|
23794
23881
|
label {
|
|
23795
23882
|
&[data-interactive] {
|
|
@@ -23821,7 +23908,7 @@ const reportDisabledToLabel = value => {
|
|
|
23821
23908
|
};
|
|
23822
23909
|
const LabelPseudoClasses = [":hover", ":active", ":focus", ":focus-visible", ":read-only", ":disabled", ":-navi-loading"];
|
|
23823
23910
|
const Label = props => {
|
|
23824
|
-
import.meta.css = [css$
|
|
23911
|
+
import.meta.css = [css$n, "@jsenv/navi/src/field/label.jsx"];
|
|
23825
23912
|
const {
|
|
23826
23913
|
readOnly,
|
|
23827
23914
|
disabled,
|
|
@@ -23855,7 +23942,7 @@ const Label = props => {
|
|
|
23855
23942
|
});
|
|
23856
23943
|
};
|
|
23857
23944
|
|
|
23858
|
-
installImportMetaCssBuild(import.meta);const css$
|
|
23945
|
+
installImportMetaCssBuild(import.meta);const css$m = /* css */`
|
|
23859
23946
|
@layer navi {
|
|
23860
23947
|
.navi_checkbox {
|
|
23861
23948
|
--margin: 3px 3px 3px 4px;
|
|
@@ -24182,7 +24269,7 @@ installImportMetaCssBuild(import.meta);const css$l = /* css */`
|
|
|
24182
24269
|
}
|
|
24183
24270
|
`;
|
|
24184
24271
|
const InputCheckbox = props => {
|
|
24185
|
-
import.meta.css = [css$
|
|
24272
|
+
import.meta.css = [css$m, "@jsenv/navi/src/field/input_checkbox.jsx"];
|
|
24186
24273
|
const {
|
|
24187
24274
|
value = "on"
|
|
24188
24275
|
} = props;
|
|
@@ -24596,7 +24683,7 @@ forwardRef((props, ref) => {
|
|
|
24596
24683
|
});
|
|
24597
24684
|
});
|
|
24598
24685
|
|
|
24599
|
-
installImportMetaCssBuild(import.meta);const css$
|
|
24686
|
+
installImportMetaCssBuild(import.meta);const css$l = /* css */`
|
|
24600
24687
|
@layer navi {
|
|
24601
24688
|
.navi_radio {
|
|
24602
24689
|
--margin: 3px 3px 0 5px;
|
|
@@ -24889,7 +24976,7 @@ installImportMetaCssBuild(import.meta);const css$k = /* css */`
|
|
|
24889
24976
|
}
|
|
24890
24977
|
`;
|
|
24891
24978
|
const InputRadio = props => {
|
|
24892
|
-
import.meta.css = [css$
|
|
24979
|
+
import.meta.css = [css$l, "@jsenv/navi/src/field/input_radio.jsx"];
|
|
24893
24980
|
const {
|
|
24894
24981
|
value = "on"
|
|
24895
24982
|
} = props;
|
|
@@ -25135,7 +25222,7 @@ const InputRadioWithAction = () => {
|
|
|
25135
25222
|
throw new Error(`<Input type="radio" /> with an action make no sense. Use <RadioList action={something} /> instead`);
|
|
25136
25223
|
};
|
|
25137
25224
|
|
|
25138
|
-
installImportMetaCssBuild(import.meta);const css$
|
|
25225
|
+
installImportMetaCssBuild(import.meta);const css$k = /* css */`
|
|
25139
25226
|
@layer navi {
|
|
25140
25227
|
.navi_input_range {
|
|
25141
25228
|
--border-radius: 6px;
|
|
@@ -25344,7 +25431,7 @@ installImportMetaCssBuild(import.meta);const css$j = /* css */`
|
|
|
25344
25431
|
}
|
|
25345
25432
|
`;
|
|
25346
25433
|
const InputRange = props => {
|
|
25347
|
-
import.meta.css = [css$
|
|
25434
|
+
import.meta.css = [css$k, "@jsenv/navi/src/field/input_range.jsx"];
|
|
25348
25435
|
const uiStateController = useUIStateController(props, "input");
|
|
25349
25436
|
const uiState = useUIState(uiStateController);
|
|
25350
25437
|
const input = renderActionableComponent(props, {
|
|
@@ -25614,24 +25701,8 @@ const SearchSvg = () => jsx("svg", {
|
|
|
25614
25701
|
})
|
|
25615
25702
|
});
|
|
25616
25703
|
|
|
25617
|
-
installImportMetaCssBuild(import.meta)
|
|
25618
|
-
|
|
25619
|
-
*
|
|
25620
|
-
* Supports:
|
|
25621
|
-
* - text (default)
|
|
25622
|
-
* - password
|
|
25623
|
-
* - hidden
|
|
25624
|
-
* - email
|
|
25625
|
-
* - url
|
|
25626
|
-
* - search
|
|
25627
|
-
* - tel
|
|
25628
|
-
* - etc.
|
|
25629
|
-
*
|
|
25630
|
-
* For non-textual inputs, specialized components will be used:
|
|
25631
|
-
* - <InputCheckbox /> for type="checkbox"
|
|
25632
|
-
* - <InputRadio /> for type="radio"
|
|
25633
|
-
*/
|
|
25634
|
-
const css$i = /* css */`
|
|
25704
|
+
installImportMetaCssBuild(import.meta);/* eslint-disable jsenv/no-unknown-params */
|
|
25705
|
+
const css$j = /* css */`
|
|
25635
25706
|
@layer navi {
|
|
25636
25707
|
.navi_input {
|
|
25637
25708
|
--border-radius: 2px;
|
|
@@ -25843,7 +25914,7 @@ const css$i = /* css */`
|
|
|
25843
25914
|
}
|
|
25844
25915
|
`;
|
|
25845
25916
|
const InputTextual = props => {
|
|
25846
|
-
import.meta.css = [css$
|
|
25917
|
+
import.meta.css = [css$j, "@jsenv/navi/src/field/input_textual.jsx"];
|
|
25847
25918
|
const uiStateController = useUIStateController(props, "input");
|
|
25848
25919
|
const uiState = useUIState(uiStateController);
|
|
25849
25920
|
const input = renderActionableComponent(props, {
|
|
@@ -25916,6 +25987,197 @@ Object.assign(PSEUDO_CLASSES, {
|
|
|
25916
25987
|
const InputPseudoElements = ["::-navi-loader"];
|
|
25917
25988
|
const InputChildPropSet = new Set([...fieldPropSet]);
|
|
25918
25989
|
const InputTextualBasic = props => {
|
|
25990
|
+
if (props.combobox) {
|
|
25991
|
+
return jsx(InputTextualCombobox, {
|
|
25992
|
+
...props
|
|
25993
|
+
});
|
|
25994
|
+
}
|
|
25995
|
+
return jsx(InputTextualPlain, {
|
|
25996
|
+
...props
|
|
25997
|
+
});
|
|
25998
|
+
};
|
|
25999
|
+
const InputTextualCombobox = ({
|
|
26000
|
+
combobox,
|
|
26001
|
+
onInput,
|
|
26002
|
+
onFocus,
|
|
26003
|
+
onBlur,
|
|
26004
|
+
...rest
|
|
26005
|
+
}) => {
|
|
26006
|
+
const defaultRef = useRef();
|
|
26007
|
+
const ref = rest.ref || defaultRef;
|
|
26008
|
+
const [comboboxOpen, setComboboxOpen] = useState(false);
|
|
26009
|
+
const comboboxOpenRef = useRef(false);
|
|
26010
|
+
comboboxOpenRef.current = comboboxOpen;
|
|
26011
|
+
const showPopover = e => {
|
|
26012
|
+
if (comboboxOpenRef.current) {
|
|
26013
|
+
return;
|
|
26014
|
+
}
|
|
26015
|
+
console.debug(`showPopover (e.type:${e.type})`);
|
|
26016
|
+
const popoverEl = document.getElementById(combobox);
|
|
26017
|
+
positionPopover();
|
|
26018
|
+
popoverEl.showPopover();
|
|
26019
|
+
comboboxOpenRef.current = true;
|
|
26020
|
+
setComboboxOpen(true);
|
|
26021
|
+
window.addEventListener("scroll", positionPopover, {
|
|
26022
|
+
capture: true,
|
|
26023
|
+
passive: true
|
|
26024
|
+
});
|
|
26025
|
+
};
|
|
26026
|
+
const hidePopover = e => {
|
|
26027
|
+
if (!comboboxOpenRef.current) {
|
|
26028
|
+
return;
|
|
26029
|
+
}
|
|
26030
|
+
console.debug(`hidePopover (e.type:${e.type})`);
|
|
26031
|
+
comboboxOpenRef.current = false;
|
|
26032
|
+
setComboboxOpen(false);
|
|
26033
|
+
window.removeEventListener("scroll", positionPopover, {
|
|
26034
|
+
capture: true
|
|
26035
|
+
});
|
|
26036
|
+
const popoverEl = document.getElementById(combobox);
|
|
26037
|
+
if (popoverEl) {
|
|
26038
|
+
popoverEl.dispatchEvent(new CustomEvent("combobox-clear"));
|
|
26039
|
+
popoverEl.hidePopover();
|
|
26040
|
+
}
|
|
26041
|
+
setComboboxOpen(false);
|
|
26042
|
+
};
|
|
26043
|
+
const positionPopover = () => {
|
|
26044
|
+
const input = ref.current;
|
|
26045
|
+
const rect = input.getBoundingClientRect();
|
|
26046
|
+
const popoverEl = document.getElementById(combobox);
|
|
26047
|
+
if (popoverEl) {
|
|
26048
|
+
popoverEl.style.top = `${rect.bottom + 2}px`;
|
|
26049
|
+
popoverEl.style.left = `${rect.left}px`;
|
|
26050
|
+
popoverEl.style.width = `${rect.width}px`;
|
|
26051
|
+
}
|
|
26052
|
+
};
|
|
26053
|
+
const dispatchToOptionList = customEvent => {
|
|
26054
|
+
const popoverEl = document.getElementById(combobox);
|
|
26055
|
+
if (!popoverEl) {
|
|
26056
|
+
return false;
|
|
26057
|
+
}
|
|
26058
|
+
popoverEl.dispatchEvent(customEvent);
|
|
26059
|
+
return customEvent.defaultPrevented;
|
|
26060
|
+
};
|
|
26061
|
+
useKeyboardShortcuts(ref, [{
|
|
26062
|
+
key: "arrowdown",
|
|
26063
|
+
description: "Open popover and highlight next option",
|
|
26064
|
+
handler: e => {
|
|
26065
|
+
showPopover(e);
|
|
26066
|
+
const popoverEl = document.getElementById(combobox);
|
|
26067
|
+
if (!popoverEl) {
|
|
26068
|
+
return false;
|
|
26069
|
+
}
|
|
26070
|
+
popoverEl.dispatchEvent(new CustomEvent("combobox-navigate", {
|
|
26071
|
+
detail: {
|
|
26072
|
+
direction: "down"
|
|
26073
|
+
}
|
|
26074
|
+
}));
|
|
26075
|
+
return true;
|
|
26076
|
+
}
|
|
26077
|
+
}, {
|
|
26078
|
+
key: "arrowup",
|
|
26079
|
+
description: "Open popover and highlight previous option",
|
|
26080
|
+
handler: e => {
|
|
26081
|
+
showPopover(e);
|
|
26082
|
+
return dispatchToOptionList(new CustomEvent("combobox-navigate", {
|
|
26083
|
+
detail: {
|
|
26084
|
+
direction: "up"
|
|
26085
|
+
}
|
|
26086
|
+
}));
|
|
26087
|
+
}
|
|
26088
|
+
}, {
|
|
26089
|
+
key: "home",
|
|
26090
|
+
description: "Highlight first option",
|
|
26091
|
+
handler: () => {
|
|
26092
|
+
if (!comboboxOpenRef.current) {
|
|
26093
|
+
return false;
|
|
26094
|
+
}
|
|
26095
|
+
return dispatchToOptionList(new CustomEvent("combobox-navigate", {
|
|
26096
|
+
detail: {
|
|
26097
|
+
direction: "first"
|
|
26098
|
+
}
|
|
26099
|
+
}));
|
|
26100
|
+
}
|
|
26101
|
+
}, {
|
|
26102
|
+
key: "end",
|
|
26103
|
+
description: "Highlight last option",
|
|
26104
|
+
handler: () => {
|
|
26105
|
+
if (!comboboxOpenRef.current) {
|
|
26106
|
+
return false;
|
|
26107
|
+
}
|
|
26108
|
+
return dispatchToOptionList(new CustomEvent("combobox-navigate", {
|
|
26109
|
+
detail: {
|
|
26110
|
+
direction: "last"
|
|
26111
|
+
}
|
|
26112
|
+
}));
|
|
26113
|
+
}
|
|
26114
|
+
}, {
|
|
26115
|
+
key: "enter",
|
|
26116
|
+
description: "Confirm highlighted option",
|
|
26117
|
+
handler: () => {
|
|
26118
|
+
if (!comboboxOpenRef.current) {
|
|
26119
|
+
return false;
|
|
26120
|
+
}
|
|
26121
|
+
return dispatchToOptionList(new CustomEvent("combobox-confirm", {
|
|
26122
|
+
cancelable: true
|
|
26123
|
+
}));
|
|
26124
|
+
}
|
|
26125
|
+
}, {
|
|
26126
|
+
key: "escape",
|
|
26127
|
+
description: "Close popover",
|
|
26128
|
+
handler: e => {
|
|
26129
|
+
if (!comboboxOpenRef.current) {
|
|
26130
|
+
return false;
|
|
26131
|
+
}
|
|
26132
|
+
hidePopover(e);
|
|
26133
|
+
return true;
|
|
26134
|
+
}
|
|
26135
|
+
}]);
|
|
26136
|
+
useEffect(() => {
|
|
26137
|
+
const inputEl = ref.current;
|
|
26138
|
+
const popoverEl = document.getElementById(combobox);
|
|
26139
|
+
if (!popoverEl) {
|
|
26140
|
+
return undefined;
|
|
26141
|
+
}
|
|
26142
|
+
const onSelected = e => {
|
|
26143
|
+
inputEl.value = e.detail.value;
|
|
26144
|
+
inputEl.dispatchEvent(new Event("input", {
|
|
26145
|
+
bubbles: true
|
|
26146
|
+
}));
|
|
26147
|
+
hidePopover(e);
|
|
26148
|
+
};
|
|
26149
|
+
popoverEl.addEventListener("combobox-selected", onSelected);
|
|
26150
|
+
return () => {
|
|
26151
|
+
popoverEl.removeEventListener("combobox-selected", onSelected);
|
|
26152
|
+
};
|
|
26153
|
+
}, [combobox]);
|
|
26154
|
+
return jsx(InputTextualPlain, {
|
|
26155
|
+
ref: ref,
|
|
26156
|
+
role: "combobox",
|
|
26157
|
+
autoComplete: "off",
|
|
26158
|
+
"aria-controls": combobox,
|
|
26159
|
+
"aria-haspopup": "listbox",
|
|
26160
|
+
"aria-expanded": comboboxOpen,
|
|
26161
|
+
"aria-autocomplete": "list",
|
|
26162
|
+
onnavi_callout_open: e => {
|
|
26163
|
+
hidePopover(e);
|
|
26164
|
+
},
|
|
26165
|
+
onFocus: e => {
|
|
26166
|
+
onFocus?.(e);
|
|
26167
|
+
showPopover(e);
|
|
26168
|
+
},
|
|
26169
|
+
onBlur: e => {
|
|
26170
|
+
onBlur?.(e);
|
|
26171
|
+
hidePopover(e);
|
|
26172
|
+
},
|
|
26173
|
+
onInput: e => {
|
|
26174
|
+
onInput?.(e);
|
|
26175
|
+
showPopover(e);
|
|
26176
|
+
},
|
|
26177
|
+
...rest
|
|
26178
|
+
});
|
|
26179
|
+
};
|
|
26180
|
+
const InputTextualPlain = props => {
|
|
25919
26181
|
const contextReadOnly = useContext(ReadOnlyContext);
|
|
25920
26182
|
const contextDisabled = useContext(DisabledContext);
|
|
25921
26183
|
const contextLoading = useContext(LoadingContext);
|
|
@@ -25953,6 +26215,9 @@ const InputTextualBasic = props => {
|
|
|
25953
26215
|
const innerOnInput = useStableCallback(onInput);
|
|
25954
26216
|
const autoId = useId();
|
|
25955
26217
|
const innerId = rest.id || autoId;
|
|
26218
|
+
const {
|
|
26219
|
+
...remainingRest
|
|
26220
|
+
} = remainingProps;
|
|
25956
26221
|
const renderInput = inputProps => {
|
|
25957
26222
|
return jsx(Box, {
|
|
25958
26223
|
...inputProps,
|
|
@@ -26021,7 +26286,7 @@ const InputTextualBasic = props => {
|
|
|
26021
26286
|
baseChildPropSet: InputChildPropSet,
|
|
26022
26287
|
"data-start-icon": innerIcon ? "" : undefined,
|
|
26023
26288
|
"data-end-icon": cancelButton ? "" : undefined,
|
|
26024
|
-
...
|
|
26289
|
+
...remainingRest,
|
|
26025
26290
|
ref: undefined,
|
|
26026
26291
|
children: [jsx(LoaderBackground, {
|
|
26027
26292
|
loading: innerLoading,
|
|
@@ -26213,7 +26478,7 @@ installImportMetaCssBuild(import.meta);/**
|
|
|
26213
26478
|
* This means an editable thing MUST have a parent with position relative that wraps the content and the eventual editable input
|
|
26214
26479
|
*
|
|
26215
26480
|
*/
|
|
26216
|
-
const css$
|
|
26481
|
+
const css$i = /* css */`
|
|
26217
26482
|
.navi_editable_wrapper {
|
|
26218
26483
|
--inset-top: 0px;
|
|
26219
26484
|
--inset-right: 0px;
|
|
@@ -26262,7 +26527,7 @@ const useEditionController = () => {
|
|
|
26262
26527
|
};
|
|
26263
26528
|
};
|
|
26264
26529
|
const Editable = props => {
|
|
26265
|
-
import.meta.css = [css$
|
|
26530
|
+
import.meta.css = [css$i, "@jsenv/navi/src/field/edition/editable.jsx"];
|
|
26266
26531
|
let {
|
|
26267
26532
|
children,
|
|
26268
26533
|
action,
|
|
@@ -26673,7 +26938,7 @@ const FormWithAction = props => {
|
|
|
26673
26938
|
// form.dispatchEvent(customEvent);
|
|
26674
26939
|
// };
|
|
26675
26940
|
|
|
26676
|
-
installImportMetaCssBuild(import.meta);const css$
|
|
26941
|
+
installImportMetaCssBuild(import.meta);const css$h = /* css */`
|
|
26677
26942
|
.navi_group {
|
|
26678
26943
|
--border-width: 1px;
|
|
26679
26944
|
|
|
@@ -26770,7 +27035,7 @@ const Group = ({
|
|
|
26770
27035
|
vertical = row,
|
|
26771
27036
|
...props
|
|
26772
27037
|
}) => {
|
|
26773
|
-
import.meta.css = [css$
|
|
27038
|
+
import.meta.css = [css$h, "@jsenv/navi/src/field/group.jsx"];
|
|
26774
27039
|
if (typeof borderWidth === "string") {
|
|
26775
27040
|
borderWidth = parseFloat(borderWidth);
|
|
26776
27041
|
}
|
|
@@ -26788,55 +27053,435 @@ const Group = ({
|
|
|
26788
27053
|
});
|
|
26789
27054
|
};
|
|
26790
27055
|
|
|
26791
|
-
const
|
|
26792
|
-
const
|
|
26793
|
-
|
|
26794
|
-
|
|
26795
|
-
|
|
26796
|
-
|
|
26797
|
-
|
|
26798
|
-
|
|
26799
|
-
|
|
27056
|
+
const createItemTracker = () => {
|
|
27057
|
+
const ItemTrackerContext = createContext();
|
|
27058
|
+
const useItemTrackerProvider = () => {
|
|
27059
|
+
const itemsRef = useRef([]);
|
|
27060
|
+
const items = itemsRef.current;
|
|
27061
|
+
const itemCountRef = useRef(0);
|
|
27062
|
+
const tracker = useMemo(() => {
|
|
27063
|
+
const ItemTrackerProvider = ({
|
|
27064
|
+
children
|
|
27065
|
+
}) => {
|
|
27066
|
+
// Reset on each render to start fresh
|
|
27067
|
+
tracker.reset();
|
|
27068
|
+
return jsx(ItemTrackerContext.Provider, {
|
|
27069
|
+
value: tracker,
|
|
27070
|
+
children: children
|
|
27071
|
+
});
|
|
27072
|
+
};
|
|
27073
|
+
ItemTrackerProvider.items = items;
|
|
27074
|
+
return {
|
|
27075
|
+
ItemTrackerProvider,
|
|
27076
|
+
items,
|
|
27077
|
+
registerItem: data => {
|
|
27078
|
+
const index = itemCountRef.current++;
|
|
27079
|
+
items[index] = data;
|
|
27080
|
+
return index;
|
|
27081
|
+
},
|
|
27082
|
+
getItem: index => {
|
|
27083
|
+
return items[index];
|
|
27084
|
+
},
|
|
27085
|
+
getAllItems: () => {
|
|
27086
|
+
return items;
|
|
27087
|
+
},
|
|
27088
|
+
reset: () => {
|
|
27089
|
+
items.length = 0;
|
|
27090
|
+
itemCountRef.current = 0;
|
|
26800
27091
|
}
|
|
26801
|
-
}
|
|
26802
|
-
|
|
27092
|
+
};
|
|
27093
|
+
}, []);
|
|
27094
|
+
return tracker.ItemTrackerProvider;
|
|
27095
|
+
};
|
|
27096
|
+
const useTrackItem = data => {
|
|
27097
|
+
const tracker = useContext(ItemTrackerContext);
|
|
27098
|
+
if (!tracker) {
|
|
27099
|
+
throw new Error("useTrackItem must be used within SimpleItemTrackerProvider");
|
|
26803
27100
|
}
|
|
26804
|
-
|
|
26805
|
-
|
|
26806
|
-
const
|
|
26807
|
-
|
|
26808
|
-
|
|
26809
|
-
|
|
26810
|
-
|
|
26811
|
-
|
|
26812
|
-
|
|
26813
|
-
|
|
26814
|
-
|
|
26815
|
-
}
|
|
26816
|
-
|
|
27101
|
+
return tracker.registerItem(data);
|
|
27102
|
+
};
|
|
27103
|
+
const useTrackedItem = index => {
|
|
27104
|
+
const trackedItems = useTrackedItems();
|
|
27105
|
+
const item = trackedItems[index];
|
|
27106
|
+
return item;
|
|
27107
|
+
};
|
|
27108
|
+
const useTrackedItems = () => {
|
|
27109
|
+
const tracker = useContext(ItemTrackerContext);
|
|
27110
|
+
if (!tracker) {
|
|
27111
|
+
throw new Error("useTrackedItems must be used within SimpleItemTrackerProvider");
|
|
27112
|
+
}
|
|
27113
|
+
return tracker.items;
|
|
27114
|
+
};
|
|
27115
|
+
return [useItemTrackerProvider, useTrackItem, useTrackedItem, useTrackedItems];
|
|
26817
27116
|
};
|
|
26818
|
-
|
|
26819
|
-
const
|
|
26820
|
-
|
|
26821
|
-
|
|
26822
|
-
|
|
26823
|
-
|
|
26824
|
-
|
|
26825
|
-
|
|
26826
|
-
|
|
26827
|
-
|
|
26828
|
-
|
|
26829
|
-
|
|
26830
|
-
|
|
26831
|
-
|
|
26832
|
-
|
|
26833
|
-
|
|
26834
|
-
|
|
26835
|
-
|
|
26836
|
-
|
|
26837
|
-
|
|
26838
|
-
|
|
26839
|
-
|
|
27117
|
+
|
|
27118
|
+
installImportMetaCssBuild(import.meta);const [useOptionItemTrackerProvider, useTrackOption] = createItemTracker();
|
|
27119
|
+
|
|
27120
|
+
/**
|
|
27121
|
+
* OptionList + Option: a composable accessible listbox.
|
|
27122
|
+
*
|
|
27123
|
+
* Usage:
|
|
27124
|
+
* <OptionList id="my-list" value={selected} onChange={setSelected}>
|
|
27125
|
+
* <Option value="a">Option A</Option>
|
|
27126
|
+
* <Option value="b">Option B</Option>
|
|
27127
|
+
* </OptionList>
|
|
27128
|
+
*
|
|
27129
|
+
* CSS vars on .navi_option_list:
|
|
27130
|
+
* --border-radius, --border-width, --border-color, --background-color, --max-height
|
|
27131
|
+
*
|
|
27132
|
+
* CSS vars on .navi_option:
|
|
27133
|
+
* --padding, --color, --background-color, --font-weight
|
|
27134
|
+
* --color-hover, --background-color-hover
|
|
27135
|
+
* --color-highlighted, --background-color-highlighted
|
|
27136
|
+
* --color-selected, --background-color-selected, --font-weight-selected
|
|
27137
|
+
* --color-highlighted-selected, --background-color-highlighted-selected
|
|
27138
|
+
*/
|
|
27139
|
+
|
|
27140
|
+
const css$g = /* css */`
|
|
27141
|
+
@layer navi {
|
|
27142
|
+
.navi_option_list {
|
|
27143
|
+
--border-radius: 4px;
|
|
27144
|
+
--border-width: 1px;
|
|
27145
|
+
--border-color: light-dark(#ccc, #555);
|
|
27146
|
+
--background-color: light-dark(#fff, #1e1e1e);
|
|
27147
|
+
--max-height: 220px;
|
|
27148
|
+
}
|
|
27149
|
+
.navi_option {
|
|
27150
|
+
--padding: 8px 12px;
|
|
27151
|
+
--color: inherit;
|
|
27152
|
+
--background-color: transparent;
|
|
27153
|
+
--font-weight: inherit;
|
|
27154
|
+
|
|
27155
|
+
/* Hover (mouse) */
|
|
27156
|
+
--color-hover: var(--color);
|
|
27157
|
+
--background-color-hover: light-dark(#f5f5f5, #2a2a2a);
|
|
27158
|
+
|
|
27159
|
+
/* Highlighted (keyboard navigation cursor) */
|
|
27160
|
+
--color-highlighted: var(--color);
|
|
27161
|
+
--background-color-highlighted: light-dark(#e8f0fe, #1c3a6e);
|
|
27162
|
+
|
|
27163
|
+
/* Selected */
|
|
27164
|
+
--color-selected: light-dark(#1a73e8, #7baaf7);
|
|
27165
|
+
--background-color-selected: light-dark(#e8f0fe, #1c3a6e);
|
|
27166
|
+
--font-weight-selected: 500;
|
|
27167
|
+
|
|
27168
|
+
/* Highlighted + selected */
|
|
27169
|
+
--color-highlighted-selected: var(--color-selected);
|
|
27170
|
+
--background-color-highlighted-selected: light-dark(#d2e3fc, #174ea6);
|
|
27171
|
+
}
|
|
27172
|
+
}
|
|
27173
|
+
|
|
27174
|
+
.navi_option_list {
|
|
27175
|
+
--x-border-radius: var(--border-radius);
|
|
27176
|
+
--x-border-width: var(--border-width);
|
|
27177
|
+
--x-border-color: var(--border-color);
|
|
27178
|
+
--x-background-color: var(--background-color);
|
|
27179
|
+
box-sizing: border-box;
|
|
27180
|
+
max-height: var(--max-height);
|
|
27181
|
+
|
|
27182
|
+
margin: 0;
|
|
27183
|
+
padding: 0;
|
|
27184
|
+
list-style: none;
|
|
27185
|
+
background-color: var(--x-background-color);
|
|
27186
|
+
border: var(--x-border-width) solid var(--x-border-color);
|
|
27187
|
+
border-radius: var(--x-border-radius);
|
|
27188
|
+
outline: none;
|
|
27189
|
+
overflow-y: auto;
|
|
27190
|
+
|
|
27191
|
+
/* Popover reset — browser adds border, background, padding, margin by default */
|
|
27192
|
+
&[popover] {
|
|
27193
|
+
position: fixed;
|
|
27194
|
+
inset: unset;
|
|
27195
|
+
margin: 0;
|
|
27196
|
+
padding: 0;
|
|
27197
|
+
border: none;
|
|
27198
|
+
}
|
|
27199
|
+
}
|
|
27200
|
+
.navi_option {
|
|
27201
|
+
--x-color: var(--color);
|
|
27202
|
+
--x-background-color: var(--background-color);
|
|
27203
|
+
--x-font-weight: var(--font-weight);
|
|
27204
|
+
|
|
27205
|
+
padding: var(--padding);
|
|
27206
|
+
color: var(--x-color);
|
|
27207
|
+
font-weight: var(--x-font-weight);
|
|
27208
|
+
background-color: var(--x-background-color);
|
|
27209
|
+
cursor: pointer;
|
|
27210
|
+
user-select: none;
|
|
27211
|
+
|
|
27212
|
+
&:hover {
|
|
27213
|
+
--x-color: var(--color-hover);
|
|
27214
|
+
--x-background-color: var(--background-color-hover);
|
|
27215
|
+
}
|
|
27216
|
+
|
|
27217
|
+
&[data-highlighted] {
|
|
27218
|
+
--x-color: var(--color-highlighted);
|
|
27219
|
+
--x-background-color: var(--background-color-highlighted);
|
|
27220
|
+
}
|
|
27221
|
+
|
|
27222
|
+
&[data-selected] {
|
|
27223
|
+
--x-color: var(--color-selected);
|
|
27224
|
+
--x-background-color: var(--background-color-selected);
|
|
27225
|
+
--x-font-weight: var(--font-weight-selected);
|
|
27226
|
+
}
|
|
27227
|
+
|
|
27228
|
+
&[data-highlighted][data-selected] {
|
|
27229
|
+
--x-color: var(--color-highlighted-selected);
|
|
27230
|
+
--x-background-color: var(--background-color-highlighted-selected);
|
|
27231
|
+
}
|
|
27232
|
+
}
|
|
27233
|
+
`;
|
|
27234
|
+
|
|
27235
|
+
/**
|
|
27236
|
+
* Context OptionList provides downward to its Option children.
|
|
27237
|
+
*/
|
|
27238
|
+
const OptionListContext = createContext(null);
|
|
27239
|
+
const OptionList = ({
|
|
27240
|
+
popover,
|
|
27241
|
+
onChange: onChangeProp,
|
|
27242
|
+
children,
|
|
27243
|
+
...rest
|
|
27244
|
+
}) => {
|
|
27245
|
+
import.meta.css = [css$g, "@jsenv/navi/src/field/option_list.jsx"];
|
|
27246
|
+
const ItemTrackerProvider = useOptionItemTrackerProvider();
|
|
27247
|
+
const [highlightedValue, setHighlightedValue] = useState(null);
|
|
27248
|
+
const highlightedValueRef = useRef(null);
|
|
27249
|
+
highlightedValueRef.current = highlightedValue;
|
|
27250
|
+
const ownId = useId();
|
|
27251
|
+
const id = rest.id ?? ownId;
|
|
27252
|
+
const listRef = useRef(null);
|
|
27253
|
+
const effectiveOnChange = popover ? value => {
|
|
27254
|
+
onChangeProp?.(value);
|
|
27255
|
+
listRef.current?.dispatchEvent(new CustomEvent("combobox-selected", {
|
|
27256
|
+
detail: {
|
|
27257
|
+
value
|
|
27258
|
+
},
|
|
27259
|
+
bubbles: true
|
|
27260
|
+
}));
|
|
27261
|
+
} : onChangeProp;
|
|
27262
|
+
const onChangeRef = useRef(effectiveOnChange);
|
|
27263
|
+
onChangeRef.current = effectiveOnChange;
|
|
27264
|
+
const navigate = direction => {
|
|
27265
|
+
const values = ItemTrackerProvider.items.filter(item => !item.hidden).map(item => item.value);
|
|
27266
|
+
if (values.length === 0) {
|
|
27267
|
+
return false;
|
|
27268
|
+
}
|
|
27269
|
+
const current = highlightedValueRef.current;
|
|
27270
|
+
if (direction === "down") {
|
|
27271
|
+
const idx = current === null ? -1 : values.indexOf(current);
|
|
27272
|
+
setHighlightedValue(values[idx < values.length - 1 ? idx + 1 : idx]);
|
|
27273
|
+
} else if (direction === "up") {
|
|
27274
|
+
const idx = current === null ? -1 : values.indexOf(current);
|
|
27275
|
+
setHighlightedValue(values[idx > 0 ? idx - 1 : 0]);
|
|
27276
|
+
} else if (direction === "first") {
|
|
27277
|
+
setHighlightedValue(values[0]);
|
|
27278
|
+
} else if (direction === "last") {
|
|
27279
|
+
setHighlightedValue(values[values.length - 1]);
|
|
27280
|
+
}
|
|
27281
|
+
return true;
|
|
27282
|
+
};
|
|
27283
|
+
|
|
27284
|
+
// Listen for commands dispatched by a linked Input (combobox mode)
|
|
27285
|
+
const noopRef = useRef(null);
|
|
27286
|
+
useEffect(() => {
|
|
27287
|
+
if (!popover || !listRef.current) {
|
|
27288
|
+
return undefined;
|
|
27289
|
+
}
|
|
27290
|
+
const el = listRef.current;
|
|
27291
|
+
const onNavigate = e => {
|
|
27292
|
+
navigate(e.detail.direction);
|
|
27293
|
+
};
|
|
27294
|
+
const onConfirm = e => {
|
|
27295
|
+
const current = highlightedValueRef.current;
|
|
27296
|
+
if (current !== null) {
|
|
27297
|
+
onChangeRef.current?.(current);
|
|
27298
|
+
e.preventDefault();
|
|
27299
|
+
}
|
|
27300
|
+
};
|
|
27301
|
+
const onClear = () => {
|
|
27302
|
+
setHighlightedValue(null);
|
|
27303
|
+
};
|
|
27304
|
+
el.addEventListener("combobox-navigate", onNavigate);
|
|
27305
|
+
el.addEventListener("combobox-confirm", onConfirm);
|
|
27306
|
+
el.addEventListener("combobox-clear", onClear);
|
|
27307
|
+
return () => {
|
|
27308
|
+
el.removeEventListener("combobox-navigate", onNavigate);
|
|
27309
|
+
el.removeEventListener("combobox-confirm", onConfirm);
|
|
27310
|
+
el.removeEventListener("combobox-clear", onClear);
|
|
27311
|
+
};
|
|
27312
|
+
}, [popover]);
|
|
27313
|
+
useKeyboardShortcuts(popover ? noopRef : listRef, [{
|
|
27314
|
+
key: "arrowdown",
|
|
27315
|
+
description: "Highlight next option",
|
|
27316
|
+
handler: () => navigate("down")
|
|
27317
|
+
}, {
|
|
27318
|
+
key: "arrowup",
|
|
27319
|
+
description: "Highlight previous option",
|
|
27320
|
+
handler: () => navigate("up")
|
|
27321
|
+
}, {
|
|
27322
|
+
key: "home",
|
|
27323
|
+
description: "Highlight first option",
|
|
27324
|
+
handler: () => navigate("first")
|
|
27325
|
+
}, {
|
|
27326
|
+
key: "end",
|
|
27327
|
+
description: "Highlight last option",
|
|
27328
|
+
handler: () => navigate("last")
|
|
27329
|
+
}, {
|
|
27330
|
+
key: "enter",
|
|
27331
|
+
description: "Select highlighted option",
|
|
27332
|
+
handler: () => {
|
|
27333
|
+
const current = highlightedValueRef.current;
|
|
27334
|
+
if (current === null) {
|
|
27335
|
+
return false;
|
|
27336
|
+
}
|
|
27337
|
+
onChangeRef.current?.(current);
|
|
27338
|
+
return true;
|
|
27339
|
+
}
|
|
27340
|
+
}, {
|
|
27341
|
+
key: "escape",
|
|
27342
|
+
description: "Clear highlighted option",
|
|
27343
|
+
handler: () => {
|
|
27344
|
+
setHighlightedValue(null);
|
|
27345
|
+
return true;
|
|
27346
|
+
}
|
|
27347
|
+
}]);
|
|
27348
|
+
const optionListContext = {
|
|
27349
|
+
highlightedValue,
|
|
27350
|
+
setHighlightedValue,
|
|
27351
|
+
onSelect: effectiveOnChange
|
|
27352
|
+
};
|
|
27353
|
+
return jsx(Box, {
|
|
27354
|
+
as: "ul",
|
|
27355
|
+
ref: listRef,
|
|
27356
|
+
id: id,
|
|
27357
|
+
role: "listbox",
|
|
27358
|
+
tabIndex: popover ? -1 : 0,
|
|
27359
|
+
popover: popover ? "manual" : undefined,
|
|
27360
|
+
...rest,
|
|
27361
|
+
baseClassName: "navi_option_list",
|
|
27362
|
+
children: jsx(OptionListContext.Provider, {
|
|
27363
|
+
value: optionListContext,
|
|
27364
|
+
children: jsx(ItemTrackerProvider, {
|
|
27365
|
+
children: children
|
|
27366
|
+
})
|
|
27367
|
+
})
|
|
27368
|
+
});
|
|
27369
|
+
};
|
|
27370
|
+
const OPTION_PSEUDO_CLASSES = [":-navi-highlighted", ":-navi-selected"];
|
|
27371
|
+
const Option = ({
|
|
27372
|
+
value,
|
|
27373
|
+
selected,
|
|
27374
|
+
hidden,
|
|
27375
|
+
children,
|
|
27376
|
+
...rest
|
|
27377
|
+
}) => {
|
|
27378
|
+
import.meta.css = [css$g, "@jsenv/navi/src/field/option_list.jsx"];
|
|
27379
|
+
const optionId = useId();
|
|
27380
|
+
const id = rest.id || optionId;
|
|
27381
|
+
useTrackOption({
|
|
27382
|
+
value,
|
|
27383
|
+
optionId: id,
|
|
27384
|
+
hidden
|
|
27385
|
+
});
|
|
27386
|
+
const {
|
|
27387
|
+
highlightedValue,
|
|
27388
|
+
setHighlightedValue,
|
|
27389
|
+
onSelect
|
|
27390
|
+
} = useContext(OptionListContext);
|
|
27391
|
+
const isHighlighted = highlightedValue === value;
|
|
27392
|
+
const optionRef = useRef(null);
|
|
27393
|
+
useEffect(() => {
|
|
27394
|
+
const optionEl = optionRef.current;
|
|
27395
|
+
if (isHighlighted && optionEl) {
|
|
27396
|
+
optionEl.scrollIntoView({
|
|
27397
|
+
block: "nearest"
|
|
27398
|
+
});
|
|
27399
|
+
}
|
|
27400
|
+
}, [isHighlighted]);
|
|
27401
|
+
return jsx(Box, {
|
|
27402
|
+
as: "li",
|
|
27403
|
+
ref: optionRef,
|
|
27404
|
+
baseClassName: "navi_option",
|
|
27405
|
+
id: optionId,
|
|
27406
|
+
role: "option",
|
|
27407
|
+
"aria-selected": selected,
|
|
27408
|
+
"aria-hidden": hidden ? true : undefined,
|
|
27409
|
+
hidden: hidden,
|
|
27410
|
+
basePseudoState: {
|
|
27411
|
+
":-navi-highlighted": isHighlighted,
|
|
27412
|
+
":-navi-selected": selected
|
|
27413
|
+
},
|
|
27414
|
+
pseudoClasses: OPTION_PSEUDO_CLASSES,
|
|
27415
|
+
onMouseEnter: () => {
|
|
27416
|
+
if (!hidden) {
|
|
27417
|
+
setHighlightedValue(value);
|
|
27418
|
+
}
|
|
27419
|
+
},
|
|
27420
|
+
onMouseLeave: () => {
|
|
27421
|
+
if (!hidden) {
|
|
27422
|
+
setHighlightedValue(null);
|
|
27423
|
+
}
|
|
27424
|
+
},
|
|
27425
|
+
onMouseDown: e => {
|
|
27426
|
+
if (hidden || e.button !== 0) {
|
|
27427
|
+
return;
|
|
27428
|
+
}
|
|
27429
|
+
onSelect?.(value);
|
|
27430
|
+
},
|
|
27431
|
+
...rest,
|
|
27432
|
+
children: children
|
|
27433
|
+
});
|
|
27434
|
+
};
|
|
27435
|
+
|
|
27436
|
+
const RadioList = props => {
|
|
27437
|
+
const uiStateController = useUIGroupStateController(props, "radio_list", {
|
|
27438
|
+
childComponentType: "radio",
|
|
27439
|
+
aggregateChildStates: childUIStateControllers => {
|
|
27440
|
+
let activeValue;
|
|
27441
|
+
for (const childUIStateController of childUIStateControllers) {
|
|
27442
|
+
if (childUIStateController.uiState) {
|
|
27443
|
+
activeValue = childUIStateController.uiState;
|
|
27444
|
+
break;
|
|
27445
|
+
}
|
|
27446
|
+
}
|
|
27447
|
+
return activeValue;
|
|
27448
|
+
}
|
|
27449
|
+
});
|
|
27450
|
+
const uiState = useUIState(uiStateController);
|
|
27451
|
+
const radioList = renderActionableComponent(props, {
|
|
27452
|
+
Basic: RadioListBasic,
|
|
27453
|
+
WithAction: RadioListWithAction
|
|
27454
|
+
});
|
|
27455
|
+
return jsx(UIStateControllerContext.Provider, {
|
|
27456
|
+
value: uiStateController,
|
|
27457
|
+
children: jsx(UIStateContext.Provider, {
|
|
27458
|
+
value: uiState,
|
|
27459
|
+
children: radioList
|
|
27460
|
+
})
|
|
27461
|
+
});
|
|
27462
|
+
};
|
|
27463
|
+
const Radio = InputRadio;
|
|
27464
|
+
const RadioListBasic = props => {
|
|
27465
|
+
const contextReadOnly = useContext(ReadOnlyContext);
|
|
27466
|
+
const contextDisabled = useContext(DisabledContext);
|
|
27467
|
+
const contextLoading = useContext(LoadingContext);
|
|
27468
|
+
const uiStateController = useContext(UIStateControllerContext);
|
|
27469
|
+
const {
|
|
27470
|
+
name,
|
|
27471
|
+
loading,
|
|
27472
|
+
disabled,
|
|
27473
|
+
readOnly,
|
|
27474
|
+
children,
|
|
27475
|
+
required,
|
|
27476
|
+
...rest
|
|
27477
|
+
} = props;
|
|
27478
|
+
const innerLoading = loading || contextLoading;
|
|
27479
|
+
const innerReadOnly = readOnly || contextReadOnly || innerLoading || uiStateController.readOnly;
|
|
27480
|
+
const innerDisabled = disabled || contextDisabled;
|
|
27481
|
+
return jsx(Box, {
|
|
27482
|
+
"data-action": rest["data-action"],
|
|
27483
|
+
flex: "y",
|
|
27484
|
+
...rest,
|
|
26840
27485
|
baseClassName: "navi_radio_list",
|
|
26841
27486
|
"data-radio-list": "",
|
|
26842
27487
|
onresetuistate: e => {
|
|
@@ -27258,6 +27903,131 @@ const filterTableSelection = (selection, predicate) => {
|
|
|
27258
27903
|
return matching;
|
|
27259
27904
|
};
|
|
27260
27905
|
|
|
27906
|
+
// https://github.com/reach/reach-ui/tree/b3d94d22811db6b5c0f272b9a7e2e3c1bb4699ae/packages/descendants
|
|
27907
|
+
// https://github.com/pacocoursey/use-descendants/tree/master
|
|
27908
|
+
|
|
27909
|
+
const createIsolatedItemTracker = () => {
|
|
27910
|
+
// Producer contexts (ref-based, no re-renders)
|
|
27911
|
+
const ProducerTrackerContext = createContext();
|
|
27912
|
+
const ProducerItemCountRefContext = createContext();
|
|
27913
|
+
const ProducerListRenderIdContext = createContext();
|
|
27914
|
+
|
|
27915
|
+
// Consumer contexts (state-based, re-renders)
|
|
27916
|
+
const ConsumerItemsContext = createContext();
|
|
27917
|
+
const useIsolatedItemTrackerProvider = () => {
|
|
27918
|
+
const itemsRef = useRef([]);
|
|
27919
|
+
const items = itemsRef.current;
|
|
27920
|
+
const itemCountRef = useRef();
|
|
27921
|
+
const itemTracker = useMemo(() => {
|
|
27922
|
+
// Snapshot taken by FlushSentinel after all producer children rendered.
|
|
27923
|
+
// Consumers read from this — always up-to-date within the same render pass.
|
|
27924
|
+
const itemsSnapshotRef = {
|
|
27925
|
+
current: items
|
|
27926
|
+
};
|
|
27927
|
+
const registerItem = (index, value) => {
|
|
27928
|
+
const hasValue = index in items;
|
|
27929
|
+
if (hasValue) {
|
|
27930
|
+
const currentValue = items[index];
|
|
27931
|
+
if (compareTwoJsValues(currentValue, value)) {
|
|
27932
|
+
return;
|
|
27933
|
+
}
|
|
27934
|
+
}
|
|
27935
|
+
items[index] = value;
|
|
27936
|
+
};
|
|
27937
|
+
const getProducerItem = itemIndex => {
|
|
27938
|
+
return items[itemIndex];
|
|
27939
|
+
};
|
|
27940
|
+
const ItemProducerProvider = ({
|
|
27941
|
+
children
|
|
27942
|
+
}) => {
|
|
27943
|
+
items.length = 0;
|
|
27944
|
+
itemCountRef.current = 0;
|
|
27945
|
+
const listRenderId = {};
|
|
27946
|
+
return jsx(ProducerItemCountRefContext.Provider, {
|
|
27947
|
+
value: itemCountRef,
|
|
27948
|
+
children: jsx(ProducerListRenderIdContext.Provider, {
|
|
27949
|
+
value: listRenderId,
|
|
27950
|
+
children: jsxs(ProducerTrackerContext.Provider, {
|
|
27951
|
+
value: itemTracker,
|
|
27952
|
+
children: [children, jsx(FlushSentinel, {})]
|
|
27953
|
+
})
|
|
27954
|
+
})
|
|
27955
|
+
});
|
|
27956
|
+
};
|
|
27957
|
+
|
|
27958
|
+
// Renders after all producer children (e.g. <Col>) have registered their
|
|
27959
|
+
// items. Taking a snapshot here guarantees the consumer sees the correct
|
|
27960
|
+
// item list within the same render pass, without any heuristic.
|
|
27961
|
+
const FlushSentinel = () => {
|
|
27962
|
+
itemsSnapshotRef.current = items;
|
|
27963
|
+
return null;
|
|
27964
|
+
};
|
|
27965
|
+
const ItemConsumerProvider = ({
|
|
27966
|
+
children
|
|
27967
|
+
}) => {
|
|
27968
|
+
// FlushSentinel (last child of ItemProducerProvider) already set
|
|
27969
|
+
// itemsSnapshotRef.current to the up-to-date items array before any
|
|
27970
|
+
// consumer rendered. Reading from the snapshot is always correct.
|
|
27971
|
+
return jsx(ConsumerItemsContext.Provider, {
|
|
27972
|
+
value: itemsSnapshotRef.current,
|
|
27973
|
+
children: children
|
|
27974
|
+
});
|
|
27975
|
+
};
|
|
27976
|
+
return {
|
|
27977
|
+
registerItem,
|
|
27978
|
+
getProducerItem,
|
|
27979
|
+
ItemProducerProvider,
|
|
27980
|
+
ItemConsumerProvider
|
|
27981
|
+
};
|
|
27982
|
+
}, []);
|
|
27983
|
+
const {
|
|
27984
|
+
ItemProducerProvider,
|
|
27985
|
+
ItemConsumerProvider
|
|
27986
|
+
} = itemTracker;
|
|
27987
|
+
return [ItemProducerProvider, ItemConsumerProvider, items];
|
|
27988
|
+
};
|
|
27989
|
+
|
|
27990
|
+
// Hook for producers to register items (ref-based, no re-renders)
|
|
27991
|
+
const useTrackIsolatedItem = data => {
|
|
27992
|
+
const listRenderId = useContext(ProducerListRenderIdContext);
|
|
27993
|
+
const itemCountRef = useContext(ProducerItemCountRefContext);
|
|
27994
|
+
const itemTracker = useContext(ProducerTrackerContext);
|
|
27995
|
+
const listRenderIdRef = useRef();
|
|
27996
|
+
const itemIndexRef = useRef();
|
|
27997
|
+
const dataRef = useRef();
|
|
27998
|
+
const prevListRenderId = listRenderIdRef.current;
|
|
27999
|
+
if (prevListRenderId === listRenderId) {
|
|
28000
|
+
const itemIndex = itemIndexRef.current;
|
|
28001
|
+
itemTracker.registerItem(itemIndex, data);
|
|
28002
|
+
dataRef.current = data;
|
|
28003
|
+
return itemIndex;
|
|
28004
|
+
}
|
|
28005
|
+
listRenderIdRef.current = listRenderId;
|
|
28006
|
+
const itemCount = itemCountRef.current;
|
|
28007
|
+
const itemIndex = itemCount;
|
|
28008
|
+
itemCountRef.current = itemIndex + 1;
|
|
28009
|
+
itemIndexRef.current = itemIndex;
|
|
28010
|
+
dataRef.current = data;
|
|
28011
|
+
itemTracker.registerItem(itemIndex, data);
|
|
28012
|
+
return itemIndex;
|
|
28013
|
+
};
|
|
28014
|
+
const useTrackedIsolatedItem = itemIndex => {
|
|
28015
|
+
const items = useTrackedIsolatedItems();
|
|
28016
|
+
const item = items[itemIndex];
|
|
28017
|
+
return item;
|
|
28018
|
+
};
|
|
28019
|
+
|
|
28020
|
+
// Hooks for consumers to read items (state-based, re-renders)
|
|
28021
|
+
const useTrackedIsolatedItems = () => {
|
|
28022
|
+
const consumerItems = useContext(ConsumerItemsContext);
|
|
28023
|
+
if (!consumerItems) {
|
|
28024
|
+
throw new Error("useTrackedIsolatedItems must be used within <ItemConsumerProvider />");
|
|
28025
|
+
}
|
|
28026
|
+
return consumerItems;
|
|
28027
|
+
};
|
|
28028
|
+
return [useIsolatedItemTrackerProvider, useTrackIsolatedItem, useTrackedIsolatedItem, useTrackedIsolatedItems];
|
|
28029
|
+
};
|
|
28030
|
+
|
|
27261
28031
|
const Z_INDEX_EDITING = 1; /* To go above neighbours, but should not be too big to stay under the sticky cells */
|
|
27262
28032
|
|
|
27263
28033
|
/* needed because cell uses position:relative, sticky must win even if before in DOM order */
|
|
@@ -27714,193 +28484,6 @@ const createTableAttributeSync = (table, tableClone) => {
|
|
|
27714
28484
|
return observer;
|
|
27715
28485
|
};
|
|
27716
28486
|
|
|
27717
|
-
// https://github.com/reach/reach-ui/tree/b3d94d22811db6b5c0f272b9a7e2e3c1bb4699ae/packages/descendants
|
|
27718
|
-
// https://github.com/pacocoursey/use-descendants/tree/master
|
|
27719
|
-
|
|
27720
|
-
const createIsolatedItemTracker = () => {
|
|
27721
|
-
// Producer contexts (ref-based, no re-renders)
|
|
27722
|
-
const ProducerTrackerContext = createContext();
|
|
27723
|
-
const ProducerItemCountRefContext = createContext();
|
|
27724
|
-
const ProducerListRenderIdContext = createContext();
|
|
27725
|
-
|
|
27726
|
-
// Consumer contexts (state-based, re-renders)
|
|
27727
|
-
const ConsumerItemsContext = createContext();
|
|
27728
|
-
const useIsolatedItemTrackerProvider = () => {
|
|
27729
|
-
const itemsRef = useRef([]);
|
|
27730
|
-
const items = itemsRef.current;
|
|
27731
|
-
const itemCountRef = useRef();
|
|
27732
|
-
const itemTracker = useMemo(() => {
|
|
27733
|
-
// Snapshot taken by FlushSentinel after all producer children rendered.
|
|
27734
|
-
// Consumers read from this — always up-to-date within the same render pass.
|
|
27735
|
-
const itemsSnapshotRef = {
|
|
27736
|
-
current: items
|
|
27737
|
-
};
|
|
27738
|
-
const registerItem = (index, value) => {
|
|
27739
|
-
const hasValue = index in items;
|
|
27740
|
-
if (hasValue) {
|
|
27741
|
-
const currentValue = items[index];
|
|
27742
|
-
if (compareTwoJsValues(currentValue, value)) {
|
|
27743
|
-
return;
|
|
27744
|
-
}
|
|
27745
|
-
}
|
|
27746
|
-
items[index] = value;
|
|
27747
|
-
};
|
|
27748
|
-
const getProducerItem = itemIndex => {
|
|
27749
|
-
return items[itemIndex];
|
|
27750
|
-
};
|
|
27751
|
-
const ItemProducerProvider = ({
|
|
27752
|
-
children
|
|
27753
|
-
}) => {
|
|
27754
|
-
items.length = 0;
|
|
27755
|
-
itemCountRef.current = 0;
|
|
27756
|
-
const listRenderId = {};
|
|
27757
|
-
return jsx(ProducerItemCountRefContext.Provider, {
|
|
27758
|
-
value: itemCountRef,
|
|
27759
|
-
children: jsx(ProducerListRenderIdContext.Provider, {
|
|
27760
|
-
value: listRenderId,
|
|
27761
|
-
children: jsxs(ProducerTrackerContext.Provider, {
|
|
27762
|
-
value: itemTracker,
|
|
27763
|
-
children: [children, jsx(FlushSentinel, {})]
|
|
27764
|
-
})
|
|
27765
|
-
})
|
|
27766
|
-
});
|
|
27767
|
-
};
|
|
27768
|
-
|
|
27769
|
-
// Renders after all producer children (e.g. <Col>) have registered their
|
|
27770
|
-
// items. Taking a snapshot here guarantees the consumer sees the correct
|
|
27771
|
-
// item list within the same render pass, without any heuristic.
|
|
27772
|
-
const FlushSentinel = () => {
|
|
27773
|
-
itemsSnapshotRef.current = items;
|
|
27774
|
-
return null;
|
|
27775
|
-
};
|
|
27776
|
-
const ItemConsumerProvider = ({
|
|
27777
|
-
children
|
|
27778
|
-
}) => {
|
|
27779
|
-
// FlushSentinel (last child of ItemProducerProvider) already set
|
|
27780
|
-
// itemsSnapshotRef.current to the up-to-date items array before any
|
|
27781
|
-
// consumer rendered. Reading from the snapshot is always correct.
|
|
27782
|
-
return jsx(ConsumerItemsContext.Provider, {
|
|
27783
|
-
value: itemsSnapshotRef.current,
|
|
27784
|
-
children: children
|
|
27785
|
-
});
|
|
27786
|
-
};
|
|
27787
|
-
return {
|
|
27788
|
-
registerItem,
|
|
27789
|
-
getProducerItem,
|
|
27790
|
-
ItemProducerProvider,
|
|
27791
|
-
ItemConsumerProvider
|
|
27792
|
-
};
|
|
27793
|
-
}, []);
|
|
27794
|
-
const {
|
|
27795
|
-
ItemProducerProvider,
|
|
27796
|
-
ItemConsumerProvider
|
|
27797
|
-
} = itemTracker;
|
|
27798
|
-
return [ItemProducerProvider, ItemConsumerProvider, items];
|
|
27799
|
-
};
|
|
27800
|
-
|
|
27801
|
-
// Hook for producers to register items (ref-based, no re-renders)
|
|
27802
|
-
const useTrackIsolatedItem = data => {
|
|
27803
|
-
const listRenderId = useContext(ProducerListRenderIdContext);
|
|
27804
|
-
const itemCountRef = useContext(ProducerItemCountRefContext);
|
|
27805
|
-
const itemTracker = useContext(ProducerTrackerContext);
|
|
27806
|
-
const listRenderIdRef = useRef();
|
|
27807
|
-
const itemIndexRef = useRef();
|
|
27808
|
-
const dataRef = useRef();
|
|
27809
|
-
const prevListRenderId = listRenderIdRef.current;
|
|
27810
|
-
if (prevListRenderId === listRenderId) {
|
|
27811
|
-
const itemIndex = itemIndexRef.current;
|
|
27812
|
-
itemTracker.registerItem(itemIndex, data);
|
|
27813
|
-
dataRef.current = data;
|
|
27814
|
-
return itemIndex;
|
|
27815
|
-
}
|
|
27816
|
-
listRenderIdRef.current = listRenderId;
|
|
27817
|
-
const itemCount = itemCountRef.current;
|
|
27818
|
-
const itemIndex = itemCount;
|
|
27819
|
-
itemCountRef.current = itemIndex + 1;
|
|
27820
|
-
itemIndexRef.current = itemIndex;
|
|
27821
|
-
dataRef.current = data;
|
|
27822
|
-
itemTracker.registerItem(itemIndex, data);
|
|
27823
|
-
return itemIndex;
|
|
27824
|
-
};
|
|
27825
|
-
const useTrackedIsolatedItem = itemIndex => {
|
|
27826
|
-
const items = useTrackedIsolatedItems();
|
|
27827
|
-
const item = items[itemIndex];
|
|
27828
|
-
return item;
|
|
27829
|
-
};
|
|
27830
|
-
|
|
27831
|
-
// Hooks for consumers to read items (state-based, re-renders)
|
|
27832
|
-
const useTrackedIsolatedItems = () => {
|
|
27833
|
-
const consumerItems = useContext(ConsumerItemsContext);
|
|
27834
|
-
if (!consumerItems) {
|
|
27835
|
-
throw new Error("useTrackedIsolatedItems must be used within <ItemConsumerProvider />");
|
|
27836
|
-
}
|
|
27837
|
-
return consumerItems;
|
|
27838
|
-
};
|
|
27839
|
-
return [useIsolatedItemTrackerProvider, useTrackIsolatedItem, useTrackedIsolatedItem, useTrackedIsolatedItems];
|
|
27840
|
-
};
|
|
27841
|
-
|
|
27842
|
-
const createItemTracker = () => {
|
|
27843
|
-
const ItemTrackerContext = createContext();
|
|
27844
|
-
const useItemTrackerProvider = () => {
|
|
27845
|
-
const itemsRef = useRef([]);
|
|
27846
|
-
const items = itemsRef.current;
|
|
27847
|
-
const itemCountRef = useRef(0);
|
|
27848
|
-
const tracker = useMemo(() => {
|
|
27849
|
-
const ItemTrackerProvider = ({
|
|
27850
|
-
children
|
|
27851
|
-
}) => {
|
|
27852
|
-
// Reset on each render to start fresh
|
|
27853
|
-
tracker.reset();
|
|
27854
|
-
return jsx(ItemTrackerContext.Provider, {
|
|
27855
|
-
value: tracker,
|
|
27856
|
-
children: children
|
|
27857
|
-
});
|
|
27858
|
-
};
|
|
27859
|
-
ItemTrackerProvider.items = items;
|
|
27860
|
-
return {
|
|
27861
|
-
ItemTrackerProvider,
|
|
27862
|
-
items,
|
|
27863
|
-
registerItem: data => {
|
|
27864
|
-
const index = itemCountRef.current++;
|
|
27865
|
-
items[index] = data;
|
|
27866
|
-
return index;
|
|
27867
|
-
},
|
|
27868
|
-
getItem: index => {
|
|
27869
|
-
return items[index];
|
|
27870
|
-
},
|
|
27871
|
-
getAllItems: () => {
|
|
27872
|
-
return items;
|
|
27873
|
-
},
|
|
27874
|
-
reset: () => {
|
|
27875
|
-
items.length = 0;
|
|
27876
|
-
itemCountRef.current = 0;
|
|
27877
|
-
}
|
|
27878
|
-
};
|
|
27879
|
-
}, []);
|
|
27880
|
-
return tracker.ItemTrackerProvider;
|
|
27881
|
-
};
|
|
27882
|
-
const useTrackItem = data => {
|
|
27883
|
-
const tracker = useContext(ItemTrackerContext);
|
|
27884
|
-
if (!tracker) {
|
|
27885
|
-
throw new Error("useTrackItem must be used within SimpleItemTrackerProvider");
|
|
27886
|
-
}
|
|
27887
|
-
return tracker.registerItem(data);
|
|
27888
|
-
};
|
|
27889
|
-
const useTrackedItem = index => {
|
|
27890
|
-
const trackedItems = useTrackedItems();
|
|
27891
|
-
const item = trackedItems[index];
|
|
27892
|
-
return item;
|
|
27893
|
-
};
|
|
27894
|
-
const useTrackedItems = () => {
|
|
27895
|
-
const tracker = useContext(ItemTrackerContext);
|
|
27896
|
-
if (!tracker) {
|
|
27897
|
-
throw new Error("useTrackedItems must be used within SimpleItemTrackerProvider");
|
|
27898
|
-
}
|
|
27899
|
-
return tracker.items;
|
|
27900
|
-
};
|
|
27901
|
-
return [useItemTrackerProvider, useTrackItem, useTrackedItem, useTrackedItems];
|
|
27902
|
-
};
|
|
27903
|
-
|
|
27904
28487
|
const TableSizeContext = createContext();
|
|
27905
28488
|
|
|
27906
28489
|
const useTableSizeContextValue = ({
|
|
@@ -32819,5 +33402,5 @@ const UserSvg = () => jsx("svg", {
|
|
|
32819
33402
|
})
|
|
32820
33403
|
});
|
|
32821
33404
|
|
|
32822
|
-
export { ActionRenderer, ActiveKeyboardShortcuts, Address, Badge, BadgeCount, Box, Button, ButtonCopyToClipboard, Caption, CheckSvg, Checkbox, CheckboxList, CloseSvg, Code, Col, Colgroup, ConstructionSvg, Details, DialogLayout, Editable, ErrorBoundary, ErrorBoundaryContext, ExclamationSvg, EyeClosedSvg, EyeSvg, Form, Group, Head, HeartSvg, HomeSvg, Icon, Image, Input, Label, Link, LinkAnchorSvg, LinkBlankTargetSvg, LinkCurrentSvg, Loading, MessageBox, Meter, Nav, Paragraph, Quantity, QuantityIntl, Radio, RadioList, Route, RowNumberCol, RowNumberTableCell, SVGMaskOverlay, SearchSvg, Select, SelectionContext, Separator, SettingsSvg, SidePanel, StarSvg, SummaryMarker, Svg, Table, TableCell, Tbody, Text, Thead, Title, Tr, UITransition, UserSvg, ViewportLayout, actionIntegratedVia, actionRunEffect, addCustomMessage, arraySignalMembership, compareTwoJsValues, createAction, createAvailableConstraint, createIntl, createRequestCanceller, createSelectionKeyboardShortcuts, enableDebugActions, enableDebugOnDocumentLoading, filterTableSelection, forwardActionRequested, installCustomConstraintValidation, isCellSelected, isColumnSelected, isRowSelected, localStorageSignal, navBack, navForward, navTo, openCallout, rawUrlPart, reload, removeCustomMessage, requestAction, rerunActions, resource, route, routeAction, setBaseUrl, setupRoutes, stateSignal, stopLoad, stringifyTableSelectionValue, syncOwnedResourceToSignals, syncResourceToSignals, updateActions, useActionStatus, useArraySignalMembership, useAsyncData, useCalloutClose, useCancelPrevious, useCellGridFromRows, useConstraintValidityState, useDarkBackgroundAttribute, useDependenciesDiff, useDocumentResource, useDocumentState, useDocumentUrl, useEditionController, useFocusGroup, useKeyboardShortcuts, useNavState$1 as useNavState, useOrderedColumns, useRouteStatus, useRunOnMount, useSelectableElement, useSelectionController, useSidePanelClose, useSignalSync, useStateArray, useTitleLevel, useUrlSearchParam, valueInLocalStorage };
|
|
33405
|
+
export { ActionRenderer, ActiveKeyboardShortcuts, Address, Badge, BadgeCount, Box, Button, ButtonCopyToClipboard, Caption, CheckSvg, Checkbox, CheckboxList, CloseSvg, Code, Col, Colgroup, ConstructionSvg, Details, DialogLayout, Editable, ErrorBoundary, ErrorBoundaryContext, ExclamationSvg, EyeClosedSvg, EyeSvg, Form, Group, Head, HeartSvg, HomeSvg, Icon, Image, Input, Label, Link, LinkAnchorSvg, LinkBlankTargetSvg, LinkCurrentSvg, Loading, MessageBox, Meter, Nav, Option, OptionList, Paragraph, Quantity, QuantityIntl, Radio, RadioList, Route, RowNumberCol, RowNumberTableCell, SVGMaskOverlay, SearchSvg, Select, SelectionContext, Separator, SettingsSvg, SidePanel, StarSvg, SummaryMarker, Svg, Table, TableCell, Tbody, Text, Thead, Title, Tr, UITransition, UserSvg, ViewportLayout, actionIntegratedVia, actionRunEffect, addCustomMessage, arraySignalMembership, compareTwoJsValues, createAction, createAvailableConstraint, createIntl, createRequestCanceller, createSelectionKeyboardShortcuts, enableDebugActions, enableDebugOnDocumentLoading, filterTableSelection, forwardActionRequested, installCustomConstraintValidation, isCellSelected, isColumnSelected, isRowSelected, localStorageSignal, navBack, navForward, navTo, openCallout, rawUrlPart, reload, removeCustomMessage, requestAction, rerunActions, resource, route, routeAction, setBaseUrl, setupRoutes, stateSignal, stopLoad, stringifyTableSelectionValue, syncOwnedResourceToSignals, syncResourceToSignals, updateActions, useActionStatus, useArraySignalMembership, useAsyncData, useCalloutClose, useCancelPrevious, useCellGridFromRows, useConstraintValidityState, useDarkBackgroundAttribute, useDependenciesDiff, useDocumentResource, useDocumentState, useDocumentUrl, useEditionController, useFocusGroup, useKeyboardShortcuts, useNavState$1 as useNavState, useOrderedColumns, useRouteStatus, useRunOnMount, useSelectableElement, useSelectionController, useSidePanelClose, useSignalSync, useStateArray, useTitleLevel, useUrlSearchParam, valueInLocalStorage };
|
|
32823
33406
|
//# sourceMappingURL=jsenv_navi.js.map
|