@jsenv/navi 0.27.30 → 0.27.31
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 +871 -501
- package/dist/jsenv_navi.js.map +115 -83
- package/dist/jsenv_navi_side_effects.js +1 -1
- package/dist/jsenv_navi_side_effects.js.map +1 -1
- package/package.json +2 -2
package/dist/jsenv_navi.js
CHANGED
|
@@ -6676,6 +6676,24 @@ const TYPO_PROPS = {
|
|
|
6676
6676
|
uppercase: applyToCssPropWhenTruthy("textTransform", "uppercase", "none"),
|
|
6677
6677
|
lowercase: applyToCssPropWhenTruthy("textTransform", "lowercase", "none"),
|
|
6678
6678
|
letterSpacing: PASS_THROUGH,
|
|
6679
|
+
maxLines: (value) => {
|
|
6680
|
+
if (!value) {
|
|
6681
|
+
return null;
|
|
6682
|
+
}
|
|
6683
|
+
if (value === 1 || value === "1") {
|
|
6684
|
+
return {
|
|
6685
|
+
overflow: "hidden",
|
|
6686
|
+
textOverflow: "ellipsis",
|
|
6687
|
+
overflowWrap: "normal",
|
|
6688
|
+
};
|
|
6689
|
+
}
|
|
6690
|
+
return {
|
|
6691
|
+
"overflow": "hidden",
|
|
6692
|
+
"display": "-webkit-box",
|
|
6693
|
+
"-webkit-box-orient": "vertical",
|
|
6694
|
+
"-webkit-line-clamp": value,
|
|
6695
|
+
};
|
|
6696
|
+
},
|
|
6679
6697
|
overflowEllipsis: (value) => {
|
|
6680
6698
|
if (!value) {
|
|
6681
6699
|
return null;
|
|
@@ -7606,9 +7624,19 @@ const definePseudoClass = (pseudoClass, definition) => {
|
|
|
7606
7624
|
PSEUDO_CLASSES[pseudoClass] = definition;
|
|
7607
7625
|
};
|
|
7608
7626
|
|
|
7627
|
+
// On touch devices (hover: none), browsers synthesize mouseenter/mouseleave
|
|
7628
|
+
// from touch events but never fire mouseleave when the finger lifts, leaving
|
|
7629
|
+
// el.matches(":hover") stuck at true. This causes hover styles (e.g. input
|
|
7630
|
+
// background highlight) to remain visible long after the user has stopped
|
|
7631
|
+
// touching the element. Checking (hover: hover) lets us skip hover tracking
|
|
7632
|
+
// entirely on touch-only devices where persistent hover makes no sense.
|
|
7633
|
+
const hoverSupported = window.matchMedia("(hover: hover)").matches;
|
|
7609
7634
|
definePseudoClass(":hover", {
|
|
7610
7635
|
attribute: "data-hover",
|
|
7611
7636
|
setup: (el, callback) => {
|
|
7637
|
+
if (!hoverSupported) {
|
|
7638
|
+
return () => {};
|
|
7639
|
+
}
|
|
7612
7640
|
const recheckProxy = (e) => {
|
|
7613
7641
|
const proxy = findControlProxy(el);
|
|
7614
7642
|
if (proxy) {
|
|
@@ -7672,6 +7700,9 @@ definePseudoClass(":hover", {
|
|
|
7672
7700
|
};
|
|
7673
7701
|
},
|
|
7674
7702
|
test: (el) => {
|
|
7703
|
+
if (!hoverSupported) {
|
|
7704
|
+
return false;
|
|
7705
|
+
}
|
|
7675
7706
|
if (el.matches(":hover")) {
|
|
7676
7707
|
return true;
|
|
7677
7708
|
}
|
|
@@ -12934,15 +12965,13 @@ const extractSearchParams = (urlObj, queryConnectionMap) => {
|
|
|
12934
12965
|
decodedValue === "true" || decodedValue === "1" || decodedValue === "";
|
|
12935
12966
|
} else if (signalType === "date") {
|
|
12936
12967
|
const decodedValue = decodeURIComponent(rawValue);
|
|
12937
|
-
//
|
|
12938
|
-
|
|
12939
|
-
const [year, month, day] = datePart.split("-").map(Number);
|
|
12940
|
-
const d = new Date(Date.UTC(year, month - 1, day));
|
|
12941
|
-
params[key] = isNaN(d.getTime()) ? decodedValue : d;
|
|
12968
|
+
// Keep as "YYYY-MM-DD" string — canonical date form, no timezone conversion
|
|
12969
|
+
params[key] = decodedValue.slice(0, 10);
|
|
12942
12970
|
} else if (signalType === "datetime") {
|
|
12943
12971
|
const decodedValue = decodeURIComponent(rawValue);
|
|
12972
|
+
// Normalize to ISO string — canonical datetime form
|
|
12944
12973
|
const d = new Date(decodedValue);
|
|
12945
|
-
params[key] = isNaN(d.getTime()) ? decodedValue : d;
|
|
12974
|
+
params[key] = isNaN(d.getTime()) ? decodedValue : d.toISOString();
|
|
12946
12975
|
} else {
|
|
12947
12976
|
params[key] = decodeURIComponent(rawValue);
|
|
12948
12977
|
}
|
|
@@ -16709,6 +16738,7 @@ const css$O = /* css */`
|
|
|
16709
16738
|
margin: 0;
|
|
16710
16739
|
padding: 0;
|
|
16711
16740
|
color: revert; /* Do no inherit element color, callout is inside the element it should use document color though */
|
|
16741
|
+
font-size: initial; /* Callout fells disconnected from the element, font size should be predictible and stable */
|
|
16712
16742
|
background: transparent;
|
|
16713
16743
|
border: none;
|
|
16714
16744
|
opacity: 0;
|
|
@@ -19212,12 +19242,20 @@ CONSTRAINT_ATTRIBUTE_SET.add("data-single-space");
|
|
|
19212
19242
|
* formatDay(tomorrow, "fr") // "mardi 12 mai (demain)"
|
|
19213
19243
|
* formatDay(nextWeek, "fr") // "lundi 18 mai"
|
|
19214
19244
|
*/
|
|
19215
|
-
const formatDay = (date, locale, { long = false } = {}) => {
|
|
19216
|
-
|
|
19245
|
+
const formatDay = (date, locale, { long = false, numeric = false } = {}) => {
|
|
19246
|
+
if (numeric) {
|
|
19247
|
+
return new Intl.DateTimeFormat(locale, {
|
|
19248
|
+
day: "2-digit",
|
|
19249
|
+
month: "2-digit",
|
|
19250
|
+
year: "numeric",
|
|
19251
|
+
}).format(date);
|
|
19252
|
+
}
|
|
19253
|
+
const result = new Intl.DateTimeFormat(locale, {
|
|
19217
19254
|
weekday: long ? "long" : "short",
|
|
19218
19255
|
day: "numeric",
|
|
19219
19256
|
month: long ? "long" : "short",
|
|
19220
19257
|
}).format(date);
|
|
19258
|
+
return result;
|
|
19221
19259
|
};
|
|
19222
19260
|
|
|
19223
19261
|
/**
|
|
@@ -19793,12 +19831,14 @@ const PATTERN_CONSTRAINT = {
|
|
|
19793
19831
|
if (regex.test(value)) {
|
|
19794
19832
|
return null;
|
|
19795
19833
|
}
|
|
19796
|
-
|
|
19797
|
-
|
|
19798
|
-
|
|
19799
|
-
|
|
19834
|
+
const type = field.type;
|
|
19835
|
+
if (type === "email") {
|
|
19836
|
+
return naviI18n("constraint.pattern.email");
|
|
19837
|
+
}
|
|
19838
|
+
if (type === "password") {
|
|
19839
|
+
return naviI18n("constraint.pattern.password");
|
|
19800
19840
|
}
|
|
19801
|
-
return
|
|
19841
|
+
return naviI18n("constraint.pattern.default");
|
|
19802
19842
|
},
|
|
19803
19843
|
};
|
|
19804
19844
|
CONSTRAINT_ATTRIBUTE_SET.add("pattern");
|
|
@@ -20144,20 +20184,20 @@ const STEP_CONSTRAINT = {
|
|
|
20144
20184
|
const before = formatMsToTime(beforeMs, showSeconds);
|
|
20145
20185
|
const after = formatMsToTime(afterMs, showSeconds);
|
|
20146
20186
|
if (stepSeconds % 3600 === 0) {
|
|
20147
|
-
return naviI18n("constraint.step.time.
|
|
20187
|
+
return naviI18n("constraint.step.time.hour", {
|
|
20148
20188
|
step: String(stepSeconds / 3600),
|
|
20149
20189
|
before,
|
|
20150
20190
|
after,
|
|
20151
20191
|
});
|
|
20152
20192
|
}
|
|
20153
20193
|
if (stepSeconds % 60 === 0) {
|
|
20154
|
-
return naviI18n("constraint.step.time.
|
|
20194
|
+
return naviI18n("constraint.step.time.minute", {
|
|
20155
20195
|
step: String(stepSeconds / 60),
|
|
20156
20196
|
before,
|
|
20157
20197
|
after,
|
|
20158
20198
|
});
|
|
20159
20199
|
}
|
|
20160
|
-
return naviI18n("constraint.step.time.
|
|
20200
|
+
return naviI18n("constraint.step.time.second", {
|
|
20161
20201
|
step: stepString,
|
|
20162
20202
|
before,
|
|
20163
20203
|
after,
|
|
@@ -20234,9 +20274,16 @@ const formatDateIso = (iso, inputType) => {
|
|
|
20234
20274
|
const date = new Date(`${iso}-01T00:00:00`);
|
|
20235
20275
|
return formatMonth(date, locale);
|
|
20236
20276
|
}
|
|
20237
|
-
// date, week, datetime-local:
|
|
20238
|
-
const
|
|
20239
|
-
|
|
20277
|
+
// date, week, datetime-local: extract YYYY-MM-DD part and parse as local date
|
|
20278
|
+
const isoMatch = /^(\d{4}-\d{2}-\d{2})/.exec(iso);
|
|
20279
|
+
if (!isoMatch) {
|
|
20280
|
+
return iso;
|
|
20281
|
+
}
|
|
20282
|
+
const datePart = isoMatch[1];
|
|
20283
|
+
const date = new Date(`${datePart}T00:00:00`);
|
|
20284
|
+
if (isNaN(date.getTime())) {
|
|
20285
|
+
return iso;
|
|
20286
|
+
}
|
|
20240
20287
|
return formatDay(date, locale, { long: true });
|
|
20241
20288
|
};
|
|
20242
20289
|
|
|
@@ -20327,9 +20374,10 @@ const onRequestInteraction = (
|
|
|
20327
20374
|
}
|
|
20328
20375
|
}
|
|
20329
20376
|
if (!skipConstraints) {
|
|
20330
|
-
checkAndReportConstraints(requestStatus,
|
|
20377
|
+
checkAndReportConstraints(requestStatus, {
|
|
20331
20378
|
event: requestInteractionCustomEvent,
|
|
20332
20379
|
requester: event.target,
|
|
20380
|
+
fromRequestInteraction: true,
|
|
20333
20381
|
debug: debugInteraction,
|
|
20334
20382
|
});
|
|
20335
20383
|
}
|
|
@@ -20417,11 +20465,11 @@ const onRequestAction = (
|
|
|
20417
20465
|
checkEvent(requestStatus, event);
|
|
20418
20466
|
}
|
|
20419
20467
|
if (requestStatus.canProceed) {
|
|
20420
|
-
checkAndReportConstraints(requestStatus,
|
|
20468
|
+
checkAndReportConstraints(requestStatus, {
|
|
20421
20469
|
event: requestActionCustomEvent,
|
|
20422
20470
|
requester,
|
|
20423
|
-
debug: debugAction,
|
|
20424
20471
|
fromRequestAction: true,
|
|
20472
|
+
debug: debugAction,
|
|
20425
20473
|
});
|
|
20426
20474
|
}
|
|
20427
20475
|
if (requestStatus.canProceed) {
|
|
@@ -20496,8 +20544,7 @@ const checkEvent = (requestStatus, event) => {
|
|
|
20496
20544
|
|
|
20497
20545
|
const checkAndReportConstraints = (
|
|
20498
20546
|
requestStatus,
|
|
20499
|
-
|
|
20500
|
-
{ event, requester, debug, fromRequestAction } = {},
|
|
20547
|
+
{ event, requester, fromRequestInteraction, fromRequestAction, debug } = {},
|
|
20501
20548
|
) => {
|
|
20502
20549
|
const onInvalid = (failedValidationInterface) => {
|
|
20503
20550
|
Object.assign(requestStatus, {
|
|
@@ -20526,9 +20573,9 @@ const checkAndReportConstraints = (
|
|
|
20526
20573
|
}
|
|
20527
20574
|
const isValid = validationInterface.checkValidity({
|
|
20528
20575
|
event,
|
|
20529
|
-
constraints,
|
|
20530
|
-
fromRequestAction,
|
|
20531
20576
|
requester,
|
|
20577
|
+
fromRequestInteraction,
|
|
20578
|
+
fromRequestAction,
|
|
20532
20579
|
});
|
|
20533
20580
|
if (!isValid) {
|
|
20534
20581
|
// checkValidity delegates to the proxy target's VI when the element is a proxy.
|
|
@@ -20703,9 +20750,9 @@ const installCustomConstraintValidation = (
|
|
|
20703
20750
|
addTeardown(resetValidity);
|
|
20704
20751
|
|
|
20705
20752
|
const checkValidity = ({
|
|
20706
|
-
constraints,
|
|
20707
20753
|
event,
|
|
20708
20754
|
requester = element,
|
|
20755
|
+
fromRequestInteraction,
|
|
20709
20756
|
fromRequestAction,
|
|
20710
20757
|
skipReadonly,
|
|
20711
20758
|
} = {}) => {
|
|
@@ -20717,8 +20764,8 @@ const installCustomConstraintValidation = (
|
|
|
20717
20764
|
targetVI = installCustomConstraintValidation(proxyTarget);
|
|
20718
20765
|
}
|
|
20719
20766
|
return targetVI.checkValidity({
|
|
20720
|
-
constraints,
|
|
20721
20767
|
event,
|
|
20768
|
+
fromRequestInteraction,
|
|
20722
20769
|
fromRequestAction,
|
|
20723
20770
|
requester,
|
|
20724
20771
|
skipReadonly,
|
|
@@ -20735,9 +20782,9 @@ const installCustomConstraintValidation = (
|
|
|
20735
20782
|
continue;
|
|
20736
20783
|
}
|
|
20737
20784
|
const managedIsValid = managedVI.checkValidity({
|
|
20738
|
-
constraints,
|
|
20739
20785
|
event,
|
|
20740
20786
|
requester,
|
|
20787
|
+
fromRequestInteraction,
|
|
20741
20788
|
fromRequestAction,
|
|
20742
20789
|
skipReadonly:
|
|
20743
20790
|
managedControl.tagName === "BUTTON" && managedControl !== requester,
|
|
@@ -20748,14 +20795,31 @@ const installCustomConstraintValidation = (
|
|
|
20748
20795
|
}
|
|
20749
20796
|
}
|
|
20750
20797
|
|
|
20798
|
+
// When checking a subset of constraints (e.g. INTERACTION_CONSTRAINTS), we must NOT
|
|
20799
|
+
// reset the full validity state — other constraints (like PATTERN) may still be failing
|
|
20800
|
+
// and we must preserve their state (failedConstraintInfo, callout, etc.).
|
|
20801
|
+
// We only do a scoped check and return its result without touching global state.
|
|
20802
|
+
if (fromRequestInteraction) {
|
|
20803
|
+
for (const constraint of INTERACTION_CONSTRAINTS) {
|
|
20804
|
+
const checkResult = constraint.check(element, {
|
|
20805
|
+
fromRequestAction,
|
|
20806
|
+
skipReadonly,
|
|
20807
|
+
skipRequired: element === requester,
|
|
20808
|
+
registerChange: () => {},
|
|
20809
|
+
});
|
|
20810
|
+
if (checkResult) {
|
|
20811
|
+
return false;
|
|
20812
|
+
}
|
|
20813
|
+
}
|
|
20814
|
+
return true;
|
|
20815
|
+
}
|
|
20751
20816
|
let newConstraintValidityState = { valid: true };
|
|
20752
|
-
|
|
20753
|
-
|
|
20754
|
-
|
|
20755
|
-
|
|
20756
|
-
: new Set([...DEFAULT_CONSTRAINT_SET, ...dynamicConstraintSet]);
|
|
20817
|
+
const constraintSet = new Set([
|
|
20818
|
+
...DEFAULT_CONSTRAINT_SET,
|
|
20819
|
+
...dynamicConstraintSet,
|
|
20820
|
+
]);
|
|
20757
20821
|
resetValidity({ fromRequestAction });
|
|
20758
|
-
for (const constraint of
|
|
20822
|
+
for (const constraint of constraintSet) {
|
|
20759
20823
|
const fieldForConstraint = element;
|
|
20760
20824
|
const constraintCleanupSet = new Set();
|
|
20761
20825
|
const registerChange = (register) => {
|
|
@@ -20829,9 +20893,11 @@ const installCustomConstraintValidation = (
|
|
|
20829
20893
|
if (!hasTitleAttribute) {
|
|
20830
20894
|
element.removeAttribute("title");
|
|
20831
20895
|
}
|
|
20896
|
+
const checkValidityCallEvent =
|
|
20897
|
+
event || new CustomEvent("checkValidity called with no event");
|
|
20832
20898
|
closeElementValidationMessage(
|
|
20833
|
-
|
|
20834
|
-
|
|
20899
|
+
checkValidityCallEvent,
|
|
20900
|
+
`now_valid (after ${checkValidityCallEvent.type})`,
|
|
20835
20901
|
);
|
|
20836
20902
|
}
|
|
20837
20903
|
|
|
@@ -20847,7 +20913,7 @@ const installCustomConstraintValidation = (
|
|
|
20847
20913
|
const [notifyCalloutOpen, onCalloutOpen] = createPubSub();
|
|
20848
20914
|
const reportValidity = ({ event, requester, debug, skipFocus } = {}) => {
|
|
20849
20915
|
if (!failedConstraintInfo) {
|
|
20850
|
-
closeElementValidationMessage(event, "
|
|
20916
|
+
closeElementValidationMessage(event, "is_valid");
|
|
20851
20917
|
return;
|
|
20852
20918
|
}
|
|
20853
20919
|
if (failedConstraintInfo.silent) {
|
|
@@ -20995,6 +21061,7 @@ const installCustomConstraintValidation = (
|
|
|
20995
21061
|
const resetOnInteraction = (e) => {
|
|
20996
21062
|
customMessageMap.clear();
|
|
20997
21063
|
closeElementValidationMessage(e, e.type);
|
|
21064
|
+
console.log("resetOnInteraction", e.type, e);
|
|
20998
21065
|
checkValidity({ event: e });
|
|
20999
21066
|
};
|
|
21000
21067
|
|
|
@@ -21003,35 +21070,57 @@ const installCustomConstraintValidation = (
|
|
|
21003
21070
|
break close_and_check_on_input; // range inputs have a special behavior where "input" is triggered on pointer release, so we don't need to wait for it
|
|
21004
21071
|
}
|
|
21005
21072
|
|
|
21006
|
-
let waitPointerRelease;
|
|
21007
21073
|
onCalloutOpen((openingEvent) => {
|
|
21008
|
-
|
|
21009
|
-
|
|
21074
|
+
const openedByMousedown = findEvent(openingEvent, "mousedown");
|
|
21075
|
+
const [cleanup, addCleanup] = createPubSub();
|
|
21076
|
+
|
|
21077
|
+
const setupResetOnInput = () => {
|
|
21078
|
+
const oninput = (e) => {
|
|
21079
|
+
resetOnInteraction(e);
|
|
21080
|
+
};
|
|
21081
|
+
element.addEventListener("input", oninput, { once: true });
|
|
21082
|
+
addCleanup(() => {
|
|
21083
|
+
element.removeEventListener("input", oninput, { once: true });
|
|
21084
|
+
});
|
|
21085
|
+
};
|
|
21086
|
+
|
|
21087
|
+
if (openedByMousedown) {
|
|
21010
21088
|
const onMouseUp = () => {
|
|
21011
|
-
setTimeout(
|
|
21012
|
-
|
|
21013
|
-
});
|
|
21089
|
+
const timeout = setTimeout(setupResetOnInput);
|
|
21090
|
+
addCleanup(() => clearTimeout(timeout));
|
|
21014
21091
|
};
|
|
21015
21092
|
document.addEventListener("mouseup", onMouseUp, {
|
|
21016
21093
|
once: true,
|
|
21017
21094
|
capture: true,
|
|
21018
21095
|
});
|
|
21019
|
-
|
|
21020
|
-
document.removeEventListener("mouseup", onMouseUp,
|
|
21021
|
-
|
|
21096
|
+
addCleanup(() => {
|
|
21097
|
+
document.removeEventListener("mouseup", onMouseUp, {
|
|
21098
|
+
once: true,
|
|
21099
|
+
capture: true,
|
|
21100
|
+
});
|
|
21101
|
+
});
|
|
21102
|
+
return cleanup;
|
|
21022
21103
|
}
|
|
21023
|
-
return undefined;
|
|
21024
|
-
});
|
|
21025
21104
|
|
|
21026
|
-
|
|
21027
|
-
if (
|
|
21028
|
-
|
|
21029
|
-
|
|
21030
|
-
|
|
21031
|
-
|
|
21032
|
-
|
|
21033
|
-
|
|
21034
|
-
|
|
21105
|
+
// "change" can happen after an input looses focus
|
|
21106
|
+
// and if loose focus as the result of typing (navi_input_full going to next input)
|
|
21107
|
+
// the browser will fire an input event shortly after
|
|
21108
|
+
// causing the callout to immediatly close
|
|
21109
|
+
// an other way to express this could be that an "input" event should be allowed
|
|
21110
|
+
// to close callout only if at least event loop or 1ms occurs
|
|
21111
|
+
let closed = false;
|
|
21112
|
+
addCleanup(() => {
|
|
21113
|
+
closed = true;
|
|
21114
|
+
});
|
|
21115
|
+
queueMicrotask(() => {
|
|
21116
|
+
if (closed) {
|
|
21117
|
+
console.log("closed before");
|
|
21118
|
+
return;
|
|
21119
|
+
}
|
|
21120
|
+
console.log("listen input");
|
|
21121
|
+
setupResetOnInput();
|
|
21122
|
+
});
|
|
21123
|
+
return cleanup;
|
|
21035
21124
|
});
|
|
21036
21125
|
}
|
|
21037
21126
|
|
|
@@ -23160,11 +23249,13 @@ const OverflowPinnedContext = createContext(null);
|
|
|
23160
23249
|
*
|
|
23161
23250
|
* @param {object} props
|
|
23162
23251
|
*
|
|
23163
|
-
* @param {
|
|
23164
|
-
* Truncates overflowing text with an ellipsis.
|
|
23252
|
+
* @param {number} [props.maxLines]
|
|
23253
|
+
* Truncates overflowing text with an ellipsis after at most N lines.
|
|
23254
|
+
* `maxLines={1}` truncates after one line (single-line ellipsis).
|
|
23255
|
+
* `maxLines={n}` (n > 1) truncates after n lines (multi-line clamp).
|
|
23165
23256
|
*
|
|
23166
23257
|
* @param {boolean} [props.overflowPinned]
|
|
23167
|
-
* Must be used inside a `<Text
|
|
23258
|
+
* Must be used inside a `<Text maxLines>` parent.
|
|
23168
23259
|
* Pins this element outside the truncated text flow (e.g. a badge or icon).
|
|
23169
23260
|
*
|
|
23170
23261
|
* @param {string} [props.spacing]
|
|
@@ -23226,7 +23317,7 @@ const TextDispatcher = props => {
|
|
|
23226
23317
|
...props
|
|
23227
23318
|
});
|
|
23228
23319
|
}
|
|
23229
|
-
if (props.
|
|
23320
|
+
if (props.maxLines === 1 || props.maxLines === "1") {
|
|
23230
23321
|
return jsx(TextOverflow, {
|
|
23231
23322
|
...props
|
|
23232
23323
|
});
|
|
@@ -23405,6 +23496,7 @@ const TextSkeleton = ({
|
|
|
23405
23496
|
const TextOverflow = ({
|
|
23406
23497
|
noWrap,
|
|
23407
23498
|
spacing,
|
|
23499
|
+
capitalize,
|
|
23408
23500
|
children,
|
|
23409
23501
|
...rest
|
|
23410
23502
|
}) => {
|
|
@@ -23420,7 +23512,7 @@ const TextOverflow = ({
|
|
|
23420
23512
|
preLine: rest.as === "p" ? true : undefined,
|
|
23421
23513
|
noWrap: noWrap,
|
|
23422
23514
|
...rest,
|
|
23423
|
-
|
|
23515
|
+
maxLines: undefined,
|
|
23424
23516
|
"data-text-overflow": "",
|
|
23425
23517
|
spacing: "pre",
|
|
23426
23518
|
children: jsxs("span", {
|
|
@@ -23430,6 +23522,7 @@ const TextOverflow = ({
|
|
|
23430
23522
|
children: jsx(Text, {
|
|
23431
23523
|
className: "navi_text_overflow_text",
|
|
23432
23524
|
spacing: spacing,
|
|
23525
|
+
capitalize: capitalize,
|
|
23433
23526
|
children: children
|
|
23434
23527
|
})
|
|
23435
23528
|
}), overflowPinned && overflowPinned.position === "end" ? overflowPinned.vnode : null]
|
|
@@ -23447,7 +23540,7 @@ const TextOverflowPinned = props => {
|
|
|
23447
23540
|
overflowPinned: undefined
|
|
23448
23541
|
});
|
|
23449
23542
|
if (!setOverflowPinned) {
|
|
23450
|
-
console.warn(
|
|
23543
|
+
console.warn(`<Text overflowPinned> declared outside a <Text maxLines="1">`);
|
|
23451
23544
|
return text;
|
|
23452
23545
|
}
|
|
23453
23546
|
if (overflowPinned) {
|
|
@@ -24259,11 +24352,11 @@ const CONTROL_ATTRIBUTE_SET = new Set([
|
|
|
24259
24352
|
"autoComplete",
|
|
24260
24353
|
"spellcheck",
|
|
24261
24354
|
"autoCorrect",
|
|
24355
|
+
"aria-controls",
|
|
24356
|
+
"tabIndex",
|
|
24262
24357
|
|
|
24263
24358
|
"navi-input-type",
|
|
24264
24359
|
"navi-control-proxy-for",
|
|
24265
|
-
"aria-controls",
|
|
24266
|
-
"tabIndex",
|
|
24267
24360
|
|
|
24268
24361
|
"data-callout-arrow-x",
|
|
24269
24362
|
"data-callout-point-to-border-box",
|
|
@@ -24272,7 +24365,7 @@ const CONTROL_ATTRIBUTE_SET = new Set([
|
|
|
24272
24365
|
"data-callout-position",
|
|
24273
24366
|
"data-callout-position-fixed",
|
|
24274
24367
|
|
|
24275
|
-
"data-testid",
|
|
24368
|
+
"data-testid", // playwright, cypress
|
|
24276
24369
|
]);
|
|
24277
24370
|
// prop concerning control but that won't end up in the DOM if not inside CONTROL_ATTRIBUTE_SET
|
|
24278
24371
|
const CONTROL_PROP_SET = new Set([
|
|
@@ -25736,7 +25829,13 @@ const ControlChildrenWrapper = ({
|
|
|
25736
25829
|
value: undefined,
|
|
25737
25830
|
children: jsx(ControlToInterfaceContext.Provider, {
|
|
25738
25831
|
value: undefined,
|
|
25739
|
-
children:
|
|
25832
|
+
children: jsx(RequiredContext.Provider, {
|
|
25833
|
+
value: undefined,
|
|
25834
|
+
children: jsx(ControlNameContext.Provider, {
|
|
25835
|
+
value: undefined,
|
|
25836
|
+
children: children
|
|
25837
|
+
})
|
|
25838
|
+
})
|
|
25740
25839
|
})
|
|
25741
25840
|
})
|
|
25742
25841
|
});
|
|
@@ -27551,7 +27650,7 @@ const LinkPlain = props => {
|
|
|
27551
27650
|
endIcon,
|
|
27552
27651
|
revealOnInteraction = Boolean(titleLevel),
|
|
27553
27652
|
hrefFallback = !anchor,
|
|
27554
|
-
|
|
27653
|
+
maxLines,
|
|
27555
27654
|
children,
|
|
27556
27655
|
constraints,
|
|
27557
27656
|
...remainingProps
|
|
@@ -27641,7 +27740,7 @@ const LinkPlain = props => {
|
|
|
27641
27740
|
fontWeight: "bold"
|
|
27642
27741
|
} : undefined,
|
|
27643
27742
|
preventSpaceUnderlines: true,
|
|
27644
|
-
|
|
27743
|
+
maxLines: maxLines
|
|
27645
27744
|
// Visual
|
|
27646
27745
|
,
|
|
27647
27746
|
|
|
@@ -27694,7 +27793,7 @@ const LinkPlain = props => {
|
|
|
27694
27793
|
color: "var(--link-loader-color)"
|
|
27695
27794
|
}), currentIndicatorEl]
|
|
27696
27795
|
}),
|
|
27697
|
-
children: [startIconEl, innerChildren, endIconEl ?
|
|
27796
|
+
children: [startIconEl, innerChildren, endIconEl ? maxLines === 1 || maxLines === "1" ? jsx(Text, {
|
|
27698
27797
|
overflowPinned: true,
|
|
27699
27798
|
children: endIconEl
|
|
27700
27799
|
}) : endIconEl : null]
|
|
@@ -28907,6 +29006,316 @@ const CheckboxPseudoClasses = [":hover", ":active", ":focus", ":focus-visible",
|
|
|
28907
29006
|
const CheckboxPseudoElements = ["::-navi-loader", "::-navi-checkmark"];
|
|
28908
29007
|
|
|
28909
29008
|
installImportMetaCssBuild(import.meta);const css$z = /* css */`
|
|
29009
|
+
@layer navi {
|
|
29010
|
+
[data-navi-field] {
|
|
29011
|
+
.navi_checkbox {
|
|
29012
|
+
--margin: 0;
|
|
29013
|
+
}
|
|
29014
|
+
.navi_radio {
|
|
29015
|
+
--margin: 0;
|
|
29016
|
+
}
|
|
29017
|
+
}
|
|
29018
|
+
|
|
29019
|
+
label[data-navi-field] {
|
|
29020
|
+
&[data-interactive] {
|
|
29021
|
+
cursor: pointer;
|
|
29022
|
+
user-select: none;
|
|
29023
|
+
}
|
|
29024
|
+
&[data-readonly],
|
|
29025
|
+
&[data-disabled] {
|
|
29026
|
+
color: rgba(0, 0, 0, 0.5);
|
|
29027
|
+
cursor: default;
|
|
29028
|
+
}
|
|
29029
|
+
}
|
|
29030
|
+
|
|
29031
|
+
[data-navi-field-container] {
|
|
29032
|
+
--field-spacing: var(--navi-xs);
|
|
29033
|
+
|
|
29034
|
+
> * + .navi_label {
|
|
29035
|
+
padding-left: var(--field-spacing);
|
|
29036
|
+
}
|
|
29037
|
+
> .navi_label:first-child {
|
|
29038
|
+
padding-right: var(--field-spacing);
|
|
29039
|
+
}
|
|
29040
|
+
&[data-vertical] > .navi_label:first-child {
|
|
29041
|
+
padding-bottom: var(--field-spacing);
|
|
29042
|
+
}
|
|
29043
|
+
|
|
29044
|
+
&[data-interactive] {
|
|
29045
|
+
.navi_label {
|
|
29046
|
+
cursor: pointer;
|
|
29047
|
+
/* When label is interactive ability to select text oftens conflicts with other click interactions */
|
|
29048
|
+
user-select: none;
|
|
29049
|
+
}
|
|
29050
|
+
}
|
|
29051
|
+
&[data-readonly],
|
|
29052
|
+
&[data-disabled] {
|
|
29053
|
+
.navi_label {
|
|
29054
|
+
color: rgba(0, 0, 0, 0.5);
|
|
29055
|
+
cursor: default;
|
|
29056
|
+
}
|
|
29057
|
+
}
|
|
29058
|
+
}
|
|
29059
|
+
}
|
|
29060
|
+
`;
|
|
29061
|
+
|
|
29062
|
+
/**
|
|
29063
|
+
* Field — a semantic wrapper that connects a label to a form control.
|
|
29064
|
+
*
|
|
29065
|
+
* It generates a stable `fieldId` (or accepts an explicit `id`) that is
|
|
29066
|
+
* automatically forwarded to the `Label` inside the field as `htmlFor` and to
|
|
29067
|
+
* any interactive control (Picker, Input, …) as its `id`, so clicking the
|
|
29068
|
+
* label focuses the control without requiring manual wiring.
|
|
29069
|
+
*
|
|
29070
|
+
* It also tracks the readOnly / disabled / interactive state reported by its
|
|
29071
|
+
* child control and reflects it on the `Label` (dimmed color, cursor change).
|
|
29072
|
+
*
|
|
29073
|
+
* Props:
|
|
29074
|
+
* id — optional explicit id used as the field id instead of the auto-generated one
|
|
29075
|
+
* vertical — shorthand for flex="y" + alignX="start"
|
|
29076
|
+
* children — any JSX; should contain a `Label` and a form control
|
|
29077
|
+
* ...rest — forwarded to the wrapping `<div>` (className, style, flex, spacing, …)
|
|
29078
|
+
*
|
|
29079
|
+
* @example
|
|
29080
|
+
* <Field flex spacing="s">
|
|
29081
|
+
* Date de début
|
|
29082
|
+
* <Input name="start_date" required />
|
|
29083
|
+
* </Field>
|
|
29084
|
+
*/
|
|
29085
|
+
const Field = props => {
|
|
29086
|
+
import.meta.css = [css$z, "@jsenv/navi/src/control/field.jsx"];
|
|
29087
|
+
const refDefault = useRef();
|
|
29088
|
+
props.ref = props.ref || refDefault;
|
|
29089
|
+
const {
|
|
29090
|
+
as,
|
|
29091
|
+
vertical
|
|
29092
|
+
} = props;
|
|
29093
|
+
if (as === undefined && !vertical) {
|
|
29094
|
+
props.as = "label";
|
|
29095
|
+
}
|
|
29096
|
+
if (props.as === "label") {
|
|
29097
|
+
return jsx(FieldAsLabel, {
|
|
29098
|
+
...props
|
|
29099
|
+
});
|
|
29100
|
+
}
|
|
29101
|
+
return jsx(FieldAsContainer, {
|
|
29102
|
+
...props
|
|
29103
|
+
});
|
|
29104
|
+
};
|
|
29105
|
+
const FieldAsLabel = props => {
|
|
29106
|
+
return jsx(FieldUI, {
|
|
29107
|
+
...props
|
|
29108
|
+
});
|
|
29109
|
+
};
|
|
29110
|
+
const FieldAsContainer = props => {
|
|
29111
|
+
const idDefault = useId();
|
|
29112
|
+
const fieldId = `field_${idDefault}`;
|
|
29113
|
+
props.fieldId = props.fieldId || props.id ? `${props.id}_field` : fieldId;
|
|
29114
|
+
return jsx(FieldUI, {
|
|
29115
|
+
...props,
|
|
29116
|
+
"data-navi-field-container": "",
|
|
29117
|
+
styleCSSVars: FieldCSSVars
|
|
29118
|
+
});
|
|
29119
|
+
};
|
|
29120
|
+
const FieldCSSVars = {
|
|
29121
|
+
spacing: "--field-spacing"
|
|
29122
|
+
};
|
|
29123
|
+
const FieldUI = props => {
|
|
29124
|
+
import.meta.css = [css$z, "@jsenv/navi/src/control/field.jsx"];
|
|
29125
|
+
const {
|
|
29126
|
+
vertical
|
|
29127
|
+
} = props;
|
|
29128
|
+
const {
|
|
29129
|
+
fieldId,
|
|
29130
|
+
name,
|
|
29131
|
+
disabled,
|
|
29132
|
+
readOnly,
|
|
29133
|
+
required,
|
|
29134
|
+
loading,
|
|
29135
|
+
interactive,
|
|
29136
|
+
...rest
|
|
29137
|
+
} = props;
|
|
29138
|
+
const [messageProps, remainingProps] = extractMessageAndRemainingProps(rest);
|
|
29139
|
+
const messagePropsRef = useRef();
|
|
29140
|
+
messagePropsRef.current = messageProps;
|
|
29141
|
+
const [disabledByChild, setDisabledByChild] = useState(false);
|
|
29142
|
+
const [readOnlyFromChild, setReadOnlyFromChild] = useState(false);
|
|
29143
|
+
const [interactiveFromChild, setInteractiveFromChild] = useState(false);
|
|
29144
|
+
const parentControlName = useContext(ControlNameContext);
|
|
29145
|
+
const parentControlDisabled = useContext(DisabledContext);
|
|
29146
|
+
const parentControlReadOnly = useContext(ReadOnlyContext);
|
|
29147
|
+
const parentControlRequired = useContext(RequiredContext);
|
|
29148
|
+
const parentControlLoading = useContext(LoadingContext);
|
|
29149
|
+
const nameResolved = name || parentControlName;
|
|
29150
|
+
const disabledResolved = disabled || parentControlDisabled;
|
|
29151
|
+
const readOnlyResolved = readOnly || parentControlReadOnly;
|
|
29152
|
+
const requiredResolved = required || parentControlRequired;
|
|
29153
|
+
const loadingResolved = loading || parentControlLoading;
|
|
29154
|
+
const controlToInterfaceContextValue = useMemo(() => ({
|
|
29155
|
+
id: fieldId,
|
|
29156
|
+
setReadOnly: setReadOnlyFromChild,
|
|
29157
|
+
setDisabled: setDisabledByChild,
|
|
29158
|
+
setInteractive: setInteractiveFromChild
|
|
29159
|
+
}), [fieldId]);
|
|
29160
|
+
let childrenWithContext;
|
|
29161
|
+
if (props.children === undefined) ; else {
|
|
29162
|
+
childrenWithContext = jsx(MessagePropsRefContext.Provider, {
|
|
29163
|
+
value: messagePropsRef,
|
|
29164
|
+
children: jsx(ControlToInterfaceContext.Provider, {
|
|
29165
|
+
value: controlToInterfaceContextValue,
|
|
29166
|
+
children: jsx(ControlNameContext.Provider, {
|
|
29167
|
+
value: nameResolved,
|
|
29168
|
+
children: jsx(DisabledContext.Provider, {
|
|
29169
|
+
value: disabledResolved,
|
|
29170
|
+
children: jsx(ReadOnlyContext.Provider, {
|
|
29171
|
+
value: readOnlyResolved,
|
|
29172
|
+
children: jsx(RequiredContext.Provider, {
|
|
29173
|
+
value: requiredResolved,
|
|
29174
|
+
children: jsx(LoadingContext.Provider, {
|
|
29175
|
+
value: loadingResolved,
|
|
29176
|
+
children: props.children
|
|
29177
|
+
})
|
|
29178
|
+
})
|
|
29179
|
+
})
|
|
29180
|
+
})
|
|
29181
|
+
})
|
|
29182
|
+
})
|
|
29183
|
+
});
|
|
29184
|
+
}
|
|
29185
|
+
|
|
29186
|
+
// a field inteface can make the field component
|
|
29187
|
+
// disabled/readonly when that field interface is disabled/readonly
|
|
29188
|
+
// this is the only bottom up communication there is
|
|
29189
|
+
// (apart from action requested by child which cause ancestor action to execute)
|
|
29190
|
+
const disabledOrByChild = disabledResolved || disabledByChild;
|
|
29191
|
+
const readOnlyOrByChild = readOnlyResolved || readOnlyFromChild;
|
|
29192
|
+
const interactiveOrByChild = interactive || interactiveFromChild;
|
|
29193
|
+
const fieldProps = {
|
|
29194
|
+
"data-navi-field": "",
|
|
29195
|
+
"data-interactive": interactiveOrByChild ? "" : undefined,
|
|
29196
|
+
...remainingProps,
|
|
29197
|
+
"children": childrenWithContext,
|
|
29198
|
+
"pseudoClasses": FieldPseudoClasses,
|
|
29199
|
+
"basePseudoState": {
|
|
29200
|
+
":disabled": disabledOrByChild,
|
|
29201
|
+
":read-only": readOnlyOrByChild,
|
|
29202
|
+
...remainingProps.basePseudoState
|
|
29203
|
+
}
|
|
29204
|
+
};
|
|
29205
|
+
return jsx(Box, {
|
|
29206
|
+
flex: vertical ? "y" : undefined,
|
|
29207
|
+
alignX: vertical ? "start" : undefined,
|
|
29208
|
+
"data-vertical": vertical ? "" : undefined,
|
|
29209
|
+
...fieldProps
|
|
29210
|
+
});
|
|
29211
|
+
};
|
|
29212
|
+
const FieldPseudoClasses = [":hover", ":active", ":focus", ":focus-visible", ":read-only", ":disabled", ":-navi-loading"];
|
|
29213
|
+
const Label = props => {
|
|
29214
|
+
const {
|
|
29215
|
+
children,
|
|
29216
|
+
htmlFor,
|
|
29217
|
+
...rest
|
|
29218
|
+
} = props;
|
|
29219
|
+
const controlToInterface = useContext(ControlToInterfaceContext);
|
|
29220
|
+
const fieldId = controlToInterface?.id;
|
|
29221
|
+
return jsx(Box, {
|
|
29222
|
+
as: "label",
|
|
29223
|
+
htmlFor: htmlFor || fieldId,
|
|
29224
|
+
baseClassName: "navi_label",
|
|
29225
|
+
pseudoClasses: LabelPseudoClasses,
|
|
29226
|
+
...rest,
|
|
29227
|
+
children: children
|
|
29228
|
+
});
|
|
29229
|
+
};
|
|
29230
|
+
const LabelPseudoClasses = [":hover", ":active", ":focus", ":focus-visible", ":read-only", ":disabled", ":-navi-loading"];
|
|
29231
|
+
|
|
29232
|
+
const InputTextualContext = createContext(null);
|
|
29233
|
+
|
|
29234
|
+
const InputLeftSlot = props => {
|
|
29235
|
+
return jsx(InputSlot, {
|
|
29236
|
+
...props,
|
|
29237
|
+
side: "left"
|
|
29238
|
+
});
|
|
29239
|
+
};
|
|
29240
|
+
const InputRightSlot = props => {
|
|
29241
|
+
return jsx(InputSlot, {
|
|
29242
|
+
...props,
|
|
29243
|
+
side: "right"
|
|
29244
|
+
});
|
|
29245
|
+
};
|
|
29246
|
+
const InputIconSlot = ({
|
|
29247
|
+
children,
|
|
29248
|
+
side = "right",
|
|
29249
|
+
...props
|
|
29250
|
+
}) => {
|
|
29251
|
+
return jsx(InputSlot, {
|
|
29252
|
+
side: side,
|
|
29253
|
+
children: jsx(Icon, {
|
|
29254
|
+
...props,
|
|
29255
|
+
children: children
|
|
29256
|
+
})
|
|
29257
|
+
});
|
|
29258
|
+
};
|
|
29259
|
+
const InputUnitSlot = ({
|
|
29260
|
+
children,
|
|
29261
|
+
side = "right",
|
|
29262
|
+
...props
|
|
29263
|
+
}) => {
|
|
29264
|
+
return jsx(InputSlot, {
|
|
29265
|
+
side: side,
|
|
29266
|
+
marginLeft: "xxs",
|
|
29267
|
+
noWrap: true,
|
|
29268
|
+
...props,
|
|
29269
|
+
children: children
|
|
29270
|
+
});
|
|
29271
|
+
};
|
|
29272
|
+
const InputSlot = ({
|
|
29273
|
+
side,
|
|
29274
|
+
onClick,
|
|
29275
|
+
hideWhileEmpty,
|
|
29276
|
+
...props
|
|
29277
|
+
}) => {
|
|
29278
|
+
const ctx = useContext(InputTextualContext);
|
|
29279
|
+
const {
|
|
29280
|
+
id,
|
|
29281
|
+
readOnly,
|
|
29282
|
+
disabled
|
|
29283
|
+
} = ctx || {};
|
|
29284
|
+
return jsx(Label, {
|
|
29285
|
+
htmlFor: id,
|
|
29286
|
+
className: "navi_input_slot",
|
|
29287
|
+
disabled: disabled,
|
|
29288
|
+
readOnly: readOnly,
|
|
29289
|
+
"data-readonly": readOnly,
|
|
29290
|
+
"data-disabled": disabled,
|
|
29291
|
+
"data-left": side === "left" ? "" : undefined,
|
|
29292
|
+
"data-right": side === "right" ? "" : undefined,
|
|
29293
|
+
"data-hide-while-empty": hideWhileEmpty ? "" : undefined,
|
|
29294
|
+
inline: true,
|
|
29295
|
+
flex: true,
|
|
29296
|
+
align: "center",
|
|
29297
|
+
onMouseDown: e => {
|
|
29298
|
+
// Only prevent focus from leaving when the input already has focus.
|
|
29299
|
+
// If the input is not focused, let the mousedown proceed normally so
|
|
29300
|
+
// the slot element (e.g. a clear button) can receive focus itself.
|
|
29301
|
+
const inputEl = document.getElementById(id);
|
|
29302
|
+
if (inputEl && inputEl === document.activeElement) {
|
|
29303
|
+
e.preventDefault();
|
|
29304
|
+
}
|
|
29305
|
+
},
|
|
29306
|
+
onClick: e => {
|
|
29307
|
+
onClick?.(e);
|
|
29308
|
+
const input = document.getElementById(id);
|
|
29309
|
+
const allowed = dispatchRequestInteraction(input, e);
|
|
29310
|
+
if (!allowed) {
|
|
29311
|
+
e.preventDefault();
|
|
29312
|
+
}
|
|
29313
|
+
},
|
|
29314
|
+
...props
|
|
29315
|
+
});
|
|
29316
|
+
};
|
|
29317
|
+
|
|
29318
|
+
installImportMetaCssBuild(import.meta);const css$y = /* css */`
|
|
28910
29319
|
@layer navi {
|
|
28911
29320
|
.navi_radio {
|
|
28912
29321
|
--margin: 3px 3px 0 5px;
|
|
@@ -29261,7 +29670,7 @@ const InputRadioHeadless = props => {
|
|
|
29261
29670
|
};
|
|
29262
29671
|
const APPEARANCE_SET = new Set(["icon", "button", "radio"]);
|
|
29263
29672
|
const InputRadioFieldInterface = props => {
|
|
29264
|
-
import.meta.css = [css$
|
|
29673
|
+
import.meta.css = [css$y, "@jsenv/navi/src/control/input/input_radio.jsx"];
|
|
29265
29674
|
const [radioProps, remainingProps] = useCheckableProps(props);
|
|
29266
29675
|
const {
|
|
29267
29676
|
icon,
|
|
@@ -29549,7 +29958,7 @@ const NAVI_TYPE_DEFAULTS = {
|
|
|
29549
29958
|
type: "text",
|
|
29550
29959
|
inputMode: "numeric",
|
|
29551
29960
|
autoCorrect: "off",
|
|
29552
|
-
spellcheck:
|
|
29961
|
+
spellcheck: false,
|
|
29553
29962
|
autoComplete: "off",
|
|
29554
29963
|
},
|
|
29555
29964
|
};
|
|
@@ -29605,16 +30014,8 @@ const resolveInputProps = (props) => {
|
|
|
29605
30014
|
}
|
|
29606
30015
|
|
|
29607
30016
|
const currentType = props.type;
|
|
29608
|
-
|
|
29609
|
-
|
|
29610
|
-
return;
|
|
29611
|
-
}
|
|
29612
|
-
for (const key of Object.keys(currentTypeDefaults)) {
|
|
29613
|
-
if (props[key] === undefined) {
|
|
29614
|
-
props[key] = currentTypeDefaults[key];
|
|
29615
|
-
}
|
|
29616
|
-
}
|
|
29617
|
-
// Apply formatters for the original navi type before remapping
|
|
30017
|
+
// Apply min/max/step formatters before anything else — this must run even for
|
|
30018
|
+
// standard HTML types (date, time, etc.) that have no NAVI_TYPE_DEFAULTS entry.
|
|
29618
30019
|
const currentTypeMinMaxFormatter = MIN_MAX_FORMATTER_BY_TYPE[currentType];
|
|
29619
30020
|
const currentTypeStepFormatter = STEP_FORMATTER_BY_TYPE[currentType];
|
|
29620
30021
|
if (currentTypeMinMaxFormatter) {
|
|
@@ -29624,6 +30025,15 @@ const resolveInputProps = (props) => {
|
|
|
29624
30025
|
if (currentTypeStepFormatter) {
|
|
29625
30026
|
props.step = currentTypeStepFormatter(props.step);
|
|
29626
30027
|
}
|
|
30028
|
+
const currentTypeDefaults = NAVI_TYPE_DEFAULTS[currentType];
|
|
30029
|
+
if (!currentTypeDefaults) {
|
|
30030
|
+
return;
|
|
30031
|
+
}
|
|
30032
|
+
for (const key of Object.keys(currentTypeDefaults)) {
|
|
30033
|
+
if (props[key] === undefined) {
|
|
30034
|
+
props[key] = currentTypeDefaults[key];
|
|
30035
|
+
}
|
|
30036
|
+
}
|
|
29627
30037
|
const targetType = currentTypeDefaults.type;
|
|
29628
30038
|
props.type = targetType;
|
|
29629
30039
|
resolveInputProps(props);
|
|
@@ -29750,7 +30160,7 @@ const STEP_FORMATTER_BY_TYPE = {
|
|
|
29750
30160
|
"datetime": parseStepToSeconds,
|
|
29751
30161
|
};
|
|
29752
30162
|
|
|
29753
|
-
installImportMetaCssBuild(import.meta);const css$
|
|
30163
|
+
installImportMetaCssBuild(import.meta);const css$x = /* css */`
|
|
29754
30164
|
@layer navi {
|
|
29755
30165
|
.navi_input_range {
|
|
29756
30166
|
--border-radius: 6px;
|
|
@@ -30004,7 +30414,7 @@ const InputRange = props => {
|
|
|
30004
30414
|
});
|
|
30005
30415
|
};
|
|
30006
30416
|
const InputRangeFieldInterface = props => {
|
|
30007
|
-
import.meta.css = [css$
|
|
30417
|
+
import.meta.css = [css$x, "@jsenv/navi/src/control/input/input_range.jsx"];
|
|
30008
30418
|
const {
|
|
30009
30419
|
ref
|
|
30010
30420
|
} = props;
|
|
@@ -30122,316 +30532,6 @@ const RangeStyleCSSVars = {
|
|
|
30122
30532
|
const RangePseudoClasses = [":hover", ":active", ":-navi-pressed", ":focus", ":focus-visible", ":read-only", ":disabled", ":-navi-loading"];
|
|
30123
30533
|
const RangePseudoElements = ["::-navi-loader"];
|
|
30124
30534
|
|
|
30125
|
-
installImportMetaCssBuild(import.meta);const css$x = /* css */`
|
|
30126
|
-
@layer navi {
|
|
30127
|
-
[data-navi-field] {
|
|
30128
|
-
.navi_checkbox {
|
|
30129
|
-
--margin: 0;
|
|
30130
|
-
}
|
|
30131
|
-
.navi_radio {
|
|
30132
|
-
--margin: 0;
|
|
30133
|
-
}
|
|
30134
|
-
}
|
|
30135
|
-
|
|
30136
|
-
label[data-navi-field] {
|
|
30137
|
-
&[data-interactive] {
|
|
30138
|
-
cursor: pointer;
|
|
30139
|
-
user-select: none;
|
|
30140
|
-
}
|
|
30141
|
-
&[data-readonly],
|
|
30142
|
-
&[data-disabled] {
|
|
30143
|
-
color: rgba(0, 0, 0, 0.5);
|
|
30144
|
-
cursor: default;
|
|
30145
|
-
}
|
|
30146
|
-
}
|
|
30147
|
-
|
|
30148
|
-
[data-navi-field-container] {
|
|
30149
|
-
--field-spacing: var(--navi-xs);
|
|
30150
|
-
|
|
30151
|
-
> * + .navi_label {
|
|
30152
|
-
padding-left: var(--field-spacing);
|
|
30153
|
-
}
|
|
30154
|
-
> .navi_label:first-child {
|
|
30155
|
-
padding-right: var(--field-spacing);
|
|
30156
|
-
}
|
|
30157
|
-
&[data-vertical] > .navi_label:first-child {
|
|
30158
|
-
padding-bottom: var(--field-spacing);
|
|
30159
|
-
}
|
|
30160
|
-
|
|
30161
|
-
&[data-interactive] {
|
|
30162
|
-
.navi_label {
|
|
30163
|
-
cursor: pointer;
|
|
30164
|
-
/* When label is interactive ability to select text oftens conflicts with other click interactions */
|
|
30165
|
-
user-select: none;
|
|
30166
|
-
}
|
|
30167
|
-
}
|
|
30168
|
-
&[data-readonly],
|
|
30169
|
-
&[data-disabled] {
|
|
30170
|
-
.navi_label {
|
|
30171
|
-
color: rgba(0, 0, 0, 0.5);
|
|
30172
|
-
cursor: default;
|
|
30173
|
-
}
|
|
30174
|
-
}
|
|
30175
|
-
}
|
|
30176
|
-
}
|
|
30177
|
-
`;
|
|
30178
|
-
|
|
30179
|
-
/**
|
|
30180
|
-
* Field — a semantic wrapper that connects a label to a form control.
|
|
30181
|
-
*
|
|
30182
|
-
* It generates a stable `fieldId` (or accepts an explicit `id`) that is
|
|
30183
|
-
* automatically forwarded to the `Label` inside the field as `htmlFor` and to
|
|
30184
|
-
* any interactive control (Picker, Input, …) as its `id`, so clicking the
|
|
30185
|
-
* label focuses the control without requiring manual wiring.
|
|
30186
|
-
*
|
|
30187
|
-
* It also tracks the readOnly / disabled / interactive state reported by its
|
|
30188
|
-
* child control and reflects it on the `Label` (dimmed color, cursor change).
|
|
30189
|
-
*
|
|
30190
|
-
* Props:
|
|
30191
|
-
* id — optional explicit id used as the field id instead of the auto-generated one
|
|
30192
|
-
* vertical — shorthand for flex="y" + alignX="start"
|
|
30193
|
-
* children — any JSX; should contain a `Label` and a form control
|
|
30194
|
-
* ...rest — forwarded to the wrapping `<div>` (className, style, flex, spacing, …)
|
|
30195
|
-
*
|
|
30196
|
-
* @example
|
|
30197
|
-
* <Field flex spacing="s">
|
|
30198
|
-
* Date de début
|
|
30199
|
-
* <Input name="start_date" required />
|
|
30200
|
-
* </Field>
|
|
30201
|
-
*/
|
|
30202
|
-
const Field = props => {
|
|
30203
|
-
import.meta.css = [css$x, "@jsenv/navi/src/control/field.jsx"];
|
|
30204
|
-
const refDefault = useRef();
|
|
30205
|
-
props.ref = props.ref || refDefault;
|
|
30206
|
-
const {
|
|
30207
|
-
as,
|
|
30208
|
-
vertical
|
|
30209
|
-
} = props;
|
|
30210
|
-
if (as === undefined && !vertical) {
|
|
30211
|
-
props.as = "label";
|
|
30212
|
-
}
|
|
30213
|
-
if (props.as === "label") {
|
|
30214
|
-
return jsx(FieldAsLabel, {
|
|
30215
|
-
...props
|
|
30216
|
-
});
|
|
30217
|
-
}
|
|
30218
|
-
return jsx(FieldAsContainer, {
|
|
30219
|
-
...props
|
|
30220
|
-
});
|
|
30221
|
-
};
|
|
30222
|
-
const FieldAsLabel = props => {
|
|
30223
|
-
return jsx(FieldUI, {
|
|
30224
|
-
...props
|
|
30225
|
-
});
|
|
30226
|
-
};
|
|
30227
|
-
const FieldAsContainer = props => {
|
|
30228
|
-
const idDefault = useId();
|
|
30229
|
-
const fieldId = `field_${idDefault}`;
|
|
30230
|
-
props.fieldId = props.fieldId || props.id ? `${props.id}_field` : fieldId;
|
|
30231
|
-
return jsx(FieldUI, {
|
|
30232
|
-
...props,
|
|
30233
|
-
"data-navi-field-container": "",
|
|
30234
|
-
styleCSSVars: FieldCSSVars
|
|
30235
|
-
});
|
|
30236
|
-
};
|
|
30237
|
-
const FieldCSSVars = {
|
|
30238
|
-
spacing: "--field-spacing"
|
|
30239
|
-
};
|
|
30240
|
-
const FieldUI = props => {
|
|
30241
|
-
import.meta.css = [css$x, "@jsenv/navi/src/control/field.jsx"];
|
|
30242
|
-
const {
|
|
30243
|
-
vertical
|
|
30244
|
-
} = props;
|
|
30245
|
-
const {
|
|
30246
|
-
fieldId,
|
|
30247
|
-
name,
|
|
30248
|
-
disabled,
|
|
30249
|
-
readOnly,
|
|
30250
|
-
required,
|
|
30251
|
-
loading,
|
|
30252
|
-
interactive,
|
|
30253
|
-
...rest
|
|
30254
|
-
} = props;
|
|
30255
|
-
const [messageProps, remainingProps] = extractMessageAndRemainingProps(rest);
|
|
30256
|
-
const messagePropsRef = useRef();
|
|
30257
|
-
messagePropsRef.current = messageProps;
|
|
30258
|
-
const [disabledByChild, setDisabledByChild] = useState(false);
|
|
30259
|
-
const [readOnlyFromChild, setReadOnlyFromChild] = useState(false);
|
|
30260
|
-
const [interactiveFromChild, setInteractiveFromChild] = useState(false);
|
|
30261
|
-
const parentControlName = useContext(ControlNameContext);
|
|
30262
|
-
const parentControlDisabled = useContext(DisabledContext);
|
|
30263
|
-
const parentControlReadOnly = useContext(ReadOnlyContext);
|
|
30264
|
-
const parentControlRequired = useContext(RequiredContext);
|
|
30265
|
-
const parentControlLoading = useContext(LoadingContext);
|
|
30266
|
-
const nameResolved = name || parentControlName;
|
|
30267
|
-
const disabledResolved = disabled || parentControlDisabled;
|
|
30268
|
-
const readOnlyResolved = readOnly || parentControlReadOnly;
|
|
30269
|
-
const requiredResolved = required || parentControlRequired;
|
|
30270
|
-
const loadingResolved = loading || parentControlLoading;
|
|
30271
|
-
const controlToInterfaceContextValue = useMemo(() => ({
|
|
30272
|
-
id: fieldId,
|
|
30273
|
-
setReadOnly: setReadOnlyFromChild,
|
|
30274
|
-
setDisabled: setDisabledByChild,
|
|
30275
|
-
setInteractive: setInteractiveFromChild
|
|
30276
|
-
}), [fieldId]);
|
|
30277
|
-
let childrenWithContext;
|
|
30278
|
-
if (props.children === undefined) ; else {
|
|
30279
|
-
childrenWithContext = jsx(MessagePropsRefContext.Provider, {
|
|
30280
|
-
value: messagePropsRef,
|
|
30281
|
-
children: jsx(ControlToInterfaceContext.Provider, {
|
|
30282
|
-
value: controlToInterfaceContextValue,
|
|
30283
|
-
children: jsx(ControlNameContext.Provider, {
|
|
30284
|
-
value: nameResolved,
|
|
30285
|
-
children: jsx(DisabledContext.Provider, {
|
|
30286
|
-
value: disabledResolved,
|
|
30287
|
-
children: jsx(ReadOnlyContext.Provider, {
|
|
30288
|
-
value: readOnlyResolved,
|
|
30289
|
-
children: jsx(RequiredContext.Provider, {
|
|
30290
|
-
value: requiredResolved,
|
|
30291
|
-
children: jsx(LoadingContext.Provider, {
|
|
30292
|
-
value: loadingResolved,
|
|
30293
|
-
children: props.children
|
|
30294
|
-
})
|
|
30295
|
-
})
|
|
30296
|
-
})
|
|
30297
|
-
})
|
|
30298
|
-
})
|
|
30299
|
-
})
|
|
30300
|
-
});
|
|
30301
|
-
}
|
|
30302
|
-
|
|
30303
|
-
// a field inteface can make the field component
|
|
30304
|
-
// disabled/readonly when that field interface is disabled/readonly
|
|
30305
|
-
// this is the only bottom up communication there is
|
|
30306
|
-
// (apart from action requested by child which cause ancestor action to execute)
|
|
30307
|
-
const disabledOrByChild = disabledResolved || disabledByChild;
|
|
30308
|
-
const readOnlyOrByChild = readOnlyResolved || readOnlyFromChild;
|
|
30309
|
-
const interactiveOrByChild = interactive || interactiveFromChild;
|
|
30310
|
-
const fieldProps = {
|
|
30311
|
-
"data-navi-field": "",
|
|
30312
|
-
"data-interactive": interactiveOrByChild ? "" : undefined,
|
|
30313
|
-
...remainingProps,
|
|
30314
|
-
"children": childrenWithContext,
|
|
30315
|
-
"pseudoClasses": FieldPseudoClasses,
|
|
30316
|
-
"basePseudoState": {
|
|
30317
|
-
":disabled": disabledOrByChild,
|
|
30318
|
-
":read-only": readOnlyOrByChild,
|
|
30319
|
-
...remainingProps.basePseudoState
|
|
30320
|
-
}
|
|
30321
|
-
};
|
|
30322
|
-
return jsx(Box, {
|
|
30323
|
-
flex: vertical ? "y" : undefined,
|
|
30324
|
-
alignX: vertical ? "start" : undefined,
|
|
30325
|
-
"data-vertical": vertical ? "" : undefined,
|
|
30326
|
-
...fieldProps
|
|
30327
|
-
});
|
|
30328
|
-
};
|
|
30329
|
-
const FieldPseudoClasses = [":hover", ":active", ":focus", ":focus-visible", ":read-only", ":disabled", ":-navi-loading"];
|
|
30330
|
-
const Label = props => {
|
|
30331
|
-
const {
|
|
30332
|
-
children,
|
|
30333
|
-
htmlFor,
|
|
30334
|
-
...rest
|
|
30335
|
-
} = props;
|
|
30336
|
-
const controlToInterface = useContext(ControlToInterfaceContext);
|
|
30337
|
-
const fieldId = controlToInterface?.id;
|
|
30338
|
-
return jsx(Box, {
|
|
30339
|
-
as: "label",
|
|
30340
|
-
htmlFor: htmlFor || fieldId,
|
|
30341
|
-
baseClassName: "navi_label",
|
|
30342
|
-
pseudoClasses: LabelPseudoClasses,
|
|
30343
|
-
...rest,
|
|
30344
|
-
children: children
|
|
30345
|
-
});
|
|
30346
|
-
};
|
|
30347
|
-
const LabelPseudoClasses = [":hover", ":active", ":focus", ":focus-visible", ":read-only", ":disabled", ":-navi-loading"];
|
|
30348
|
-
|
|
30349
|
-
const InputTextualContext = createContext(null);
|
|
30350
|
-
|
|
30351
|
-
const InputLeftSlot = props => {
|
|
30352
|
-
return jsx(InputSlot, {
|
|
30353
|
-
...props,
|
|
30354
|
-
side: "left"
|
|
30355
|
-
});
|
|
30356
|
-
};
|
|
30357
|
-
const InputRightSlot = props => {
|
|
30358
|
-
return jsx(InputSlot, {
|
|
30359
|
-
...props,
|
|
30360
|
-
side: "right"
|
|
30361
|
-
});
|
|
30362
|
-
};
|
|
30363
|
-
const InputIconSlot = ({
|
|
30364
|
-
children,
|
|
30365
|
-
side = "right",
|
|
30366
|
-
...props
|
|
30367
|
-
}) => {
|
|
30368
|
-
return jsx(InputSlot, {
|
|
30369
|
-
side: side,
|
|
30370
|
-
children: jsx(Icon, {
|
|
30371
|
-
...props,
|
|
30372
|
-
children: children
|
|
30373
|
-
})
|
|
30374
|
-
});
|
|
30375
|
-
};
|
|
30376
|
-
const InputUnitSlot = ({
|
|
30377
|
-
children,
|
|
30378
|
-
side = "right",
|
|
30379
|
-
...props
|
|
30380
|
-
}) => {
|
|
30381
|
-
return jsx(InputSlot, {
|
|
30382
|
-
side: side,
|
|
30383
|
-
marginLeft: "xxs",
|
|
30384
|
-
noWrap: true,
|
|
30385
|
-
...props,
|
|
30386
|
-
children: children
|
|
30387
|
-
});
|
|
30388
|
-
};
|
|
30389
|
-
const InputSlot = ({
|
|
30390
|
-
side,
|
|
30391
|
-
onClick,
|
|
30392
|
-
hideWhileEmpty,
|
|
30393
|
-
...props
|
|
30394
|
-
}) => {
|
|
30395
|
-
const ctx = useContext(InputTextualContext);
|
|
30396
|
-
const {
|
|
30397
|
-
id,
|
|
30398
|
-
readOnly,
|
|
30399
|
-
disabled
|
|
30400
|
-
} = ctx;
|
|
30401
|
-
return jsx(Label, {
|
|
30402
|
-
htmlFor: id,
|
|
30403
|
-
className: "navi_input_slot",
|
|
30404
|
-
disabled: disabled,
|
|
30405
|
-
readOnly: readOnly,
|
|
30406
|
-
"data-readonly": readOnly,
|
|
30407
|
-
"data-disabled": disabled,
|
|
30408
|
-
"data-left": side === "left" ? "" : undefined,
|
|
30409
|
-
"data-right": side === "right" ? "" : undefined,
|
|
30410
|
-
"data-hide-while-empty": hideWhileEmpty ? "" : undefined,
|
|
30411
|
-
inline: true,
|
|
30412
|
-
flex: true,
|
|
30413
|
-
align: "center",
|
|
30414
|
-
onMouseDown: e => {
|
|
30415
|
-
// Only prevent focus from leaving when the input already has focus.
|
|
30416
|
-
// If the input is not focused, let the mousedown proceed normally so
|
|
30417
|
-
// the slot element (e.g. a clear button) can receive focus itself.
|
|
30418
|
-
const inputEl = document.getElementById(id);
|
|
30419
|
-
if (inputEl && inputEl === document.activeElement) {
|
|
30420
|
-
e.preventDefault();
|
|
30421
|
-
}
|
|
30422
|
-
},
|
|
30423
|
-
onClick: e => {
|
|
30424
|
-
onClick?.(e);
|
|
30425
|
-
const input = document.getElementById(id);
|
|
30426
|
-
const allowed = dispatchRequestInteraction(input, e);
|
|
30427
|
-
if (!allowed) {
|
|
30428
|
-
e.preventDefault();
|
|
30429
|
-
}
|
|
30430
|
-
},
|
|
30431
|
-
...props
|
|
30432
|
-
});
|
|
30433
|
-
};
|
|
30434
|
-
|
|
30435
30535
|
const InputNaviHourResolver = props => {
|
|
30436
30536
|
const Next = useNextResolver();
|
|
30437
30537
|
if (props["navi-input-type"] === "hour") {
|
|
@@ -30523,39 +30623,72 @@ const InputModeNumeric = props => {
|
|
|
30523
30623
|
return jsx(Next, {
|
|
30524
30624
|
maxLength: maxLength,
|
|
30525
30625
|
...props,
|
|
30526
|
-
|
|
30527
|
-
props.
|
|
30626
|
+
onInput: e => {
|
|
30627
|
+
props.onInput?.(e);
|
|
30528
30628
|
if (e.defaultPrevented) {
|
|
30529
30629
|
return;
|
|
30530
30630
|
}
|
|
30531
|
-
if (
|
|
30631
|
+
if (maxLength === undefined) {
|
|
30532
30632
|
return;
|
|
30533
30633
|
}
|
|
30534
|
-
e.
|
|
30535
|
-
|
|
30536
|
-
if (Number.isNaN(currentValue)) {
|
|
30634
|
+
const input = e.currentTarget;
|
|
30635
|
+
if (input.value.length < maxLength) {
|
|
30537
30636
|
return;
|
|
30538
30637
|
}
|
|
30539
|
-
|
|
30540
|
-
|
|
30541
|
-
const stepBase = min !== undefined ? min : 0;
|
|
30542
|
-
const offset = currentValue - stepBase;
|
|
30543
|
-
const currentStepIndex = Math.round(offset / step);
|
|
30544
|
-
const snapped = stepBase + currentStepIndex * step;
|
|
30545
|
-
let nextValue = snapped + delta;
|
|
30546
|
-
if (min !== undefined && nextValue < min) {
|
|
30547
|
-
nextValue = min;
|
|
30548
|
-
}
|
|
30549
|
-
if (max !== undefined && nextValue > max) {
|
|
30550
|
-
nextValue = max;
|
|
30638
|
+
if (input.selectionStart !== maxLength) {
|
|
30639
|
+
return;
|
|
30551
30640
|
}
|
|
30552
|
-
|
|
30553
|
-
|
|
30554
|
-
|
|
30641
|
+
// Field is full and caret is at the end: notify listeners then
|
|
30642
|
+
// select all so the next keystroke starts a fresh value instead of
|
|
30643
|
+
// being silently blocked by maxlength.
|
|
30644
|
+
const allowed = dispatchPublicCustomEvent(input, "navi_input_full", {
|
|
30645
|
+
event: e
|
|
30555
30646
|
});
|
|
30647
|
+
if (allowed) {
|
|
30648
|
+
input.select();
|
|
30649
|
+
}
|
|
30650
|
+
},
|
|
30651
|
+
onKeyDown: e => {
|
|
30652
|
+
props.onKeyDown?.(e);
|
|
30653
|
+
if (e.defaultPrevented) {
|
|
30654
|
+
return;
|
|
30655
|
+
}
|
|
30656
|
+
if (e.key === "ArrowUp" || e.key === "ArrowDown") {
|
|
30657
|
+
performArrowUpDown(e);
|
|
30658
|
+
return;
|
|
30659
|
+
}
|
|
30556
30660
|
}
|
|
30557
30661
|
});
|
|
30558
30662
|
};
|
|
30663
|
+
const performArrowUpDown = e => {
|
|
30664
|
+
const input = e.currentTarget;
|
|
30665
|
+
const currentValue = Number(input.value);
|
|
30666
|
+
if (Number.isNaN(currentValue)) {
|
|
30667
|
+
e.preventDefault();
|
|
30668
|
+
return;
|
|
30669
|
+
}
|
|
30670
|
+
const min = input.min !== "" ? Number(input.min) : undefined;
|
|
30671
|
+
const max = input.max !== "" ? Number(input.max) : undefined;
|
|
30672
|
+
const step = input.step !== "" && input.step !== "any" ? Number(input.step) : 1;
|
|
30673
|
+
const delta = e.key === "ArrowUp" ? step : -step;
|
|
30674
|
+
// Snap to step grid relative to step base (min ?? 0), then move
|
|
30675
|
+
const stepBase = min !== undefined ? min : 0;
|
|
30676
|
+
const offset = currentValue - stepBase;
|
|
30677
|
+
const currentStepIndex = Math.round(offset / step);
|
|
30678
|
+
const snapped = stepBase + currentStepIndex * step;
|
|
30679
|
+
let nextValue = snapped + delta;
|
|
30680
|
+
if (min !== undefined && nextValue < min) {
|
|
30681
|
+
nextValue = min;
|
|
30682
|
+
}
|
|
30683
|
+
if (max !== undefined && nextValue > max) {
|
|
30684
|
+
nextValue = max;
|
|
30685
|
+
}
|
|
30686
|
+
triggerStringAction("update", nextValue, {
|
|
30687
|
+
event: e,
|
|
30688
|
+
actionTarget: e.currentTarget
|
|
30689
|
+
});
|
|
30690
|
+
e.preventDefault();
|
|
30691
|
+
};
|
|
30559
30692
|
|
|
30560
30693
|
const SearchSvg = () => jsx("svg", {
|
|
30561
30694
|
viewBox: "0 0 24 24",
|
|
@@ -31071,12 +31204,8 @@ const css$w = /* css */`
|
|
|
31071
31204
|
var(--border-color) 45%,
|
|
31072
31205
|
transparent
|
|
31073
31206
|
);
|
|
31074
|
-
--background-color-readonly: var(--background-color);
|
|
31075
|
-
--color-readonly: color-mix(
|
|
31076
|
-
in srgb,
|
|
31077
|
-
var(--picker-border-color) 45%,
|
|
31078
|
-
transparent
|
|
31079
|
-
);
|
|
31207
|
+
--background-color-readonly: var(--background-color-hover);
|
|
31208
|
+
--color-readonly: color-mix(in srgb, var(--color) 65%, transparent);
|
|
31080
31209
|
/* Disabled */
|
|
31081
31210
|
--border-color-disabled: var(--border-color-readonly);
|
|
31082
31211
|
--background-color-disabled: color-mix(
|
|
@@ -31241,6 +31370,49 @@ const css$w = /* css */`
|
|
|
31241
31370
|
--x-background-color: transparent;
|
|
31242
31371
|
}
|
|
31243
31372
|
}
|
|
31373
|
+
|
|
31374
|
+
&[data-variant="underline"] {
|
|
31375
|
+
border: none;
|
|
31376
|
+
border-radius: 0;
|
|
31377
|
+
--x-background-color: transparent;
|
|
31378
|
+
padding-right: 0;
|
|
31379
|
+
padding-left: 0;
|
|
31380
|
+
|
|
31381
|
+
.navi_input_real_input_wrapper {
|
|
31382
|
+
position: relative;
|
|
31383
|
+
display: inline-flex;
|
|
31384
|
+
flex-grow: 1;
|
|
31385
|
+
}
|
|
31386
|
+
|
|
31387
|
+
.navi_input_underline {
|
|
31388
|
+
position: absolute;
|
|
31389
|
+
top: calc(100% - 1px);
|
|
31390
|
+
right: 0;
|
|
31391
|
+
left: 0;
|
|
31392
|
+
height: 1px;
|
|
31393
|
+
background-color: var(--x-border-color);
|
|
31394
|
+
pointer-events: none;
|
|
31395
|
+
}
|
|
31396
|
+
|
|
31397
|
+
&[data-hover] {
|
|
31398
|
+
--x-background-color: transparent;
|
|
31399
|
+
}
|
|
31400
|
+
&[data-focus-visible] {
|
|
31401
|
+
--x-background-color: transparent;
|
|
31402
|
+
outline-style: none;
|
|
31403
|
+
|
|
31404
|
+
.navi_input_underline {
|
|
31405
|
+
height: 2px;
|
|
31406
|
+
background-color: var(--outline-color);
|
|
31407
|
+
}
|
|
31408
|
+
}
|
|
31409
|
+
&[data-readonly] {
|
|
31410
|
+
--x-background-color: transparent;
|
|
31411
|
+
}
|
|
31412
|
+
&[data-disabled] {
|
|
31413
|
+
--x-background-color: transparent;
|
|
31414
|
+
}
|
|
31415
|
+
}
|
|
31244
31416
|
}
|
|
31245
31417
|
|
|
31246
31418
|
.navi_input .navi_control_input::placeholder {
|
|
@@ -31284,6 +31456,7 @@ const InputTextualUI = props => {
|
|
|
31284
31456
|
const {
|
|
31285
31457
|
ui,
|
|
31286
31458
|
discrete,
|
|
31459
|
+
variant,
|
|
31287
31460
|
width = "maxLength"
|
|
31288
31461
|
} = props;
|
|
31289
31462
|
const [inputProps, remainingProps] = useInputTextualProps(props);
|
|
@@ -31337,6 +31510,7 @@ const InputTextualUI = props => {
|
|
|
31337
31510
|
discrete: undefined // handled via data attribute
|
|
31338
31511
|
,
|
|
31339
31512
|
|
|
31513
|
+
"data-variant": variant || undefined,
|
|
31340
31514
|
styleCSSVars: InputStyleCSSVars,
|
|
31341
31515
|
pseudoStateSelector: ".navi_control_input",
|
|
31342
31516
|
pseudoClasses: InputPseudoClasses,
|
|
@@ -31345,7 +31519,14 @@ const InputTextualUI = props => {
|
|
|
31345
31519
|
loading: loading,
|
|
31346
31520
|
color: "var(--loader-color)",
|
|
31347
31521
|
inset: -1
|
|
31348
|
-
}),
|
|
31522
|
+
}), variant === "underline" ? jsxs("span", {
|
|
31523
|
+
className: "navi_input_real_input_wrapper",
|
|
31524
|
+
children: [jsx(RealInput, {
|
|
31525
|
+
...inputProps
|
|
31526
|
+
}), jsx("span", {
|
|
31527
|
+
className: "navi_input_underline"
|
|
31528
|
+
})]
|
|
31529
|
+
}) : jsx(RealInput, {
|
|
31349
31530
|
...inputProps
|
|
31350
31531
|
}), childrenWithContext]
|
|
31351
31532
|
});
|
|
@@ -31437,7 +31618,9 @@ const Input = props => {
|
|
|
31437
31618
|
};
|
|
31438
31619
|
Input.UI = {
|
|
31439
31620
|
LeftSlot: InputLeftSlot,
|
|
31440
|
-
RightSlot: InputRightSlot
|
|
31621
|
+
RightSlot: InputRightSlot,
|
|
31622
|
+
IconSlot: InputIconSlot,
|
|
31623
|
+
UnitSlot: InputUnitSlot
|
|
31441
31624
|
};
|
|
31442
31625
|
|
|
31443
31626
|
installImportMetaCssBuild(import.meta);/**
|
|
@@ -31963,6 +32146,111 @@ const CheckboxGroupInterface = props => {
|
|
|
31963
32146
|
});
|
|
31964
32147
|
};
|
|
31965
32148
|
|
|
32149
|
+
const InputGroup = props => {
|
|
32150
|
+
const ref = useRef(null);
|
|
32151
|
+
useInputGroup(ref);
|
|
32152
|
+
return jsx(Box, {
|
|
32153
|
+
ref: ref,
|
|
32154
|
+
...props
|
|
32155
|
+
});
|
|
32156
|
+
};
|
|
32157
|
+
const useInputGroup = ref => {
|
|
32158
|
+
const debugFocus = useDebugFocus();
|
|
32159
|
+
useEffect(() => {
|
|
32160
|
+
const el = ref.current;
|
|
32161
|
+
if (!el) {
|
|
32162
|
+
return () => {};
|
|
32163
|
+
}
|
|
32164
|
+
const getInputs = () => Array.from(el.querySelectorAll(".navi_control_input"));
|
|
32165
|
+
const focusInput = input => {
|
|
32166
|
+
input.focus();
|
|
32167
|
+
input.select();
|
|
32168
|
+
};
|
|
32169
|
+
const handleKeyDown = e => {
|
|
32170
|
+
if (e.key !== "ArrowRight" && e.key !== "ArrowLeft") {
|
|
32171
|
+
return;
|
|
32172
|
+
}
|
|
32173
|
+
const active = document.activeElement;
|
|
32174
|
+
if (!isTextInputElement(active) || !el.contains(active)) {
|
|
32175
|
+
return;
|
|
32176
|
+
}
|
|
32177
|
+
if (e.key === "ArrowRight") {
|
|
32178
|
+
const atEnd = active.selectionStart === active.value.length && active.selectionEnd === active.value.length;
|
|
32179
|
+
if (!atEnd) {
|
|
32180
|
+
return;
|
|
32181
|
+
}
|
|
32182
|
+
const inputs = getInputs();
|
|
32183
|
+
const idx = inputs.indexOf(active);
|
|
32184
|
+
if (idx === -1) {
|
|
32185
|
+
debugFocus(e, "InputGroup ArrowRight on non group input → do nothing");
|
|
32186
|
+
return;
|
|
32187
|
+
}
|
|
32188
|
+
if (idx === inputs.length - 1) {
|
|
32189
|
+
debugFocus(e, "InputGroup ArrowRight at end of last input → do nothing");
|
|
32190
|
+
return;
|
|
32191
|
+
}
|
|
32192
|
+
debugFocus(e, "InputGroup ArrowRight at end of input[%d] → focus input[%d]", idx, idx + 1);
|
|
32193
|
+
e.preventDefault();
|
|
32194
|
+
focusInput(inputs[idx + 1]);
|
|
32195
|
+
return;
|
|
32196
|
+
}
|
|
32197
|
+
const atStart = active.selectionStart === 0 && active.selectionEnd === 0;
|
|
32198
|
+
if (!atStart) {
|
|
32199
|
+
return;
|
|
32200
|
+
}
|
|
32201
|
+
const inputs = getInputs();
|
|
32202
|
+
const idx = inputs.indexOf(active);
|
|
32203
|
+
if (idx === 0) {
|
|
32204
|
+
return;
|
|
32205
|
+
}
|
|
32206
|
+
debugFocus(e, "InputGroup ArrowLeft at start of input[%d] → focus input[%d]", idx, idx - 1);
|
|
32207
|
+
e.preventDefault();
|
|
32208
|
+
focusInput(inputs[idx - 1]);
|
|
32209
|
+
};
|
|
32210
|
+
const handleNaviInputFull = e => {
|
|
32211
|
+
const input = e.detail.event.currentTarget;
|
|
32212
|
+
if (!el.contains(input)) {
|
|
32213
|
+
return;
|
|
32214
|
+
}
|
|
32215
|
+
const inputs = getInputs();
|
|
32216
|
+
const idx = inputs.indexOf(input);
|
|
32217
|
+
if (idx === -1) {
|
|
32218
|
+
return;
|
|
32219
|
+
}
|
|
32220
|
+
if (idx === inputs.length - 1) {
|
|
32221
|
+
return;
|
|
32222
|
+
}
|
|
32223
|
+
const nextInput = inputs[idx + 1];
|
|
32224
|
+
debugFocus(e, "InputGroup navi_input_full on input -> move to next input", input, nextInput);
|
|
32225
|
+
e.preventDefault();
|
|
32226
|
+
focusInput(nextInput);
|
|
32227
|
+
};
|
|
32228
|
+
el.addEventListener("keydown", handleKeyDown, {
|
|
32229
|
+
capture: false
|
|
32230
|
+
});
|
|
32231
|
+
el.addEventListener("navi_input_full", handleNaviInputFull);
|
|
32232
|
+
return () => {
|
|
32233
|
+
el.removeEventListener("keydown", handleKeyDown, {
|
|
32234
|
+
capture: false
|
|
32235
|
+
});
|
|
32236
|
+
el.removeEventListener("navi_input_full", handleNaviInputFull);
|
|
32237
|
+
};
|
|
32238
|
+
}, [debugFocus]);
|
|
32239
|
+
};
|
|
32240
|
+
const isTextInputElement = el => {
|
|
32241
|
+
if (!el) {
|
|
32242
|
+
return false;
|
|
32243
|
+
}
|
|
32244
|
+
if (el.tagName === "TEXTAREA") {
|
|
32245
|
+
return true;
|
|
32246
|
+
}
|
|
32247
|
+
if (el.tagName !== "INPUT") {
|
|
32248
|
+
return false;
|
|
32249
|
+
}
|
|
32250
|
+
const type = el.type || "text";
|
|
32251
|
+
return type === "text" || type === "search" || type === "url" || type === "tel" || type === "email" || type === "password" || type === "number";
|
|
32252
|
+
};
|
|
32253
|
+
|
|
31966
32254
|
installImportMetaCssBuild(import.meta);const css$s = /* css */`
|
|
31967
32255
|
.navi_radio_group {
|
|
31968
32256
|
border-style: solid;
|
|
@@ -33144,6 +33432,7 @@ const TimeDate = ({
|
|
|
33144
33432
|
children,
|
|
33145
33433
|
locale,
|
|
33146
33434
|
long,
|
|
33435
|
+
numeric,
|
|
33147
33436
|
dayLabel,
|
|
33148
33437
|
now,
|
|
33149
33438
|
...props
|
|
@@ -33169,7 +33458,8 @@ const TimeDate = ({
|
|
|
33169
33458
|
});
|
|
33170
33459
|
}
|
|
33171
33460
|
const base = formatDay(date, lang, {
|
|
33172
|
-
long
|
|
33461
|
+
long,
|
|
33462
|
+
numeric
|
|
33173
33463
|
});
|
|
33174
33464
|
let text;
|
|
33175
33465
|
if (dayLabel) {
|
|
@@ -33474,7 +33764,7 @@ const PickerText = props => {
|
|
|
33474
33764
|
const PickerArray = props => {
|
|
33475
33765
|
const Next = useNextResolver();
|
|
33476
33766
|
return jsx(Next, {
|
|
33477
|
-
|
|
33767
|
+
maxLines: "3",
|
|
33478
33768
|
ui: jsx(PickerArrayUI, {}),
|
|
33479
33769
|
...props,
|
|
33480
33770
|
type: "navi_picker"
|
|
@@ -33484,7 +33774,7 @@ const PickerArrayUI = () => {
|
|
|
33484
33774
|
const {
|
|
33485
33775
|
value,
|
|
33486
33776
|
placeholder,
|
|
33487
|
-
|
|
33777
|
+
maxLines
|
|
33488
33778
|
} = useContext(PickerContext);
|
|
33489
33779
|
if (!value || value.length === 0) {
|
|
33490
33780
|
if (!placeholder) {
|
|
@@ -33495,8 +33785,7 @@ const PickerArrayUI = () => {
|
|
|
33495
33785
|
return jsx(Text, {
|
|
33496
33786
|
spacing: ", ",
|
|
33497
33787
|
shrinkWrap: true,
|
|
33498
|
-
|
|
33499
|
-
overflowEllipsis: maxRows === 1 ? true : undefined,
|
|
33788
|
+
maxLines: maxLines,
|
|
33500
33789
|
children: value.map(item => {
|
|
33501
33790
|
return jsx("span", {
|
|
33502
33791
|
children: item
|
|
@@ -33547,6 +33836,8 @@ const PickerDateUI = props => {
|
|
|
33547
33836
|
return jsx(Time, {
|
|
33548
33837
|
type: "date",
|
|
33549
33838
|
color: "var(--picker-placeholder-color",
|
|
33839
|
+
capitalize: true,
|
|
33840
|
+
maxLines: "1",
|
|
33550
33841
|
...props
|
|
33551
33842
|
});
|
|
33552
33843
|
}
|
|
@@ -33555,6 +33846,7 @@ const PickerDateUI = props => {
|
|
|
33555
33846
|
return jsx(Time, {
|
|
33556
33847
|
type: "date",
|
|
33557
33848
|
capitalize: true,
|
|
33849
|
+
maxLines: "1",
|
|
33558
33850
|
...props,
|
|
33559
33851
|
children: value
|
|
33560
33852
|
});
|
|
@@ -33568,7 +33860,7 @@ const PickerMonth = props => {
|
|
|
33568
33860
|
type: "month"
|
|
33569
33861
|
});
|
|
33570
33862
|
};
|
|
33571
|
-
const PickerMonthUI =
|
|
33863
|
+
const PickerMonthUI = props => {
|
|
33572
33864
|
const {
|
|
33573
33865
|
value,
|
|
33574
33866
|
placeholder
|
|
@@ -33577,14 +33869,18 @@ const PickerMonthUI = () => {
|
|
|
33577
33869
|
if (!placeholder) {
|
|
33578
33870
|
return jsx(Time, {
|
|
33579
33871
|
type: "month",
|
|
33580
|
-
color: "var(--picker-placeholder-color"
|
|
33872
|
+
color: "var(--picker-placeholder-color",
|
|
33873
|
+
maxLines: "1",
|
|
33874
|
+
...props
|
|
33581
33875
|
});
|
|
33582
33876
|
}
|
|
33583
33877
|
return placeholder;
|
|
33584
33878
|
}
|
|
33585
33879
|
return jsx(Time, {
|
|
33586
33880
|
type: "month",
|
|
33881
|
+
maxLines: "1",
|
|
33587
33882
|
capitalize: true,
|
|
33883
|
+
...props,
|
|
33588
33884
|
children: value
|
|
33589
33885
|
});
|
|
33590
33886
|
};
|
|
@@ -33597,7 +33893,7 @@ const PickerWeek = props => {
|
|
|
33597
33893
|
type: "week"
|
|
33598
33894
|
});
|
|
33599
33895
|
};
|
|
33600
|
-
const PickerWeekUI =
|
|
33896
|
+
const PickerWeekUI = props => {
|
|
33601
33897
|
const {
|
|
33602
33898
|
value,
|
|
33603
33899
|
placeholder
|
|
@@ -33606,7 +33902,9 @@ const PickerWeekUI = () => {
|
|
|
33606
33902
|
if (!placeholder) {
|
|
33607
33903
|
return jsx(Time, {
|
|
33608
33904
|
type: "week",
|
|
33609
|
-
color: "var(--picker-placeholder-color"
|
|
33905
|
+
color: "var(--picker-placeholder-color",
|
|
33906
|
+
maxLines: "1",
|
|
33907
|
+
...props
|
|
33610
33908
|
});
|
|
33611
33909
|
}
|
|
33612
33910
|
return placeholder;
|
|
@@ -33614,6 +33912,8 @@ const PickerWeekUI = () => {
|
|
|
33614
33912
|
return jsx(Time, {
|
|
33615
33913
|
type: "week",
|
|
33616
33914
|
capitalize: true,
|
|
33915
|
+
maxLines: "1",
|
|
33916
|
+
...props,
|
|
33617
33917
|
children: value
|
|
33618
33918
|
});
|
|
33619
33919
|
};
|
|
@@ -33636,6 +33936,7 @@ const PickerTimeUI = props => {
|
|
|
33636
33936
|
return jsx(Time, {
|
|
33637
33937
|
type: "time",
|
|
33638
33938
|
color: "var(--picker-placeholder-color",
|
|
33939
|
+
maxLines: "1",
|
|
33639
33940
|
...props
|
|
33640
33941
|
});
|
|
33641
33942
|
}
|
|
@@ -33643,6 +33944,7 @@ const PickerTimeUI = props => {
|
|
|
33643
33944
|
}
|
|
33644
33945
|
return jsx(Time, {
|
|
33645
33946
|
type: "time",
|
|
33947
|
+
maxLines: "1",
|
|
33646
33948
|
...props,
|
|
33647
33949
|
children: value
|
|
33648
33950
|
});
|
|
@@ -33656,7 +33958,7 @@ const PickerDatetime = props => {
|
|
|
33656
33958
|
type: "datetime-local"
|
|
33657
33959
|
});
|
|
33658
33960
|
};
|
|
33659
|
-
const PickerDatetimeUI =
|
|
33961
|
+
const PickerDatetimeUI = props => {
|
|
33660
33962
|
const {
|
|
33661
33963
|
value,
|
|
33662
33964
|
placeholder
|
|
@@ -33665,13 +33967,16 @@ const PickerDatetimeUI = () => {
|
|
|
33665
33967
|
if (!placeholder) {
|
|
33666
33968
|
return jsx(Time, {
|
|
33667
33969
|
type: "datetime",
|
|
33668
|
-
color: "var(--picker-placeholder-color"
|
|
33970
|
+
color: "var(--picker-placeholder-color",
|
|
33971
|
+
maxLines: "1",
|
|
33972
|
+
...props
|
|
33669
33973
|
});
|
|
33670
33974
|
}
|
|
33671
33975
|
return placeholder;
|
|
33672
33976
|
}
|
|
33673
33977
|
return jsx(Time, {
|
|
33674
33978
|
type: "datetime",
|
|
33979
|
+
maxLines: "1",
|
|
33675
33980
|
children: value
|
|
33676
33981
|
});
|
|
33677
33982
|
};
|
|
@@ -34298,15 +34603,18 @@ installImportMetaCssBuild(import.meta);const css$m = /* css */`
|
|
|
34298
34603
|
&[data-callout] {
|
|
34299
34604
|
--x-list-border-color: var(--callout-color);
|
|
34300
34605
|
}
|
|
34606
|
+
|
|
34607
|
+
.navi_list_item {
|
|
34608
|
+
--x-list-item-cursor: default;
|
|
34609
|
+
--x-list-item-border-color: var(--list-item-border-color);
|
|
34610
|
+
|
|
34611
|
+
position: relative;
|
|
34612
|
+
font-size: var(--navi-control-font-size);
|
|
34613
|
+
font-family: var(--navi-control-font-family);
|
|
34614
|
+
}
|
|
34301
34615
|
}
|
|
34302
34616
|
|
|
34303
34617
|
.navi_list_item[navi-selectable] {
|
|
34304
|
-
--x-list-item-cursor: default;
|
|
34305
|
-
--x-list-item-border-color: var(--list-item-border-color);
|
|
34306
|
-
|
|
34307
|
-
position: relative;
|
|
34308
|
-
font-size: var(--navi-control-font-size);
|
|
34309
|
-
font-family: var(--navi-control-font-family);
|
|
34310
34618
|
outline-width: var(--list-item-outline-width);
|
|
34311
34619
|
outline-color: var(--list-item-outline-color);
|
|
34312
34620
|
outline-offset: var(--list-item-outline-offset);
|
|
@@ -34380,7 +34688,7 @@ installImportMetaCssBuild(import.meta);const css$m = /* css */`
|
|
|
34380
34688
|
}
|
|
34381
34689
|
|
|
34382
34690
|
input,
|
|
34383
|
-
.
|
|
34691
|
+
.navi_picker_content {
|
|
34384
34692
|
color: revert;
|
|
34385
34693
|
}
|
|
34386
34694
|
}
|
|
@@ -35129,6 +35437,7 @@ const css$l = /* css */`
|
|
|
35129
35437
|
background-color: var(--x-list-item-background-color);
|
|
35130
35438
|
border: var(--x-list-item-border-width) solid
|
|
35131
35439
|
var(--x-list-item-border-color);
|
|
35440
|
+
border-radius: var(--list-item-border-radius, 0px);
|
|
35132
35441
|
/*
|
|
35133
35442
|
CSS impossible d'obtenir un layout qui ferait en gros:
|
|
35134
35443
|
width = max(min(max-content, 100%), unbreakable-content)
|
|
@@ -35138,7 +35447,7 @@ const css$l = /* css */`
|
|
|
35138
35447
|
-> NOPE
|
|
35139
35448
|
- Force overflow hidden + ellipsis
|
|
35140
35449
|
- casse la lisibilité des mots insécables
|
|
35141
|
-
- possible d'optin en utilisant
|
|
35450
|
+
- possible d'optin en utilisant maxLines sur le ListItem
|
|
35142
35451
|
-> Bien mais pas par défaut
|
|
35143
35452
|
- Forcer le retour a la ligne des mot inécables
|
|
35144
35453
|
- Aucun des inconvénient ci dessus
|
|
@@ -36147,6 +36456,8 @@ const ListItemReal = props => {
|
|
|
36147
36456
|
});
|
|
36148
36457
|
};
|
|
36149
36458
|
const LIST_ITEM_STYLE_CSS_VARS = {
|
|
36459
|
+
"borderRadius": "--list-item-border-radius",
|
|
36460
|
+
"borderWidth": "--list-item-border-width",
|
|
36150
36461
|
"padding": "--list-item-padding",
|
|
36151
36462
|
"paddingX": "--list-item-padding-x",
|
|
36152
36463
|
"paddingY": "--list-item-padding-y",
|
|
@@ -36157,7 +36468,6 @@ const LIST_ITEM_STYLE_CSS_VARS = {
|
|
|
36157
36468
|
"color": "--list-item-color",
|
|
36158
36469
|
"backgroundColor": "--list-item-background-color",
|
|
36159
36470
|
"fontWeight": "--list-item-font-weight",
|
|
36160
|
-
"borderWidth": "--list-item-border-width",
|
|
36161
36471
|
"borderColor": "--list-item-border-color",
|
|
36162
36472
|
":-navi-pointed": {
|
|
36163
36473
|
color: "--list-item-color-keyboard-pointed",
|
|
@@ -36537,7 +36847,6 @@ installImportMetaCssBuild(import.meta);const css$k = /* css */`
|
|
|
36537
36847
|
align-self: flex-start;
|
|
36538
36848
|
justify-content: center;
|
|
36539
36849
|
color: var(--x-picker-icon-color);
|
|
36540
|
-
transform: translateX(25%);
|
|
36541
36850
|
}
|
|
36542
36851
|
.navi_picker_input {
|
|
36543
36852
|
position: absolute;
|
|
@@ -36554,13 +36863,17 @@ installImportMetaCssBuild(import.meta);const css$k = /* css */`
|
|
|
36554
36863
|
pointer-events: none;
|
|
36555
36864
|
}
|
|
36556
36865
|
|
|
36866
|
+
.navi_picker_content {
|
|
36867
|
+
display: contents;
|
|
36868
|
+
}
|
|
36869
|
+
|
|
36557
36870
|
&[data-line-clamp] {
|
|
36558
36871
|
overflow-wrap: anywhere;
|
|
36559
36872
|
.navi_picker_value {
|
|
36560
36873
|
display: -webkit-box;
|
|
36561
36874
|
white-space: normal;
|
|
36562
36875
|
-webkit-box-orient: vertical;
|
|
36563
|
-
-webkit-line-clamp: var(--picker-max-
|
|
36876
|
+
-webkit-line-clamp: var(--picker-max-lines);
|
|
36564
36877
|
}
|
|
36565
36878
|
}
|
|
36566
36879
|
|
|
@@ -36594,6 +36907,17 @@ installImportMetaCssBuild(import.meta);const css$k = /* css */`
|
|
|
36594
36907
|
&[data-callout] {
|
|
36595
36908
|
--x-picker-border-color: var(--callout-color);
|
|
36596
36909
|
}
|
|
36910
|
+
|
|
36911
|
+
&[data-variant="icon"] {
|
|
36912
|
+
--x-picker-padding-top: 0;
|
|
36913
|
+
--x-picker-padding-right: 0;
|
|
36914
|
+
--x-picker-padding-bottom: 0;
|
|
36915
|
+
--x-picker-padding-left: 0;
|
|
36916
|
+
--picker-border-width: 0;
|
|
36917
|
+
--x-picker-border-color: transparent;
|
|
36918
|
+
--x-picker-background-color: transparent;
|
|
36919
|
+
--x-picker-icon-color: currentColor;
|
|
36920
|
+
}
|
|
36597
36921
|
}
|
|
36598
36922
|
`;
|
|
36599
36923
|
|
|
@@ -36630,12 +36954,16 @@ installImportMetaCssBuild(import.meta);const css$k = /* css */`
|
|
|
36630
36954
|
*/
|
|
36631
36955
|
const PickerButton = props => {
|
|
36632
36956
|
import.meta.css = [css$k, "@jsenv/navi/src/control/picker/picker.jsx"];
|
|
36957
|
+
if (typeof props.maxLines === "string") {
|
|
36958
|
+
props.maxLines = parseInt(props.maxLines);
|
|
36959
|
+
}
|
|
36633
36960
|
const {
|
|
36634
36961
|
ref,
|
|
36962
|
+
variant,
|
|
36635
36963
|
icon,
|
|
36636
36964
|
placeholder,
|
|
36637
36965
|
ui,
|
|
36638
|
-
|
|
36966
|
+
maxLines
|
|
36639
36967
|
} = props;
|
|
36640
36968
|
const inputRef = useRef(null);
|
|
36641
36969
|
const [inputProps, pickerRemainingProps] = useControlProps({
|
|
@@ -36657,7 +36985,7 @@ const PickerButton = props => {
|
|
|
36657
36985
|
children
|
|
36658
36986
|
} = inputProps;
|
|
36659
36987
|
const loading = basePseudoState[":-navi-loading"];
|
|
36660
|
-
const hasLineClamp =
|
|
36988
|
+
const hasLineClamp = maxLines && maxLines > 1;
|
|
36661
36989
|
return jsxs(Box, {
|
|
36662
36990
|
as: "button",
|
|
36663
36991
|
ref: ref,
|
|
@@ -36667,8 +36995,9 @@ const PickerButton = props => {
|
|
|
36667
36995
|
pseudoClasses: PICKER_BUTTON_PSEUDO_CLASSES,
|
|
36668
36996
|
disabled: disabled,
|
|
36669
36997
|
"data-line-clamp": hasLineClamp ? "" : undefined,
|
|
36998
|
+
"data-variant": variant,
|
|
36670
36999
|
style: {
|
|
36671
|
-
"--picker-max-
|
|
37000
|
+
"--picker-max-lines": maxLines
|
|
36672
37001
|
},
|
|
36673
37002
|
...pickerRemainingProps,
|
|
36674
37003
|
basePseudoState: basePseudoState,
|
|
@@ -36678,9 +37007,10 @@ const PickerButton = props => {
|
|
|
36678
37007
|
,
|
|
36679
37008
|
|
|
36680
37009
|
id: id,
|
|
37010
|
+
variant: undefined,
|
|
36681
37011
|
icon: undefined,
|
|
36682
37012
|
ui: undefined,
|
|
36683
|
-
|
|
37013
|
+
maxLines: undefined,
|
|
36684
37014
|
dayLabel: undefined
|
|
36685
37015
|
// The button is handling the pointer interactions
|
|
36686
37016
|
,
|
|
@@ -36711,14 +37041,14 @@ const PickerButton = props => {
|
|
|
36711
37041
|
onMouseDown: undefined,
|
|
36712
37042
|
onClick: undefined,
|
|
36713
37043
|
onKeyDown: undefined
|
|
36714
|
-
}), jsx(Text, {
|
|
37044
|
+
}), variant === "icon" ? null : jsx(Text, {
|
|
36715
37045
|
className: "navi_picker_value",
|
|
36716
37046
|
"navi-placeholder": value === undefined || value === "" ? "" : undefined,
|
|
36717
37047
|
children: jsx(PickerContext.Provider, {
|
|
36718
37048
|
value: {
|
|
36719
37049
|
value,
|
|
36720
37050
|
placeholder,
|
|
36721
|
-
|
|
37051
|
+
maxLines
|
|
36722
37052
|
},
|
|
36723
37053
|
children: ui === undefined ? jsx(PickerDefaultUI, {}) : ui
|
|
36724
37054
|
})
|
|
@@ -36729,7 +37059,10 @@ const PickerButton = props => {
|
|
|
36729
37059
|
children: icon === undefined ? jsx(ChevronDownSvg, {}) : icon
|
|
36730
37060
|
})
|
|
36731
37061
|
}), jsx(ControlChildrenWrapper, {
|
|
36732
|
-
children:
|
|
37062
|
+
children: jsx("div", {
|
|
37063
|
+
className: "navi_picker_content",
|
|
37064
|
+
children: children
|
|
37065
|
+
})
|
|
36733
37066
|
})]
|
|
36734
37067
|
});
|
|
36735
37068
|
};
|
|
@@ -36809,6 +37142,12 @@ Picker.UI.Datetime = PickerDatetimeUI;
|
|
|
36809
37142
|
Picker.UI.File = PickerFileUI;
|
|
36810
37143
|
Picker.UI.Color = PickerColorUI;
|
|
36811
37144
|
Picker.UI.Multiple = PickerArrayUI;
|
|
37145
|
+
Picker.UI.PencilSvg = PencilSvg;
|
|
37146
|
+
Picker.UI.ChevronDownSvg = ChevronDownSvg;
|
|
37147
|
+
Picker.UI.ClockSvg = ClockSvg;
|
|
37148
|
+
Picker.UI.CalendarSvg = CalendarSvg;
|
|
37149
|
+
Picker.UI.FileSvg = FileSvg;
|
|
37150
|
+
Picker.UI.ColorSvg = ColorSvg;
|
|
36812
37151
|
|
|
36813
37152
|
/**
|
|
36814
37153
|
* applySearch — matches value against searchText.
|
|
@@ -41001,7 +41340,7 @@ const Badge = ({
|
|
|
41001
41340
|
return jsx(Text, {
|
|
41002
41341
|
className: withPropsClassName("navi_badge", className),
|
|
41003
41342
|
bold: true,
|
|
41004
|
-
|
|
41343
|
+
maxLines: 1,
|
|
41005
41344
|
...props,
|
|
41006
41345
|
styleCSSVars: BadgeStyleCSSVars$1,
|
|
41007
41346
|
spacing: jsx("span", {}),
|
|
@@ -41378,7 +41717,6 @@ const BadgeList = ({
|
|
|
41378
41717
|
children,
|
|
41379
41718
|
shrinkWrap = true,
|
|
41380
41719
|
max,
|
|
41381
|
-
maxRows,
|
|
41382
41720
|
...props
|
|
41383
41721
|
}) => {
|
|
41384
41722
|
import.meta.css = [css$9, "@jsenv/navi/src/text/badge_list.jsx"];
|
|
@@ -41442,7 +41780,6 @@ const BadgeList = ({
|
|
|
41442
41780
|
baseClassName: "navi_badge_list",
|
|
41443
41781
|
...sharedProps,
|
|
41444
41782
|
ref: visibleRef,
|
|
41445
|
-
lineClamp: maxRows,
|
|
41446
41783
|
children: [visibleChildren.length ? visibleChildren : fallback, hiddenCount > 0 && jsx(Badge, {
|
|
41447
41784
|
className: "navi_badge_more",
|
|
41448
41785
|
children: naviI18n("badge_list.more", {
|
|
@@ -41831,12 +42168,74 @@ const Interpolate = ({
|
|
|
41831
42168
|
});
|
|
41832
42169
|
};
|
|
41833
42170
|
|
|
42171
|
+
const Unit = ({
|
|
42172
|
+
unit,
|
|
42173
|
+
plural,
|
|
42174
|
+
lang,
|
|
42175
|
+
size = "smaller",
|
|
42176
|
+
sizeRatio,
|
|
42177
|
+
style,
|
|
42178
|
+
...props
|
|
42179
|
+
}) => {
|
|
42180
|
+
let resolvedSize = size;
|
|
42181
|
+
let resolvedStyle = style;
|
|
42182
|
+
if (size === "smaller" || sizeRatio !== undefined) {
|
|
42183
|
+
resolvedSize = undefined;
|
|
42184
|
+
const ratio = sizeRatio !== undefined ? sizeRatio : 0.8;
|
|
42185
|
+
resolvedStyle = {
|
|
42186
|
+
fontSize: `calc(${ratio} * 1em)`,
|
|
42187
|
+
...style
|
|
42188
|
+
};
|
|
42189
|
+
}
|
|
42190
|
+
const isPlural = Boolean(plural);
|
|
42191
|
+
let unitText = unit;
|
|
42192
|
+
const singularText = naviI18n(unit, undefined, {
|
|
42193
|
+
lang
|
|
42194
|
+
});
|
|
42195
|
+
if (singularText !== unit) {
|
|
42196
|
+
// unit is known to naviI18n
|
|
42197
|
+
if (isPlural) {
|
|
42198
|
+
const pluralKey = `${unit}__plural`;
|
|
42199
|
+
const pluralText = naviI18n(pluralKey, undefined, {
|
|
42200
|
+
lang
|
|
42201
|
+
});
|
|
42202
|
+
// fallback to singular if no plural key registered
|
|
42203
|
+
unitText = pluralText !== pluralKey ? pluralText : singularText;
|
|
42204
|
+
} else {
|
|
42205
|
+
unitText = singularText;
|
|
42206
|
+
}
|
|
42207
|
+
} else {
|
|
42208
|
+
// naviI18n has no translation — try Intl.NumberFormat with style:"unit"
|
|
42209
|
+
const intlText = formatIntlUnit(unit, isPlural, lang);
|
|
42210
|
+
if (intlText !== null) {
|
|
42211
|
+
unitText = intlText;
|
|
42212
|
+
}
|
|
42213
|
+
}
|
|
42214
|
+
return jsx(Text, {
|
|
42215
|
+
baseClassName: "navi_unit",
|
|
42216
|
+
size: resolvedSize,
|
|
42217
|
+
style: resolvedStyle,
|
|
42218
|
+
...props,
|
|
42219
|
+
children: unitText
|
|
42220
|
+
});
|
|
42221
|
+
};
|
|
42222
|
+
const formatIntlUnit = (unit, plural, lang) => {
|
|
42223
|
+
try {
|
|
42224
|
+
const count = plural ? 2 : 1;
|
|
42225
|
+
const parts = new Intl.NumberFormat(lang, {
|
|
42226
|
+
style: "unit",
|
|
42227
|
+
unit,
|
|
42228
|
+
unitDisplay: "long"
|
|
42229
|
+
}).formatToParts(count);
|
|
42230
|
+
const unitPart = parts.find(p => p.type === "unit");
|
|
42231
|
+
return unitPart ? unitPart.value : null;
|
|
42232
|
+
} catch {
|
|
42233
|
+
return null;
|
|
42234
|
+
}
|
|
42235
|
+
};
|
|
42236
|
+
|
|
41834
42237
|
installImportMetaCssBuild(import.meta);const css$7 = /* css */`
|
|
41835
42238
|
@layer navi {
|
|
41836
|
-
.navi_quantity {
|
|
41837
|
-
--unit-color: color-mix(in srgb, currentColor 50%, white);
|
|
41838
|
-
--unit-size-ratio: 0.7;
|
|
41839
|
-
}
|
|
41840
42239
|
}
|
|
41841
42240
|
|
|
41842
42241
|
.navi_quantity {
|
|
@@ -41854,10 +42253,8 @@ installImportMetaCssBuild(import.meta);const css$7 = /* css */`
|
|
|
41854
42253
|
letter-spacing: 0.06em;
|
|
41855
42254
|
}
|
|
41856
42255
|
.navi_quantity_body {
|
|
41857
|
-
.
|
|
41858
|
-
color: var(--unit-color);
|
|
42256
|
+
.navi_unit {
|
|
41859
42257
|
font-weight: normal;
|
|
41860
|
-
font-size: calc(var(--unit-size-ratio) * 1em);
|
|
41861
42258
|
}
|
|
41862
42259
|
}
|
|
41863
42260
|
|
|
@@ -41879,7 +42276,7 @@ installImportMetaCssBuild(import.meta);const css$7 = /* css */`
|
|
|
41879
42276
|
text-align: center;
|
|
41880
42277
|
}
|
|
41881
42278
|
.navi_quantity_body {
|
|
41882
|
-
.
|
|
42279
|
+
.navi_unit {
|
|
41883
42280
|
display: inline-block;
|
|
41884
42281
|
width: 100%;
|
|
41885
42282
|
text-align: center;
|
|
@@ -41892,6 +42289,9 @@ const Quantity = ({
|
|
|
41892
42289
|
children,
|
|
41893
42290
|
unit,
|
|
41894
42291
|
unitPosition = "right",
|
|
42292
|
+
unitSize = "smaller",
|
|
42293
|
+
unitSizeRatio,
|
|
42294
|
+
unitColor,
|
|
41895
42295
|
label,
|
|
41896
42296
|
size,
|
|
41897
42297
|
lang,
|
|
@@ -41936,50 +42336,20 @@ const Quantity = ({
|
|
|
41936
42336
|
children: jsx(LoadingDotsSvg, {})
|
|
41937
42337
|
}) : valueFormatted
|
|
41938
42338
|
}), unit && jsx(Unit, {
|
|
41939
|
-
value: value,
|
|
41940
42339
|
unit: unit,
|
|
41941
|
-
|
|
42340
|
+
plural: typeof value === "number" ? value > 1 : false,
|
|
42341
|
+
lang: lang,
|
|
42342
|
+
size: unitSize,
|
|
42343
|
+
sizeRatio: unitSizeRatio,
|
|
42344
|
+
color: unitColor
|
|
41942
42345
|
})]
|
|
41943
42346
|
})]
|
|
41944
42347
|
});
|
|
41945
42348
|
};
|
|
41946
42349
|
const QuantityPropsCSSVars = {
|
|
41947
|
-
unitColor: "--unit-color"
|
|
41948
|
-
unitSizeRatio: "--unit-size-ratio"
|
|
42350
|
+
unitColor: "--unit-color"
|
|
41949
42351
|
};
|
|
41950
42352
|
const QuantityPseudoClasses = [":hover", ":active", ":read-only", ":disabled", ":-navi-loading"];
|
|
41951
|
-
const Unit = ({
|
|
41952
|
-
value,
|
|
41953
|
-
unit,
|
|
41954
|
-
lang
|
|
41955
|
-
}) => {
|
|
41956
|
-
let unitText = unit;
|
|
41957
|
-
if (Array.isArray(unit)) {
|
|
41958
|
-
const [singular, plural] = unit;
|
|
41959
|
-
unitText = value > 1 ? plural : singular;
|
|
41960
|
-
} else {
|
|
41961
|
-
const singularText = naviI18n(unit, undefined, {
|
|
41962
|
-
lang
|
|
41963
|
-
});
|
|
41964
|
-
if (singularText !== unit) {
|
|
41965
|
-
// unit is known to naviI18n
|
|
41966
|
-
if (value > 1) {
|
|
41967
|
-
const pluralKey = `${unit}__plural`;
|
|
41968
|
-
const pluralText = naviI18n(pluralKey, undefined, {
|
|
41969
|
-
lang
|
|
41970
|
-
});
|
|
41971
|
-
// fallback to singular if no plural key registered
|
|
41972
|
-
unitText = pluralText !== pluralKey ? pluralText : singularText;
|
|
41973
|
-
} else {
|
|
41974
|
-
unitText = singularText;
|
|
41975
|
-
}
|
|
41976
|
-
}
|
|
41977
|
-
}
|
|
41978
|
-
return jsx("span", {
|
|
41979
|
-
className: "navi_quantity_unit",
|
|
41980
|
-
children: unitText
|
|
41981
|
-
});
|
|
41982
|
-
};
|
|
41983
42353
|
const parseQuantityValue = children => {
|
|
41984
42354
|
if (typeof children !== "string") {
|
|
41985
42355
|
return children;
|
|
@@ -43027,5 +43397,5 @@ const UserSvg = () => jsx("svg", {
|
|
|
43027
43397
|
})
|
|
43028
43398
|
});
|
|
43029
43399
|
|
|
43030
|
-
export { ActionRenderer, ActiveKeyboardShortcuts, Address, Badge, BadgeCount, BadgeList, Box, Button, ButtonCopyToClipboard, Caption, CheckSvg, CheckboxGroup, CloseSvg, Code, Col, Colgroup, Color, ConstructionSvg, Details, Dialog, DialogLayout, Editable, ErrorBoundary, ErrorBoundaryContext, ExclamationSvg, EyeClosedSvg, EyeSvg, Field, Form, Group, Head, HeartSvg, HomeSvg, Icon, Image, Input, Interpolate, Label, Link, LinkAnchorSvg, LinkBlankTargetSvg, LinkCurrentSvg, List, ListItem, ListItemGroup, Loading, LoadingDotsSvg, LoadingIndicator, LoadingIndicatorFluid, LoadingOutline, MessageBox, Meter, Nav, NaviDebug, Paragraph, Picker, Popover, Quantity, RadioGroup, Route, RowNumberCol, RowNumberTableCell, SVGMaskOverlay, SearchSvg, SelectableInput, SelectionContext, Separator, SettingsSvg, SidePanel, StarSvg, SummaryMarker, Svg, Table, TableCell, Tbody, Text, TextBox, Thead, Time, Title, Tr, UITransition, UserSvg, ViewportLayout, actionIntegratedVia, actionRunEffect, addCustomMessage, anyMatchingRouteSignal, applySearch, arraySignalMembership, compareTwoJsValues, createAction, createAvailableConstraint, createRequestCanceller, createSearch, createSelectionKeyboardShortcuts, enableDebugActions, enableDebugOnDocumentLoading, ensureDocumentStartViewTransition, filterTableSelection, formatDatetime, formatDay, formatDayRelative, formatMonth, formatNumber, formatTime, formatTimeRelative, getNowHours, getNowHoursRoundedToStep, installCustomConstraintValidation, interpolateText, isCellSelected, isColumnSelected, isRowSelected, isToday, langSignal, localStorageSignal, moveArrayItemByIndex, navBack, navForward, navTo, naviI18n, openCallout, rawUrlPart, reload, removeCustomMessage, rerunActions, resource, route, routeAction, setBaseUrl, setupRoutes, stateSignal, stopLoad, stringifyTableSelectionValue, swapArrayItemByIndex, syncOwnedResourceToSignals, syncResourceToSignals, updateActions, useActionStatus, useArraySignalMembership, useAsyncData, useCalloutRequestClose, useCancelPrevious, useCellGridFromRows, useConstraintValidityState, useDependenciesDiff, useDisplayedLayoutEffect, useDocumentResource, useDocumentState, useDocumentUrl, useEditionController, useFocusGroup, useKeyboardShortcuts, useNavState, useOrderedColumns, useRouteStatus, useRunOnMount, useSearchText, useSelectableElement, useSelectionController, useSidePanelClose, useSignalSync, useStateArray, useTitleLevel, useUrlSearchParam, valueInLocalStorage, windowWidthSignal };
|
|
43400
|
+
export { ActionRenderer, ActiveKeyboardShortcuts, Address, Badge, BadgeCount, BadgeList, Box, Button, ButtonCopyToClipboard, Caption, CheckSvg, CheckboxGroup, CloseSvg, Code, Col, Colgroup, Color, ConstructionSvg, Details, Dialog, DialogLayout, Editable, ErrorBoundary, ErrorBoundaryContext, ExclamationSvg, EyeClosedSvg, EyeSvg, Field, Form, Group, Head, HeartSvg, HomeSvg, Icon, Image, Input, InputGroup, Interpolate, Label, Link, LinkAnchorSvg, LinkBlankTargetSvg, LinkCurrentSvg, List, ListItem, ListItemGroup, Loading, LoadingDotsSvg, LoadingIndicator, LoadingIndicatorFluid, LoadingOutline, MessageBox, Meter, Nav, NaviDebug, Paragraph, Picker, Popover, Quantity, RadioGroup, Route, RowNumberCol, RowNumberTableCell, SVGMaskOverlay, SearchSvg, SelectableInput, SelectionContext, Separator, SettingsSvg, SidePanel, StarSvg, SummaryMarker, Svg, Table, TableCell, Tbody, Text, TextBox, Thead, Time, Title, Tr, UITransition, Unit, UserSvg, ViewportLayout, actionIntegratedVia, actionRunEffect, addCustomMessage, anyMatchingRouteSignal, applySearch, arraySignalMembership, compareTwoJsValues, createAction, createAvailableConstraint, createRequestCanceller, createSearch, createSelectionKeyboardShortcuts, enableDebugActions, enableDebugOnDocumentLoading, ensureDocumentStartViewTransition, filterTableSelection, formatDatetime, formatDay, formatDayRelative, formatMonth, formatNumber, formatTime, formatTimeRelative, getNowHours, getNowHoursRoundedToStep, installCustomConstraintValidation, interpolateText, isCellSelected, isColumnSelected, isRowSelected, isToday, langSignal, localStorageSignal, moveArrayItemByIndex, navBack, navForward, navTo, naviI18n, openCallout, rawUrlPart, reload, removeCustomMessage, rerunActions, resource, route, routeAction, setBaseUrl, setupRoutes, stateSignal, stopLoad, stringifyTableSelectionValue, swapArrayItemByIndex, syncOwnedResourceToSignals, syncResourceToSignals, updateActions, useActionStatus, useArraySignalMembership, useAsyncData, useCalloutRequestClose, useCancelPrevious, useCellGridFromRows, useConstraintValidityState, useDependenciesDiff, useDisplayedLayoutEffect, useDocumentResource, useDocumentState, useDocumentUrl, useEditionController, useFocusGroup, useKeyboardShortcuts, useNavState, useOrderedColumns, useRouteStatus, useRunOnMount, useSearchText, useSelectableElement, useSelectionController, useSidePanelClose, useSignalSync, useStateArray, useTitleLevel, useUrlSearchParam, valueInLocalStorage, windowWidthSignal };
|
|
43031
43401
|
//# sourceMappingURL=jsenv_navi.js.map
|