@jsenv/navi 0.29.376 → 0.29.378
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/dev/jsenv_navi.js +82 -14
- package/dist/dev/jsenv_navi.js.map +7 -7
- package/dist/jsenv_navi.js +67 -14
- package/dist/jsenv_navi.js.map +7 -7
- package/docs/AI_INSTRUCTIONS.md +3 -1
- package/docs/typography.md +28 -3
- package/package.json +1 -1
package/dist/dev/jsenv_navi.js
CHANGED
|
@@ -35096,10 +35096,18 @@ registerNaviCommand("--navi-define", (source, event) => {
|
|
|
35096
35096
|
implementation: () => executeNaviDefine(source, event, target),
|
|
35097
35097
|
};
|
|
35098
35098
|
});
|
|
35099
|
+
// A send whose target is the popup itself: what is around the source IS the
|
|
35100
|
+
// popup's answer, and a picker runs its action with that answer as it closes
|
|
35101
|
+
// (see onRequestClose in picker_custom.jsx) — dispatching the action here too
|
|
35102
|
+
// would run it twice. `isSend` tells this close from a dismissal (the cross,
|
|
35103
|
+
// a press outside, Escape): the person pressed a choice, which a picker may
|
|
35104
|
+
// act on even when the choice is the one it already held.
|
|
35099
35105
|
const executeNaviDefine = (source, event, target) => {
|
|
35100
|
-
|
|
35101
|
-
|
|
35102
|
-
|
|
35106
|
+
return dispatchCustomEvent(target, "navi_request_close", {
|
|
35107
|
+
event,
|
|
35108
|
+
source: resolveCommandProxySource(source),
|
|
35109
|
+
isSend: true,
|
|
35110
|
+
});
|
|
35103
35111
|
};
|
|
35104
35112
|
|
|
35105
35113
|
registerNaviCommand("--navi-scroll", (source, event) => {
|
|
@@ -45310,6 +45318,10 @@ time.navi_text {
|
|
|
45310
45318
|
border-radius: inherit;
|
|
45311
45319
|
}
|
|
45312
45320
|
|
|
45321
|
+
&[data-text-clamp] {
|
|
45322
|
+
min-width: 0;
|
|
45323
|
+
}
|
|
45324
|
+
|
|
45313
45325
|
&[data-text-overflow] {
|
|
45314
45326
|
text-overflow: ellipsis;
|
|
45315
45327
|
overflow-wrap: normal;
|
|
@@ -45683,6 +45695,10 @@ const shouldInjectSpacingBetween = (left, right) => {
|
|
|
45683
45695
|
* n lines. This is the only prop to use for that — `Box`'s `lineClamp` /
|
|
45684
45696
|
* `overflowEllipsis` are raw CSS mappings meant for elements that are not a
|
|
45685
45697
|
* `Text`, and `lineClamp={1}` is never the single-line truncation you want.
|
|
45698
|
+
* Either value states the `white-space` it needs — one line does not wrap,
|
|
45699
|
+
* n lines may — so it holds inside a single-line ancestor too (a `Picker`'s
|
|
45700
|
+
* value, a `Time`); an explicit `noWrap`/`pre`/`preLine` on this `Text`
|
|
45701
|
+
* still wins.
|
|
45686
45702
|
* Truncation only happens if the element may become narrower than its
|
|
45687
45703
|
* content: `maxLines` sets `min-width: 0` here, but each `Box` between this
|
|
45688
45704
|
* one and the element that carries the width must set it too.
|
|
@@ -45745,6 +45761,25 @@ const shouldInjectSpacingBetween = (left, right) => {
|
|
|
45745
45761
|
* internally for overlays such as the skeleton container.
|
|
45746
45762
|
*/
|
|
45747
45763
|
const Text = props => {
|
|
45764
|
+
if (props.maxLines > 1) {
|
|
45765
|
+
props = {
|
|
45766
|
+
...props,
|
|
45767
|
+
"data-text-clamp": ""
|
|
45768
|
+
};
|
|
45769
|
+
if (!saysWhiteSpace(props)) {
|
|
45770
|
+
// n lines means "you may wrap". white-space is inherited, so left unsaid
|
|
45771
|
+
// a single-line ancestor (a Picker's value, a Time) leaves the clamp one
|
|
45772
|
+
// line to cut, and the text runs past its box. Same tag rule as
|
|
45773
|
+
// TextOverflow: a paragraph keeps its line breaks.
|
|
45774
|
+
props = props.as === "p" ? {
|
|
45775
|
+
...props,
|
|
45776
|
+
preLine: true
|
|
45777
|
+
} : {
|
|
45778
|
+
...props,
|
|
45779
|
+
noWrap: false
|
|
45780
|
+
};
|
|
45781
|
+
}
|
|
45782
|
+
}
|
|
45748
45783
|
if (props.loading || props.skeleton) {
|
|
45749
45784
|
return jsx(TextSkeleton, {
|
|
45750
45785
|
...props
|
|
@@ -45956,6 +45991,14 @@ const TextOverflow = ({
|
|
|
45956
45991
|
children: children
|
|
45957
45992
|
});
|
|
45958
45993
|
};
|
|
45994
|
+
const saysWhiteSpace = ({
|
|
45995
|
+
noWrap,
|
|
45996
|
+
pre,
|
|
45997
|
+
preWrap,
|
|
45998
|
+
preLine
|
|
45999
|
+
}) => {
|
|
46000
|
+
return noWrap !== undefined || pre !== undefined || preWrap !== undefined || preLine !== undefined;
|
|
46001
|
+
};
|
|
45959
46002
|
const TextWithSelectRange = ({
|
|
45960
46003
|
ref,
|
|
45961
46004
|
selectRange,
|
|
@@ -59993,9 +60036,11 @@ const TimeRelative = ({
|
|
|
59993
60036
|
});
|
|
59994
60037
|
};
|
|
59995
60038
|
const TimeText = props => {
|
|
60039
|
+
// A date stays on one line, unless the caller grants it several.
|
|
60040
|
+
const noWrap = props.maxLines > 1 ? undefined : true;
|
|
59996
60041
|
return jsx(Text, {
|
|
59997
60042
|
as: "time",
|
|
59998
|
-
noWrap:
|
|
60043
|
+
noWrap: noWrap,
|
|
59999
60044
|
...props
|
|
60000
60045
|
});
|
|
60001
60046
|
};
|
|
@@ -66012,6 +66057,9 @@ const PickerCustom = props => {
|
|
|
66012
66057
|
// closed on it. A confirm picker is the one saying something (see
|
|
66013
66058
|
// picker_confirm.jsx): its press, deferred until the question is answered.
|
|
66014
66059
|
onConfirm,
|
|
66060
|
+
// A choice pressed inside the popup runs `action` even when it is the one
|
|
66061
|
+
// the picker already held. See the JSDoc.
|
|
66062
|
+
canSendWhileUnchanged,
|
|
66015
66063
|
// The popup's lifecycle, the same pair Dialog and Popover take. Taken on
|
|
66016
66064
|
// the picker and chained into its own openController below: the picker
|
|
66017
66065
|
// hands the popup that controller, and a controlled Dialog/Popover reads
|
|
@@ -66054,6 +66102,7 @@ const PickerCustom = props => {
|
|
|
66054
66102
|
delete pickerProps.defaultOpen;
|
|
66055
66103
|
delete pickerProps.escapeEffect;
|
|
66056
66104
|
delete pickerProps.onConfirm;
|
|
66105
|
+
delete pickerProps.canSendWhileUnchanged;
|
|
66057
66106
|
delete pickerProps.onOpen;
|
|
66058
66107
|
delete pickerProps.onClose;
|
|
66059
66108
|
delete pickerProps.openOn;
|
|
@@ -66155,8 +66204,17 @@ const PickerCustom = props => {
|
|
|
66155
66204
|
// suggestion to accept, and confirming `undefined` cannot mean
|
|
66156
66205
|
// anything. A picker on a defaultValue is untouched by this: it
|
|
66157
66206
|
// shows something, so closing on it still confirms it.
|
|
66158
|
-
//
|
|
66159
|
-
|
|
66207
|
+
//
|
|
66208
|
+
// Unless the close is a choice PRESSED inside the popup (a row's
|
|
66209
|
+
// `--navi-send`, a `--navi-confirm`) on a picker that asked to
|
|
66210
|
+
// send while unchanged: the person picked what was already picked,
|
|
66211
|
+
// and for that picker the same value said again means something.
|
|
66212
|
+
// A press outside, Escape, the cross say nothing and keep skipping.
|
|
66213
|
+
const said = requestCloseEvent.detail.isSend || confirmEventRef.current;
|
|
66214
|
+
if (!(canSendWhileUnchanged && said)) {
|
|
66215
|
+
// No action to run, but still allow the close.
|
|
66216
|
+
return;
|
|
66217
|
+
}
|
|
66160
66218
|
}
|
|
66161
66219
|
dispatchRequestAction(inputEl, {
|
|
66162
66220
|
event: requestCloseEvent,
|
|
@@ -66350,7 +66408,8 @@ const PickerCustom = props => {
|
|
|
66350
66408
|
intent: "read",
|
|
66351
66409
|
allowed: () => {
|
|
66352
66410
|
const closing = requestClose(e, {
|
|
66353
|
-
isCancel: e.detail.isCancel
|
|
66411
|
+
isCancel: e.detail.isCancel,
|
|
66412
|
+
isSend: e.detail.isSend
|
|
66354
66413
|
});
|
|
66355
66414
|
if (!closing) {
|
|
66356
66415
|
e.preventDefault();
|
|
@@ -76367,6 +76426,12 @@ const PickerFirstResolver = props => {
|
|
|
76367
76426
|
* press, the way a click is the innermost target's. Being a gesture, the open goes through
|
|
76368
76427
|
* the interaction gate as one: a `readOnly` picker refuses it and says so
|
|
76369
76428
|
* where the finger is, whatever `openWhileReadOnly` says.
|
|
76429
|
+
* @param {number} [maxLines=1] How many lines the value may take before it is
|
|
76430
|
+
* cut with an ellipsis — `Text`'s `maxLines`, put on the value box, and
|
|
76431
|
+
* granted to a `BadgeList` in the `ui`, which caps its rows to it (see
|
|
76432
|
+
* max_lines_context.js). `variant="text"` and `variant="bare"` are not
|
|
76433
|
+
* clamped: their drawing is the caller's own, a `Text` in the `ui` cuts
|
|
76434
|
+
* itself with its own `maxLines`. See docs/typography.md.
|
|
76370
76435
|
* @param {import("ignore:preact").ComponentChildren | "default" | import("ignore:preact").ComponentType} [ui] What the
|
|
76371
76436
|
* trigger draws in place of the value's default rendering (a date, a list
|
|
76372
76437
|
* joined by commas…) — and then all it draws: `placeholder` is not shown
|
|
@@ -76606,6 +76671,15 @@ const PickerFirstResolver = props => {
|
|
|
76606
76671
|
* @param {(confirmEvent: CustomEvent) => void} [onConfirm] Called once the
|
|
76607
76672
|
* popup has closed on a `--navi-confirm` said inside it. What a confirm
|
|
76608
76673
|
* picker uses to run its press; a picker of any type may listen too.
|
|
76674
|
+
* @param {boolean} [canSendWhileUnchanged] Run `action` when a choice pressed
|
|
76675
|
+
* inside the popup — a row's `--navi-send`, a `--navi-confirm` — is the
|
|
76676
|
+
* value the picker already held. By default that close runs nothing: the
|
|
76677
|
+
* answer has not moved, so there is nothing new to say, same as `Form`.
|
|
76678
|
+
* Set this for a picker whose value is a setting that can be valid while
|
|
76679
|
+
* what it points to is not — a channel whose account came unlinked — so
|
|
76680
|
+
* picking it again is how the person asks for it to be put right, and the
|
|
76681
|
+
* action sees the same value and re-asks what there is to re-ask. A press
|
|
76682
|
+
* outside, Escape and the cross still send nothing: nothing was pressed.
|
|
76609
76683
|
* @param {(openEvent: CustomEvent) => void} [onOpen] Called when the popup
|
|
76610
76684
|
* opens, whatever asked for it (a press, a command, history bringing it
|
|
76611
76685
|
* back). You most likely do NOT need this pair: "the user validated" is
|
|
@@ -78129,13 +78203,7 @@ const renderDayDefault = (day, {
|
|
|
78129
78203
|
type: "date",
|
|
78130
78204
|
format: format,
|
|
78131
78205
|
dayLabel: true,
|
|
78132
|
-
lang: lang
|
|
78133
|
-
// A Time keeps its date on one line by default; here a day too long for
|
|
78134
|
-
// the box is meant to wrap, so that is undone — except for maxLines={1},
|
|
78135
|
-
// which IS one line and cuts it itself (see Text's own TextOverflow):
|
|
78136
|
-
// saying "you may wrap" there would undo the truncation instead.
|
|
78137
|
-
,
|
|
78138
|
-
noWrap: maxLines === 1 || maxLines === "1" ? undefined : false,
|
|
78206
|
+
lang: lang,
|
|
78139
78207
|
maxLines: maxLines,
|
|
78140
78208
|
children: day
|
|
78141
78209
|
});
|