@jsenv/navi 0.16.56 → 0.16.58
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 +306 -146
- package/dist/jsenv_navi.js.map +22 -17
- package/package.json +1 -1
package/dist/jsenv_navi.js
CHANGED
|
@@ -5,7 +5,7 @@ import { createIterableWeakSet, mergeOneStyle, stringifyStyle, createPubSub, mer
|
|
|
5
5
|
import { prefixFirstAndIndentRemainingLines } from "@jsenv/humanize";
|
|
6
6
|
import { effect, signal, computed, batch, useSignal } from "@preact/signals";
|
|
7
7
|
import { createValidity } from "@jsenv/validity";
|
|
8
|
-
import { createContext, render, isValidElement,
|
|
8
|
+
import { createContext, toChildArray, render, isValidElement, createRef, cloneElement } from "preact";
|
|
9
9
|
import { createPortal, forwardRef } from "preact/compat";
|
|
10
10
|
|
|
11
11
|
const actionPrivatePropertiesWeakMap = new WeakMap();
|
|
@@ -6306,7 +6306,7 @@ const Box = props => {
|
|
|
6306
6306
|
// then we'll track ":hover" state changes even for basic elements like <div>
|
|
6307
6307
|
const pseudoClassesFromStyleSet = new Set();
|
|
6308
6308
|
boxPseudoNamedStyles = {};
|
|
6309
|
-
const
|
|
6309
|
+
const visitProp = (value, name, styleContext, boxStylesTarget, styleOrigin) => {
|
|
6310
6310
|
const isPseudoElement = name.startsWith("::");
|
|
6311
6311
|
const isPseudoClass = name.startsWith(":");
|
|
6312
6312
|
if (isPseudoElement || isPseudoClass) {
|
|
@@ -6324,14 +6324,14 @@ const Box = props => {
|
|
|
6324
6324
|
if (isPseudoElement) {
|
|
6325
6325
|
const pseudoElementStyles = {};
|
|
6326
6326
|
for (const key of pseudoStyleKeys) {
|
|
6327
|
-
|
|
6327
|
+
visitProp(value[key], key, pseudoStyleContext, pseudoElementStyles, "pseudo_style");
|
|
6328
6328
|
}
|
|
6329
6329
|
boxPseudoNamedStyles[name] = pseudoElementStyles;
|
|
6330
6330
|
return;
|
|
6331
6331
|
}
|
|
6332
6332
|
const pseudoClassStyles = {};
|
|
6333
6333
|
for (const key of pseudoStyleKeys) {
|
|
6334
|
-
|
|
6334
|
+
visitProp(value[key], key, pseudoStyleContext, pseudoClassStyles, "pseudo_style");
|
|
6335
6335
|
boxPseudoNamedStyles[name] = pseudoClassStyles;
|
|
6336
6336
|
}
|
|
6337
6337
|
return;
|
|
@@ -6395,23 +6395,28 @@ const Box = props => {
|
|
|
6395
6395
|
if (baseStyle) {
|
|
6396
6396
|
for (const key of baseStyle) {
|
|
6397
6397
|
const value = baseStyle[key];
|
|
6398
|
-
|
|
6398
|
+
visitProp(value, key, styleContext, boxStyles, "baseStyle");
|
|
6399
6399
|
}
|
|
6400
6400
|
}
|
|
6401
6401
|
for (const propName of remainingPropKeySet) {
|
|
6402
6402
|
const propValue = rest[propName];
|
|
6403
|
-
|
|
6403
|
+
const isDataAttribute = propName.startsWith("data-");
|
|
6404
|
+
if (isDataAttribute) {
|
|
6405
|
+
selfForwardedProps[propName] = propValue;
|
|
6406
|
+
continue;
|
|
6407
|
+
}
|
|
6408
|
+
visitProp(propValue, propName, styleContext, boxStyles, "prop");
|
|
6404
6409
|
}
|
|
6405
6410
|
if (typeof style === "string") {
|
|
6406
6411
|
const styleObject = normalizeStyles(style, "css");
|
|
6407
6412
|
for (const styleName of Object.keys(styleObject)) {
|
|
6408
6413
|
const styleValue = styleObject[styleName];
|
|
6409
|
-
|
|
6414
|
+
visitProp(styleValue, styleName, styleContext, boxStyles, "style");
|
|
6410
6415
|
}
|
|
6411
6416
|
} else if (style && typeof style === "object") {
|
|
6412
6417
|
for (const styleName of Object.keys(style)) {
|
|
6413
6418
|
const styleValue = style[styleName];
|
|
6414
|
-
|
|
6419
|
+
visitProp(styleValue, styleName, styleContext, boxStyles, "style");
|
|
6415
6420
|
}
|
|
6416
6421
|
}
|
|
6417
6422
|
const updateStyle = useCallback(state => {
|
|
@@ -6468,25 +6473,26 @@ const Box = props => {
|
|
|
6468
6473
|
innerChildren = children;
|
|
6469
6474
|
}
|
|
6470
6475
|
if (separator) {
|
|
6471
|
-
|
|
6472
|
-
|
|
6473
|
-
|
|
6474
|
-
|
|
6475
|
-
|
|
6476
|
-
|
|
6477
|
-
|
|
6478
|
-
|
|
6479
|
-
|
|
6480
|
-
|
|
6481
|
-
|
|
6482
|
-
}
|
|
6483
|
-
// Support function separators that receive separator index
|
|
6484
|
-
const separatorElement = typeof separator === "function" ? separator(i - 1) // i-1 because i was incremented after pushing child
|
|
6485
|
-
: separator;
|
|
6486
|
-
childrenWithSeparators.push(separatorElement);
|
|
6476
|
+
// Flatten nested arrays (e.g., from .map()) to treat each element as individual child
|
|
6477
|
+
const flattenedChildren = toChildArray(innerChildren);
|
|
6478
|
+
if (flattenedChildren.length > 1) {
|
|
6479
|
+
const childrenWithSeparators = [];
|
|
6480
|
+
let i = 0;
|
|
6481
|
+
while (true) {
|
|
6482
|
+
const child = flattenedChildren[i];
|
|
6483
|
+
childrenWithSeparators.push(child);
|
|
6484
|
+
i++;
|
|
6485
|
+
if (i === flattenedChildren.length) {
|
|
6486
|
+
break;
|
|
6487
6487
|
}
|
|
6488
|
-
|
|
6488
|
+
// Support function separators that receive separator index
|
|
6489
|
+
const separatorElement = typeof separator === "function" ? separator(i - 1) // i-1 because i was incremented after pushing child
|
|
6490
|
+
: separator;
|
|
6491
|
+
childrenWithSeparators.push(separatorElement);
|
|
6489
6492
|
}
|
|
6493
|
+
innerChildren = childrenWithSeparators;
|
|
6494
|
+
} else {
|
|
6495
|
+
innerChildren = flattenedChildren;
|
|
6490
6496
|
}
|
|
6491
6497
|
}
|
|
6492
6498
|
return jsx(TagName, {
|
|
@@ -16760,24 +16766,58 @@ const installCustomConstraintValidation = (
|
|
|
16760
16766
|
if (keydownEvent.key !== "Enter") {
|
|
16761
16767
|
return;
|
|
16762
16768
|
}
|
|
16763
|
-
|
|
16764
|
-
|
|
16765
|
-
keydownEvent.preventDefault();
|
|
16766
|
-
}
|
|
16767
|
-
dispatchActionRequestedCustomEvent(element, {
|
|
16768
|
-
event: keydownEvent,
|
|
16769
|
-
requester: element,
|
|
16770
|
-
});
|
|
16769
|
+
const elementWithAction = closestElementWithAction(element);
|
|
16770
|
+
if (!elementWithAction) {
|
|
16771
16771
|
return;
|
|
16772
16772
|
}
|
|
16773
|
-
|
|
16774
|
-
|
|
16775
|
-
|
|
16773
|
+
|
|
16774
|
+
const determineClosestFormSubmitTargetForEnterKeyEvent = () => {
|
|
16775
|
+
if (keydownEvent.defaultPrevented) {
|
|
16776
|
+
return null;
|
|
16777
|
+
}
|
|
16778
|
+
const keydownTarget = keydownEvent.target;
|
|
16779
|
+
const { form } = keydownTarget;
|
|
16780
|
+
if (!form) {
|
|
16781
|
+
return null;
|
|
16782
|
+
}
|
|
16783
|
+
if (keydownTarget.tagName === "BUTTON") {
|
|
16784
|
+
if (
|
|
16785
|
+
keydownTarget.type !== "submit" &&
|
|
16786
|
+
keydownTarget.type !== "image"
|
|
16787
|
+
) {
|
|
16788
|
+
return null;
|
|
16789
|
+
}
|
|
16790
|
+
return keydownTarget;
|
|
16791
|
+
}
|
|
16792
|
+
if (keydownTarget.tagName === "INPUT") {
|
|
16793
|
+
if (
|
|
16794
|
+
![
|
|
16795
|
+
"text",
|
|
16796
|
+
"email",
|
|
16797
|
+
"password",
|
|
16798
|
+
"search",
|
|
16799
|
+
"number",
|
|
16800
|
+
"url",
|
|
16801
|
+
"tel",
|
|
16802
|
+
].includes(keydownTarget.type)
|
|
16803
|
+
) {
|
|
16804
|
+
return null;
|
|
16805
|
+
}
|
|
16806
|
+
// when present, we use first button submitting the form as the requester
|
|
16807
|
+
// not the input, it aligns with browser behavior where
|
|
16808
|
+
// hitting Enter in a text input triggers the first submit button of the form, not the input itself
|
|
16809
|
+
return getFirstButtonSubmittingForm(keydownTarget) || keydownTarget;
|
|
16810
|
+
}
|
|
16811
|
+
return null;
|
|
16812
|
+
};
|
|
16813
|
+
const formSubmitTarget =
|
|
16814
|
+
determineClosestFormSubmitTargetForEnterKeyEvent();
|
|
16815
|
+
if (formSubmitTarget) {
|
|
16816
|
+
keydownEvent.preventDefault();
|
|
16776
16817
|
}
|
|
16777
|
-
|
|
16778
|
-
dispatchActionRequestedCustomEvent(form, {
|
|
16818
|
+
dispatchActionRequestedCustomEvent(elementWithAction, {
|
|
16779
16819
|
event: keydownEvent,
|
|
16780
|
-
requester:
|
|
16820
|
+
requester: formSubmitTarget || element,
|
|
16781
16821
|
});
|
|
16782
16822
|
};
|
|
16783
16823
|
element.addEventListener("keydown", onkeydown);
|
|
@@ -16794,29 +16834,44 @@ const installCustomConstraintValidation = (
|
|
|
16794
16834
|
if (element.tagName !== "BUTTON") {
|
|
16795
16835
|
return;
|
|
16796
16836
|
}
|
|
16797
|
-
|
|
16798
|
-
|
|
16799
|
-
|
|
16800
|
-
}
|
|
16801
|
-
dispatchActionRequestedCustomEvent(element, {
|
|
16802
|
-
event: clickEvent,
|
|
16803
|
-
requester: element,
|
|
16804
|
-
});
|
|
16805
|
-
return;
|
|
16806
|
-
}
|
|
16807
|
-
const { form } = element;
|
|
16808
|
-
if (!form) {
|
|
16809
|
-
return;
|
|
16810
|
-
}
|
|
16811
|
-
if (element.type === "reset") {
|
|
16837
|
+
const button = element;
|
|
16838
|
+
const elementWithAction = closestElementWithAction(button);
|
|
16839
|
+
if (!elementWithAction) {
|
|
16812
16840
|
return;
|
|
16813
16841
|
}
|
|
16814
|
-
|
|
16842
|
+
const determineClosestFormSubmitTargetForClickEvent = () => {
|
|
16843
|
+
if (clickEvent.defaultPrevented) {
|
|
16844
|
+
return null;
|
|
16845
|
+
}
|
|
16846
|
+
const clickTarget = clickEvent.target;
|
|
16847
|
+
const { form } = clickTarget;
|
|
16848
|
+
if (!form) {
|
|
16849
|
+
return null;
|
|
16850
|
+
}
|
|
16851
|
+
const wouldSubmitFormByType =
|
|
16852
|
+
button.type === "submit" || button.type === "image";
|
|
16853
|
+
if (wouldSubmitFormByType) {
|
|
16854
|
+
return button;
|
|
16855
|
+
}
|
|
16856
|
+
if (button.type) {
|
|
16857
|
+
// "reset", "button" or any other non submit type, it won't submit the form
|
|
16858
|
+
return null;
|
|
16859
|
+
}
|
|
16860
|
+
const firstButtonSubmittingForm = getFirstButtonSubmittingForm(form);
|
|
16861
|
+
if (button !== firstButtonSubmittingForm) {
|
|
16862
|
+
// an other button is explicitly submitting the form, this one would not submit it
|
|
16863
|
+
return null;
|
|
16864
|
+
}
|
|
16865
|
+
// this is the only button inside the form without type attribute, so it defaults to type="submit"
|
|
16866
|
+
return button;
|
|
16867
|
+
};
|
|
16868
|
+
const formSubmitTarget = determineClosestFormSubmitTargetForClickEvent();
|
|
16869
|
+
if (formSubmitTarget) {
|
|
16815
16870
|
clickEvent.preventDefault();
|
|
16816
16871
|
}
|
|
16817
|
-
dispatchActionRequestedCustomEvent(
|
|
16872
|
+
dispatchActionRequestedCustomEvent(elementWithAction, {
|
|
16818
16873
|
event: clickEvent,
|
|
16819
|
-
requester:
|
|
16874
|
+
requester: formSubmitTarget || button,
|
|
16820
16875
|
});
|
|
16821
16876
|
};
|
|
16822
16877
|
element.addEventListener("click", onclick);
|
|
@@ -16832,13 +16887,14 @@ const installCustomConstraintValidation = (
|
|
|
16832
16887
|
break request_on_input_change;
|
|
16833
16888
|
}
|
|
16834
16889
|
const stop = listenInputChange(element, (e) => {
|
|
16835
|
-
|
|
16836
|
-
|
|
16837
|
-
event: e,
|
|
16838
|
-
requester: element,
|
|
16839
|
-
});
|
|
16890
|
+
const elementWithAction = closestElementWithAction(element);
|
|
16891
|
+
if (!elementWithAction) {
|
|
16840
16892
|
return;
|
|
16841
16893
|
}
|
|
16894
|
+
dispatchActionRequestedCustomEvent(elementWithAction, {
|
|
16895
|
+
event: e,
|
|
16896
|
+
requester: element,
|
|
16897
|
+
});
|
|
16842
16898
|
});
|
|
16843
16899
|
addTeardown(() => {
|
|
16844
16900
|
stop();
|
|
@@ -16936,6 +16992,31 @@ const installCustomConstraintValidation = (
|
|
|
16936
16992
|
return validationInterface;
|
|
16937
16993
|
};
|
|
16938
16994
|
|
|
16995
|
+
// When interacting with an element we want to find the closest element
|
|
16996
|
+
// eventually handling the action
|
|
16997
|
+
// 1. <button> itself has an action
|
|
16998
|
+
// 2. <button> is inside a <form> with an action
|
|
16999
|
+
// 3. <button> is inside a wrapper <div> with an action (data-action is not necessarly on the interactive element itself, it can be on a wrapper, we want to support that)
|
|
17000
|
+
// 4. <button> is inside a <fieldset> or any element that catches the action like a <form> would
|
|
17001
|
+
// In examples above <button> can also be <input> etc..
|
|
17002
|
+
const closestElementWithAction = (el) => {
|
|
17003
|
+
if (el.hasAttribute("data-action")) {
|
|
17004
|
+
return el;
|
|
17005
|
+
}
|
|
17006
|
+
const closestDataActionElement = el.closest("[data-action]");
|
|
17007
|
+
if (!closestDataActionElement) {
|
|
17008
|
+
return null;
|
|
17009
|
+
}
|
|
17010
|
+
const visualSelector = closestDataActionElement.getAttribute(
|
|
17011
|
+
"data-visual-selector",
|
|
17012
|
+
);
|
|
17013
|
+
if (!visualSelector) {
|
|
17014
|
+
return closestDataActionElement;
|
|
17015
|
+
}
|
|
17016
|
+
const visualElement = closestDataActionElement.querySelector(visualSelector);
|
|
17017
|
+
return visualElement;
|
|
17018
|
+
};
|
|
17019
|
+
|
|
16939
17020
|
const pickConstraint = (a, b) => {
|
|
16940
17021
|
const aPrio = getConstraintPriority(a);
|
|
16941
17022
|
const bPrio = getConstraintPriority(b);
|
|
@@ -16954,60 +17035,14 @@ const getConstraintPriority = (constraint) => {
|
|
|
16954
17035
|
return 1;
|
|
16955
17036
|
};
|
|
16956
17037
|
|
|
16957
|
-
const wouldButtonClickSubmitForm = (button, clickEvent) => {
|
|
16958
|
-
if (clickEvent.defaultPrevented) {
|
|
16959
|
-
return false;
|
|
16960
|
-
}
|
|
16961
|
-
const { form } = button;
|
|
16962
|
-
if (!form) {
|
|
16963
|
-
return false;
|
|
16964
|
-
}
|
|
16965
|
-
if (!button) {
|
|
16966
|
-
return false;
|
|
16967
|
-
}
|
|
16968
|
-
const wouldSubmitFormByType =
|
|
16969
|
-
button.type === "submit" || button.type === "image";
|
|
16970
|
-
if (wouldSubmitFormByType) {
|
|
16971
|
-
return true;
|
|
16972
|
-
}
|
|
16973
|
-
if (button.type) {
|
|
16974
|
-
return false;
|
|
16975
|
-
}
|
|
16976
|
-
if (getFirstButtonSubmittingForm(form)) {
|
|
16977
|
-
// an other button is explicitly submitting the form, this one would not submit it
|
|
16978
|
-
return false;
|
|
16979
|
-
}
|
|
16980
|
-
// this is the only button inside the form without type attribute, so it defaults to type="submit"
|
|
16981
|
-
return true;
|
|
16982
|
-
};
|
|
16983
17038
|
const getFirstButtonSubmittingForm = (form) => {
|
|
16984
17039
|
return form.querySelector(
|
|
16985
17040
|
`button[type="submit"], input[type="submit"], input[type="image"]`,
|
|
16986
17041
|
);
|
|
16987
17042
|
};
|
|
16988
17043
|
|
|
16989
|
-
const wouldKeydownSubmitForm = (keydownEvent) => {
|
|
16990
|
-
if (keydownEvent.defaultPrevented) {
|
|
16991
|
-
return false;
|
|
16992
|
-
}
|
|
16993
|
-
const keydownTarget = keydownEvent.target;
|
|
16994
|
-
const { form } = keydownTarget;
|
|
16995
|
-
if (!form) {
|
|
16996
|
-
return false;
|
|
16997
|
-
}
|
|
16998
|
-
if (keydownEvent.key !== "Enter") {
|
|
16999
|
-
return false;
|
|
17000
|
-
}
|
|
17001
|
-
const isTextInput =
|
|
17002
|
-
keydownTarget.tagName === "INPUT" || keydownTarget.tagName === "TEXTAREA";
|
|
17003
|
-
if (!isTextInput) {
|
|
17004
|
-
return false;
|
|
17005
|
-
}
|
|
17006
|
-
return true;
|
|
17007
|
-
};
|
|
17008
|
-
|
|
17009
17044
|
const dispatchActionRequestedCustomEvent = (
|
|
17010
|
-
|
|
17045
|
+
elementWithAction,
|
|
17011
17046
|
{ actionOrigin = "action_prop", event, requester },
|
|
17012
17047
|
) => {
|
|
17013
17048
|
const actionRequestedCustomEvent = new CustomEvent("actionrequested", {
|
|
@@ -17018,7 +17053,7 @@ const dispatchActionRequestedCustomEvent = (
|
|
|
17018
17053
|
requester,
|
|
17019
17054
|
},
|
|
17020
17055
|
});
|
|
17021
|
-
|
|
17056
|
+
elementWithAction.dispatchEvent(actionRequestedCustomEvent);
|
|
17022
17057
|
};
|
|
17023
17058
|
// https://developer.mozilla.org/en-US/docs/Web/HTML/Guides/Constraint_validation
|
|
17024
17059
|
const requestSubmit = HTMLFormElement.prototype.requestSubmit;
|
|
@@ -17759,7 +17794,6 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
|
17759
17794
|
const Icon = ({
|
|
17760
17795
|
href,
|
|
17761
17796
|
children,
|
|
17762
|
-
className,
|
|
17763
17797
|
charWidth = 1,
|
|
17764
17798
|
// 0 (zéro) is the real char width
|
|
17765
17799
|
// but 2 zéros gives too big icons
|
|
@@ -17786,7 +17820,7 @@ const Icon = ({
|
|
|
17786
17820
|
const hasExplicitWidth = width !== undefined;
|
|
17787
17821
|
const hasExplicitHeight = height !== undefined;
|
|
17788
17822
|
if (!hasExplicitWidth && !hasExplicitHeight) {
|
|
17789
|
-
if (decorative === undefined) {
|
|
17823
|
+
if (decorative === undefined && !onClick) {
|
|
17790
17824
|
decorative = true;
|
|
17791
17825
|
}
|
|
17792
17826
|
} else {
|
|
@@ -17821,7 +17855,7 @@ const Icon = ({
|
|
|
17821
17855
|
return jsxs(Text, {
|
|
17822
17856
|
...props,
|
|
17823
17857
|
...ariaProps,
|
|
17824
|
-
className: withPropsClassName("navi_icon", className),
|
|
17858
|
+
className: withPropsClassName("navi_icon", props.className),
|
|
17825
17859
|
spacing: "pre",
|
|
17826
17860
|
"data-icon-char": "",
|
|
17827
17861
|
"data-has-width": hasExplicitWidth ? "" : undefined,
|
|
@@ -22450,6 +22484,15 @@ const InputRangeWithAction = props => {
|
|
|
22450
22484
|
});
|
|
22451
22485
|
};
|
|
22452
22486
|
|
|
22487
|
+
const SearchSvg = () => jsx("svg", {
|
|
22488
|
+
viewBox: "0 0 24 24",
|
|
22489
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
22490
|
+
children: jsx("path", {
|
|
22491
|
+
d: "M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z",
|
|
22492
|
+
fill: "currentColor"
|
|
22493
|
+
})
|
|
22494
|
+
});
|
|
22495
|
+
|
|
22453
22496
|
installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
22454
22497
|
@layer navi {
|
|
22455
22498
|
.navi_input {
|
|
@@ -22513,29 +22556,73 @@ installImportMetaCss(import.meta);import.meta.css = /* css */`
|
|
|
22513
22556
|
--x-background-color: var(--background-color);
|
|
22514
22557
|
--x-color: var(--color);
|
|
22515
22558
|
--x-placeholder-color: var(--placeholder-color);
|
|
22516
|
-
}
|
|
22517
22559
|
|
|
22518
|
-
|
|
22519
|
-
|
|
22520
|
-
|
|
22521
|
-
|
|
22522
|
-
|
|
22523
|
-
|
|
22524
|
-
|
|
22525
|
-
|
|
22526
|
-
|
|
22527
|
-
|
|
22528
|
-
|
|
22529
|
-
|
|
22530
|
-
|
|
22531
|
-
|
|
22532
|
-
|
|
22533
|
-
|
|
22534
|
-
|
|
22535
|
-
|
|
22536
|
-
|
|
22537
|
-
|
|
22560
|
+
.navi_native_input {
|
|
22561
|
+
box-sizing: border-box;
|
|
22562
|
+
padding-top: var(--padding-top, var(--padding-y, var(--padding, 1px)));
|
|
22563
|
+
padding-right: var(
|
|
22564
|
+
--padding-right,
|
|
22565
|
+
var(--padding-x, var(--padding, 2px))
|
|
22566
|
+
);
|
|
22567
|
+
padding-bottom: var(
|
|
22568
|
+
--padding-bottom,
|
|
22569
|
+
var(--padding-y, var(--padding, 1px))
|
|
22570
|
+
);
|
|
22571
|
+
padding-left: var(--padding-left, var(--padding-x, var(--padding, 2px)));
|
|
22572
|
+
color: var(--x-color);
|
|
22573
|
+
background-color: var(--x-background-color);
|
|
22574
|
+
border-width: var(--x-outer-width);
|
|
22575
|
+
border-width: var(--x-outer-width);
|
|
22576
|
+
border-style: solid;
|
|
22577
|
+
border-color: transparent;
|
|
22578
|
+
border-radius: var(--x-border-radius);
|
|
22579
|
+
outline-width: var(--x-border-width);
|
|
22580
|
+
outline-style: solid;
|
|
22581
|
+
outline-color: var(--x-border-color);
|
|
22582
|
+
outline-offset: calc(-1 * (var(--x-border-width)));
|
|
22583
|
+
|
|
22584
|
+
&[type="search"] {
|
|
22585
|
+
-webkit-appearance: textfield;
|
|
22586
|
+
|
|
22587
|
+
&::-webkit-search-cancel-button {
|
|
22588
|
+
display: none;
|
|
22589
|
+
}
|
|
22590
|
+
}
|
|
22591
|
+
}
|
|
22592
|
+
|
|
22593
|
+
.navi_start_icon_label {
|
|
22594
|
+
position: absolute;
|
|
22595
|
+
top: 0;
|
|
22596
|
+
bottom: 0;
|
|
22597
|
+
left: 0.25em;
|
|
22598
|
+
}
|
|
22599
|
+
.navi_end_icon_label {
|
|
22600
|
+
position: absolute;
|
|
22601
|
+
top: 0;
|
|
22602
|
+
right: 0.25em;
|
|
22603
|
+
bottom: 0;
|
|
22604
|
+
opacity: 0;
|
|
22605
|
+
pointer-events: none;
|
|
22606
|
+
}
|
|
22607
|
+
&[data-has-value] {
|
|
22608
|
+
.navi_end_icon_label {
|
|
22609
|
+
opacity: 1;
|
|
22610
|
+
pointer-events: auto;
|
|
22611
|
+
}
|
|
22612
|
+
}
|
|
22613
|
+
|
|
22614
|
+
&[data-start-icon] {
|
|
22615
|
+
.navi_native_input {
|
|
22616
|
+
padding-left: 20px;
|
|
22617
|
+
}
|
|
22618
|
+
}
|
|
22619
|
+
&[data-end-icon] {
|
|
22620
|
+
.navi_native_input {
|
|
22621
|
+
padding-right: 20px;
|
|
22622
|
+
}
|
|
22623
|
+
}
|
|
22538
22624
|
}
|
|
22625
|
+
|
|
22539
22626
|
.navi_input .navi_native_input::placeholder {
|
|
22540
22627
|
color: var(--x-placeholder-color);
|
|
22541
22628
|
}
|
|
@@ -22614,7 +22701,52 @@ const InputStyleCSSVars = {
|
|
|
22614
22701
|
color: "--color-disabled"
|
|
22615
22702
|
}
|
|
22616
22703
|
};
|
|
22617
|
-
const InputPseudoClasses = [":hover", ":active", ":focus", ":focus-visible", ":read-only", ":disabled", ":-navi-loading"];
|
|
22704
|
+
const InputPseudoClasses = [":hover", ":active", ":focus", ":focus-visible", ":read-only", ":disabled", ":-navi-loading", ":navi-has-value"];
|
|
22705
|
+
Object.assign(PSEUDO_CLASSES, {
|
|
22706
|
+
":navi-has-value": {
|
|
22707
|
+
attribute: "data-has-value",
|
|
22708
|
+
setup: (el, callback) => {
|
|
22709
|
+
const onValueChange = () => {
|
|
22710
|
+
callback();
|
|
22711
|
+
};
|
|
22712
|
+
|
|
22713
|
+
// Standard user input (typing)
|
|
22714
|
+
el.addEventListener("input", onValueChange);
|
|
22715
|
+
// Autocomplete, programmatic changes, form restoration
|
|
22716
|
+
el.addEventListener("change", onValueChange);
|
|
22717
|
+
// Form reset - need to check the form
|
|
22718
|
+
const form = el.form;
|
|
22719
|
+
const onFormReset = () => {
|
|
22720
|
+
// Form reset happens asynchronously, check value after reset completes
|
|
22721
|
+
setTimeout(onValueChange, 0);
|
|
22722
|
+
};
|
|
22723
|
+
if (form) {
|
|
22724
|
+
form.addEventListener("reset", onFormReset);
|
|
22725
|
+
}
|
|
22726
|
+
|
|
22727
|
+
// Paste events (some browsers need special handling)
|
|
22728
|
+
el.addEventListener("paste", onValueChange);
|
|
22729
|
+
// Focus events to catch programmatic changes that don't fire other events
|
|
22730
|
+
// (like when value is set before user interaction)
|
|
22731
|
+
el.addEventListener("focus", onValueChange);
|
|
22732
|
+
return () => {
|
|
22733
|
+
el.removeEventListener("input", onValueChange);
|
|
22734
|
+
el.removeEventListener("change", onValueChange);
|
|
22735
|
+
el.removeEventListener("paste", onValueChange);
|
|
22736
|
+
el.removeEventListener("focus", onValueChange);
|
|
22737
|
+
if (form) {
|
|
22738
|
+
form.removeEventListener("reset", onFormReset);
|
|
22739
|
+
}
|
|
22740
|
+
};
|
|
22741
|
+
},
|
|
22742
|
+
test: el => {
|
|
22743
|
+
if (el.value === "") {
|
|
22744
|
+
return false;
|
|
22745
|
+
}
|
|
22746
|
+
return true;
|
|
22747
|
+
}
|
|
22748
|
+
}
|
|
22749
|
+
});
|
|
22618
22750
|
const InputPseudoElements = ["::-navi-loader"];
|
|
22619
22751
|
const InputTextualBasic = props => {
|
|
22620
22752
|
const contextReadOnly = useContext(ReadOnlyContext);
|
|
@@ -22633,6 +22765,8 @@ const InputTextualBasic = props => {
|
|
|
22633
22765
|
autoFocus,
|
|
22634
22766
|
autoFocusVisible,
|
|
22635
22767
|
autoSelect,
|
|
22768
|
+
icon,
|
|
22769
|
+
cancelButton = type === "search",
|
|
22636
22770
|
...rest
|
|
22637
22771
|
} = props;
|
|
22638
22772
|
const defaultRef = useRef();
|
|
@@ -22649,10 +22783,13 @@ const InputTextualBasic = props => {
|
|
|
22649
22783
|
});
|
|
22650
22784
|
const remainingProps = useConstraints(ref, rest);
|
|
22651
22785
|
const innerOnInput = useStableCallback(onInput);
|
|
22786
|
+
const autoId = useId();
|
|
22787
|
+
const innerId = rest.id || autoId;
|
|
22652
22788
|
const renderInput = inputProps => {
|
|
22653
22789
|
return jsx(Box, {
|
|
22654
22790
|
...inputProps,
|
|
22655
22791
|
as: "input",
|
|
22792
|
+
id: innerId,
|
|
22656
22793
|
ref: ref,
|
|
22657
22794
|
type: type,
|
|
22658
22795
|
"data-value": uiState,
|
|
@@ -22683,7 +22820,15 @@ const InputTextualBasic = props => {
|
|
|
22683
22820
|
baseClassName: "navi_native_input"
|
|
22684
22821
|
});
|
|
22685
22822
|
};
|
|
22686
|
-
const renderInputMemoized = useCallback(renderInput, [type, uiState, innerValue, innerOnInput]);
|
|
22823
|
+
const renderInputMemoized = useCallback(renderInput, [type, uiState, innerValue, innerOnInput, innerId]);
|
|
22824
|
+
let innerIcon;
|
|
22825
|
+
if (icon === undefined) {
|
|
22826
|
+
if (type === "search") {
|
|
22827
|
+
innerIcon = jsx(SearchSvg, {});
|
|
22828
|
+
}
|
|
22829
|
+
} else {
|
|
22830
|
+
innerIcon = icon;
|
|
22831
|
+
}
|
|
22687
22832
|
return jsxs(Box, {
|
|
22688
22833
|
as: "span",
|
|
22689
22834
|
box: true,
|
|
@@ -22699,13 +22844,37 @@ const InputTextualBasic = props => {
|
|
|
22699
22844
|
pseudoClasses: InputPseudoClasses,
|
|
22700
22845
|
pseudoElements: InputPseudoElements,
|
|
22701
22846
|
hasChildFunction: true,
|
|
22847
|
+
"data-start-icon": innerIcon ? "" : undefined,
|
|
22848
|
+
"data-end-icon": cancelButton ? "" : undefined,
|
|
22702
22849
|
...remainingProps,
|
|
22703
22850
|
ref: undefined,
|
|
22704
22851
|
children: [jsx(LoaderBackground, {
|
|
22705
22852
|
loading: innerLoading,
|
|
22706
22853
|
color: "var(--loader-color)",
|
|
22707
22854
|
inset: -1
|
|
22708
|
-
}),
|
|
22855
|
+
}), innerIcon && jsx(Icon, {
|
|
22856
|
+
as: "label",
|
|
22857
|
+
htmlFor: innerId,
|
|
22858
|
+
className: "navi_start_icon_label",
|
|
22859
|
+
alignY: "center",
|
|
22860
|
+
color: "rgba(28, 43, 52, 0.5)",
|
|
22861
|
+
children: innerIcon
|
|
22862
|
+
}), renderInputMemoized, cancelButton && jsx(Icon, {
|
|
22863
|
+
as: "label",
|
|
22864
|
+
htmlFor: innerId,
|
|
22865
|
+
className: "navi_end_icon_label",
|
|
22866
|
+
alignY: "center",
|
|
22867
|
+
color: "rgba(28, 43, 52, 0.5)",
|
|
22868
|
+
onMousedown: e => {
|
|
22869
|
+
e.preventDefault(); // keep focus on the button
|
|
22870
|
+
},
|
|
22871
|
+
onClick: () => {
|
|
22872
|
+
uiStateController.setUIState("", {
|
|
22873
|
+
trigger: "cancel_button"
|
|
22874
|
+
});
|
|
22875
|
+
},
|
|
22876
|
+
children: jsx(CloseSvg, {})
|
|
22877
|
+
})]
|
|
22709
22878
|
});
|
|
22710
22879
|
};
|
|
22711
22880
|
const InputTextualWithAction = props => {
|
|
@@ -28495,15 +28664,6 @@ const HomeSvg = () => jsx("svg", {
|
|
|
28495
28664
|
})
|
|
28496
28665
|
});
|
|
28497
28666
|
|
|
28498
|
-
const SearchSvg = () => jsx("svg", {
|
|
28499
|
-
viewBox: "0 0 24 24",
|
|
28500
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
28501
|
-
children: jsx("path", {
|
|
28502
|
-
d: "M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z",
|
|
28503
|
-
fill: "currentColor"
|
|
28504
|
-
})
|
|
28505
|
-
});
|
|
28506
|
-
|
|
28507
28667
|
const SettingsSvg = () => jsx("svg", {
|
|
28508
28668
|
viewBox: "0 0 24 24",
|
|
28509
28669
|
xmlns: "http://www.w3.org/2000/svg",
|