@jsenv/navi 0.29.388 → 0.29.389
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 +163 -89
- package/dist/dev/jsenv_navi.js.map +18 -18
- package/dist/dev/jsenv_navi_side_effects.js +87 -78
- package/dist/dev/jsenv_navi_side_effects.js.map +4 -4
- package/dist/jsenv_navi.js +162 -88
- package/dist/jsenv_navi.js.map +18 -18
- package/dist/jsenv_navi_side_effects.js +87 -78
- package/dist/jsenv_navi_side_effects.js.map +4 -4
- package/docs/dialog_shape.md +3 -2
- package/docs/drag_interactions.md +5 -5
- package/docs/drag_to_travel.md +3 -1
- package/docs/error_handling.md +5 -3
- package/docs/i18n.md +16 -7
- package/docs/list_refresh.md +5 -4
- package/docs/network_policy.md +12 -4
- package/docs/pan_zoom.md +14 -7
- package/docs/resource.md +8 -4
- package/docs/safe_area.md +28 -24
- package/package.json +2 -2
package/dist/jsenv_navi.js
CHANGED
|
@@ -527,7 +527,10 @@ effect(() => {
|
|
|
527
527
|
* The active language is read from `languagesSignal` (see lang_signal.js —
|
|
528
528
|
* combines the browser's own `navigator.languages`, an optional
|
|
529
529
|
* `setPreferredLanguage()` user override, and an optional
|
|
530
|
-
* `setSupportedLanguages()` app-wide allow-list), live on every lookup.
|
|
530
|
+
* `setSupportedLanguages()` app-wide allow-list), live on every lookup. Each
|
|
531
|
+
* key is looked up in those languages in order, then in English, which
|
|
532
|
+
* translates every key: a language shipped for part of the keys only (German
|
|
533
|
+
* has the `time.*` words) never shows a raw key.
|
|
531
534
|
*
|
|
532
535
|
* Built-in key namespaces, all overridable — the registrations below are the
|
|
533
536
|
* exhaustive list, read them to find the exact key to override:
|
|
@@ -1447,19 +1450,25 @@ const isNetworkPolicyError = (error) => {
|
|
|
1447
1450
|
* is already saying it in words the person understands.
|
|
1448
1451
|
*
|
|
1449
1452
|
* navi's own report leaves it alone (action_error_report.js). What is left is
|
|
1450
|
-
* the
|
|
1451
|
-
*
|
|
1452
|
-
*
|
|
1453
|
-
*
|
|
1454
|
-
* asked. Cancelling the event is what says it is handled: the browser drops
|
|
1453
|
+
* the error reaching `window` on its own — a run called by hand whose failure
|
|
1454
|
+
* nobody catches, a render throw no boundary took — where it lands as an
|
|
1455
|
+
* uncaught error in the console, about a request the app itself declared would
|
|
1456
|
+
* not leave. Cancelling the event is what says it is handled: the browser drops
|
|
1455
1457
|
* the console line, and the jsenv supervisor skips prevented events too.
|
|
1456
1458
|
*
|
|
1457
1459
|
* Both shapes a failure travels in are covered, since which one it is depends
|
|
1458
1460
|
* on whether the resource callback happened to be async — the throw reaching
|
|
1459
1461
|
* `window`, and the rejection nobody caught.
|
|
1460
1462
|
*
|
|
1461
|
-
*
|
|
1462
|
-
*
|
|
1463
|
+
* A boundary displaying it raises no event at all. In dev, `preact/debug` hands
|
|
1464
|
+
* every error a boundary caught to `console.error`, after the boundary took it
|
|
1465
|
+
* and before it rendered anything; it reads no option and no flag, so that line
|
|
1466
|
+
* stays. Muting it from here is not done: wrapping `console.error` rewrites a
|
|
1467
|
+
* global, and wrapping `options._catchError` reaches into preact's private
|
|
1468
|
+
* hooks, both to hide one class of error.
|
|
1469
|
+
*
|
|
1470
|
+
* Scoped to the policy's own error and to nothing else — every other error
|
|
1471
|
+
* thrown at window, and every other rejection let go, stays exactly as loud as
|
|
1463
1472
|
* it is.
|
|
1464
1473
|
*/
|
|
1465
1474
|
let networkPolicyErrorSilenced = false;
|
|
@@ -1620,8 +1629,8 @@ const markErrorAsStoppingRender = (error) => {
|
|
|
1620
1629
|
* An error the network policy produced is never reported: the app declared the
|
|
1621
1630
|
* state that produced it, the request never left, and there is nothing for a
|
|
1622
1631
|
* developer to fix. It is data a screen shows, and it stays data whether or not
|
|
1623
|
-
* one does (see network_policy.js, which also
|
|
1624
|
-
*
|
|
1632
|
+
* one does (see network_policy.js, which also cancels it when it reaches
|
|
1633
|
+
* window).
|
|
1625
1634
|
*/
|
|
1626
1635
|
const errorIsAccountedFor = (error) => {
|
|
1627
1636
|
return (
|
|
@@ -12162,8 +12171,9 @@ defineInteractionDetector({
|
|
|
12162
12171
|
name: "surface",
|
|
12163
12172
|
claims: (type) =>
|
|
12164
12173
|
type === PAN || type === ZOOM || type === GRAB || type === RELEASE,
|
|
12165
|
-
// A press on the surface may be a tap, a hold or the
|
|
12166
|
-
// nothing may read it as the first until the pointer has said
|
|
12174
|
+
// A press on the surface may be a tap, a hold or the first finger of a pan or
|
|
12175
|
+
// a pinch, and nothing may read it as the first until the pointer has said
|
|
12176
|
+
// which.
|
|
12167
12177
|
disputesPress: true,
|
|
12168
12178
|
setup: (element, trigger, { types, readConfig }) => {
|
|
12169
12179
|
const canPan = types.includes(PAN);
|
|
@@ -15166,21 +15176,33 @@ const getActionResultProperties = (action) => {
|
|
|
15166
15176
|
return actionResultPropertiesMap.get(action);
|
|
15167
15177
|
};
|
|
15168
15178
|
|
|
15169
|
-
// PUT/PATCH results update the UI through the store, and DELETE resets the GET
|
|
15170
|
-
// instead of rerunning it, so a GET rerun would only ever cost a request.
|
|
15171
|
-
// A POST is the one case the client cannot decide alone: whether a new item
|
|
15172
|
-
// belongs to a list depends on filters/pagination the backend owns.
|
|
15173
15179
|
// Rationale in full, plus when to override: docs/list_refresh.md
|
|
15174
15180
|
const defaultRerunOn = {
|
|
15181
|
+
// PUT/PATCH results update the UI through the store, and DELETE resets the
|
|
15182
|
+
// GET rather than rerunning it, so a GET rerun would only ever cost a request.
|
|
15175
15183
|
GET: false,
|
|
15184
|
+
// A POST is the one case the client cannot decide alone: whether a new item
|
|
15185
|
+
// belongs to a list depends on filters/pagination the backend owns.
|
|
15176
15186
|
GET_MANY: ["POST"],
|
|
15187
|
+
// DELETE is in there, unlike for GET_MANY: an action holds ids and the store
|
|
15188
|
+
// drops the deleted one out of every list holding it, while a list reading
|
|
15189
|
+
// by slices holds places — the row that left takes the ones after it one
|
|
15190
|
+
// rank up, and only the collection knows who fills the last one.
|
|
15191
|
+
GET_RANGE: ["POST", "DELETE"],
|
|
15192
|
+
};
|
|
15193
|
+
// A key a `rerunOn` leaves out keeps the value it would have had without it:
|
|
15194
|
+
// the default for a resource, the value of the resource it is declared on for
|
|
15195
|
+
// a withParams() scope or a relation.
|
|
15196
|
+
const resolveRerunOn = (rerunOn, inheritedRerunOn = defaultRerunOn) => {
|
|
15197
|
+
if (!rerunOn) {
|
|
15198
|
+
return inheritedRerunOn;
|
|
15199
|
+
}
|
|
15200
|
+
return {
|
|
15201
|
+
GET: rerunOn.GET ?? inheritedRerunOn.GET,
|
|
15202
|
+
GET_MANY: rerunOn.GET_MANY ?? inheritedRerunOn.GET_MANY,
|
|
15203
|
+
GET_RANGE: rerunOn.GET_RANGE ?? inheritedRerunOn.GET_RANGE,
|
|
15204
|
+
};
|
|
15177
15205
|
};
|
|
15178
|
-
// What makes a range reader stale (rerunOn.GET_RANGE overrides it). DELETE is
|
|
15179
|
-
// in there, unlike for GET_MANY: an action holds ids and the store drops the
|
|
15180
|
-
// deleted one out of every list holding it, while a list reading by slices
|
|
15181
|
-
// holds places — the row that left takes the ones after it one rank up, and
|
|
15182
|
-
// only the collection knows who fills the last one.
|
|
15183
|
-
const defaultInvalidateRangeOn = ["POST", "DELETE"];
|
|
15184
15206
|
|
|
15185
15207
|
// This handles ALL resource lifecycle logic (rerun/reset) across all resources
|
|
15186
15208
|
const createResourceLifecycleManager = () => {
|
|
@@ -15190,7 +15212,7 @@ const createResourceLifecycleManager = () => {
|
|
|
15190
15212
|
|
|
15191
15213
|
const registerResource = (resourceScope, config) => {
|
|
15192
15214
|
const {
|
|
15193
|
-
rerunOn
|
|
15215
|
+
rerunOn,
|
|
15194
15216
|
paramScope = null,
|
|
15195
15217
|
dependencies = [],
|
|
15196
15218
|
uniqueKeys = [],
|
|
@@ -15473,8 +15495,7 @@ const createResourceLifecycleManager = () => {
|
|
|
15473
15495
|
if (!isSameResource && !isDependent) {
|
|
15474
15496
|
continue;
|
|
15475
15497
|
}
|
|
15476
|
-
|
|
15477
|
-
if (!shouldRerunAfter(invalidateOn, triggerVerb)) {
|
|
15498
|
+
if (!shouldRerunAfter(config.rerunOn.GET_RANGE, triggerVerb)) {
|
|
15478
15499
|
continue;
|
|
15479
15500
|
}
|
|
15480
15501
|
for (const rangeReader of config.rangeReaderSet) {
|
|
@@ -15975,7 +15996,7 @@ const resource = (
|
|
|
15975
15996
|
addItemSetup,
|
|
15976
15997
|
createRestAction: createRestActionForRoot,
|
|
15977
15998
|
paramScope: getParamScope(undefined),
|
|
15978
|
-
rerunOn,
|
|
15999
|
+
rerunOn: resolveRerunOn(rerunOn),
|
|
15979
16000
|
dependencies,
|
|
15980
16001
|
});
|
|
15981
16002
|
};
|
|
@@ -16039,7 +16060,7 @@ const createResource = (
|
|
|
16039
16060
|
* identical parameters, preventing cross-contamination between different parameter sets.
|
|
16040
16061
|
*
|
|
16041
16062
|
* @param {Object} params - Parameters to bind to all actions of this resource (required)
|
|
16042
|
-
* @param {{ rerunOn?: Object, dependencies?: Object[] }} [options] - reruns of that scope; left out
|
|
16063
|
+
* @param {{ rerunOn?: Object, dependencies?: Object[] }} [options] - reruns of that scope; a `rerunOn` key left out keeps the resource's value, and `dependencies` left out are the resource's
|
|
16043
16064
|
* @returns {Object} A new resource instance with parameter-bound actions and isolated lifecycle
|
|
16044
16065
|
* @see docs/resource.md — what a scope isolates, and `dependencies`
|
|
16045
16066
|
*
|
|
@@ -16085,7 +16106,7 @@ const createResource = (
|
|
|
16085
16106
|
addItemSetup,
|
|
16086
16107
|
createRestAction: createRestActionWithParams,
|
|
16087
16108
|
paramScope: resolvedParamScope,
|
|
16088
|
-
rerunOn: withParamsRerunOn
|
|
16109
|
+
rerunOn: resolveRerunOn(withParamsRerunOn, rerunOn),
|
|
16089
16110
|
dependencies: withParamsDeps ?? dependencies,
|
|
16090
16111
|
});
|
|
16091
16112
|
};
|
|
@@ -16103,14 +16124,15 @@ const createResource = (
|
|
|
16103
16124
|
* Callback return contracts:
|
|
16104
16125
|
* - GET / PUT → the parent object with the relationship nested inside:
|
|
16105
16126
|
* `async ({ id }) => ({ id, session: { id: 10, token: "abc" } })`; `null` for no relationship
|
|
16106
|
-
* - DELETE → the parent id
|
|
16127
|
+
* - DELETE → the parent id, or `{ id }`; the property is set to `null`
|
|
16107
16128
|
*
|
|
16108
16129
|
* The backend may also embed the child inline in a parent GET/POST response — the
|
|
16109
16130
|
* setter on the property upserts the nested object into the child store.
|
|
16110
16131
|
*
|
|
16111
|
-
* Returns the relationship resource
|
|
16112
|
-
*
|
|
16113
|
-
*
|
|
16132
|
+
* Returns the relationship resource, itself chainable. Its items are the child
|
|
16133
|
+
* resource's own, shared by every parent: `USER_SESSION.one("device", DEVICE)`
|
|
16134
|
+
* adds a reactive `.device` property to every session, as
|
|
16135
|
+
* `SESSION.one("device", DEVICE)` would.
|
|
16114
16136
|
*
|
|
16115
16137
|
* @param {string} propertyName - property holding the child on each parent item
|
|
16116
16138
|
* @param {Object} childResource - the independent resource created by `resource()`
|
|
@@ -16193,11 +16215,11 @@ const createResource = (
|
|
|
16193
16215
|
const createRestActionForOne = (verb, callback, { onActionComplete }) => {
|
|
16194
16216
|
const applyResultToValue =
|
|
16195
16217
|
verb === "DELETE"
|
|
16196
|
-
? (
|
|
16197
|
-
const item = store.select(
|
|
16218
|
+
? (itemIdOrItemProps) => {
|
|
16219
|
+
const item = store.select(itemIdOrItemProps);
|
|
16198
16220
|
const childItemId = item[propertyName][childIdKey];
|
|
16199
16221
|
store.upsert({
|
|
16200
|
-
[idKey]:
|
|
16222
|
+
[idKey]: item[idKey],
|
|
16201
16223
|
[propertyName]: null,
|
|
16202
16224
|
});
|
|
16203
16225
|
return childItemId;
|
|
@@ -16225,7 +16247,7 @@ const createResource = (
|
|
|
16225
16247
|
if (!isProps(result) && !primitiveCanBeId(result)) {
|
|
16226
16248
|
throwInvalidResult(
|
|
16227
16249
|
action.name,
|
|
16228
|
-
`
|
|
16250
|
+
`the "${name}" id, or { ${idKey} } (the item whose "${propertyName}" becomes null)`,
|
|
16229
16251
|
result,
|
|
16230
16252
|
);
|
|
16231
16253
|
}
|
|
@@ -16250,11 +16272,11 @@ const createResource = (
|
|
|
16250
16272
|
PUT,
|
|
16251
16273
|
DELETE,
|
|
16252
16274
|
},
|
|
16253
|
-
store,
|
|
16254
|
-
addItemSetup,
|
|
16275
|
+
store: childStore,
|
|
16276
|
+
addItemSetup: childResource.addItemSetup,
|
|
16255
16277
|
createRestAction: createRestActionForOne,
|
|
16256
16278
|
paramScope,
|
|
16257
|
-
rerunOn: oneRerunOn
|
|
16279
|
+
rerunOn: resolveRerunOn(oneRerunOn, rerunOn),
|
|
16258
16280
|
dependencies: oneDependencies ?? dependencies,
|
|
16259
16281
|
});
|
|
16260
16282
|
};
|
|
@@ -16277,6 +16299,9 @@ const createResource = (
|
|
|
16277
16299
|
* - DELETE → `[parentId, childId]`
|
|
16278
16300
|
* - DELETE_MANY → `[parentId, [childId, childId, …]]`
|
|
16279
16301
|
*
|
|
16302
|
+
* Returns the relationship resource, itself chainable; its items are the child
|
|
16303
|
+
* resource's own, as for `.one()`.
|
|
16304
|
+
*
|
|
16280
16305
|
* @param {string} propertyName - property holding the child array on each parent item
|
|
16281
16306
|
* @param {Object} childResource - the independent resource created by `resource()`
|
|
16282
16307
|
* @param {Object} [restCallbacks] - `{ rerunOn, dependencies, GET, GET_MANY, POST, POST_MANY, PUT, PUT_MANY, PATCH, PATCH_MANY, DELETE, DELETE_MANY }`
|
|
@@ -16512,11 +16537,11 @@ const createResource = (
|
|
|
16512
16537
|
DELETE,
|
|
16513
16538
|
DELETE_MANY,
|
|
16514
16539
|
},
|
|
16515
|
-
store,
|
|
16516
|
-
addItemSetup,
|
|
16540
|
+
store: childStore,
|
|
16541
|
+
addItemSetup: childResource.addItemSetup,
|
|
16517
16542
|
createRestAction: createRestActionForMany,
|
|
16518
16543
|
paramScope,
|
|
16519
|
-
rerunOn: manyRerunOn
|
|
16544
|
+
rerunOn: resolveRerunOn(manyRerunOn, rerunOn),
|
|
16520
16545
|
dependencies: manyDependencies ?? dependencies,
|
|
16521
16546
|
});
|
|
16522
16547
|
};
|
|
@@ -16645,7 +16670,7 @@ const createResource = (
|
|
|
16645
16670
|
addItemSetup: childAddItemSetup,
|
|
16646
16671
|
createRestAction: createRestActionForScopedOne,
|
|
16647
16672
|
paramScope,
|
|
16648
|
-
rerunOn: scopedOneRerunOn
|
|
16673
|
+
rerunOn: resolveRerunOn(scopedOneRerunOn, rerunOn),
|
|
16649
16674
|
dependencies: scopedOneDependencies ?? dependencies,
|
|
16650
16675
|
});
|
|
16651
16676
|
};
|
|
@@ -16880,7 +16905,7 @@ const createResource = (
|
|
|
16880
16905
|
addItemSetup: childAddItemSetup,
|
|
16881
16906
|
createRestAction: createRestActionForScopedMany,
|
|
16882
16907
|
paramScope,
|
|
16883
|
-
rerunOn: scopedManyRerunOn
|
|
16908
|
+
rerunOn: resolveRerunOn(scopedManyRerunOn, rerunOn),
|
|
16884
16909
|
dependencies: scopedManyDependencies ?? dependencies,
|
|
16885
16910
|
});
|
|
16886
16911
|
// When a scoped child collection is mutated (POST etc.), the parent GET must
|
|
@@ -19592,9 +19617,9 @@ const isSizeSpacingKey = (key) => {
|
|
|
19592
19617
|
// "vvw"/"vvh" are navi's own: the *visual* viewport, which — unlike vw/dvw —
|
|
19593
19618
|
// shrinks when the mobile virtual keyboard opens (see layout/responsive.js), so
|
|
19594
19619
|
// they are what a popup meant to stay clear of the keyboard should use.
|
|
19595
|
-
// "appw"/"apph" are the same thing narrowed to the app's own screen:
|
|
19596
|
-
//
|
|
19597
|
-
//
|
|
19620
|
+
// "appw"/"apph" are the same thing narrowed to the app's own screen: the
|
|
19621
|
+
// visual viewport minus the app's bands (--navi-app-inset-*), so identical to
|
|
19622
|
+
// vvw/vvh until the app declares bands. A gap meant to read as "a small margin" must use these —
|
|
19598
19623
|
// 3vvw on a 1500px window is a 45px gap around a 600px app.
|
|
19599
19624
|
// Functions rather than the signals themselves: appw/apph are not a signal to
|
|
19600
19625
|
// read but a value to compute (a signal, then a CSS var read back). Reading the
|
|
@@ -29296,8 +29321,8 @@ const TRANSITION_FURNITURE_CSS = /* css */ `.navi_fixed_bar[data-navi-transition
|
|
|
29296
29321
|
}
|
|
29297
29322
|
`;
|
|
29298
29323
|
|
|
29299
|
-
// Called
|
|
29300
|
-
//
|
|
29324
|
+
// Called as a movement starts over a marked area, never at module scope: a
|
|
29325
|
+
// page that never travels between routes must not carry this sheet, and a
|
|
29301
29326
|
// build that sees no caller drops the css with the function.
|
|
29302
29327
|
const installTransitionFurnitureCss = () => {
|
|
29303
29328
|
import.meta.css = [TRANSITION_FURNITURE_CSS, "@jsenv/navi/src/nav/transition_furniture.js"];
|
|
@@ -29760,9 +29785,10 @@ const TRANSITION_WINDOW_CSS = /* css */ `@property --navi-transition-cover-top {
|
|
|
29760
29785
|
}
|
|
29761
29786
|
`;
|
|
29762
29787
|
|
|
29763
|
-
// Called
|
|
29764
|
-
// a page that never travels between routes must not
|
|
29765
|
-
// build that sees no caller drops the css with the
|
|
29788
|
+
// Called by whatever needs the window — a render, or a movement starting —
|
|
29789
|
+
// never at module scope: a page that never travels between routes must not
|
|
29790
|
+
// carry this sheet, and a build that sees no caller drops the css with the
|
|
29791
|
+
// function.
|
|
29766
29792
|
const installTransitionWindowCss = () => {
|
|
29767
29793
|
import.meta.css = [TRANSITION_WINDOW_CSS, "@jsenv/navi/src/nav/transition_window.js"];
|
|
29768
29794
|
};
|
|
@@ -30575,9 +30601,6 @@ const RouteTransitionArea = ({
|
|
|
30575
30601
|
children,
|
|
30576
30602
|
...rest
|
|
30577
30603
|
}) => {
|
|
30578
|
-
import.meta.css = [css$12, "@jsenv/navi/src/nav/route_transition.jsx"];
|
|
30579
|
-
installTransitionWindowCss();
|
|
30580
|
-
installTransitionFurnitureCss();
|
|
30581
30604
|
const props = {
|
|
30582
30605
|
...rest,
|
|
30583
30606
|
[TRANSITION_AREA_ATTRIBUTE]: ""
|
|
@@ -30646,8 +30669,6 @@ const RouteTransitionArea = ({
|
|
|
30646
30669
|
* @returns {() => void} remove this relation.
|
|
30647
30670
|
*/
|
|
30648
30671
|
const defineRouteTransition = (from, to, transition) => {
|
|
30649
|
-
import.meta.css = [css$12, "@jsenv/navi/src/nav/route_transition.jsx"];
|
|
30650
|
-
installTransitionWindowCss();
|
|
30651
30672
|
if (!to) {
|
|
30652
30673
|
throw new TypeError(`defineRouteTransition needs a destination: "to" is ${to}. The page reached from anywhere is written defineRouteTransition(null, THAT_PAGE, ...) — there is no relation the other way round, a page LEFT for anywhere being the back half of that one.`);
|
|
30653
30674
|
}
|
|
@@ -30687,8 +30708,6 @@ const defineRouteTransition = (from, to, transition) => {
|
|
|
30687
30708
|
* @returns {() => void} remove this default.
|
|
30688
30709
|
*/
|
|
30689
30710
|
const defineRouteDefaultTransition = transition => {
|
|
30690
|
-
import.meta.css = [css$12, "@jsenv/navi/src/nav/route_transition.jsx"];
|
|
30691
|
-
installTransitionWindowCss();
|
|
30692
30711
|
const value = normalizeTransition(transition);
|
|
30693
30712
|
defaultTransition = value;
|
|
30694
30713
|
return () => {
|
|
@@ -31270,6 +31289,10 @@ const beginTransition = ({
|
|
|
31270
31289
|
// Said before the picture is taken: whoever names something for a movement
|
|
31271
31290
|
// between two pages decides on it now (see transition_destination.js).
|
|
31272
31291
|
holdTransitionDestination(transition, url);
|
|
31292
|
+
// Adopted by what starts a movement rather than by what declares one: a link
|
|
31293
|
+
// or a navTo() asks for a movement in an app that declared none, and an app
|
|
31294
|
+
// that never moves never carries the sheet.
|
|
31295
|
+
import.meta.css = [css$12, "@jsenv/navi/src/nav/route_transition.jsx"];
|
|
31273
31296
|
documentElement.setAttribute(TRANSITION_ATTRIBUTE, direction);
|
|
31274
31297
|
if (type) {
|
|
31275
31298
|
documentElement.setAttribute(TRANSITION_TYPE_ATTRIBUTE, type);
|
|
@@ -31291,6 +31314,10 @@ const beginTransition = ({
|
|
|
31291
31314
|
// left (see transition_window.js).
|
|
31292
31315
|
let areaStateBefore = null;
|
|
31293
31316
|
if (areaElement) {
|
|
31317
|
+
// The area is the application's element as often as <RouteTransitionArea>,
|
|
31318
|
+
// so what a movement on it plays with is adopted here, where it is found.
|
|
31319
|
+
installTransitionWindowCss();
|
|
31320
|
+
installTransitionFurnitureCss();
|
|
31294
31321
|
documentElement.setAttribute(TRANSITION_TARGET_ATTRIBUTE, "area");
|
|
31295
31322
|
// Said before the picture is taken, like every name (see
|
|
31296
31323
|
// transition_furniture.js): what the bars are wearing when the transition
|
|
@@ -44279,16 +44306,6 @@ const css$Z = /* css */`@layer navi {
|
|
|
44279
44306
|
border-radius: .2em;
|
|
44280
44307
|
}
|
|
44281
44308
|
|
|
44282
|
-
&[data-capitalize] {
|
|
44283
|
-
text-transform: capitalize;
|
|
44284
|
-
|
|
44285
|
-
& .navi_text_sizer {
|
|
44286
|
-
& .navi_text {
|
|
44287
|
-
display: inline-block;
|
|
44288
|
-
}
|
|
44289
|
-
}
|
|
44290
|
-
}
|
|
44291
|
-
|
|
44292
44309
|
&[data-shrinkwrap] {
|
|
44293
44310
|
display: inline-block;
|
|
44294
44311
|
}
|
|
@@ -44311,12 +44328,6 @@ time.navi_text {
|
|
|
44311
44328
|
}
|
|
44312
44329
|
|
|
44313
44330
|
.navi_text {
|
|
44314
|
-
&[data-capitalize] {
|
|
44315
|
-
&:first-letter, & .navi_text_sizer_placeholder:first-letter, & .navi_text_sizer_overlay:first-letter {
|
|
44316
|
-
text-transform: uppercase;
|
|
44317
|
-
}
|
|
44318
|
-
}
|
|
44319
|
-
|
|
44320
44331
|
& .navi_text_sizer, & .navi_text_sizer_placeholder, & .navi_text_sizer_overlay {
|
|
44321
44332
|
display: inherit;
|
|
44322
44333
|
width: inherit;
|
|
@@ -44764,7 +44775,9 @@ const shouldInjectSpacingBetween = (left, right) => {
|
|
|
44764
44775
|
* text block from being wider than its content when inside a flex/grid container.
|
|
44765
44776
|
*
|
|
44766
44777
|
* @param {boolean} [capitalize]
|
|
44767
|
-
* Uppercases the first letter of the text
|
|
44778
|
+
* Uppercases the first letter of the text, and only that one: "lundi 11 mai"
|
|
44779
|
+
* reads "Lundi 11 mai". Applied to the string the text starts with; a text
|
|
44780
|
+
* starting with an element keeps its first letter as written.
|
|
44768
44781
|
*
|
|
44769
44782
|
* @param {string|[number,number]|[string,string]} [selectRange]
|
|
44770
44783
|
* Selects a portion of the text on mount. Pass a substring to search for, a
|
|
@@ -44884,11 +44897,13 @@ const TextUI = props => {
|
|
|
44884
44897
|
shrinkWrap,
|
|
44885
44898
|
...rest
|
|
44886
44899
|
} = props;
|
|
44900
|
+
if (capitalize) {
|
|
44901
|
+
children = capitalizeFirstLetter(children);
|
|
44902
|
+
}
|
|
44887
44903
|
const defaultSpace = preventSpaceUnderlines ? FAKE_SPACE : REGULAR_SPACE;
|
|
44888
44904
|
const resolvedSpacing = spacing ?? defaultSpace;
|
|
44889
44905
|
const boxProps = {
|
|
44890
44906
|
"as": "span",
|
|
44891
|
-
"data-capitalize": capitalize ? "" : undefined,
|
|
44892
44907
|
"data-shrinkwrap": shrinkWrap ? "" : undefined,
|
|
44893
44908
|
...rest,
|
|
44894
44909
|
ref,
|
|
@@ -45189,6 +45204,28 @@ const Icon = ({
|
|
|
45189
45204
|
});
|
|
45190
45205
|
};
|
|
45191
45206
|
|
|
45207
|
+
// On the string rather than with ::first-letter, which needs a block container:
|
|
45208
|
+
// an inline text made one is an atomic box, and the ellipsis of the line
|
|
45209
|
+
// holding it (a Picker's value) can then no longer cut it. The string is also
|
|
45210
|
+
// what every copy of the children (sizer, bold background) renders, so they
|
|
45211
|
+
// all read the same. Leading spaces and punctuation are skipped, and a text
|
|
45212
|
+
// starting with a digit is left as it is, as ::first-letter would.
|
|
45213
|
+
const capitalizeFirstLetter = children => {
|
|
45214
|
+
if (typeof children === "string") {
|
|
45215
|
+
return children.replace(FIRST_LOWERCASE_LETTER_REGEXP, (match, lead, letter) => `${lead}${letter.toLocaleUpperCase()}`);
|
|
45216
|
+
}
|
|
45217
|
+
if (Array.isArray(children) && children.length > 0) {
|
|
45218
|
+
const first = children[0];
|
|
45219
|
+
const firstCapitalized = capitalizeFirstLetter(first);
|
|
45220
|
+
if (firstCapitalized === first) {
|
|
45221
|
+
return children;
|
|
45222
|
+
}
|
|
45223
|
+
return [firstCapitalized, ...children.slice(1)];
|
|
45224
|
+
}
|
|
45225
|
+
return children;
|
|
45226
|
+
};
|
|
45227
|
+
const FIRST_LOWERCASE_LETTER_REGEXP = /^([\s\p{P}]*)(\p{Ll})/u;
|
|
45228
|
+
|
|
45192
45229
|
/**
|
|
45193
45230
|
* Where a link leads, asked for when the pointer or the focus arrives on it:
|
|
45194
45231
|
* the moment the user signals a destination, before the press. Only what the
|
|
@@ -60033,7 +60070,6 @@ const createSwipeToClose = (side, { grip } = {}) => {
|
|
|
60033
60070
|
panelEl.style.transform = "";
|
|
60034
60071
|
panelEl.style.clipPath = "";
|
|
60035
60072
|
panelEl.style.transitionProperty = "";
|
|
60036
|
-
panelEl.style.userSelect = "";
|
|
60037
60073
|
};
|
|
60038
60074
|
// The resting value is written first and the animation only covers the way
|
|
60039
60075
|
// to it: both end on the same number, so nothing is seen changing when the
|
|
@@ -60077,10 +60113,6 @@ const createSwipeToClose = (side, { grip } = {}) => {
|
|
|
60077
60113
|
return false;
|
|
60078
60114
|
}
|
|
60079
60115
|
panelEl.style.transitionProperty = "none";
|
|
60080
|
-
panelEl.style.userSelect = "none";
|
|
60081
|
-
// What the first pixels of the gesture may have started selecting is
|
|
60082
|
-
// not a selection, it is the beginning of this travel.
|
|
60083
|
-
window.getSelection().removeAllRanges();
|
|
60084
60116
|
// The way out is the only way there is anything: pulling the other way
|
|
60085
60117
|
// leans against a wall and comes back.
|
|
60086
60118
|
return {
|
|
@@ -60751,7 +60783,7 @@ const css$E = /* css */`
|
|
|
60751
60783
|
--navi-app-width rather than 3vvw): the gap must read as a small
|
|
60752
60784
|
margin around the dialog, and 3% of a 1500px window is a 45px gap
|
|
60753
60785
|
around a 600px app. Identical to 3vvw until the app declares
|
|
60754
|
-
--navi-app-max-width. */
|
|
60786
|
+
bands (--navi-app-max-width, or --navi-app-inset-* written by it). */
|
|
60755
60787
|
--x-dialog-container-spacing: calc(0.03 * var(--navi-app-width));
|
|
60756
60788
|
|
|
60757
60789
|
/* --navi-app-width, not --navi-vvw: a top-layer dialog is calibrated on
|
|
@@ -61488,8 +61520,8 @@ const css$E = /* css */`
|
|
|
61488
61520
|
* `positionArea`: it both caps the dialog's own size (via
|
|
61489
61521
|
* `--x-dialog-container-spacing`, written from this prop) and offsets a docked
|
|
61490
61522
|
* one from the edge it docks to. Accepts a number of pixels, a viewport
|
|
61491
|
-
* length — "appw"/"apph" being the app's own screen (the visual viewport
|
|
61492
|
-
*
|
|
61523
|
+
* length — "appw"/"apph" being the app's own screen (the visual viewport
|
|
61524
|
+
* minus the app's bands, see docs/safe_area.md) and
|
|
61493
61525
|
* "vvw"/"vvh" the visual viewport itself, which shrinks when the mobile
|
|
61494
61526
|
* keyboard opens — or a container length ("3cqw", the `layer="local"`
|
|
61495
61527
|
* default). Pass 0 for a dialog meant to sit flush (a side panel).
|
|
@@ -64542,6 +64574,8 @@ const css$C = /* css */`@layer navi {
|
|
|
64542
64574
|
* `maxWidth` below.
|
|
64543
64575
|
* @param {boolean} [props.sizeFromAnchor] - **Dialog-only**, same guard.
|
|
64544
64576
|
* @param {"box"|"scene"} [props.lift] - **Dialog-only**, same guard.
|
|
64577
|
+
* @param {Element|{current: Element}|string} [props.liftAnchor] -
|
|
64578
|
+
* **Dialog-only**, same guard.
|
|
64545
64579
|
* @param {string} [props.positionArea] - Forwarded as-is — `Dialog` and
|
|
64546
64580
|
* `Popover` have different own defaults (`"center"` vs. `"bottom"`),
|
|
64547
64581
|
* deliberately not homogenized here (each reads best for its own typical
|
|
@@ -64575,8 +64609,13 @@ const css$C = /* css */`@layer navi {
|
|
|
64575
64609
|
* identically): the wash the backdrop paints over what is behind.
|
|
64576
64610
|
* @param {string} [props.backdropFilter] - Forwarded as-is: what that wash
|
|
64577
64611
|
* does to the picture underneath, `"blur(4px)"` and the like.
|
|
64578
|
-
* @param {boolean|"auto"|"fading"|"scaling"|"sliding"
|
|
64579
|
-
* - Forwarded
|
|
64612
|
+
* @param {boolean|"auto"|"fading"|"scaling"|"sliding"|`slide-from-${string}`|"expanding"|`expand-${string}`|"lifting"|{open: boolean|"auto"|"fading"|"scaling"|"sliding"|`slide-from-${string}`, close: "lifting"}} [props.animation]
|
|
64613
|
+
* - Forwarded to whichever renders — see either component's own doc.
|
|
64614
|
+
* `"expanding"`/`"expand-*"` are `Popover`'s own; `"lifting"` and
|
|
64615
|
+
* `{ open, close: "lifting" }` are `Dialog`'s. A popover has no lift, so in
|
|
64616
|
+
* popover mode `"lifting"` plays no movement (what a dialog does with no
|
|
64617
|
+
* anchor to lift out of) and the object form opens with its `open`, which
|
|
64618
|
+
* the close plays backwards like every other kind.
|
|
64580
64619
|
* @param {string} [props.animationDuration] - Forwarded as-is.
|
|
64581
64620
|
* @param {string} [props.maxWidth] - Forwarded as-is to both; also read
|
|
64582
64621
|
* here directly to help decide the automatic `mode` (a fixed length under
|
|
@@ -64642,6 +64681,8 @@ const Popup = props => {
|
|
|
64642
64681
|
// mode the automatic screen-size resolution happens to pick.
|
|
64643
64682
|
pressOutside = "close",
|
|
64644
64683
|
backdrop,
|
|
64684
|
+
// A popover is handed only the values it understands (toPopoverAnimation).
|
|
64685
|
+
animation,
|
|
64645
64686
|
// Popover-only (see this component's own doc) — destructured out so
|
|
64646
64687
|
// they're never part of ...rest, and therefore never forwarded to
|
|
64647
64688
|
// Dialog below, where they'd otherwise leak onto the real <dialog>
|
|
@@ -64656,6 +64697,7 @@ const Popup = props => {
|
|
|
64656
64697
|
dockedOnSmallTouchScreen,
|
|
64657
64698
|
sizeFromAnchor,
|
|
64658
64699
|
lift,
|
|
64700
|
+
liftAnchor,
|
|
64659
64701
|
...rest
|
|
64660
64702
|
} = props;
|
|
64661
64703
|
const [mode] = useResolvedPopupMode(modeProp, maxWidth, {
|
|
@@ -64675,6 +64717,8 @@ const Popup = props => {
|
|
|
64675
64717
|
dockedOnSmallTouchScreen: dockedOnSmallTouchScreen,
|
|
64676
64718
|
sizeFromAnchor: sizeFromAnchor,
|
|
64677
64719
|
lift: lift,
|
|
64720
|
+
liftAnchor: liftAnchor,
|
|
64721
|
+
animation: animation,
|
|
64678
64722
|
maxWidth: maxWidth,
|
|
64679
64723
|
pressOutside: pressOutside,
|
|
64680
64724
|
backdrop: backdrop,
|
|
@@ -64688,6 +64732,7 @@ const Popup = props => {
|
|
|
64688
64732
|
}
|
|
64689
64733
|
return jsx(Popover, {
|
|
64690
64734
|
...rest,
|
|
64735
|
+
animation: toPopoverAnimation(animation),
|
|
64691
64736
|
maxWidth: maxWidth,
|
|
64692
64737
|
pressOutside: pressOutside,
|
|
64693
64738
|
backdrop: backdrop,
|
|
@@ -64705,6 +64750,18 @@ const Popup = props => {
|
|
|
64705
64750
|
};
|
|
64706
64751
|
Popup.Close = PopupClose;
|
|
64707
64752
|
|
|
64753
|
+
// What Dialog's own animation values mean to a popover, which has no lift
|
|
64754
|
+
// (see the `animation` doc above).
|
|
64755
|
+
const toPopoverAnimation = animation => {
|
|
64756
|
+
if (animation === "lifting") {
|
|
64757
|
+
return undefined;
|
|
64758
|
+
}
|
|
64759
|
+
if (animation !== null && typeof animation === "object") {
|
|
64760
|
+
return animation.open;
|
|
64761
|
+
}
|
|
64762
|
+
return animation;
|
|
64763
|
+
};
|
|
64764
|
+
|
|
64708
64765
|
installImportMetaCssBuild(import.meta);
|
|
64709
64766
|
const css$B = /* css */`.navi_picker_callout_dock > [data-picker-content] {
|
|
64710
64767
|
display: none;
|
|
@@ -66015,9 +66072,14 @@ const PickerNaviMinute = props => {
|
|
|
66015
66072
|
step,
|
|
66016
66073
|
value
|
|
66017
66074
|
} = props;
|
|
66075
|
+
|
|
66076
|
+
// resolveInputProps has already run (PickerFirstResolver), so the type
|
|
66077
|
+
// handed on is one the picker renders as is — the text field a navi numeric
|
|
66078
|
+
// type resolves to, told what its value is.
|
|
66018
66079
|
return jsx(Next, {
|
|
66019
66080
|
...props,
|
|
66020
|
-
type: "
|
|
66081
|
+
type: "text",
|
|
66082
|
+
"navi-input-type": "minute",
|
|
66021
66083
|
children: jsxs(Box, {
|
|
66022
66084
|
flex: "y",
|
|
66023
66085
|
spacing: "s",
|
|
@@ -86439,6 +86501,8 @@ const css$3 = /* css */`@layer navi {
|
|
|
86439
86501
|
}
|
|
86440
86502
|
|
|
86441
86503
|
.navi_card_layout {
|
|
86504
|
+
box-sizing: border-box;
|
|
86505
|
+
min-height: 100%;
|
|
86442
86506
|
padding-top: var(--layout-margin-top, var(--layout-margin-y, var(--layout-margin)));
|
|
86443
86507
|
padding-right: var(--layout-margin-right, var(--layout-margin-x, var(--layout-margin)));
|
|
86444
86508
|
padding-bottom: var(--layout-margin-bottom, var(--layout-margin-y, var(--layout-margin)));
|
|
@@ -86480,6 +86544,11 @@ const CardLayoutStyleCSSVars = {
|
|
|
86480
86544
|
minHeight: "--layout-min-height"
|
|
86481
86545
|
};
|
|
86482
86546
|
/**
|
|
86547
|
+
* The card is centered in the area both ways and is as wide as its content,
|
|
86548
|
+
* `minWidth` at least. Down the area, the layout takes at least the height of
|
|
86549
|
+
* what holds it, so how tall that area is is up to the page around it, as for
|
|
86550
|
+
* `ViewportLayout`.
|
|
86551
|
+
*
|
|
86483
86552
|
* @type {import("ignore:preact").FunctionComponent<{
|
|
86484
86553
|
* alignX?: string,
|
|
86485
86554
|
* alignY?: string,
|
|
@@ -86509,6 +86578,11 @@ const CardLayout = ({
|
|
|
86509
86578
|
}) => {
|
|
86510
86579
|
import.meta.css = [css$3, "@jsenv/navi/src/layout/card_layout.jsx"];
|
|
86511
86580
|
return jsx(Box, {
|
|
86581
|
+
flex: true
|
|
86582
|
+
// The card's place in the area; alignX/alignY below are its content's.
|
|
86583
|
+
,
|
|
86584
|
+
alignX: "center",
|
|
86585
|
+
alignY: "center",
|
|
86512
86586
|
baseClassName: "navi_card_layout",
|
|
86513
86587
|
styleCSSVars: CardLayoutStyleCSSVars,
|
|
86514
86588
|
visualSelector: ".navi_card",
|