@jsenv/navi 0.30.11 → 0.30.13

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.
@@ -3729,6 +3729,7 @@ const actionWeakMap = new WeakMap();
3729
3729
  * long is this still true?" belongs to the question: a court list is good for
3730
3730
  * the session, a count of people watching grows on its own and is worth a few
3731
3731
  * minutes, a payment status is worth nothing at all.
3732
+ * A resource declares it for its reads: `resource()`'s `keep`.
3732
3733
  * @param {Array<Object | { resource: Object, on: string[] }> | (() => Array<Object | { resource: Object, on: string[] }>)} [rootOptions.dependencies] -
3733
3734
  * the resources whose writes make the answer out of date — a count, a
3734
3735
  * summary, anything read that is no row of a resource. After a listed write
@@ -28971,7 +28972,7 @@ const debug$2 = (...args) => {
28971
28972
  * "What a read shows while its params move").
28972
28973
  *
28973
28974
  * @param {string} name - resource name, used in action names and error messages
28974
- * @param {Object} restCallbacks - `{ idKey, uniqueKeys, rerunOn, dependencies, persist, writes, GET, GET_MANY, GET_RANGE, POST, POST_MANY, PUT, PUT_MANY, PATCH, PATCH_MANY, DELETE, DELETE_MANY }`
28975
+ * @param {Object} restCallbacks - `{ idKey, uniqueKeys, rerunOn, keep, dependencies, persist, writes, GET, GET_MANY, GET_RANGE, POST, POST_MANY, PUT, PUT_MANY, PATCH, PATCH_MANY, DELETE, DELETE_MANY }`
28975
28976
  * @param {string} [restCallbacks.idKey] - primary key property, defaults to `"id"`
28976
28977
  * @param {string[]} [restCallbacks.uniqueKeys] - alternate keys the store can find an item by (e.g. `"username"`)
28977
28978
  * @param {Array<Object | { resource: Object, on?: string[], reads?: Array<"GET" | "GET_MANY" | "GET_RANGE"> }> | (() => Array<Object | { resource: Object, on?: string[], reads?: Array<"GET" | "GET_MANY" | "GET_RANGE"> }>)} [restCallbacks.dependencies] -
@@ -28995,6 +28996,22 @@ const debug$2 = (...args) => {
28995
28996
  * follows `rerunOn` for its verb. A name a verb takes, or one the resource
28996
28997
  * already exposes (`withParams`, `store`…), throws. A `.scopedOne()` or
28997
28998
  * `.scopedMany()` takes `writes` too, `.scopedMany()` with the plural verbs.
28999
+ * @param {{ GET?: { ms?: number, max?: number }, GET_MANY?: { ms?: number, max?: number } }} [restCallbacks.keep] -
29000
+ * how long an answer of a read is trusted, coming back to the same params
29001
+ * within `ms` asking nothing. Left out, coming back asks again: the right
29002
+ * default for anything that moves on its own (a count of registrations), and
29003
+ * worth declaring for what barely does (a description, a finished
29004
+ * tournament). The store keeps the rows either way, and a `GET` draws the row
29005
+ * it holds while its request is out, so a kept answer and a fresh one look
29006
+ * alike: what `keep` saves is the request. Keyed by read, so a list can be
29007
+ * trusted for less time than an item. The rules are createAction's `keep`:
29008
+ * `ms` counts from the moment the answer landed, `max` caps the answers held
29009
+ * at once (the least recently looked-at going first), and past either the
29010
+ * read is asked again. A write that reruns the read (`rerunOn`,
29011
+ * `dependencies`) reruns a kept answer too, and the new one counts its `ms`
29012
+ * again. A `withParams()` scope keeps as its resource does, `max` counted per
29013
+ * scope; the reads of a relation are questions of their own and keep
29014
+ * nothing. `GET_RANGE` throws: a range reader holds no answer to keep.
28998
29015
  * @param {{ signal: import("@preact/signals").Signal, when?: () => boolean }} [restCallbacks.persist] -
28999
29016
  * mirrors the rows `GET` lands with into `signal` — a `stateSignal` with
29000
29017
  * `persists: true` and `type: "object"` keeps them across a reload, whose
@@ -29035,6 +29052,7 @@ const resource = (name, restCallbacks = {}) => {
29035
29052
  idKey = "id",
29036
29053
  uniqueKeys = [],
29037
29054
  rerunOn,
29055
+ keep,
29038
29056
  dependencies,
29039
29057
  persist,
29040
29058
  writes,
@@ -29051,6 +29069,9 @@ const resource = (name, restCallbacks = {}) => {
29051
29069
  DELETE,
29052
29070
  DELETE_MANY,
29053
29071
  } = restCallbacks;
29072
+ if (keep) {
29073
+ assertKeepNamesReads(name, keep);
29074
+ }
29054
29075
  const declarationSite = getDeclarationSite();
29055
29076
  const setupCallbackSet = new Set();
29056
29077
  const addItemSetup = (callback) => {
@@ -29175,6 +29196,7 @@ const resource = (name, restCallbacks = {}) => {
29175
29196
  findItemForGet,
29176
29197
  persistence,
29177
29198
  declarationSite,
29199
+ keep,
29178
29200
  });
29179
29201
  return createResource(name, {
29180
29202
  idKey,
@@ -30502,6 +30524,7 @@ const createRestActionFactoryForRoot = (
30502
30524
  findItemForGet,
30503
30525
  persistence,
30504
30526
  declarationSite,
30527
+ keep = {},
30505
30528
  },
30506
30529
  ) => {
30507
30530
  const createActionForRoot = (
@@ -30603,6 +30626,7 @@ const createRestActionFactoryForRoot = (
30603
30626
  : undefined,
30604
30627
  // Another params' answer is another row.
30605
30628
  inheritData: verb !== "GET",
30629
+ keep: verb === "GET" ? keep.GET : undefined,
30606
30630
  completeSideEffect: onActionComplete,
30607
30631
  });
30608
30632
  if (verb === "GET") {
@@ -30634,6 +30658,7 @@ const createRestActionFactoryForRoot = (
30634
30658
  // A binding moving to new params hands over the previous answer: a list
30635
30659
  // standing in for the next one beats a skeleton.
30636
30660
  inheritData: true,
30661
+ keep: verb === "GET" ? keep.GET_MANY : undefined,
30637
30662
  // The rows the page kept from the previous document (kept_reads.js),
30638
30663
  // drawn while the request is out when nothing was handed over.
30639
30664
  provisionalValue:
@@ -30716,6 +30741,24 @@ const applyNetworkPolicy = (
30716
30741
  };
30717
30742
  };
30718
30743
 
30744
+ // What can never be kept throws, as a rerunOn that never fires does: a range
30745
+ // reader holds no answer, its lists ask again for the window they draw.
30746
+ const KEEP_READS = ["GET", "GET_MANY"];
30747
+ const assertKeepNamesReads = (name, keep) => {
30748
+ for (const read of Object.keys(keep)) {
30749
+ if (read === "GET_RANGE") {
30750
+ throw new Error(
30751
+ `resource(${name}): keep.GET_RANGE keeps nothing — a range reader holds no answer, its lists ask again for the window they draw`,
30752
+ );
30753
+ }
30754
+ if (!KEEP_READS.includes(read)) {
30755
+ throw new Error(
30756
+ `resource(${name}): keep.${read} is not a read that keeps an answer — keep takes GET and GET_MANY`,
30757
+ );
30758
+ }
30759
+ }
30760
+ };
30761
+
30719
30762
  // A `dependencies` given as a function is read before the first request
30720
30763
  // leaves (see item_lifecycle_manager.js).
30721
30764
  const readLazyDependenciesFirst = (restCallback) => {
@@ -54440,6 +54483,7 @@ const TextAnchor = ({
54440
54483
  lineLayout
54441
54484
  }) => {
54442
54485
  import.meta.css = [css$11, "@jsenv/navi/src/text/text_anchor.jsx"];
54486
+ const fontArrival = fontArrivalSignal.value;
54443
54487
  const anchorRef = useRef();
54444
54488
  // The correction reads the layout, with the other reads of the commit (see
54445
54489
  // layout_batch.js) — an anchor per icon, each measured between two writes,
@@ -54509,7 +54553,7 @@ const TextAnchor = ({
54509
54553
  };
54510
54554
  };
54511
54555
  });
54512
- }, [textAnchor, textKey, textSize, lineLayout?.size, lineLayout?.verticalAlign]);
54556
+ }, [textAnchor, textKey, textSize, lineLayout?.size, lineLayout?.verticalAlign, fontArrival]);
54513
54557
  return jsxs(Fragment, {
54514
54558
  children: [children, jsx("span", {
54515
54559
  ref: anchorRef,
@@ -54590,6 +54634,23 @@ const computeTopOffset = ({
54590
54634
  };
54591
54635
  const charTopCanvas = document.createElement("canvas");
54592
54636
 
54637
+ // Bumped each time the document finishes loading fonts. A correction measured
54638
+ // while a web font is still loading is made of the fallback face's line box,
54639
+ // baseline and capitals, and every one of them moves when the font arrives.
54640
+ // One listener for every anchor, held while one is mounted: the anchors re-render
54641
+ // together and their reads join the same layout round.
54642
+ const onFontsLoaded = () => {
54643
+ fontArrivalSignal.value++;
54644
+ };
54645
+ const fontArrivalSignal = /*#__PURE__*/signal(0, {
54646
+ watched: () => {
54647
+ document.fonts.addEventListener("loadingdone", onFontsLoaded);
54648
+ },
54649
+ unwatched: () => {
54650
+ document.fonts.removeEventListener("loadingdone", onFontsLoaded);
54651
+ }
54652
+ });
54653
+
54593
54654
  const useInitialTextSelection = (ref, textSelection) => {
54594
54655
  const deps = [];
54595
54656
  if (Array.isArray(textSelection)) {
@@ -84094,6 +84155,7 @@ const css$w = /* css */`@property --list-group-label-height {
84094
84155
 
84095
84156
  &[data-continued] {
84096
84157
  margin-top: calc(-1 * var(--x-list-gap, 0px));
84158
+ grid-template-columns: minmax(0, 1fr);
84097
84159
  display: grid;
84098
84160
 
84099
84161
  & > .navi_list_item_group_label, & > .navi_list_item_group_list {