@jsenv/navi 0.12.30 → 0.12.32
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 +1007 -879
- package/dist/jsenv_navi.js.map +92 -88
- package/package.json +1 -1
package/dist/jsenv_navi.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { installImportMetaCss } from "./jsenv_navi_side_effects.js";
|
|
2
|
-
import { createIterableWeakSet, createPubSub, createValueEffect, createStyleController, getVisuallyVisibleInfo, getFirstVisuallyVisibleAncestor, allowWheelThrough, resolveCSSColor, visibleRectEffect, pickPositionRelativeTo, getBorderSizes, getPaddingSizes, activeElementSignal, canInterceptKeys, createGroupTransitionController, getElementSignature, getBorderRadius, preventIntermediateScrollbar, createOpacityTransition, stringifyStyle, mergeOneStyle, mergeTwoStyles, normalizeStyles, resolveCSSSize, findBefore, findAfter, hasCSSSizeUnit,
|
|
2
|
+
import { createIterableWeakSet, createPubSub, createValueEffect, createStyleController, getVisuallyVisibleInfo, getFirstVisuallyVisibleAncestor, allowWheelThrough, resolveCSSColor, visibleRectEffect, pickPositionRelativeTo, getBorderSizes, getPaddingSizes, activeElementSignal, canInterceptKeys, createGroupTransitionController, getElementSignature, getBorderRadius, preventIntermediateScrollbar, createOpacityTransition, stringifyStyle, mergeOneStyle, mergeTwoStyles, normalizeStyles, resolveCSSSize, findBefore, findAfter, hasCSSSizeUnit, pickLightOrDark, resolveColorLuminance, initFocusGroup, elementIsFocusable, dragAfterThreshold, getScrollContainer, stickyAsRelativeCoords, createDragToMoveGestureController, getDropTargetInfo, setStyles, useActiveElement } from "@jsenv/dom";
|
|
3
3
|
import { prefixFirstAndIndentRemainingLines } from "@jsenv/humanize";
|
|
4
4
|
import { effect, signal, computed, batch, useSignal } from "@preact/signals";
|
|
5
|
-
import { useEffect, useRef, useCallback, useContext, useState, useLayoutEffect, useMemo,
|
|
5
|
+
import { useEffect, useRef, useCallback, useContext, useState, useLayoutEffect, useMemo, useImperativeHandle, useErrorBoundary, useId } from "preact/hooks";
|
|
6
6
|
import { createContext, toChildArray, createRef, cloneElement } from "preact";
|
|
7
7
|
import { jsxs, jsx, Fragment } from "preact/jsx-runtime";
|
|
8
8
|
import { createPortal, forwardRef } from "preact/compat";
|
|
@@ -7690,7 +7690,9 @@ const createRoute = (urlPatternInput) => {
|
|
|
7690
7690
|
// always remove the wildcard part for URL building since it's optional
|
|
7691
7691
|
if (relativeUrl.endsWith("/*?")) {
|
|
7692
7692
|
// Always remove the optional wildcard part for URL building
|
|
7693
|
-
relativeUrl = relativeUrl.
|
|
7693
|
+
relativeUrl = relativeUrl.slice(0, -"/*?".length);
|
|
7694
|
+
} else if (relativeUrl.endsWith("{/}?*")) {
|
|
7695
|
+
relativeUrl = relativeUrl.slice(0, -"{/}?*".length);
|
|
7694
7696
|
} else {
|
|
7695
7697
|
// For required wildcards (/*) or other patterns, replace normally
|
|
7696
7698
|
let wildcardIndex = 0;
|
|
@@ -13851,7 +13853,7 @@ const TextBasic = ({
|
|
|
13851
13853
|
as: "span",
|
|
13852
13854
|
baseClassName: "navi_text",
|
|
13853
13855
|
...rest,
|
|
13854
|
-
children: rest.as === "pre" ? children : applySpacingOnTextChildren(children, spacing)
|
|
13856
|
+
children: rest.as === "pre" || rest.box || rest.column || rest.row ? children : applySpacingOnTextChildren(children, spacing)
|
|
13855
13857
|
});
|
|
13856
13858
|
};
|
|
13857
13859
|
|
|
@@ -15622,562 +15624,294 @@ const RouteLink = ({
|
|
|
15622
15624
|
});
|
|
15623
15625
|
};
|
|
15624
15626
|
|
|
15625
|
-
installImportMetaCss(import.meta);
|
|
15626
|
-
|
|
15627
|
-
|
|
15628
|
-
background: #fdd;
|
|
15629
|
-
border: 1px solid red;
|
|
15630
|
-
margin-top: 0;
|
|
15631
|
-
margin-bottom: 20px;
|
|
15632
|
-
}
|
|
15633
|
-
`;
|
|
15634
|
-
const renderIdleDefault = () => null;
|
|
15635
|
-
const renderLoadingDefault = () => null;
|
|
15636
|
-
const renderAbortedDefault = () => null;
|
|
15637
|
-
const renderErrorDefault = error => {
|
|
15638
|
-
let routeErrorText = error && error.message ? error.message : error;
|
|
15639
|
-
return jsxs("p", {
|
|
15640
|
-
className: "action_error",
|
|
15641
|
-
children: ["An error occured: ", routeErrorText]
|
|
15642
|
-
});
|
|
15643
|
-
};
|
|
15644
|
-
const renderCompletedDefault = () => null;
|
|
15645
|
-
const ActionRenderer = ({
|
|
15646
|
-
action,
|
|
15647
|
-
children,
|
|
15648
|
-
disabled
|
|
15649
|
-
}) => {
|
|
15650
|
-
const {
|
|
15651
|
-
idle: renderIdle = renderIdleDefault,
|
|
15652
|
-
loading: renderLoading = renderLoadingDefault,
|
|
15653
|
-
aborted: renderAborted = renderAbortedDefault,
|
|
15654
|
-
error: renderError = renderErrorDefault,
|
|
15655
|
-
completed: renderCompleted,
|
|
15656
|
-
always: renderAlways
|
|
15657
|
-
} = typeof children === "function" ? {
|
|
15658
|
-
completed: children
|
|
15659
|
-
} : children || {};
|
|
15660
|
-
if (disabled) {
|
|
15661
|
-
return null;
|
|
15662
|
-
}
|
|
15663
|
-
if (action === undefined) {
|
|
15664
|
-
throw new Error("ActionRenderer requires an action to render, but none was provided.");
|
|
15627
|
+
installImportMetaCss(import.meta);Object.assign(PSEUDO_CLASSES, {
|
|
15628
|
+
":-navi-selected": {
|
|
15629
|
+
attribute: "data-selected"
|
|
15665
15630
|
}
|
|
15666
|
-
|
|
15667
|
-
|
|
15668
|
-
|
|
15669
|
-
|
|
15670
|
-
|
|
15671
|
-
|
|
15672
|
-
|
|
15673
|
-
const UIRenderedPromise = useUIRenderedPromise(action);
|
|
15674
|
-
const [errorBoundary, resetErrorBoundary] = useErrorBoundary();
|
|
15675
|
-
|
|
15676
|
-
// Mark this action as bound to UI components (has renderers)
|
|
15677
|
-
// This tells the action system that errors should be caught and stored
|
|
15678
|
-
// in the action's error state rather than bubbling up
|
|
15679
|
-
useLayoutEffect(() => {
|
|
15680
|
-
if (action) {
|
|
15681
|
-
const {
|
|
15682
|
-
ui
|
|
15683
|
-
} = getActionPrivateProperties(action);
|
|
15684
|
-
ui.hasRenderers = true;
|
|
15685
|
-
}
|
|
15686
|
-
}, [action]);
|
|
15687
|
-
useLayoutEffect(() => {
|
|
15688
|
-
resetErrorBoundary();
|
|
15689
|
-
}, [action, loading, idle, resetErrorBoundary]);
|
|
15690
|
-
useLayoutEffect(() => {
|
|
15691
|
-
UIRenderedPromise.resolve();
|
|
15692
|
-
return () => {
|
|
15693
|
-
actionUIRenderedPromiseWeakMap.delete(action);
|
|
15694
|
-
};
|
|
15695
|
-
}, [action]);
|
|
15631
|
+
});
|
|
15632
|
+
import.meta.css = /* css */`
|
|
15633
|
+
@layer navi {
|
|
15634
|
+
.navi_tablist {
|
|
15635
|
+
--tablist-border-radius: 8px;
|
|
15636
|
+
--tablist-background: transparent;
|
|
15637
|
+
--tab-border-radius: calc(var(--tablist-border-radius) - 2px);
|
|
15696
15638
|
|
|
15697
|
-
|
|
15698
|
-
|
|
15699
|
-
|
|
15700
|
-
|
|
15701
|
-
|
|
15702
|
-
|
|
15703
|
-
|
|
15704
|
-
|
|
15705
|
-
});
|
|
15706
|
-
}
|
|
15707
|
-
if (idle) {
|
|
15708
|
-
return renderIdle(action);
|
|
15709
|
-
}
|
|
15710
|
-
if (errorBoundary) {
|
|
15711
|
-
return renderError(errorBoundary, "ui_error", action);
|
|
15712
|
-
}
|
|
15713
|
-
if (error) {
|
|
15714
|
-
return renderError(error, "action_error", action);
|
|
15715
|
-
}
|
|
15716
|
-
if (aborted) {
|
|
15717
|
-
return renderAborted(action);
|
|
15718
|
-
}
|
|
15719
|
-
let renderCompletedSafe;
|
|
15720
|
-
if (renderCompleted) {
|
|
15721
|
-
renderCompletedSafe = renderCompleted;
|
|
15722
|
-
} else {
|
|
15723
|
-
const {
|
|
15724
|
-
ui
|
|
15725
|
-
} = getActionPrivateProperties(action);
|
|
15726
|
-
if (ui.renderCompleted) {
|
|
15727
|
-
renderCompletedSafe = ui.renderCompleted;
|
|
15728
|
-
} else {
|
|
15729
|
-
renderCompletedSafe = renderCompletedDefault;
|
|
15639
|
+
--tab-background: transparent;
|
|
15640
|
+
--tab-background-hover: #dae0e7;
|
|
15641
|
+
--tab-background-selected: transparent;
|
|
15642
|
+
--tab-color: inherit;
|
|
15643
|
+
--tab-color-hover: #010409;
|
|
15644
|
+
--tab-color-selected: inherit;
|
|
15645
|
+
--tab-marker-height: 2px;
|
|
15646
|
+
--tab-marker-color: rgb(205, 52, 37);
|
|
15730
15647
|
}
|
|
15731
15648
|
}
|
|
15732
|
-
|
|
15733
|
-
|
|
15734
|
-
|
|
15735
|
-
|
|
15736
|
-
|
|
15649
|
+
|
|
15650
|
+
.navi_tablist {
|
|
15651
|
+
display: flex;
|
|
15652
|
+
line-height: 2em;
|
|
15653
|
+
background: var(--tablist-background);
|
|
15654
|
+
border-radius: var(--tablist-border-radius);
|
|
15655
|
+
overflow-x: auto;
|
|
15656
|
+
overflow-y: hidden;
|
|
15737
15657
|
}
|
|
15738
|
-
|
|
15739
|
-
|
|
15740
|
-
|
|
15741
|
-
|
|
15742
|
-
|
|
15743
|
-
|
|
15744
|
-
|
|
15745
|
-
|
|
15658
|
+
.navi_tablist > ul {
|
|
15659
|
+
display: flex;
|
|
15660
|
+
width: 100%;
|
|
15661
|
+
margin: 0;
|
|
15662
|
+
padding: 0;
|
|
15663
|
+
align-items: center;
|
|
15664
|
+
gap: 0.5rem;
|
|
15665
|
+
list-style: none;
|
|
15746
15666
|
}
|
|
15747
|
-
|
|
15748
|
-
|
|
15749
|
-
|
|
15667
|
+
.navi_tablist > ul > li {
|
|
15668
|
+
position: relative;
|
|
15669
|
+
display: inline-flex;
|
|
15750
15670
|
}
|
|
15751
|
-
let resolve;
|
|
15752
|
-
const promise = new Promise(res => {
|
|
15753
|
-
resolve = res;
|
|
15754
|
-
});
|
|
15755
|
-
promise.resolve = resolve;
|
|
15756
|
-
actionUIRenderedPromiseWeakMap.set(action, promise);
|
|
15757
|
-
return promise;
|
|
15758
|
-
};
|
|
15759
15671
|
|
|
15760
|
-
|
|
15761
|
-
|
|
15762
|
-
|
|
15763
|
-
) => {
|
|
15764
|
-
useLayoutEffect(() => {
|
|
15765
|
-
if (!enabled) {
|
|
15766
|
-
return null;
|
|
15767
|
-
}
|
|
15768
|
-
const focusGroup = initFocusGroup(elementRef.current, {
|
|
15769
|
-
direction,
|
|
15770
|
-
skipTab,
|
|
15771
|
-
loop,
|
|
15772
|
-
name,
|
|
15773
|
-
});
|
|
15774
|
-
return focusGroup.cleanup;
|
|
15775
|
-
}, [direction, skipTab, loop, name]);
|
|
15776
|
-
};
|
|
15672
|
+
.navi_tab {
|
|
15673
|
+
--x-tab-background: var(--tab-background);
|
|
15674
|
+
--x-tab-color: var(--tab-color);
|
|
15777
15675
|
|
|
15778
|
-
|
|
15779
|
-
|
|
15780
|
-
|
|
15781
|
-
|
|
15782
|
-
|
|
15783
|
-
|
|
15784
|
-
|
|
15785
|
-
|
|
15786
|
-
|
|
15787
|
-
|
|
15788
|
-
|
|
15789
|
-
|
|
15790
|
-
|
|
15791
|
-
|
|
15792
|
-
|
|
15793
|
-
|
|
15794
|
-
|
|
15795
|
-
|
|
15796
|
-
|
|
15676
|
+
display: flex;
|
|
15677
|
+
flex-direction: column;
|
|
15678
|
+
white-space: nowrap;
|
|
15679
|
+
border-radius: var(--tab-border-radius);
|
|
15680
|
+
|
|
15681
|
+
.navi_tab_content {
|
|
15682
|
+
display: flex;
|
|
15683
|
+
padding: 0 0.5rem;
|
|
15684
|
+
color: var(--x-tab-color);
|
|
15685
|
+
background: var(--x-tab-background);
|
|
15686
|
+
border-radius: inherit;
|
|
15687
|
+
transition: background 0.12s ease-out;
|
|
15688
|
+
}
|
|
15689
|
+
/* Hidden bold clone to reserve space for bold width without affecting height */
|
|
15690
|
+
.navi_tab_content_bold_clone {
|
|
15691
|
+
display: block; /* in-flow so it contributes to width */
|
|
15692
|
+
height: 0; /* zero height so it doesn't change layout height */
|
|
15693
|
+
font-weight: 600; /* force bold to compute max width */
|
|
15694
|
+
visibility: hidden; /* not visible */
|
|
15695
|
+
pointer-events: none; /* inert */
|
|
15696
|
+
overflow: hidden; /* avoid any accidental height */
|
|
15697
|
+
}
|
|
15698
|
+
.navi_tab_selected_marker {
|
|
15699
|
+
z-index: 1;
|
|
15700
|
+
display: flex;
|
|
15701
|
+
width: 100%;
|
|
15702
|
+
height: var(--tab-marker-height);
|
|
15703
|
+
margin-top: 5px;
|
|
15704
|
+
background: transparent;
|
|
15705
|
+
border-radius: 0.1px;
|
|
15797
15706
|
}
|
|
15798
|
-
|
|
15799
|
-
|
|
15707
|
+
|
|
15708
|
+
/* Interactive */
|
|
15709
|
+
&[data-interactive] {
|
|
15710
|
+
cursor: pointer;
|
|
15800
15711
|
}
|
|
15801
|
-
|
|
15802
|
-
|
|
15803
|
-
|
|
15804
|
-
|
|
15805
|
-
@keyframes morph-to-right {
|
|
15806
|
-
from {
|
|
15807
|
-
d: path("${downArrowPath}");
|
|
15712
|
+
/* Hover */
|
|
15713
|
+
&:hover {
|
|
15714
|
+
--x-tab-background: var(--tab-background-hover);
|
|
15715
|
+
--x-tab-color: var(--tab-color-hover);
|
|
15808
15716
|
}
|
|
15809
|
-
|
|
15810
|
-
|
|
15717
|
+
/* Selected */
|
|
15718
|
+
&[data-selected] {
|
|
15719
|
+
--x-tab-background: var(--tab-background-selected);
|
|
15720
|
+
--x-tab-color: var(--tab-color-selected);
|
|
15721
|
+
|
|
15722
|
+
.navi_tab_content {
|
|
15723
|
+
font-weight: 600;
|
|
15724
|
+
}
|
|
15725
|
+
.navi_tab_selected_marker {
|
|
15726
|
+
background: var(--tab-marker-color);
|
|
15727
|
+
}
|
|
15811
15728
|
}
|
|
15812
15729
|
}
|
|
15813
15730
|
|
|
15814
|
-
.
|
|
15815
|
-
|
|
15816
|
-
|
|
15817
|
-
|
|
15818
|
-
}
|
|
15819
|
-
@keyframes progress-around-circle {
|
|
15820
|
-
0% {
|
|
15821
|
-
stroke-dashoffset: 0;
|
|
15822
|
-
}
|
|
15823
|
-
100% {
|
|
15824
|
-
stroke-dashoffset: -2010;
|
|
15731
|
+
.navi_tablist[data-expand] {
|
|
15732
|
+
.navi_tab {
|
|
15733
|
+
flex: 1;
|
|
15734
|
+
align-items: center;
|
|
15825
15735
|
}
|
|
15826
|
-
}
|
|
15827
15736
|
|
|
15828
|
-
|
|
15829
|
-
|
|
15830
|
-
|
|
15831
|
-
|
|
15832
|
-
}
|
|
15833
|
-
.summary_marker_svg .loading_container {
|
|
15834
|
-
transition: transform 0.3s linear;
|
|
15835
|
-
transform: scale(0.3);
|
|
15836
|
-
}
|
|
15837
|
-
.summary_marker_svg .background_circle,
|
|
15838
|
-
.summary_marker_svg .foreground_circle {
|
|
15839
|
-
transition: opacity 0.3s ease-in-out;
|
|
15840
|
-
opacity: 0;
|
|
15841
|
-
}
|
|
15842
|
-
.summary_marker_svg[data-loading] .arrow {
|
|
15843
|
-
opacity: 0;
|
|
15844
|
-
}
|
|
15845
|
-
.summary_marker_svg[data-loading] .loading_container {
|
|
15846
|
-
transform: scale(1);
|
|
15847
|
-
}
|
|
15848
|
-
.summary_marker_svg[data-loading] .background_circle {
|
|
15849
|
-
opacity: 0.2;
|
|
15850
|
-
}
|
|
15851
|
-
.summary_marker_svg[data-loading] .foreground_circle {
|
|
15852
|
-
opacity: 1;
|
|
15737
|
+
.navi_tab_content {
|
|
15738
|
+
width: 100%;
|
|
15739
|
+
justify-content: center;
|
|
15740
|
+
}
|
|
15853
15741
|
}
|
|
15854
15742
|
`;
|
|
15855
|
-
const
|
|
15856
|
-
|
|
15857
|
-
|
|
15743
|
+
const TabListUnderlinerContext = createContext();
|
|
15744
|
+
const TabListStyleCSSVars = {
|
|
15745
|
+
borderRadius: "--tablist-border-radius",
|
|
15746
|
+
background: "--tablist-background"
|
|
15747
|
+
};
|
|
15748
|
+
const TabList = ({
|
|
15749
|
+
children,
|
|
15750
|
+
spacing,
|
|
15751
|
+
underline,
|
|
15752
|
+
expand,
|
|
15753
|
+
expandX,
|
|
15754
|
+
...props
|
|
15858
15755
|
}) => {
|
|
15859
|
-
|
|
15860
|
-
|
|
15861
|
-
|
|
15862
|
-
|
|
15863
|
-
|
|
15864
|
-
|
|
15865
|
-
|
|
15866
|
-
|
|
15867
|
-
|
|
15868
|
-
|
|
15869
|
-
|
|
15870
|
-
|
|
15871
|
-
|
|
15872
|
-
|
|
15873
|
-
|
|
15874
|
-
|
|
15875
|
-
|
|
15876
|
-
|
|
15877
|
-
|
|
15878
|
-
|
|
15879
|
-
|
|
15880
|
-
|
|
15881
|
-
|
|
15882
|
-
|
|
15883
|
-
cy: "-480",
|
|
15884
|
-
r: "320",
|
|
15885
|
-
stroke: "currentColor",
|
|
15886
|
-
fill: "none",
|
|
15887
|
-
strokeWidth: "60",
|
|
15888
|
-
opacity: "0.2"
|
|
15889
|
-
}), jsx("circle", {
|
|
15890
|
-
className: "foreground_circle",
|
|
15891
|
-
cx: "480",
|
|
15892
|
-
cy: "-480",
|
|
15893
|
-
r: "320",
|
|
15894
|
-
stroke: "currentColor",
|
|
15895
|
-
fill: "none",
|
|
15896
|
-
strokeWidth: "60",
|
|
15897
|
-
strokeLinecap: "round",
|
|
15898
|
-
strokeDasharray: "503 1507"
|
|
15899
|
-
})]
|
|
15900
|
-
}), jsx("g", {
|
|
15901
|
-
className: "arrow_container",
|
|
15902
|
-
"transform-origin": "480px -480px",
|
|
15903
|
-
children: jsx("path", {
|
|
15904
|
-
className: "arrow",
|
|
15905
|
-
fill: "currentColor",
|
|
15906
|
-
"data-animation-target": shouldAnimate ? open ? "down" : "right" : undefined,
|
|
15907
|
-
d: open ? downArrowPath : rightArrowPath
|
|
15756
|
+
return jsx(Box, {
|
|
15757
|
+
as: "nav",
|
|
15758
|
+
baseClassName: "navi_tablist",
|
|
15759
|
+
role: "tablist",
|
|
15760
|
+
"data-expand": expand || expandX ? "" : undefined,
|
|
15761
|
+
expand: expand,
|
|
15762
|
+
expandX: expandX,
|
|
15763
|
+
...props,
|
|
15764
|
+
styleCSSVars: TabListStyleCSSVars,
|
|
15765
|
+
children: jsx(Box, {
|
|
15766
|
+
as: "ul",
|
|
15767
|
+
column: true,
|
|
15768
|
+
role: "list",
|
|
15769
|
+
spacing: spacing,
|
|
15770
|
+
children: jsx(TabListUnderlinerContext.Provider, {
|
|
15771
|
+
value: underline,
|
|
15772
|
+
children: children.map(child => {
|
|
15773
|
+
return jsx(Box, {
|
|
15774
|
+
as: "li",
|
|
15775
|
+
column: true,
|
|
15776
|
+
expandX: expandX,
|
|
15777
|
+
expand: expand,
|
|
15778
|
+
children: child
|
|
15779
|
+
}, child.props.key);
|
|
15908
15780
|
})
|
|
15909
|
-
})
|
|
15781
|
+
})
|
|
15910
15782
|
})
|
|
15911
15783
|
});
|
|
15912
15784
|
};
|
|
15913
|
-
|
|
15914
|
-
|
|
15915
|
-
|
|
15916
|
-
|
|
15917
|
-
|
|
15918
|
-
|
|
15919
|
-
|
|
15920
|
-
|
|
15921
|
-
|
|
15922
|
-
|
|
15923
|
-
.navi_details > summary {
|
|
15924
|
-
display: flex;
|
|
15925
|
-
flex-shrink: 0;
|
|
15926
|
-
flex-direction: column;
|
|
15927
|
-
cursor: pointer;
|
|
15928
|
-
user-select: none;
|
|
15929
|
-
}
|
|
15930
|
-
.summary_body {
|
|
15931
|
-
display: flex;
|
|
15932
|
-
width: 100%;
|
|
15933
|
-
flex-direction: row;
|
|
15934
|
-
align-items: center;
|
|
15935
|
-
gap: 0.2em;
|
|
15785
|
+
const TAB_STYLE_CSS_VARS = {
|
|
15786
|
+
"background": "--tab-background",
|
|
15787
|
+
"color": "--tab-color",
|
|
15788
|
+
":hover": {
|
|
15789
|
+
background: "--tab-background-hover",
|
|
15790
|
+
color: "--tab-color-hover"
|
|
15791
|
+
},
|
|
15792
|
+
":-navi-selected": {
|
|
15793
|
+
background: "--tab-color-selected",
|
|
15794
|
+
color: "--tab-color-selected"
|
|
15936
15795
|
}
|
|
15937
|
-
|
|
15938
|
-
|
|
15939
|
-
|
|
15940
|
-
|
|
15941
|
-
|
|
15942
|
-
|
|
15796
|
+
};
|
|
15797
|
+
const TAB_PSEUDO_CLASSES = [":hover", ":-navi-selected"];
|
|
15798
|
+
const TAB_PSEUDO_ELEMENTS = ["::-navi-marker"];
|
|
15799
|
+
const Tab = props => {
|
|
15800
|
+
if (props.route) {
|
|
15801
|
+
return jsx(TabRoute, {
|
|
15802
|
+
...props
|
|
15803
|
+
});
|
|
15943
15804
|
}
|
|
15805
|
+
return jsx(TabBasic, {
|
|
15806
|
+
...props
|
|
15807
|
+
});
|
|
15808
|
+
};
|
|
15809
|
+
const TabRoute = ({
|
|
15810
|
+
route,
|
|
15811
|
+
children,
|
|
15812
|
+
...props
|
|
15813
|
+
}) => {
|
|
15814
|
+
const {
|
|
15815
|
+
active
|
|
15816
|
+
} = useRouteStatus(route);
|
|
15817
|
+
return jsx(TabBasic, {
|
|
15818
|
+
selected: active,
|
|
15819
|
+
...props,
|
|
15820
|
+
children: jsx(RouteLink, {
|
|
15821
|
+
route: route,
|
|
15822
|
+
underline: false,
|
|
15823
|
+
color: "inherit",
|
|
15824
|
+
children: children
|
|
15825
|
+
})
|
|
15826
|
+
});
|
|
15827
|
+
};
|
|
15828
|
+
const TabBasic = ({
|
|
15829
|
+
children,
|
|
15830
|
+
selected,
|
|
15831
|
+
onClick,
|
|
15832
|
+
...props
|
|
15833
|
+
}) => {
|
|
15834
|
+
const tabListUnderline = useContext(TabListUnderlinerContext);
|
|
15835
|
+
return jsxs(Box, {
|
|
15836
|
+
role: "tab",
|
|
15837
|
+
"aria-selected": selected ? "true" : "false",
|
|
15838
|
+
"data-interactive": onClick ? "" : undefined,
|
|
15839
|
+
onClick: onClick
|
|
15840
|
+
// Style system
|
|
15841
|
+
,
|
|
15842
|
+
baseClassName: "navi_tab",
|
|
15843
|
+
styleCSSVars: TAB_STYLE_CSS_VARS,
|
|
15844
|
+
pseudoClasses: TAB_PSEUDO_CLASSES,
|
|
15845
|
+
pseudoElements: TAB_PSEUDO_ELEMENTS,
|
|
15846
|
+
basePseudoState: {
|
|
15847
|
+
":-navi-selected": selected
|
|
15848
|
+
},
|
|
15849
|
+
...props,
|
|
15850
|
+
children: [jsx("div", {
|
|
15851
|
+
className: "navi_tab_content",
|
|
15852
|
+
children: children
|
|
15853
|
+
}), jsx("div", {
|
|
15854
|
+
className: "navi_tab_content_bold_clone",
|
|
15855
|
+
"aria-hidden": "true",
|
|
15856
|
+
children: children
|
|
15857
|
+
}), tabListUnderline && jsx("span", {
|
|
15858
|
+
className: "navi_tab_selected_marker"
|
|
15859
|
+
})]
|
|
15860
|
+
});
|
|
15861
|
+
};
|
|
15944
15862
|
|
|
15945
|
-
|
|
15946
|
-
|
|
15863
|
+
installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
15864
|
+
@layer navi {
|
|
15865
|
+
label {
|
|
15866
|
+
cursor: pointer;
|
|
15867
|
+
}
|
|
15868
|
+
|
|
15869
|
+
label[data-readonly],
|
|
15870
|
+
label[data-disabled] {
|
|
15871
|
+
color: rgba(0, 0, 0, 0.5);
|
|
15872
|
+
cursor: default;
|
|
15873
|
+
}
|
|
15947
15874
|
}
|
|
15948
15875
|
`;
|
|
15949
|
-
const
|
|
15950
|
-
|
|
15951
|
-
|
|
15952
|
-
const DetailsBasic = forwardRef((props, ref) => {
|
|
15876
|
+
const ReportReadOnlyOnLabelContext = createContext();
|
|
15877
|
+
const ReportDisabledOnLabelContext = createContext();
|
|
15878
|
+
const Label = props => {
|
|
15953
15879
|
const {
|
|
15954
|
-
|
|
15955
|
-
|
|
15956
|
-
open,
|
|
15957
|
-
loading,
|
|
15958
|
-
className,
|
|
15959
|
-
focusGroup,
|
|
15960
|
-
focusGroupDirection,
|
|
15961
|
-
arrowKeyShortcuts = true,
|
|
15962
|
-
openKeyShortcut = "ArrowRight",
|
|
15963
|
-
closeKeyShortcut = "ArrowLeft",
|
|
15964
|
-
onToggle,
|
|
15880
|
+
readOnly,
|
|
15881
|
+
disabled,
|
|
15965
15882
|
children,
|
|
15966
15883
|
...rest
|
|
15967
15884
|
} = props;
|
|
15968
|
-
const
|
|
15969
|
-
|
|
15970
|
-
const [
|
|
15971
|
-
const
|
|
15972
|
-
|
|
15973
|
-
|
|
15974
|
-
|
|
15975
|
-
|
|
15885
|
+
const [inputReadOnly, setInputReadOnly] = useState(false);
|
|
15886
|
+
const innerReadOnly = readOnly || inputReadOnly;
|
|
15887
|
+
const [inputDisabled, setInputDisabled] = useState(false);
|
|
15888
|
+
const innerDisabled = disabled || inputDisabled;
|
|
15889
|
+
return jsx(Box, {
|
|
15890
|
+
...rest,
|
|
15891
|
+
as: "label",
|
|
15892
|
+
basePseudoState: {
|
|
15893
|
+
readOnly: innerReadOnly,
|
|
15894
|
+
disabled: innerDisabled
|
|
15895
|
+
},
|
|
15896
|
+
children: jsx(ReportReadOnlyOnLabelContext.Provider, {
|
|
15897
|
+
value: setInputReadOnly,
|
|
15898
|
+
children: jsx(ReportDisabledOnLabelContext.Provider, {
|
|
15899
|
+
value: setInputDisabled,
|
|
15900
|
+
children: children
|
|
15901
|
+
})
|
|
15902
|
+
})
|
|
15976
15903
|
});
|
|
15904
|
+
};
|
|
15977
15905
|
|
|
15978
|
-
|
|
15979
|
-
|
|
15980
|
-
|
|
15981
|
-
|
|
15982
|
-
|
|
15983
|
-
|
|
15984
|
-
|
|
15985
|
-
|
|
15986
|
-
|
|
15987
|
-
* - https://techblog.thescore.com/2024/10/08/why-we-decided-to-change-how-the-details-element-works/
|
|
15988
|
-
* - https://github.com/whatwg/html/issues/4500
|
|
15989
|
-
* - https://stackoverflow.com/questions/58942600/react-html-details-toggles-uncontrollably-when-starts-open
|
|
15990
|
-
*
|
|
15991
|
-
*/
|
|
15992
|
-
|
|
15993
|
-
const summaryRef = useRef(null);
|
|
15994
|
-
useKeyboardShortcuts(innerRef, [{
|
|
15995
|
-
key: openKeyShortcut,
|
|
15996
|
-
enabled: arrowKeyShortcuts,
|
|
15997
|
-
when: e => document.activeElement === summaryRef.current &&
|
|
15998
|
-
// avoid handling openKeyShortcut twice when keydown occurs inside nested details
|
|
15999
|
-
!e.defaultPrevented,
|
|
16000
|
-
action: e => {
|
|
16001
|
-
const details = innerRef.current;
|
|
16002
|
-
if (!details.open) {
|
|
16003
|
-
e.preventDefault();
|
|
16004
|
-
details.open = true;
|
|
16005
|
-
return;
|
|
16006
|
-
}
|
|
16007
|
-
const summary = summaryRef.current;
|
|
16008
|
-
const firstFocusableElementInDetails = findAfter(summary, elementIsFocusable, {
|
|
16009
|
-
root: details
|
|
16010
|
-
});
|
|
16011
|
-
if (!firstFocusableElementInDetails) {
|
|
16012
|
-
return;
|
|
16013
|
-
}
|
|
16014
|
-
e.preventDefault();
|
|
16015
|
-
firstFocusableElementInDetails.focus();
|
|
16016
|
-
}
|
|
16017
|
-
}, {
|
|
16018
|
-
key: closeKeyShortcut,
|
|
16019
|
-
enabled: arrowKeyShortcuts,
|
|
16020
|
-
when: () => {
|
|
16021
|
-
const details = innerRef.current;
|
|
16022
|
-
return details.open;
|
|
16023
|
-
},
|
|
16024
|
-
action: e => {
|
|
16025
|
-
const details = innerRef.current;
|
|
16026
|
-
const summary = summaryRef.current;
|
|
16027
|
-
if (document.activeElement === summary) {
|
|
16028
|
-
e.preventDefault();
|
|
16029
|
-
summary.focus();
|
|
16030
|
-
details.open = false;
|
|
16031
|
-
} else {
|
|
16032
|
-
e.preventDefault();
|
|
16033
|
-
summary.focus();
|
|
16034
|
-
}
|
|
16035
|
-
}
|
|
16036
|
-
}]);
|
|
16037
|
-
const mountedRef = useRef(false);
|
|
16038
|
-
useEffect(() => {
|
|
16039
|
-
mountedRef.current = true;
|
|
16040
|
-
}, []);
|
|
16041
|
-
return jsxs("details", {
|
|
16042
|
-
...rest,
|
|
16043
|
-
ref: innerRef,
|
|
16044
|
-
id: id,
|
|
16045
|
-
className: ["navi_details", ...(className ? className.split(" ") : [])].join(" "),
|
|
16046
|
-
onToggle: e => {
|
|
16047
|
-
const isOpen = e.newState === "open";
|
|
16048
|
-
if (mountedRef.current) {
|
|
16049
|
-
if (isOpen) {
|
|
16050
|
-
innerOpenSetter(true);
|
|
16051
|
-
setNavState(true);
|
|
16052
|
-
} else {
|
|
16053
|
-
innerOpenSetter(false);
|
|
16054
|
-
setNavState(undefined);
|
|
16055
|
-
}
|
|
16056
|
-
}
|
|
16057
|
-
onToggle?.(e);
|
|
16058
|
-
},
|
|
16059
|
-
open: innerOpen,
|
|
16060
|
-
children: [jsx("summary", {
|
|
16061
|
-
ref: summaryRef,
|
|
16062
|
-
children: jsxs("div", {
|
|
16063
|
-
className: "summary_body",
|
|
16064
|
-
children: [jsx(SummaryMarker, {
|
|
16065
|
-
open: innerOpen,
|
|
16066
|
-
loading: loading
|
|
16067
|
-
}), jsx("div", {
|
|
16068
|
-
className: "summary_label",
|
|
16069
|
-
children: label
|
|
16070
|
-
})]
|
|
16071
|
-
})
|
|
16072
|
-
}), children]
|
|
16073
|
-
});
|
|
16074
|
-
});
|
|
16075
|
-
forwardRef((props, ref) => {
|
|
16076
|
-
const {
|
|
16077
|
-
action,
|
|
16078
|
-
loading,
|
|
16079
|
-
onToggle,
|
|
16080
|
-
onActionPrevented,
|
|
16081
|
-
onActionStart,
|
|
16082
|
-
onActionError,
|
|
16083
|
-
onActionEnd,
|
|
16084
|
-
children,
|
|
16085
|
-
...rest
|
|
16086
|
-
} = props;
|
|
16087
|
-
const innerRef = useRef();
|
|
16088
|
-
useImperativeHandle(ref, () => innerRef.current);
|
|
16089
|
-
const effectiveAction = useAction(action);
|
|
16090
|
-
const {
|
|
16091
|
-
loading: actionLoading
|
|
16092
|
-
} = useActionStatus(effectiveAction);
|
|
16093
|
-
const executeAction = useExecuteAction(innerRef, {
|
|
16094
|
-
// the error will be displayed by actionRenderer inside <details>
|
|
16095
|
-
errorEffect: "none"
|
|
16096
|
-
});
|
|
16097
|
-
useActionEvents(innerRef, {
|
|
16098
|
-
onPrevented: onActionPrevented,
|
|
16099
|
-
onAction: e => {
|
|
16100
|
-
executeAction(e);
|
|
16101
|
-
},
|
|
16102
|
-
onStart: onActionStart,
|
|
16103
|
-
onError: onActionError,
|
|
16104
|
-
onEnd: onActionEnd
|
|
16105
|
-
});
|
|
16106
|
-
return jsx(DetailsBasic, {
|
|
16107
|
-
...rest,
|
|
16108
|
-
ref: innerRef,
|
|
16109
|
-
loading: loading || actionLoading,
|
|
16110
|
-
onToggle: toggleEvent => {
|
|
16111
|
-
const isOpen = toggleEvent.newState === "open";
|
|
16112
|
-
if (isOpen) {
|
|
16113
|
-
requestAction(toggleEvent.target, effectiveAction, {
|
|
16114
|
-
event: toggleEvent,
|
|
16115
|
-
method: "run"
|
|
16116
|
-
});
|
|
16117
|
-
} else {
|
|
16118
|
-
effectiveAction.abort();
|
|
16119
|
-
}
|
|
16120
|
-
onToggle?.(toggleEvent);
|
|
16121
|
-
},
|
|
16122
|
-
children: jsx(ActionRenderer, {
|
|
16123
|
-
action: effectiveAction,
|
|
16124
|
-
children: children
|
|
16125
|
-
})
|
|
16126
|
-
});
|
|
16127
|
-
});
|
|
16128
|
-
|
|
16129
|
-
installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
16130
|
-
@layer navi {
|
|
16131
|
-
label {
|
|
16132
|
-
cursor: pointer;
|
|
16133
|
-
}
|
|
16134
|
-
|
|
16135
|
-
label[data-readonly],
|
|
16136
|
-
label[data-disabled] {
|
|
16137
|
-
color: rgba(0, 0, 0, 0.5);
|
|
16138
|
-
cursor: default;
|
|
16139
|
-
}
|
|
16140
|
-
}
|
|
16141
|
-
`;
|
|
16142
|
-
const ReportReadOnlyOnLabelContext = createContext();
|
|
16143
|
-
const ReportDisabledOnLabelContext = createContext();
|
|
16144
|
-
const Label = props => {
|
|
16145
|
-
const {
|
|
16146
|
-
readOnly,
|
|
16147
|
-
disabled,
|
|
16148
|
-
children,
|
|
16149
|
-
...rest
|
|
16150
|
-
} = props;
|
|
16151
|
-
const [inputReadOnly, setInputReadOnly] = useState(false);
|
|
16152
|
-
const innerReadOnly = readOnly || inputReadOnly;
|
|
16153
|
-
const [inputDisabled, setInputDisabled] = useState(false);
|
|
16154
|
-
const innerDisabled = disabled || inputDisabled;
|
|
16155
|
-
return jsx(Box, {
|
|
16156
|
-
...rest,
|
|
16157
|
-
as: "label",
|
|
16158
|
-
basePseudoState: {
|
|
16159
|
-
readOnly: innerReadOnly,
|
|
16160
|
-
disabled: innerDisabled
|
|
16161
|
-
},
|
|
16162
|
-
children: jsx(ReportReadOnlyOnLabelContext.Provider, {
|
|
16163
|
-
value: setInputReadOnly,
|
|
16164
|
-
children: jsx(ReportDisabledOnLabelContext.Provider, {
|
|
16165
|
-
value: setInputDisabled,
|
|
16166
|
-
children: children
|
|
16167
|
-
})
|
|
16168
|
-
})
|
|
16169
|
-
});
|
|
16170
|
-
};
|
|
16171
|
-
|
|
16172
|
-
installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
16173
|
-
@layer navi {
|
|
16174
|
-
.navi_checkbox {
|
|
16175
|
-
--outline-offset: 1px;
|
|
16176
|
-
--outline-width: 2px;
|
|
16177
|
-
--border-width: 1px;
|
|
16178
|
-
--border-radius: 2px;
|
|
16179
|
-
--width: 13px;
|
|
16180
|
-
--height: 13px;
|
|
15906
|
+
installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
15907
|
+
@layer navi {
|
|
15908
|
+
.navi_checkbox {
|
|
15909
|
+
--outline-offset: 1px;
|
|
15910
|
+
--outline-width: 2px;
|
|
15911
|
+
--border-width: 1px;
|
|
15912
|
+
--border-radius: 2px;
|
|
15913
|
+
--width: 13px;
|
|
15914
|
+
--height: 13px;
|
|
16181
15915
|
|
|
16182
15916
|
--outline-color: var(--navi-focus-outline-color);
|
|
16183
15917
|
--loader-color: var(--navi-loader-color);
|
|
@@ -18065,252 +17799,798 @@ forwardRef((props, ref) => {
|
|
|
18065
17799
|
children: children
|
|
18066
17800
|
})
|
|
18067
17801
|
});
|
|
18068
|
-
});
|
|
18069
|
-
|
|
18070
|
-
const useRefArray = (items, keyFromItem) => {
|
|
18071
|
-
const refMapRef = useRef(new Map());
|
|
18072
|
-
const previousKeySetRef = useRef(new Set());
|
|
18073
|
-
|
|
18074
|
-
return useMemo(() => {
|
|
18075
|
-
const refMap = refMapRef.current;
|
|
18076
|
-
const previousKeySet = previousKeySetRef.current;
|
|
18077
|
-
const currentKeySet = new Set();
|
|
18078
|
-
const refArray = [];
|
|
18079
|
-
|
|
18080
|
-
for (let i = 0; i < items.length; i++) {
|
|
18081
|
-
const item = items[i];
|
|
18082
|
-
const key = keyFromItem(item);
|
|
18083
|
-
currentKeySet.add(key);
|
|
18084
|
-
|
|
18085
|
-
const refForKey = refMap.get(key);
|
|
18086
|
-
if (refForKey) {
|
|
18087
|
-
refArray[i] = refForKey;
|
|
18088
|
-
} else {
|
|
18089
|
-
const newRef = createRef();
|
|
18090
|
-
refMap.set(key, newRef);
|
|
18091
|
-
refArray[i] = newRef;
|
|
18092
|
-
}
|
|
18093
|
-
}
|
|
18094
|
-
|
|
18095
|
-
for (const key of previousKeySet) {
|
|
18096
|
-
if (!currentKeySet.has(key)) {
|
|
18097
|
-
refMap.delete(key);
|
|
18098
|
-
}
|
|
18099
|
-
}
|
|
18100
|
-
previousKeySetRef.current = currentKeySet;
|
|
18101
|
-
|
|
18102
|
-
return refArray;
|
|
18103
|
-
}, [items]);
|
|
17802
|
+
});
|
|
17803
|
+
|
|
17804
|
+
const useRefArray = (items, keyFromItem) => {
|
|
17805
|
+
const refMapRef = useRef(new Map());
|
|
17806
|
+
const previousKeySetRef = useRef(new Set());
|
|
17807
|
+
|
|
17808
|
+
return useMemo(() => {
|
|
17809
|
+
const refMap = refMapRef.current;
|
|
17810
|
+
const previousKeySet = previousKeySetRef.current;
|
|
17811
|
+
const currentKeySet = new Set();
|
|
17812
|
+
const refArray = [];
|
|
17813
|
+
|
|
17814
|
+
for (let i = 0; i < items.length; i++) {
|
|
17815
|
+
const item = items[i];
|
|
17816
|
+
const key = keyFromItem(item);
|
|
17817
|
+
currentKeySet.add(key);
|
|
17818
|
+
|
|
17819
|
+
const refForKey = refMap.get(key);
|
|
17820
|
+
if (refForKey) {
|
|
17821
|
+
refArray[i] = refForKey;
|
|
17822
|
+
} else {
|
|
17823
|
+
const newRef = createRef();
|
|
17824
|
+
refMap.set(key, newRef);
|
|
17825
|
+
refArray[i] = newRef;
|
|
17826
|
+
}
|
|
17827
|
+
}
|
|
17828
|
+
|
|
17829
|
+
for (const key of previousKeySet) {
|
|
17830
|
+
if (!currentKeySet.has(key)) {
|
|
17831
|
+
refMap.delete(key);
|
|
17832
|
+
}
|
|
17833
|
+
}
|
|
17834
|
+
previousKeySetRef.current = currentKeySet;
|
|
17835
|
+
|
|
17836
|
+
return refArray;
|
|
17837
|
+
}, [items]);
|
|
17838
|
+
};
|
|
17839
|
+
|
|
17840
|
+
installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
17841
|
+
.navi_select[data-readonly] {
|
|
17842
|
+
pointer-events: none;
|
|
17843
|
+
}
|
|
17844
|
+
`;
|
|
17845
|
+
const Select = forwardRef((props, ref) => {
|
|
17846
|
+
const select = renderActionableComponent(props, ref);
|
|
17847
|
+
return select;
|
|
17848
|
+
});
|
|
17849
|
+
const SelectControlled = forwardRef((props, ref) => {
|
|
17850
|
+
const {
|
|
17851
|
+
name,
|
|
17852
|
+
value,
|
|
17853
|
+
loading,
|
|
17854
|
+
disabled,
|
|
17855
|
+
readOnly,
|
|
17856
|
+
children,
|
|
17857
|
+
...rest
|
|
17858
|
+
} = props;
|
|
17859
|
+
const innerRef = useRef();
|
|
17860
|
+
useImperativeHandle(ref, () => innerRef.current);
|
|
17861
|
+
const selectElement = jsx("select", {
|
|
17862
|
+
className: "navi_select",
|
|
17863
|
+
ref: innerRef,
|
|
17864
|
+
"data-readonly": readOnly && !disabled ? "" : undefined,
|
|
17865
|
+
onKeyDown: e => {
|
|
17866
|
+
if (readOnly) {
|
|
17867
|
+
e.preventDefault();
|
|
17868
|
+
}
|
|
17869
|
+
},
|
|
17870
|
+
...rest,
|
|
17871
|
+
children: children.map(child => {
|
|
17872
|
+
const {
|
|
17873
|
+
label,
|
|
17874
|
+
readOnly: childReadOnly,
|
|
17875
|
+
disabled: childDisabled,
|
|
17876
|
+
loading: childLoading,
|
|
17877
|
+
value: childValue,
|
|
17878
|
+
...childRest
|
|
17879
|
+
} = child;
|
|
17880
|
+
return jsx("option", {
|
|
17881
|
+
name: name,
|
|
17882
|
+
value: childValue,
|
|
17883
|
+
selected: childValue === value,
|
|
17884
|
+
readOnly: readOnly || childReadOnly,
|
|
17885
|
+
disabled: disabled || childDisabled,
|
|
17886
|
+
loading: loading || childLoading,
|
|
17887
|
+
...childRest,
|
|
17888
|
+
children: label
|
|
17889
|
+
}, childValue);
|
|
17890
|
+
})
|
|
17891
|
+
});
|
|
17892
|
+
return jsx(LoaderBackground, {
|
|
17893
|
+
loading: loading,
|
|
17894
|
+
color: "light-dark(#355fcc, #3b82f6)",
|
|
17895
|
+
inset: -1,
|
|
17896
|
+
children: selectElement
|
|
17897
|
+
});
|
|
17898
|
+
});
|
|
17899
|
+
forwardRef((props, ref) => {
|
|
17900
|
+
const {
|
|
17901
|
+
value: initialValue,
|
|
17902
|
+
id,
|
|
17903
|
+
children,
|
|
17904
|
+
...rest
|
|
17905
|
+
} = props;
|
|
17906
|
+
const innerRef = useRef();
|
|
17907
|
+
useImperativeHandle(ref, () => innerRef.current);
|
|
17908
|
+
const [navState, setNavState] = useNavState(id);
|
|
17909
|
+
const valueAtStart = navState === undefined ? initialValue : navState;
|
|
17910
|
+
const [value, setValue] = useState(valueAtStart);
|
|
17911
|
+
useEffect(() => {
|
|
17912
|
+
setNavState(value);
|
|
17913
|
+
}, [value]);
|
|
17914
|
+
return jsx(SelectControlled, {
|
|
17915
|
+
ref: innerRef,
|
|
17916
|
+
value: value,
|
|
17917
|
+
onChange: event => {
|
|
17918
|
+
const select = event.target;
|
|
17919
|
+
const selectedValue = select.value;
|
|
17920
|
+
setValue(selectedValue);
|
|
17921
|
+
},
|
|
17922
|
+
...rest,
|
|
17923
|
+
children: children
|
|
17924
|
+
});
|
|
17925
|
+
});
|
|
17926
|
+
forwardRef((props, ref) => {
|
|
17927
|
+
const {
|
|
17928
|
+
id,
|
|
17929
|
+
name,
|
|
17930
|
+
value: externalValue,
|
|
17931
|
+
valueSignal,
|
|
17932
|
+
action,
|
|
17933
|
+
children,
|
|
17934
|
+
onCancel,
|
|
17935
|
+
onActionPrevented,
|
|
17936
|
+
onActionStart,
|
|
17937
|
+
onActionAbort,
|
|
17938
|
+
onActionError,
|
|
17939
|
+
onActionEnd,
|
|
17940
|
+
actionErrorEffect,
|
|
17941
|
+
...rest
|
|
17942
|
+
} = props;
|
|
17943
|
+
const innerRef = useRef();
|
|
17944
|
+
useImperativeHandle(ref, () => innerRef.current);
|
|
17945
|
+
const [navState, setNavState, resetNavState] = useNavState(id);
|
|
17946
|
+
const [boundAction, value, setValue, initialValue] = useActionBoundToOneParam(action, name);
|
|
17947
|
+
const {
|
|
17948
|
+
loading: actionLoading
|
|
17949
|
+
} = useActionStatus(boundAction);
|
|
17950
|
+
const executeAction = useExecuteAction(innerRef, {
|
|
17951
|
+
errorEffect: actionErrorEffect
|
|
17952
|
+
});
|
|
17953
|
+
useEffect(() => {
|
|
17954
|
+
setNavState(value);
|
|
17955
|
+
}, [value]);
|
|
17956
|
+
const actionRequesterRef = useRef(null);
|
|
17957
|
+
useActionEvents(innerRef, {
|
|
17958
|
+
onCancel: (e, reason) => {
|
|
17959
|
+
resetNavState();
|
|
17960
|
+
setValue(initialValue);
|
|
17961
|
+
onCancel?.(e, reason);
|
|
17962
|
+
},
|
|
17963
|
+
onPrevented: onActionPrevented,
|
|
17964
|
+
onAction: actionEvent => {
|
|
17965
|
+
actionRequesterRef.current = actionEvent.detail.requester;
|
|
17966
|
+
executeAction(actionEvent);
|
|
17967
|
+
},
|
|
17968
|
+
onStart: onActionStart,
|
|
17969
|
+
onAbort: e => {
|
|
17970
|
+
setValue(initialValue);
|
|
17971
|
+
onActionAbort?.(e);
|
|
17972
|
+
},
|
|
17973
|
+
onError: error => {
|
|
17974
|
+
setValue(initialValue);
|
|
17975
|
+
onActionError?.(error);
|
|
17976
|
+
},
|
|
17977
|
+
onEnd: () => {
|
|
17978
|
+
resetNavState();
|
|
17979
|
+
onActionEnd?.();
|
|
17980
|
+
}
|
|
17981
|
+
});
|
|
17982
|
+
const childRefArray = useRefArray(children, child => child.value);
|
|
17983
|
+
return jsx(SelectControlled, {
|
|
17984
|
+
ref: innerRef,
|
|
17985
|
+
name: name,
|
|
17986
|
+
value: value,
|
|
17987
|
+
"data-action": boundAction,
|
|
17988
|
+
onChange: event => {
|
|
17989
|
+
const select = event.target;
|
|
17990
|
+
const selectedValue = select.value;
|
|
17991
|
+
setValue(selectedValue);
|
|
17992
|
+
const radioListContainer = innerRef.current;
|
|
17993
|
+
const optionSelected = select.querySelector(`option[value="${selectedValue}"]`);
|
|
17994
|
+
requestAction(radioListContainer, boundAction, {
|
|
17995
|
+
event,
|
|
17996
|
+
requester: optionSelected
|
|
17997
|
+
});
|
|
17998
|
+
},
|
|
17999
|
+
...rest,
|
|
18000
|
+
children: children.map((child, i) => {
|
|
18001
|
+
const childRef = childRefArray[i];
|
|
18002
|
+
return {
|
|
18003
|
+
...child,
|
|
18004
|
+
ref: childRef,
|
|
18005
|
+
loading: child.loading || actionLoading && actionRequesterRef.current === childRef.current,
|
|
18006
|
+
readOnly: child.readOnly || actionLoading
|
|
18007
|
+
};
|
|
18008
|
+
})
|
|
18009
|
+
});
|
|
18010
|
+
});
|
|
18011
|
+
forwardRef((props, ref) => {
|
|
18012
|
+
const {
|
|
18013
|
+
id,
|
|
18014
|
+
name,
|
|
18015
|
+
value: externalValue,
|
|
18016
|
+
children,
|
|
18017
|
+
...rest
|
|
18018
|
+
} = props;
|
|
18019
|
+
const innerRef = useRef();
|
|
18020
|
+
useImperativeHandle(ref, () => innerRef.current);
|
|
18021
|
+
const [navState, setNavState] = useNavState(id);
|
|
18022
|
+
const [value, setValue, initialValue] = [name, externalValue, navState];
|
|
18023
|
+
useEffect(() => {
|
|
18024
|
+
setNavState(value);
|
|
18025
|
+
}, [value]);
|
|
18026
|
+
useFormEvents(innerRef, {
|
|
18027
|
+
onFormReset: () => {
|
|
18028
|
+
setValue(undefined);
|
|
18029
|
+
},
|
|
18030
|
+
onFormActionAbort: () => {
|
|
18031
|
+
setValue(initialValue);
|
|
18032
|
+
},
|
|
18033
|
+
onFormActionError: () => {
|
|
18034
|
+
setValue(initialValue);
|
|
18035
|
+
}
|
|
18036
|
+
});
|
|
18037
|
+
return jsx(SelectControlled, {
|
|
18038
|
+
ref: innerRef,
|
|
18039
|
+
name: name,
|
|
18040
|
+
value: value,
|
|
18041
|
+
onChange: event => {
|
|
18042
|
+
const select = event.target;
|
|
18043
|
+
const selectedValue = select.checked;
|
|
18044
|
+
setValue(selectedValue);
|
|
18045
|
+
},
|
|
18046
|
+
...rest,
|
|
18047
|
+
children: children
|
|
18048
|
+
});
|
|
18049
|
+
});
|
|
18050
|
+
|
|
18051
|
+
const createUniqueValueConstraint = (
|
|
18052
|
+
// the set might be incomplete (the front usually don't have the full copy of all the items from the backend)
|
|
18053
|
+
// but this is already nice to help user with what we know
|
|
18054
|
+
// it's also possible that front is unsync with backend, preventing user to choose a value
|
|
18055
|
+
// that is actually free.
|
|
18056
|
+
// But this is unlikely to happen and user could reload the page to be able to choose that name
|
|
18057
|
+
// that suddenly became available
|
|
18058
|
+
existingValueSet,
|
|
18059
|
+
message = `"{value}" already exists. Please choose another value.`,
|
|
18060
|
+
) => {
|
|
18061
|
+
return {
|
|
18062
|
+
name: "unique_value",
|
|
18063
|
+
check: (input) => {
|
|
18064
|
+
const inputValue = input.value;
|
|
18065
|
+
const hasConflict = existingValueSet.has(inputValue);
|
|
18066
|
+
// console.log({
|
|
18067
|
+
// inputValue,
|
|
18068
|
+
// names: Array.from(otherNameSet.values()),
|
|
18069
|
+
// hasConflict,
|
|
18070
|
+
// });
|
|
18071
|
+
if (hasConflict) {
|
|
18072
|
+
return message.replace("{value}", inputValue);
|
|
18073
|
+
}
|
|
18074
|
+
return "";
|
|
18075
|
+
},
|
|
18076
|
+
};
|
|
18077
|
+
};
|
|
18078
|
+
|
|
18079
|
+
const SINGLE_SPACE_CONSTRAINT = {
|
|
18080
|
+
name: "single_space",
|
|
18081
|
+
check: (input) => {
|
|
18082
|
+
const inputValue = input.value;
|
|
18083
|
+
const hasLeadingSpace = inputValue.startsWith(" ");
|
|
18084
|
+
const hasTrailingSpace = inputValue.endsWith(" ");
|
|
18085
|
+
const hasDoubleSpace = inputValue.includes(" ");
|
|
18086
|
+
if (hasLeadingSpace || hasDoubleSpace || hasTrailingSpace) {
|
|
18087
|
+
return "Spaces at the beginning, end, or consecutive spaces are not allowed";
|
|
18088
|
+
}
|
|
18089
|
+
return "";
|
|
18090
|
+
},
|
|
18091
|
+
};
|
|
18092
|
+
|
|
18093
|
+
installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
18094
|
+
.action_error {
|
|
18095
|
+
padding: 20px;
|
|
18096
|
+
background: #fdd;
|
|
18097
|
+
border: 1px solid red;
|
|
18098
|
+
margin-top: 0;
|
|
18099
|
+
margin-bottom: 20px;
|
|
18100
|
+
}
|
|
18101
|
+
`;
|
|
18102
|
+
const renderIdleDefault = () => null;
|
|
18103
|
+
const renderLoadingDefault = () => null;
|
|
18104
|
+
const renderAbortedDefault = () => null;
|
|
18105
|
+
const renderErrorDefault = error => {
|
|
18106
|
+
let routeErrorText = error && error.message ? error.message : error;
|
|
18107
|
+
return jsxs("p", {
|
|
18108
|
+
className: "action_error",
|
|
18109
|
+
children: ["An error occured: ", routeErrorText]
|
|
18110
|
+
});
|
|
18111
|
+
};
|
|
18112
|
+
const renderCompletedDefault = () => null;
|
|
18113
|
+
const ActionRenderer = ({
|
|
18114
|
+
action,
|
|
18115
|
+
children,
|
|
18116
|
+
disabled
|
|
18117
|
+
}) => {
|
|
18118
|
+
const {
|
|
18119
|
+
idle: renderIdle = renderIdleDefault,
|
|
18120
|
+
loading: renderLoading = renderLoadingDefault,
|
|
18121
|
+
aborted: renderAborted = renderAbortedDefault,
|
|
18122
|
+
error: renderError = renderErrorDefault,
|
|
18123
|
+
completed: renderCompleted,
|
|
18124
|
+
always: renderAlways
|
|
18125
|
+
} = typeof children === "function" ? {
|
|
18126
|
+
completed: children
|
|
18127
|
+
} : children || {};
|
|
18128
|
+
if (disabled) {
|
|
18129
|
+
return null;
|
|
18130
|
+
}
|
|
18131
|
+
if (action === undefined) {
|
|
18132
|
+
throw new Error("ActionRenderer requires an action to render, but none was provided.");
|
|
18133
|
+
}
|
|
18134
|
+
const {
|
|
18135
|
+
idle,
|
|
18136
|
+
loading,
|
|
18137
|
+
aborted,
|
|
18138
|
+
error,
|
|
18139
|
+
data
|
|
18140
|
+
} = useActionStatus(action);
|
|
18141
|
+
const UIRenderedPromise = useUIRenderedPromise(action);
|
|
18142
|
+
const [errorBoundary, resetErrorBoundary] = useErrorBoundary();
|
|
18143
|
+
|
|
18144
|
+
// Mark this action as bound to UI components (has renderers)
|
|
18145
|
+
// This tells the action system that errors should be caught and stored
|
|
18146
|
+
// in the action's error state rather than bubbling up
|
|
18147
|
+
useLayoutEffect(() => {
|
|
18148
|
+
if (action) {
|
|
18149
|
+
const {
|
|
18150
|
+
ui
|
|
18151
|
+
} = getActionPrivateProperties(action);
|
|
18152
|
+
ui.hasRenderers = true;
|
|
18153
|
+
}
|
|
18154
|
+
}, [action]);
|
|
18155
|
+
useLayoutEffect(() => {
|
|
18156
|
+
resetErrorBoundary();
|
|
18157
|
+
}, [action, loading, idle, resetErrorBoundary]);
|
|
18158
|
+
useLayoutEffect(() => {
|
|
18159
|
+
UIRenderedPromise.resolve();
|
|
18160
|
+
return () => {
|
|
18161
|
+
actionUIRenderedPromiseWeakMap.delete(action);
|
|
18162
|
+
};
|
|
18163
|
+
}, [action]);
|
|
18164
|
+
|
|
18165
|
+
// If renderAlways is provided, it wins and handles all rendering
|
|
18166
|
+
if (renderAlways) {
|
|
18167
|
+
return renderAlways({
|
|
18168
|
+
idle,
|
|
18169
|
+
loading,
|
|
18170
|
+
aborted,
|
|
18171
|
+
error,
|
|
18172
|
+
data
|
|
18173
|
+
});
|
|
18174
|
+
}
|
|
18175
|
+
if (idle) {
|
|
18176
|
+
return renderIdle(action);
|
|
18177
|
+
}
|
|
18178
|
+
if (errorBoundary) {
|
|
18179
|
+
return renderError(errorBoundary, "ui_error", action);
|
|
18180
|
+
}
|
|
18181
|
+
if (error) {
|
|
18182
|
+
return renderError(error, "action_error", action);
|
|
18183
|
+
}
|
|
18184
|
+
if (aborted) {
|
|
18185
|
+
return renderAborted(action);
|
|
18186
|
+
}
|
|
18187
|
+
let renderCompletedSafe;
|
|
18188
|
+
if (renderCompleted) {
|
|
18189
|
+
renderCompletedSafe = renderCompleted;
|
|
18190
|
+
} else {
|
|
18191
|
+
const {
|
|
18192
|
+
ui
|
|
18193
|
+
} = getActionPrivateProperties(action);
|
|
18194
|
+
if (ui.renderCompleted) {
|
|
18195
|
+
renderCompletedSafe = ui.renderCompleted;
|
|
18196
|
+
} else {
|
|
18197
|
+
renderCompletedSafe = renderCompletedDefault;
|
|
18198
|
+
}
|
|
18199
|
+
}
|
|
18200
|
+
if (loading) {
|
|
18201
|
+
if (action.canDisplayOldData && data !== undefined) {
|
|
18202
|
+
return renderCompletedSafe(data, action);
|
|
18203
|
+
}
|
|
18204
|
+
return renderLoading(action);
|
|
18205
|
+
}
|
|
18206
|
+
return renderCompletedSafe(data, action);
|
|
18207
|
+
};
|
|
18208
|
+
const defaultPromise = Promise.resolve();
|
|
18209
|
+
defaultPromise.resolve = () => {};
|
|
18210
|
+
const actionUIRenderedPromiseWeakMap = new WeakMap();
|
|
18211
|
+
const useUIRenderedPromise = action => {
|
|
18212
|
+
if (!action) {
|
|
18213
|
+
return defaultPromise;
|
|
18214
|
+
}
|
|
18215
|
+
const actionUIRenderedPromise = actionUIRenderedPromiseWeakMap.get(action);
|
|
18216
|
+
if (actionUIRenderedPromise) {
|
|
18217
|
+
return actionUIRenderedPromise;
|
|
18218
|
+
}
|
|
18219
|
+
let resolve;
|
|
18220
|
+
const promise = new Promise(res => {
|
|
18221
|
+
resolve = res;
|
|
18222
|
+
});
|
|
18223
|
+
promise.resolve = resolve;
|
|
18224
|
+
actionUIRenderedPromiseWeakMap.set(action, promise);
|
|
18225
|
+
return promise;
|
|
18226
|
+
};
|
|
18227
|
+
|
|
18228
|
+
const useFocusGroup = (
|
|
18229
|
+
elementRef,
|
|
18230
|
+
{ enabled = true, direction, skipTab, loop, name } = {},
|
|
18231
|
+
) => {
|
|
18232
|
+
useLayoutEffect(() => {
|
|
18233
|
+
if (!enabled) {
|
|
18234
|
+
return null;
|
|
18235
|
+
}
|
|
18236
|
+
const focusGroup = initFocusGroup(elementRef.current, {
|
|
18237
|
+
direction,
|
|
18238
|
+
skipTab,
|
|
18239
|
+
loop,
|
|
18240
|
+
name,
|
|
18241
|
+
});
|
|
18242
|
+
return focusGroup.cleanup;
|
|
18243
|
+
}, [direction, skipTab, loop, name]);
|
|
18244
|
+
};
|
|
18245
|
+
|
|
18246
|
+
installImportMetaCss(import.meta);const rightArrowPath = "M680-480L360-160l-80-80 240-240-240-240 80-80 320 320z";
|
|
18247
|
+
const downArrowPath = "M480-280L160-600l80-80 240 240 240-240 80 80-320 320z";
|
|
18248
|
+
import.meta.css = /* css */`
|
|
18249
|
+
.summary_marker {
|
|
18250
|
+
width: 1em;
|
|
18251
|
+
height: 1em;
|
|
18252
|
+
line-height: 1em;
|
|
18253
|
+
}
|
|
18254
|
+
.summary_marker_svg .arrow {
|
|
18255
|
+
animation-duration: 0.3s;
|
|
18256
|
+
animation-fill-mode: forwards;
|
|
18257
|
+
animation-timing-function: cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
18258
|
+
}
|
|
18259
|
+
.summary_marker_svg .arrow[data-animation-target="down"] {
|
|
18260
|
+
animation-name: morph-to-down;
|
|
18261
|
+
}
|
|
18262
|
+
@keyframes morph-to-down {
|
|
18263
|
+
from {
|
|
18264
|
+
d: path("${rightArrowPath}");
|
|
18265
|
+
}
|
|
18266
|
+
to {
|
|
18267
|
+
d: path("${downArrowPath}");
|
|
18268
|
+
}
|
|
18269
|
+
}
|
|
18270
|
+
.summary_marker_svg .arrow[data-animation-target="right"] {
|
|
18271
|
+
animation-name: morph-to-right;
|
|
18272
|
+
}
|
|
18273
|
+
@keyframes morph-to-right {
|
|
18274
|
+
from {
|
|
18275
|
+
d: path("${downArrowPath}");
|
|
18276
|
+
}
|
|
18277
|
+
to {
|
|
18278
|
+
d: path("${rightArrowPath}");
|
|
18279
|
+
}
|
|
18280
|
+
}
|
|
18281
|
+
|
|
18282
|
+
.summary_marker_svg .foreground_circle {
|
|
18283
|
+
stroke-dasharray: 503 1507; /* ~25% of circle perimeter */
|
|
18284
|
+
stroke-dashoffset: 0;
|
|
18285
|
+
animation: progress-around-circle 1.5s linear infinite;
|
|
18286
|
+
}
|
|
18287
|
+
@keyframes progress-around-circle {
|
|
18288
|
+
0% {
|
|
18289
|
+
stroke-dashoffset: 0;
|
|
18290
|
+
}
|
|
18291
|
+
100% {
|
|
18292
|
+
stroke-dashoffset: -2010;
|
|
18293
|
+
}
|
|
18294
|
+
}
|
|
18295
|
+
|
|
18296
|
+
/* fading and scaling */
|
|
18297
|
+
.summary_marker_svg .arrow {
|
|
18298
|
+
transition: opacity 0.3s ease-in-out;
|
|
18299
|
+
opacity: 1;
|
|
18300
|
+
}
|
|
18301
|
+
.summary_marker_svg .loading_container {
|
|
18302
|
+
transition: transform 0.3s linear;
|
|
18303
|
+
transform: scale(0.3);
|
|
18304
|
+
}
|
|
18305
|
+
.summary_marker_svg .background_circle,
|
|
18306
|
+
.summary_marker_svg .foreground_circle {
|
|
18307
|
+
transition: opacity 0.3s ease-in-out;
|
|
18308
|
+
opacity: 0;
|
|
18309
|
+
}
|
|
18310
|
+
.summary_marker_svg[data-loading] .arrow {
|
|
18311
|
+
opacity: 0;
|
|
18312
|
+
}
|
|
18313
|
+
.summary_marker_svg[data-loading] .loading_container {
|
|
18314
|
+
transform: scale(1);
|
|
18315
|
+
}
|
|
18316
|
+
.summary_marker_svg[data-loading] .background_circle {
|
|
18317
|
+
opacity: 0.2;
|
|
18318
|
+
}
|
|
18319
|
+
.summary_marker_svg[data-loading] .foreground_circle {
|
|
18320
|
+
opacity: 1;
|
|
18321
|
+
}
|
|
18322
|
+
`;
|
|
18323
|
+
const SummaryMarker = ({
|
|
18324
|
+
open,
|
|
18325
|
+
loading
|
|
18326
|
+
}) => {
|
|
18327
|
+
const showLoading = useDebounceTrue(loading, 300);
|
|
18328
|
+
const mountedRef = useRef(false);
|
|
18329
|
+
const prevOpenRef = useRef(open);
|
|
18330
|
+
useLayoutEffect(() => {
|
|
18331
|
+
mountedRef.current = true;
|
|
18332
|
+
return () => {
|
|
18333
|
+
mountedRef.current = false;
|
|
18334
|
+
};
|
|
18335
|
+
}, []);
|
|
18336
|
+
const shouldAnimate = mountedRef.current && prevOpenRef.current !== open;
|
|
18337
|
+
prevOpenRef.current = open;
|
|
18338
|
+
return jsx("span", {
|
|
18339
|
+
className: "summary_marker",
|
|
18340
|
+
children: jsxs("svg", {
|
|
18341
|
+
className: "summary_marker_svg",
|
|
18342
|
+
viewBox: "0 -960 960 960",
|
|
18343
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
18344
|
+
"data-loading": open ? showLoading || undefined : undefined,
|
|
18345
|
+
children: [jsxs("g", {
|
|
18346
|
+
className: "loading_container",
|
|
18347
|
+
"transform-origin": "480px -480px",
|
|
18348
|
+
children: [jsx("circle", {
|
|
18349
|
+
className: "background_circle",
|
|
18350
|
+
cx: "480",
|
|
18351
|
+
cy: "-480",
|
|
18352
|
+
r: "320",
|
|
18353
|
+
stroke: "currentColor",
|
|
18354
|
+
fill: "none",
|
|
18355
|
+
strokeWidth: "60",
|
|
18356
|
+
opacity: "0.2"
|
|
18357
|
+
}), jsx("circle", {
|
|
18358
|
+
className: "foreground_circle",
|
|
18359
|
+
cx: "480",
|
|
18360
|
+
cy: "-480",
|
|
18361
|
+
r: "320",
|
|
18362
|
+
stroke: "currentColor",
|
|
18363
|
+
fill: "none",
|
|
18364
|
+
strokeWidth: "60",
|
|
18365
|
+
strokeLinecap: "round",
|
|
18366
|
+
strokeDasharray: "503 1507"
|
|
18367
|
+
})]
|
|
18368
|
+
}), jsx("g", {
|
|
18369
|
+
className: "arrow_container",
|
|
18370
|
+
"transform-origin": "480px -480px",
|
|
18371
|
+
children: jsx("path", {
|
|
18372
|
+
className: "arrow",
|
|
18373
|
+
fill: "currentColor",
|
|
18374
|
+
"data-animation-target": shouldAnimate ? open ? "down" : "right" : undefined,
|
|
18375
|
+
d: open ? downArrowPath : rightArrowPath
|
|
18376
|
+
})
|
|
18377
|
+
})]
|
|
18378
|
+
})
|
|
18379
|
+
});
|
|
18104
18380
|
};
|
|
18105
18381
|
|
|
18106
18382
|
installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
18107
|
-
.
|
|
18108
|
-
|
|
18383
|
+
.navi_details {
|
|
18384
|
+
position: relative;
|
|
18385
|
+
z-index: 1;
|
|
18386
|
+
display: flex;
|
|
18387
|
+
flex-shrink: 0;
|
|
18388
|
+
flex-direction: column;
|
|
18389
|
+
}
|
|
18390
|
+
|
|
18391
|
+
.navi_details > summary {
|
|
18392
|
+
display: flex;
|
|
18393
|
+
flex-shrink: 0;
|
|
18394
|
+
flex-direction: column;
|
|
18395
|
+
cursor: pointer;
|
|
18396
|
+
user-select: none;
|
|
18397
|
+
}
|
|
18398
|
+
.summary_body {
|
|
18399
|
+
display: flex;
|
|
18400
|
+
width: 100%;
|
|
18401
|
+
flex-direction: row;
|
|
18402
|
+
align-items: center;
|
|
18403
|
+
gap: 0.2em;
|
|
18404
|
+
}
|
|
18405
|
+
.summary_label {
|
|
18406
|
+
display: flex;
|
|
18407
|
+
padding-right: 10px;
|
|
18408
|
+
flex: 1;
|
|
18409
|
+
align-items: center;
|
|
18410
|
+
gap: 0.2em;
|
|
18411
|
+
}
|
|
18412
|
+
|
|
18413
|
+
.navi_details > summary:focus {
|
|
18414
|
+
z-index: 1;
|
|
18109
18415
|
}
|
|
18110
18416
|
`;
|
|
18111
|
-
const
|
|
18112
|
-
|
|
18113
|
-
return select;
|
|
18417
|
+
const Details = forwardRef((props, ref) => {
|
|
18418
|
+
return renderActionableComponent(props, ref);
|
|
18114
18419
|
});
|
|
18115
|
-
const
|
|
18420
|
+
const DetailsBasic = forwardRef((props, ref) => {
|
|
18116
18421
|
const {
|
|
18117
|
-
|
|
18118
|
-
|
|
18422
|
+
id,
|
|
18423
|
+
label = "Summary",
|
|
18424
|
+
open,
|
|
18119
18425
|
loading,
|
|
18120
|
-
|
|
18121
|
-
|
|
18426
|
+
className,
|
|
18427
|
+
focusGroup,
|
|
18428
|
+
focusGroupDirection,
|
|
18429
|
+
arrowKeyShortcuts = true,
|
|
18430
|
+
openKeyShortcut = "ArrowRight",
|
|
18431
|
+
closeKeyShortcut = "ArrowLeft",
|
|
18432
|
+
onToggle,
|
|
18122
18433
|
children,
|
|
18123
18434
|
...rest
|
|
18124
18435
|
} = props;
|
|
18125
18436
|
const innerRef = useRef();
|
|
18126
18437
|
useImperativeHandle(ref, () => innerRef.current);
|
|
18127
|
-
const
|
|
18128
|
-
|
|
18129
|
-
|
|
18130
|
-
|
|
18131
|
-
|
|
18132
|
-
|
|
18438
|
+
const [navState, setNavState] = useNavState(id);
|
|
18439
|
+
const [innerOpen, innerOpenSetter] = useState(open || navState);
|
|
18440
|
+
useFocusGroup(innerRef, {
|
|
18441
|
+
enabled: focusGroup,
|
|
18442
|
+
name: typeof focusGroup === "string" ? focusGroup : undefined,
|
|
18443
|
+
direction: focusGroupDirection
|
|
18444
|
+
});
|
|
18445
|
+
|
|
18446
|
+
/**
|
|
18447
|
+
* Browser will dispatch "toggle" event even if we set open={true}
|
|
18448
|
+
* When rendering the component for the first time
|
|
18449
|
+
* We have to ensure the initial "toggle" event is ignored.
|
|
18450
|
+
*
|
|
18451
|
+
* If we don't do that code will think the details has changed and run logic accordingly
|
|
18452
|
+
* For example it will try to navigate to the current url while we are already there
|
|
18453
|
+
*
|
|
18454
|
+
* See:
|
|
18455
|
+
* - https://techblog.thescore.com/2024/10/08/why-we-decided-to-change-how-the-details-element-works/
|
|
18456
|
+
* - https://github.com/whatwg/html/issues/4500
|
|
18457
|
+
* - https://stackoverflow.com/questions/58942600/react-html-details-toggles-uncontrollably-when-starts-open
|
|
18458
|
+
*
|
|
18459
|
+
*/
|
|
18460
|
+
|
|
18461
|
+
const summaryRef = useRef(null);
|
|
18462
|
+
useKeyboardShortcuts(innerRef, [{
|
|
18463
|
+
key: openKeyShortcut,
|
|
18464
|
+
enabled: arrowKeyShortcuts,
|
|
18465
|
+
when: e => document.activeElement === summaryRef.current &&
|
|
18466
|
+
// avoid handling openKeyShortcut twice when keydown occurs inside nested details
|
|
18467
|
+
!e.defaultPrevented,
|
|
18468
|
+
action: e => {
|
|
18469
|
+
const details = innerRef.current;
|
|
18470
|
+
if (!details.open) {
|
|
18133
18471
|
e.preventDefault();
|
|
18472
|
+
details.open = true;
|
|
18473
|
+
return;
|
|
18474
|
+
}
|
|
18475
|
+
const summary = summaryRef.current;
|
|
18476
|
+
const firstFocusableElementInDetails = findAfter(summary, elementIsFocusable, {
|
|
18477
|
+
root: details
|
|
18478
|
+
});
|
|
18479
|
+
if (!firstFocusableElementInDetails) {
|
|
18480
|
+
return;
|
|
18134
18481
|
}
|
|
18482
|
+
e.preventDefault();
|
|
18483
|
+
firstFocusableElementInDetails.focus();
|
|
18484
|
+
}
|
|
18485
|
+
}, {
|
|
18486
|
+
key: closeKeyShortcut,
|
|
18487
|
+
enabled: arrowKeyShortcuts,
|
|
18488
|
+
when: () => {
|
|
18489
|
+
const details = innerRef.current;
|
|
18490
|
+
return details.open;
|
|
18135
18491
|
},
|
|
18136
|
-
|
|
18137
|
-
|
|
18138
|
-
const
|
|
18139
|
-
|
|
18140
|
-
|
|
18141
|
-
|
|
18142
|
-
|
|
18143
|
-
|
|
18144
|
-
|
|
18145
|
-
|
|
18146
|
-
|
|
18147
|
-
|
|
18148
|
-
|
|
18149
|
-
|
|
18150
|
-
readOnly: readOnly || childReadOnly,
|
|
18151
|
-
disabled: disabled || childDisabled,
|
|
18152
|
-
loading: loading || childLoading,
|
|
18153
|
-
...childRest,
|
|
18154
|
-
children: label
|
|
18155
|
-
}, childValue);
|
|
18156
|
-
})
|
|
18157
|
-
});
|
|
18158
|
-
return jsx(LoaderBackground, {
|
|
18159
|
-
loading: loading,
|
|
18160
|
-
color: "light-dark(#355fcc, #3b82f6)",
|
|
18161
|
-
inset: -1,
|
|
18162
|
-
children: selectElement
|
|
18163
|
-
});
|
|
18164
|
-
});
|
|
18165
|
-
forwardRef((props, ref) => {
|
|
18166
|
-
const {
|
|
18167
|
-
value: initialValue,
|
|
18168
|
-
id,
|
|
18169
|
-
children,
|
|
18170
|
-
...rest
|
|
18171
|
-
} = props;
|
|
18172
|
-
const innerRef = useRef();
|
|
18173
|
-
useImperativeHandle(ref, () => innerRef.current);
|
|
18174
|
-
const [navState, setNavState] = useNavState(id);
|
|
18175
|
-
const valueAtStart = navState === undefined ? initialValue : navState;
|
|
18176
|
-
const [value, setValue] = useState(valueAtStart);
|
|
18492
|
+
action: e => {
|
|
18493
|
+
const details = innerRef.current;
|
|
18494
|
+
const summary = summaryRef.current;
|
|
18495
|
+
if (document.activeElement === summary) {
|
|
18496
|
+
e.preventDefault();
|
|
18497
|
+
summary.focus();
|
|
18498
|
+
details.open = false;
|
|
18499
|
+
} else {
|
|
18500
|
+
e.preventDefault();
|
|
18501
|
+
summary.focus();
|
|
18502
|
+
}
|
|
18503
|
+
}
|
|
18504
|
+
}]);
|
|
18505
|
+
const mountedRef = useRef(false);
|
|
18177
18506
|
useEffect(() => {
|
|
18178
|
-
|
|
18179
|
-
}, [
|
|
18180
|
-
return
|
|
18507
|
+
mountedRef.current = true;
|
|
18508
|
+
}, []);
|
|
18509
|
+
return jsxs("details", {
|
|
18510
|
+
...rest,
|
|
18181
18511
|
ref: innerRef,
|
|
18182
|
-
|
|
18183
|
-
|
|
18184
|
-
|
|
18185
|
-
const
|
|
18186
|
-
|
|
18512
|
+
id: id,
|
|
18513
|
+
className: ["navi_details", ...(className ? className.split(" ") : [])].join(" "),
|
|
18514
|
+
onToggle: e => {
|
|
18515
|
+
const isOpen = e.newState === "open";
|
|
18516
|
+
if (mountedRef.current) {
|
|
18517
|
+
if (isOpen) {
|
|
18518
|
+
innerOpenSetter(true);
|
|
18519
|
+
setNavState(true);
|
|
18520
|
+
} else {
|
|
18521
|
+
innerOpenSetter(false);
|
|
18522
|
+
setNavState(undefined);
|
|
18523
|
+
}
|
|
18524
|
+
}
|
|
18525
|
+
onToggle?.(e);
|
|
18187
18526
|
},
|
|
18188
|
-
|
|
18189
|
-
children:
|
|
18527
|
+
open: innerOpen,
|
|
18528
|
+
children: [jsx("summary", {
|
|
18529
|
+
ref: summaryRef,
|
|
18530
|
+
children: jsxs("div", {
|
|
18531
|
+
className: "summary_body",
|
|
18532
|
+
children: [jsx(SummaryMarker, {
|
|
18533
|
+
open: innerOpen,
|
|
18534
|
+
loading: loading
|
|
18535
|
+
}), jsx("div", {
|
|
18536
|
+
className: "summary_label",
|
|
18537
|
+
children: label
|
|
18538
|
+
})]
|
|
18539
|
+
})
|
|
18540
|
+
}), children]
|
|
18190
18541
|
});
|
|
18191
18542
|
});
|
|
18192
18543
|
forwardRef((props, ref) => {
|
|
18193
18544
|
const {
|
|
18194
|
-
id,
|
|
18195
|
-
name,
|
|
18196
|
-
value: externalValue,
|
|
18197
|
-
valueSignal,
|
|
18198
18545
|
action,
|
|
18199
|
-
|
|
18200
|
-
|
|
18546
|
+
loading,
|
|
18547
|
+
onToggle,
|
|
18201
18548
|
onActionPrevented,
|
|
18202
18549
|
onActionStart,
|
|
18203
|
-
onActionAbort,
|
|
18204
18550
|
onActionError,
|
|
18205
18551
|
onActionEnd,
|
|
18206
|
-
|
|
18552
|
+
children,
|
|
18207
18553
|
...rest
|
|
18208
18554
|
} = props;
|
|
18209
18555
|
const innerRef = useRef();
|
|
18210
18556
|
useImperativeHandle(ref, () => innerRef.current);
|
|
18211
|
-
const
|
|
18212
|
-
const [boundAction, value, setValue, initialValue] = useActionBoundToOneParam(action, name);
|
|
18557
|
+
const effectiveAction = useAction(action);
|
|
18213
18558
|
const {
|
|
18214
18559
|
loading: actionLoading
|
|
18215
|
-
} = useActionStatus(
|
|
18560
|
+
} = useActionStatus(effectiveAction);
|
|
18216
18561
|
const executeAction = useExecuteAction(innerRef, {
|
|
18217
|
-
|
|
18562
|
+
// the error will be displayed by actionRenderer inside <details>
|
|
18563
|
+
errorEffect: "none"
|
|
18218
18564
|
});
|
|
18219
|
-
useEffect(() => {
|
|
18220
|
-
setNavState(value);
|
|
18221
|
-
}, [value]);
|
|
18222
|
-
const actionRequesterRef = useRef(null);
|
|
18223
18565
|
useActionEvents(innerRef, {
|
|
18224
|
-
onCancel: (e, reason) => {
|
|
18225
|
-
resetNavState();
|
|
18226
|
-
setValue(initialValue);
|
|
18227
|
-
onCancel?.(e, reason);
|
|
18228
|
-
},
|
|
18229
18566
|
onPrevented: onActionPrevented,
|
|
18230
|
-
onAction:
|
|
18231
|
-
|
|
18232
|
-
executeAction(actionEvent);
|
|
18567
|
+
onAction: e => {
|
|
18568
|
+
executeAction(e);
|
|
18233
18569
|
},
|
|
18234
18570
|
onStart: onActionStart,
|
|
18235
|
-
|
|
18236
|
-
|
|
18237
|
-
onActionAbort?.(e);
|
|
18238
|
-
},
|
|
18239
|
-
onError: error => {
|
|
18240
|
-
setValue(initialValue);
|
|
18241
|
-
onActionError?.(error);
|
|
18242
|
-
},
|
|
18243
|
-
onEnd: () => {
|
|
18244
|
-
resetNavState();
|
|
18245
|
-
onActionEnd?.();
|
|
18246
|
-
}
|
|
18571
|
+
onError: onActionError,
|
|
18572
|
+
onEnd: onActionEnd
|
|
18247
18573
|
});
|
|
18248
|
-
|
|
18249
|
-
return jsx(SelectControlled, {
|
|
18250
|
-
ref: innerRef,
|
|
18251
|
-
name: name,
|
|
18252
|
-
value: value,
|
|
18253
|
-
"data-action": boundAction,
|
|
18254
|
-
onChange: event => {
|
|
18255
|
-
const select = event.target;
|
|
18256
|
-
const selectedValue = select.value;
|
|
18257
|
-
setValue(selectedValue);
|
|
18258
|
-
const radioListContainer = innerRef.current;
|
|
18259
|
-
const optionSelected = select.querySelector(`option[value="${selectedValue}"]`);
|
|
18260
|
-
requestAction(radioListContainer, boundAction, {
|
|
18261
|
-
event,
|
|
18262
|
-
requester: optionSelected
|
|
18263
|
-
});
|
|
18264
|
-
},
|
|
18574
|
+
return jsx(DetailsBasic, {
|
|
18265
18575
|
...rest,
|
|
18266
|
-
children: children.map((child, i) => {
|
|
18267
|
-
const childRef = childRefArray[i];
|
|
18268
|
-
return {
|
|
18269
|
-
...child,
|
|
18270
|
-
ref: childRef,
|
|
18271
|
-
loading: child.loading || actionLoading && actionRequesterRef.current === childRef.current,
|
|
18272
|
-
readOnly: child.readOnly || actionLoading
|
|
18273
|
-
};
|
|
18274
|
-
})
|
|
18275
|
-
});
|
|
18276
|
-
});
|
|
18277
|
-
forwardRef((props, ref) => {
|
|
18278
|
-
const {
|
|
18279
|
-
id,
|
|
18280
|
-
name,
|
|
18281
|
-
value: externalValue,
|
|
18282
|
-
children,
|
|
18283
|
-
...rest
|
|
18284
|
-
} = props;
|
|
18285
|
-
const innerRef = useRef();
|
|
18286
|
-
useImperativeHandle(ref, () => innerRef.current);
|
|
18287
|
-
const [navState, setNavState] = useNavState(id);
|
|
18288
|
-
const [value, setValue, initialValue] = [name, externalValue, navState];
|
|
18289
|
-
useEffect(() => {
|
|
18290
|
-
setNavState(value);
|
|
18291
|
-
}, [value]);
|
|
18292
|
-
useFormEvents(innerRef, {
|
|
18293
|
-
onFormReset: () => {
|
|
18294
|
-
setValue(undefined);
|
|
18295
|
-
},
|
|
18296
|
-
onFormActionAbort: () => {
|
|
18297
|
-
setValue(initialValue);
|
|
18298
|
-
},
|
|
18299
|
-
onFormActionError: () => {
|
|
18300
|
-
setValue(initialValue);
|
|
18301
|
-
}
|
|
18302
|
-
});
|
|
18303
|
-
return jsx(SelectControlled, {
|
|
18304
18576
|
ref: innerRef,
|
|
18305
|
-
|
|
18306
|
-
|
|
18307
|
-
|
|
18308
|
-
|
|
18309
|
-
|
|
18310
|
-
|
|
18577
|
+
loading: loading || actionLoading,
|
|
18578
|
+
onToggle: toggleEvent => {
|
|
18579
|
+
const isOpen = toggleEvent.newState === "open";
|
|
18580
|
+
if (isOpen) {
|
|
18581
|
+
requestAction(toggleEvent.target, effectiveAction, {
|
|
18582
|
+
event: toggleEvent,
|
|
18583
|
+
method: "run"
|
|
18584
|
+
});
|
|
18585
|
+
} else {
|
|
18586
|
+
effectiveAction.abort();
|
|
18587
|
+
}
|
|
18588
|
+
onToggle?.(toggleEvent);
|
|
18311
18589
|
},
|
|
18312
|
-
|
|
18313
|
-
|
|
18590
|
+
children: jsx(ActionRenderer, {
|
|
18591
|
+
action: effectiveAction,
|
|
18592
|
+
children: children
|
|
18593
|
+
})
|
|
18314
18594
|
});
|
|
18315
18595
|
});
|
|
18316
18596
|
|
|
@@ -21678,116 +21958,6 @@ const useCellsAndColumns = (cells, columns) => {
|
|
|
21678
21958
|
};
|
|
21679
21959
|
};
|
|
21680
21960
|
|
|
21681
|
-
installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
21682
|
-
.navi_tablist {
|
|
21683
|
-
display: flex;
|
|
21684
|
-
overflow-x: auto;
|
|
21685
|
-
overflow-y: hidden;
|
|
21686
|
-
justify-content: space-between;
|
|
21687
|
-
}
|
|
21688
|
-
|
|
21689
|
-
.navi_tablist > ul {
|
|
21690
|
-
align-items: center;
|
|
21691
|
-
display: flex;
|
|
21692
|
-
gap: 0.5rem;
|
|
21693
|
-
list-style: none;
|
|
21694
|
-
margin: 0;
|
|
21695
|
-
padding: 0;
|
|
21696
|
-
}
|
|
21697
|
-
|
|
21698
|
-
.navi_tablist > ul > li {
|
|
21699
|
-
display: inline-flex;
|
|
21700
|
-
position: relative;
|
|
21701
|
-
}
|
|
21702
|
-
|
|
21703
|
-
.navi_tab {
|
|
21704
|
-
white-space: nowrap;
|
|
21705
|
-
display: flex;
|
|
21706
|
-
flex-direction: column;
|
|
21707
|
-
}
|
|
21708
|
-
|
|
21709
|
-
.navi_tab_content {
|
|
21710
|
-
transition: background 0.12s ease-out;
|
|
21711
|
-
border-radius: 6px;
|
|
21712
|
-
text-decoration: none;
|
|
21713
|
-
line-height: 30px;
|
|
21714
|
-
display: flex;
|
|
21715
|
-
padding: 0 0.5rem;
|
|
21716
|
-
}
|
|
21717
|
-
|
|
21718
|
-
.navi_tab:hover .navi_tab_content {
|
|
21719
|
-
background: #dae0e7;
|
|
21720
|
-
color: #010409;
|
|
21721
|
-
}
|
|
21722
|
-
|
|
21723
|
-
.navi_tab .active_marker {
|
|
21724
|
-
display: flex;
|
|
21725
|
-
background: transparent;
|
|
21726
|
-
border-radius: 0.1px;
|
|
21727
|
-
width: 100%;
|
|
21728
|
-
z-index: 1;
|
|
21729
|
-
height: 2px;
|
|
21730
|
-
margin-top: 5px;
|
|
21731
|
-
}
|
|
21732
|
-
|
|
21733
|
-
/* Hidden bold clone to reserve space for bold width without affecting height */
|
|
21734
|
-
.navi_tab_content_bold_clone {
|
|
21735
|
-
font-weight: 600; /* force bold to compute max width */
|
|
21736
|
-
visibility: hidden; /* not visible */
|
|
21737
|
-
display: block; /* in-flow so it contributes to width */
|
|
21738
|
-
height: 0; /* zero height so it doesn't change layout height */
|
|
21739
|
-
overflow: hidden; /* avoid any accidental height */
|
|
21740
|
-
pointer-events: none; /* inert */
|
|
21741
|
-
}
|
|
21742
|
-
|
|
21743
|
-
.navi_tab[aria-selected="true"] .active_marker {
|
|
21744
|
-
background: rgb(205, 52, 37);
|
|
21745
|
-
}
|
|
21746
|
-
|
|
21747
|
-
.navi_tab[aria-selected="true"] .navi_tab_content {
|
|
21748
|
-
font-weight: 600;
|
|
21749
|
-
}
|
|
21750
|
-
`;
|
|
21751
|
-
const TabList = ({
|
|
21752
|
-
children,
|
|
21753
|
-
...props
|
|
21754
|
-
}) => {
|
|
21755
|
-
return jsx("nav", {
|
|
21756
|
-
className: "navi_tablist",
|
|
21757
|
-
role: "tablist",
|
|
21758
|
-
...props,
|
|
21759
|
-
children: jsx("ul", {
|
|
21760
|
-
children: children.map(child => {
|
|
21761
|
-
return jsx("li", {
|
|
21762
|
-
children: child
|
|
21763
|
-
}, child.props.key);
|
|
21764
|
-
})
|
|
21765
|
-
})
|
|
21766
|
-
});
|
|
21767
|
-
};
|
|
21768
|
-
const Tab = ({
|
|
21769
|
-
children,
|
|
21770
|
-
selected,
|
|
21771
|
-
...props
|
|
21772
|
-
}) => {
|
|
21773
|
-
return jsxs("div", {
|
|
21774
|
-
className: "navi_tab",
|
|
21775
|
-
role: "tab",
|
|
21776
|
-
"aria-selected": selected ? "true" : "false",
|
|
21777
|
-
...props,
|
|
21778
|
-
children: [jsx("div", {
|
|
21779
|
-
className: "navi_tab_content",
|
|
21780
|
-
children: children
|
|
21781
|
-
}), jsx("div", {
|
|
21782
|
-
className: "navi_tab_content_bold_clone",
|
|
21783
|
-
"aria-hidden": "true",
|
|
21784
|
-
children: children
|
|
21785
|
-
}), jsx("span", {
|
|
21786
|
-
className: "active_marker"
|
|
21787
|
-
})]
|
|
21788
|
-
});
|
|
21789
|
-
};
|
|
21790
|
-
|
|
21791
21961
|
/**
|
|
21792
21962
|
* Creates a signal that stays synchronized with an external value,
|
|
21793
21963
|
* only updating the signal when the value actually changes.
|
|
@@ -22357,48 +22527,6 @@ const ViewportLayout = props => {
|
|
|
22357
22527
|
});
|
|
22358
22528
|
};
|
|
22359
22529
|
|
|
22360
|
-
const createUniqueValueConstraint = (
|
|
22361
|
-
// the set might be incomplete (the front usually don't have the full copy of all the items from the backend)
|
|
22362
|
-
// but this is already nice to help user with what we know
|
|
22363
|
-
// it's also possible that front is unsync with backend, preventing user to choose a value
|
|
22364
|
-
// that is actually free.
|
|
22365
|
-
// But this is unlikely to happen and user could reload the page to be able to choose that name
|
|
22366
|
-
// that suddenly became available
|
|
22367
|
-
existingValueSet,
|
|
22368
|
-
message = `"{value}" already exists. Please choose another value.`,
|
|
22369
|
-
) => {
|
|
22370
|
-
return {
|
|
22371
|
-
name: "unique_value",
|
|
22372
|
-
check: (input) => {
|
|
22373
|
-
const inputValue = input.value;
|
|
22374
|
-
const hasConflict = existingValueSet.has(inputValue);
|
|
22375
|
-
// console.log({
|
|
22376
|
-
// inputValue,
|
|
22377
|
-
// names: Array.from(otherNameSet.values()),
|
|
22378
|
-
// hasConflict,
|
|
22379
|
-
// });
|
|
22380
|
-
if (hasConflict) {
|
|
22381
|
-
return message.replace("{value}", inputValue);
|
|
22382
|
-
}
|
|
22383
|
-
return "";
|
|
22384
|
-
},
|
|
22385
|
-
};
|
|
22386
|
-
};
|
|
22387
|
-
|
|
22388
|
-
const SINGLE_SPACE_CONSTRAINT = {
|
|
22389
|
-
name: "single_space",
|
|
22390
|
-
check: (input) => {
|
|
22391
|
-
const inputValue = input.value;
|
|
22392
|
-
const hasLeadingSpace = inputValue.startsWith(" ");
|
|
22393
|
-
const hasTrailingSpace = inputValue.endsWith(" ");
|
|
22394
|
-
const hasDoubleSpace = inputValue.includes(" ");
|
|
22395
|
-
if (hasLeadingSpace || hasDoubleSpace || hasTrailingSpace) {
|
|
22396
|
-
return "Spaces at the beginning, end, or consecutive spaces are not allowed";
|
|
22397
|
-
}
|
|
22398
|
-
return "";
|
|
22399
|
-
},
|
|
22400
|
-
};
|
|
22401
|
-
|
|
22402
22530
|
/*
|
|
22403
22531
|
* - Usage
|
|
22404
22532
|
* useEffect(() => {
|