@jsenv/navi 0.16.60 → 0.17.0
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 +150 -65
- package/dist/jsenv_navi.js.map +13 -14
- package/package.json +1 -1
package/dist/jsenv_navi.js
CHANGED
|
@@ -12083,10 +12083,11 @@ const renderActionableComponent = (props, {
|
|
|
12083
12083
|
}) => {
|
|
12084
12084
|
const {
|
|
12085
12085
|
action,
|
|
12086
|
+
liveAction,
|
|
12086
12087
|
shortcuts
|
|
12087
12088
|
} = props;
|
|
12088
12089
|
const formContext = useContext(FormContext);
|
|
12089
|
-
const hasActionProps = Boolean(action || shortcuts && shortcuts.length > 0);
|
|
12090
|
+
const hasActionProps = Boolean(action || liveAction || shortcuts && shortcuts.length > 0);
|
|
12090
12091
|
const considerInsideForm = Boolean(formContext);
|
|
12091
12092
|
if (hasActionProps && WithAction) {
|
|
12092
12093
|
if (considerInsideForm && WithActionInsideForm) {
|
|
@@ -15571,7 +15572,82 @@ const MAX_CONSTRAINT = {
|
|
|
15571
15572
|
},
|
|
15572
15573
|
};
|
|
15573
15574
|
|
|
15574
|
-
const
|
|
15575
|
+
const listenInputValue = (
|
|
15576
|
+
input,
|
|
15577
|
+
callback,
|
|
15578
|
+
{ waitForChange = false } = {},
|
|
15579
|
+
) => {
|
|
15580
|
+
if (waitForChange) {
|
|
15581
|
+
return listenInputValueChange(input, callback);
|
|
15582
|
+
}
|
|
15583
|
+
const [teardown, addTeardown] = createPubSub();
|
|
15584
|
+
let currentValue = input.value;
|
|
15585
|
+
|
|
15586
|
+
let timeout;
|
|
15587
|
+
const onAsyncEvent = (e) => {
|
|
15588
|
+
timeout = setTimeout(() => {
|
|
15589
|
+
onEvent(e);
|
|
15590
|
+
}, 0);
|
|
15591
|
+
};
|
|
15592
|
+
const onEvent = (e) => {
|
|
15593
|
+
clearTimeout(timeout);
|
|
15594
|
+
const value = input.value;
|
|
15595
|
+
if (value === currentValue) {
|
|
15596
|
+
return;
|
|
15597
|
+
}
|
|
15598
|
+
currentValue = value;
|
|
15599
|
+
callback(e);
|
|
15600
|
+
};
|
|
15601
|
+
|
|
15602
|
+
// Standard user input (typing)
|
|
15603
|
+
input.addEventListener("input", onEvent);
|
|
15604
|
+
addTeardown(() => {
|
|
15605
|
+
input.removeEventListener("input", onEvent);
|
|
15606
|
+
});
|
|
15607
|
+
|
|
15608
|
+
// Autocomplete, programmatic changes, form restoration
|
|
15609
|
+
input.addEventListener("change", onEvent);
|
|
15610
|
+
addTeardown(() => {
|
|
15611
|
+
input.removeEventListener("change", onEvent);
|
|
15612
|
+
});
|
|
15613
|
+
|
|
15614
|
+
// Form reset - need to check the form
|
|
15615
|
+
const form = input.form;
|
|
15616
|
+
if (form) {
|
|
15617
|
+
// Form reset happens asynchronously, check value after reset completes
|
|
15618
|
+
form.addEventListener("reset", onAsyncEvent);
|
|
15619
|
+
addTeardown(() => {
|
|
15620
|
+
form.removeEventListener("reset", onAsyncEvent);
|
|
15621
|
+
});
|
|
15622
|
+
}
|
|
15623
|
+
|
|
15624
|
+
// Paste events (some browsers need special handling)
|
|
15625
|
+
input.addEventListener("paste", onEvent);
|
|
15626
|
+
addTeardown(() => {
|
|
15627
|
+
input.removeEventListener("paste", onEvent);
|
|
15628
|
+
});
|
|
15629
|
+
|
|
15630
|
+
// Focus events to catch programmatic changes that don't fire other events
|
|
15631
|
+
// (like when value is set before user interaction)
|
|
15632
|
+
input.addEventListener("focus", onEvent);
|
|
15633
|
+
addTeardown(() => {
|
|
15634
|
+
input.removeEventListener("focus", onEvent);
|
|
15635
|
+
});
|
|
15636
|
+
|
|
15637
|
+
// "navi_delete_content" behaves like an async event
|
|
15638
|
+
// a bit like form reset because
|
|
15639
|
+
// our action will be updated async after the component re-renders
|
|
15640
|
+
// and we need to wait that to happen to properly call action with the right value
|
|
15641
|
+
input.addEventListener("navi_delete_content", onAsyncEvent);
|
|
15642
|
+
addTeardown(() => {
|
|
15643
|
+
input.removeEventListener("navi_delete_content", onAsyncEvent);
|
|
15644
|
+
});
|
|
15645
|
+
return () => {
|
|
15646
|
+
teardown();
|
|
15647
|
+
};
|
|
15648
|
+
};
|
|
15649
|
+
|
|
15650
|
+
const listenInputValueChange = (input, callback) => {
|
|
15575
15651
|
const [teardown, addTeardown] = createPubSub();
|
|
15576
15652
|
|
|
15577
15653
|
let valueAtInteraction;
|
|
@@ -16331,22 +16407,28 @@ const installCustomConstraintValidation = (
|
|
|
16331
16407
|
});
|
|
16332
16408
|
}
|
|
16333
16409
|
|
|
16334
|
-
|
|
16410
|
+
request_on_input_value_change: {
|
|
16335
16411
|
const isInput =
|
|
16336
16412
|
element.tagName === "INPUT" || element.tagName === "TEXTAREA";
|
|
16337
16413
|
if (!isInput) {
|
|
16338
|
-
break
|
|
16414
|
+
break request_on_input_value_change;
|
|
16339
16415
|
}
|
|
16340
|
-
const
|
|
16341
|
-
|
|
16342
|
-
|
|
16343
|
-
|
|
16344
|
-
|
|
16345
|
-
|
|
16346
|
-
|
|
16347
|
-
|
|
16348
|
-
|
|
16349
|
-
|
|
16416
|
+
const elementWithAction = closestElementWithAction(element);
|
|
16417
|
+
if (!elementWithAction) {
|
|
16418
|
+
break request_on_input_value_change;
|
|
16419
|
+
}
|
|
16420
|
+
const stop = listenInputValue(
|
|
16421
|
+
element,
|
|
16422
|
+
(e) => {
|
|
16423
|
+
dispatchActionRequestedCustomEvent(elementWithAction, {
|
|
16424
|
+
event: e,
|
|
16425
|
+
requester: element,
|
|
16426
|
+
});
|
|
16427
|
+
},
|
|
16428
|
+
{
|
|
16429
|
+
waitForChange: !element.closest("[data-live-action]"),
|
|
16430
|
+
},
|
|
16431
|
+
);
|
|
16350
16432
|
addTeardown(() => {
|
|
16351
16433
|
stop();
|
|
16352
16434
|
});
|
|
@@ -18718,8 +18800,8 @@ const useUIStateController = (
|
|
|
18718
18800
|
) => {
|
|
18719
18801
|
const parentUIStateController = useContext(ParentUIStateControllerContext);
|
|
18720
18802
|
const formContext = useContext(FormContext);
|
|
18721
|
-
const { id, name, onUIStateChange, action } = props;
|
|
18722
|
-
const uncontrolled = !formContext && !action;
|
|
18803
|
+
const { id, name, onUIStateChange, action, liveAction } = props;
|
|
18804
|
+
const uncontrolled = !formContext && !action && !liveAction;
|
|
18723
18805
|
const [navState, setNavState] = useNavState$1(id);
|
|
18724
18806
|
|
|
18725
18807
|
const uiStateControllerRef = useRef();
|
|
@@ -19246,6 +19328,7 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
|
19246
19328
|
--button-padding-left,
|
|
19247
19329
|
var(--button-padding-x, var(--button-padding))
|
|
19248
19330
|
);
|
|
19331
|
+
padding: var(--button-padding, unset);
|
|
19249
19332
|
align-items: inherit;
|
|
19250
19333
|
justify-content: inherit;
|
|
19251
19334
|
color: var(--x-button-color);
|
|
@@ -22593,25 +22676,45 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
|
22593
22676
|
}
|
|
22594
22677
|
}
|
|
22595
22678
|
|
|
22596
|
-
.
|
|
22679
|
+
.navi_input_start_icon {
|
|
22597
22680
|
position: absolute;
|
|
22598
22681
|
top: 0;
|
|
22599
22682
|
bottom: 0;
|
|
22600
22683
|
left: 0.25em;
|
|
22601
22684
|
}
|
|
22602
|
-
.
|
|
22685
|
+
.navi_input_end_button {
|
|
22603
22686
|
position: absolute;
|
|
22604
22687
|
top: 0;
|
|
22605
22688
|
right: 0.25em;
|
|
22606
22689
|
bottom: 0;
|
|
22690
|
+
display: inline-flex;
|
|
22691
|
+
margin: 0;
|
|
22692
|
+
padding: 0;
|
|
22693
|
+
justify-content: center;
|
|
22694
|
+
background: none;
|
|
22695
|
+
border: none;
|
|
22607
22696
|
opacity: 0;
|
|
22608
22697
|
pointer-events: none;
|
|
22609
22698
|
}
|
|
22610
22699
|
&[data-has-value] {
|
|
22611
|
-
.
|
|
22700
|
+
.navi_input_end_button {
|
|
22612
22701
|
opacity: 1;
|
|
22702
|
+
cursor: pointer;
|
|
22613
22703
|
pointer-events: auto;
|
|
22614
22704
|
}
|
|
22705
|
+
|
|
22706
|
+
&[data-readonly] {
|
|
22707
|
+
.navi_input_end_button {
|
|
22708
|
+
opacity: 0;
|
|
22709
|
+
pointer-events: none;
|
|
22710
|
+
}
|
|
22711
|
+
}
|
|
22712
|
+
&[data-disabled] {
|
|
22713
|
+
.navi_input_end_button {
|
|
22714
|
+
opacity: 0;
|
|
22715
|
+
pointer-events: none;
|
|
22716
|
+
}
|
|
22717
|
+
}
|
|
22615
22718
|
}
|
|
22616
22719
|
|
|
22617
22720
|
&[data-start-icon] {
|
|
@@ -22709,38 +22812,7 @@ Object.assign(PSEUDO_CLASSES, {
|
|
|
22709
22812
|
":navi-has-value": {
|
|
22710
22813
|
attribute: "data-has-value",
|
|
22711
22814
|
setup: (el, callback) => {
|
|
22712
|
-
|
|
22713
|
-
callback();
|
|
22714
|
-
};
|
|
22715
|
-
|
|
22716
|
-
// Standard user input (typing)
|
|
22717
|
-
el.addEventListener("input", onValueChange);
|
|
22718
|
-
// Autocomplete, programmatic changes, form restoration
|
|
22719
|
-
el.addEventListener("change", onValueChange);
|
|
22720
|
-
// Form reset - need to check the form
|
|
22721
|
-
const form = el.form;
|
|
22722
|
-
const onFormReset = () => {
|
|
22723
|
-
// Form reset happens asynchronously, check value after reset completes
|
|
22724
|
-
setTimeout(onValueChange, 0);
|
|
22725
|
-
};
|
|
22726
|
-
if (form) {
|
|
22727
|
-
form.addEventListener("reset", onFormReset);
|
|
22728
|
-
}
|
|
22729
|
-
|
|
22730
|
-
// Paste events (some browsers need special handling)
|
|
22731
|
-
el.addEventListener("paste", onValueChange);
|
|
22732
|
-
// Focus events to catch programmatic changes that don't fire other events
|
|
22733
|
-
// (like when value is set before user interaction)
|
|
22734
|
-
el.addEventListener("focus", onValueChange);
|
|
22735
|
-
return () => {
|
|
22736
|
-
el.removeEventListener("input", onValueChange);
|
|
22737
|
-
el.removeEventListener("change", onValueChange);
|
|
22738
|
-
el.removeEventListener("paste", onValueChange);
|
|
22739
|
-
el.removeEventListener("focus", onValueChange);
|
|
22740
|
-
if (form) {
|
|
22741
|
-
form.removeEventListener("reset", onFormReset);
|
|
22742
|
-
}
|
|
22743
|
-
};
|
|
22815
|
+
return listenInputValue(el, callback);
|
|
22744
22816
|
},
|
|
22745
22817
|
test: el => {
|
|
22746
22818
|
if (el.value === "") {
|
|
@@ -22859,28 +22931,39 @@ const InputTextualBasic = props => {
|
|
|
22859
22931
|
loading: innerLoading,
|
|
22860
22932
|
color: "var(--loader-color)",
|
|
22861
22933
|
inset: -1
|
|
22862
|
-
}), innerIcon && jsx(
|
|
22863
|
-
as: "label",
|
|
22934
|
+
}), innerIcon && jsx(Label, {
|
|
22864
22935
|
htmlFor: innerId,
|
|
22865
|
-
|
|
22936
|
+
disabled: innerDisabled,
|
|
22937
|
+
readOnly: innerReadOnly,
|
|
22938
|
+
className: "navi_input_start_icon",
|
|
22939
|
+
box: true,
|
|
22866
22940
|
alignY: "center",
|
|
22867
|
-
|
|
22868
|
-
|
|
22869
|
-
|
|
22870
|
-
|
|
22941
|
+
children: jsx(Icon, {
|
|
22942
|
+
color: "rgba(28, 43, 52, 0.5)",
|
|
22943
|
+
children: innerIcon
|
|
22944
|
+
})
|
|
22945
|
+
}), renderInputMemoized, cancelButton && jsx("label", {
|
|
22871
22946
|
htmlFor: innerId,
|
|
22872
|
-
|
|
22873
|
-
|
|
22874
|
-
|
|
22875
|
-
|
|
22876
|
-
e.preventDefault(); // keep focus
|
|
22947
|
+
"data-readonly": innerReadOnly ? "" : undefined,
|
|
22948
|
+
"data-disabled": innerDisabled ? "" : undefined,
|
|
22949
|
+
className: "navi_input_end_button",
|
|
22950
|
+
onMouseDown: e => {
|
|
22951
|
+
e.preventDefault(); // keep focus in the input
|
|
22877
22952
|
},
|
|
22878
22953
|
onClick: () => {
|
|
22954
|
+
if (innerReadOnly || innerDisabled) {
|
|
22955
|
+
return;
|
|
22956
|
+
}
|
|
22879
22957
|
uiStateController.setUIState("", {
|
|
22880
22958
|
trigger: "cancel_button"
|
|
22881
22959
|
});
|
|
22960
|
+
ref.current.value = "";
|
|
22961
|
+
ref.current.dispatchEvent(new Event("navi_delete_content"));
|
|
22882
22962
|
},
|
|
22883
|
-
children: jsx(
|
|
22963
|
+
children: jsx(Icon, {
|
|
22964
|
+
color: "rgba(28, 43, 52, 0.5)",
|
|
22965
|
+
children: jsx(CloseSvg, {})
|
|
22966
|
+
})
|
|
22884
22967
|
})]
|
|
22885
22968
|
});
|
|
22886
22969
|
};
|
|
@@ -22888,6 +22971,7 @@ const InputTextualWithAction = props => {
|
|
|
22888
22971
|
const uiState = useContext(UIStateContext);
|
|
22889
22972
|
const {
|
|
22890
22973
|
action,
|
|
22974
|
+
liveAction,
|
|
22891
22975
|
loading,
|
|
22892
22976
|
onCancel,
|
|
22893
22977
|
onActionPrevented,
|
|
@@ -22901,7 +22985,7 @@ const InputTextualWithAction = props => {
|
|
|
22901
22985
|
} = props;
|
|
22902
22986
|
const defaultRef = useRef();
|
|
22903
22987
|
const ref = props.ref || defaultRef;
|
|
22904
|
-
const [boundAction] = useActionBoundToOneParam(action, uiState);
|
|
22988
|
+
const [boundAction] = useActionBoundToOneParam(liveAction || action, uiState);
|
|
22905
22989
|
const {
|
|
22906
22990
|
loading: actionLoading
|
|
22907
22991
|
} = useActionStatus(boundAction);
|
|
@@ -22942,6 +23026,7 @@ const InputTextualWithAction = props => {
|
|
|
22942
23026
|
});
|
|
22943
23027
|
return jsx(InputTextualBasic, {
|
|
22944
23028
|
"data-action": boundAction.name,
|
|
23029
|
+
"data-live-action": liveAction ? "" : undefined,
|
|
22945
23030
|
...rest,
|
|
22946
23031
|
ref: ref,
|
|
22947
23032
|
loading: loading || actionLoading
|