@jsenv/navi 0.29.368 → 0.29.369

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.
@@ -89,6 +89,7 @@ const css$17 = /* css */ `@layer navi {
89
89
  --navi-z-index-bar: 100;
90
90
  --navi-z-index-popup: 1000;
91
91
  --navi-z-index-callout: var(--navi-z-index-popup);
92
+ --navi-z-index-top-layer: 10000;
92
93
  }
93
94
  }
94
95
  `;
@@ -29022,6 +29023,8 @@ const onDocumentClick = (clickEvent) => {
29022
29023
  }
29023
29024
  };
29024
29025
 
29026
+ installImportMetaCssBuild(import.meta);
29027
+
29025
29028
  /**
29026
29029
  * The furniture around the pages — the fixed bars, and the popups standing
29027
29030
  * over them in the top layer — photographed with them for the length of a
@@ -29069,6 +29072,23 @@ const onDocumentClick = (clickEvent) => {
29069
29072
  * that has nothing to do with it. Being unable to answer a press is the price
29070
29073
  * of being photographed, and a route transition is where it costs nothing:
29071
29074
  * both pages are pictures for those few hundred milliseconds anyway.
29075
+ *
29076
+ * The WALL of a modal dialog goes the other way round: it cannot be
29077
+ * photographed at all. It is the browser's own ::backdrop — a pseudo-element,
29078
+ * which wears no name — and the top layer it is painted in is drawn during a
29079
+ * transition only as part of the root's picture, which is opted out while an
29080
+ * area is marked (route_transition.jsx). Captured on its own, the dialog's
29081
+ * box travels; its wall is painted nowhere for the length of the movement,
29082
+ * and the page under it leaves undimmed. So the wall is painted INTO the
29083
+ * page's picture instead: a stand-in laid over the area before each of the
29084
+ * two pictures is taken, painting what the ::backdrop paints, and removed
29085
+ * with the movement. Carried by the page's picture, it leaves with the page
29086
+ * being left and arrives with the page arriving, cut at the page's edge — and
29087
+ * under the dialog's own picture, which stands over the pages (the z-order in
29088
+ * route_transition.jsx). A bar the two states share is outside both pictures
29089
+ * and goes undimmed for those few hundred milliseconds: it is the frame, not
29090
+ * part of the page. A dialog with layer="local" paints a real element for its
29091
+ * wall, inside the page, and needs none of this.
29072
29092
  */
29073
29093
 
29074
29094
  // The browser's top layer: painted above everything the document paints, so
@@ -29086,6 +29106,32 @@ const FURNITURE_SELECTOR = `.navi_fixed_bar, .navi_popover:is(${TOP_LAYER_SELECT
29086
29106
  const TRANSITION_ATTRIBUTE$1 = "data-navi-route-transition";
29087
29107
  const NAME_PROPERTY$1 = "view-transition-name";
29088
29108
  const FURNITURE_NAME_PREFIX = "navi-transition-furniture-";
29109
+ // The dialogs whose wall is the browser's ::backdrop: shown with showModal().
29110
+ // A top-layer dialog without a wall is shown as a popover and has nothing to
29111
+ // stand in for.
29112
+ const MODAL_DIALOG_SELECTOR = ".navi_dialog:modal";
29113
+ const WALL_ATTRIBUTE = "data-navi-transition-wall";
29114
+ // What the ::backdrop paints, resolved on the dialog (layout/dialog.jsx): the
29115
+ // same two properties, copied onto the wall.
29116
+ const WALL_PROPERTIES = ["--backdrop-background", "--backdrop-filter"];
29117
+
29118
+ const TRANSITION_WALL_CSS = /* css */ `[data-navi-transition-wall] {
29119
+ z-index: var(--navi-z-index-top-layer);
29120
+ background: var(--backdrop-background);
29121
+ backdrop-filter: var(--backdrop-filter);
29122
+ pointer-events: none;
29123
+ position: absolute;
29124
+ top: 0;
29125
+ left: 0;
29126
+ }
29127
+ `;
29128
+
29129
+ // Called from the render of whatever holds the pages, never at module scope:
29130
+ // a page that never travels between routes must not carry this sheet, and a
29131
+ // build that sees no caller drops the css with the function.
29132
+ const installTransitionFurnitureCss = () => {
29133
+ import.meta.css = [TRANSITION_WALL_CSS, "@jsenv/navi/src/nav/transition_furniture.js"];
29134
+ };
29089
29135
 
29090
29136
  const nameByElement = new WeakMap();
29091
29137
  let nameCount = 0;
@@ -29098,6 +29144,9 @@ let namedElements = new Set();
29098
29144
  // The rule giving the one-sided bars their movement, written for one movement
29099
29145
  // and taken down with it.
29100
29146
  let travelStyleElement = null;
29147
+ // The walls standing in for the ::backdrop of the modal dialogs open in the
29148
+ // area, painted for one picture and taken down before the next.
29149
+ let wallElements = [];
29101
29150
 
29102
29151
  /**
29103
29152
  * Name what stands around the area, before the picture of the state being left
@@ -29110,6 +29159,7 @@ const nameTransitionFurniture = (owner, areaElement) => {
29110
29159
  namedElements = new Set();
29111
29160
  }
29112
29161
  nameFurnitureAround(areaElement);
29162
+ paintTransitionWalls(areaElement);
29113
29163
  };
29114
29164
 
29115
29165
  /**
@@ -29130,6 +29180,7 @@ const holdTransitionFurniture = (owner, areaElement) => {
29130
29180
  }
29131
29181
  }
29132
29182
  const namesArriving = nameFurnitureAround(areaElement);
29183
+ paintTransitionWalls(areaElement);
29133
29184
  const cssText = `${travelRule("old", namesLeaving, "--navi-route-transition-leave")}${travelRule("new", namesArriving, "--navi-route-transition-enter")}`;
29134
29185
  if (!cssText) {
29135
29186
  return;
@@ -29212,6 +29263,40 @@ const releaseTransitionFurniture = (owner) => {
29212
29263
  travelStyleElement.remove();
29213
29264
  travelStyleElement = null;
29214
29265
  }
29266
+ removeTransitionWalls();
29267
+ };
29268
+
29269
+ // One wall per modal dialog open in the area, in document order: the
29270
+ // ::backdrops stack in the top layer, and what dims the page is all of them.
29271
+ const paintTransitionWalls = (areaElement) => {
29272
+ removeTransitionWalls();
29273
+ for (const dialog of areaElement.querySelectorAll(MODAL_DIALOG_SELECTOR)) {
29274
+ const dialogStyle = getComputedStyle(dialog);
29275
+ const wall = document.createElement("div");
29276
+ wall.setAttribute(WALL_ATTRIBUTE, "");
29277
+ for (const property of WALL_PROPERTIES) {
29278
+ wall.style.setProperty(property, dialogStyle.getPropertyValue(property));
29279
+ }
29280
+ areaElement.appendChild(wall);
29281
+ // The area is not necessarily a containing block, and made one for the
29282
+ // movement it would move whatever the page positioned against an ancestor
29283
+ // of the area: the wall is placed from wherever its containing block
29284
+ // turns out to be, by the offset between that box and the area's.
29285
+ const areaRect = areaElement.getBoundingClientRect();
29286
+ const wallRect = wall.getBoundingClientRect();
29287
+ wall.style.left = `${areaRect.left - wallRect.left}px`;
29288
+ wall.style.top = `${areaRect.top - wallRect.top}px`;
29289
+ wall.style.width = `${areaRect.width}px`;
29290
+ wall.style.height = `${areaRect.height}px`;
29291
+ wallElements.push(wall);
29292
+ }
29293
+ };
29294
+
29295
+ const removeTransitionWalls = () => {
29296
+ for (const wall of wallElements) {
29297
+ wall.remove();
29298
+ }
29299
+ wallElements = [];
29215
29300
  };
29216
29301
 
29217
29302
  installImportMetaCssBuild(import.meta);
@@ -30063,6 +30148,7 @@ const RouteTransitionArea = ({
30063
30148
  }) => {
30064
30149
  import.meta.css = [css$12, "@jsenv/navi/src/nav/route_transition.jsx"];
30065
30150
  installTransitionWindowCss();
30151
+ installTransitionFurnitureCss();
30066
30152
  const props = {
30067
30153
  ...rest,
30068
30154
  [TRANSITION_AREA_ATTRIBUTE]: ""