@jsenv/navi 0.29.370 → 0.29.372

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.
@@ -29997,8 +29997,13 @@ installImportMetaCssBuild(import.meta);
29997
29997
  * outside the area. A bar the two states share is one group with two
29998
29998
  * pictures — dimmed on the side that has a wall — and its cross-fade is the
29999
29999
  * wall fading out as the page leaves, or in as it arrives; a bar only one
30000
- * state has carries the wall with it. A popup with layer="local" paints its
30001
- * wall inside the page and needs none of this.
30000
+ * state has carries the wall with it. What no picture covers — the glass
30001
+ * beside a narrowed app, the window below a page shorter than it — shows the
30002
+ * live document through, and only the live document can paint a wall there:
30003
+ * one fixed stand-in over the window, under the pictures, with a hole cut
30004
+ * where each picture stands, its opacity taken from the state being left to
30005
+ * the state arriving on the movement's own clock. A popup with layer="local"
30006
+ * paints its wall inside the page and needs none of this.
30002
30007
  */
30003
30008
 
30004
30009
  // The browser's top layer: painted above everything the document paints, so
@@ -30040,10 +30045,24 @@ const TRANSITION_WALL_CSS = /* css */ `[data-navi-transition-wall] {
30040
30045
  position: absolute;
30041
30046
  top: 0;
30042
30047
  left: 0;
30048
+
30049
+ &[data-navi-transition-wall="rest"] {
30050
+ clip-path: var(--wall-holes);
30051
+ transition: opacity var(--navi-route-transition-duration, .3s) ease;
30052
+ position: fixed;
30053
+ inset: 0;
30054
+ }
30043
30055
  }
30044
30056
 
30045
- :root:not(:active-view-transition) [data-navi-transition-wall] {
30046
- display: none;
30057
+ :root:not(:active-view-transition) [data-navi-transition-wall="rest"] {
30058
+ clip-path: var(--wall-holes-arriving, var(--wall-holes));
30059
+ }
30060
+
30061
+ :root[data-navi-route-transition] {
30062
+ & .navi_dialog::backdrop, & .navi_popover_backdrop {
30063
+ backdrop-filter: none;
30064
+ background: none;
30065
+ }
30047
30066
  }
30048
30067
  `;
30049
30068
 
@@ -30068,6 +30087,14 @@ let travelStyleElement = null;
30068
30087
  // The stand-ins for the walls open in the top layer, painted for one picture
30069
30088
  // and taken down before the next.
30070
30089
  let wallElements = [];
30090
+ // The stand-ins for what no picture covers, kept for the whole movement, and
30091
+ // the opacity they are heading to once it plays.
30092
+ let restWallElements = [];
30093
+ let restWallOpacity = "0";
30094
+ // Where each picture stood in the state being left, by element: a hole in
30095
+ // the rest walls is cut only where a picture stands at EVERY moment of the
30096
+ // movement, which takes both states' rectangles.
30097
+ let leavingRects = new Map();
30071
30098
 
30072
30099
  /**
30073
30100
  * Name what stands around the area, before the picture of the state being left
@@ -30080,7 +30107,14 @@ const nameTransitionFurniture = (owner, areaElement) => {
30080
30107
  namedElements = new Set();
30081
30108
  }
30082
30109
  nameFurnitureAround(areaElement);
30083
- paintTransitionWalls(areaElement);
30110
+ const sources = paintTransitionWalls(areaElement);
30111
+ // The state being left has walls: what no picture covers starts dimmed.
30112
+ // The frame the first picture is taken on shows the live document, so the
30113
+ // holes are this state's rectangles, stand-ins inside.
30114
+ removeRestWalls();
30115
+ leavingRects = measurePictureRects(areaElement);
30116
+ paintRestWalls(sources, "1");
30117
+ cutRestWalls([...leavingRects.values()]);
30084
30118
  };
30085
30119
 
30086
30120
  /**
@@ -30101,7 +30135,44 @@ const holdTransitionFurniture = (owner, areaElement) => {
30101
30135
  }
30102
30136
  }
30103
30137
  const namesArriving = nameFurnitureAround(areaElement);
30104
- paintTransitionWalls(areaElement);
30138
+ const sources = paintTransitionWalls(areaElement);
30139
+ // The state arriving has walls: what no picture covers ends dimmed. Painted
30140
+ // from the state being left when that one had walls (they stay up if both
30141
+ // have), from the state arriving otherwise (they come up from nothing).
30142
+ restWallOpacity = sources.length > 0 ? "1" : "0";
30143
+ if (restWallElements.length === 0) {
30144
+ paintRestWalls(sources, "0");
30145
+ }
30146
+ // For the length of the movement a picture is only ever where the two
30147
+ // states' rectangles meet: the pages' pictures slide, and a taller page
30148
+ // arriving does not make the one leaving any taller. A picture only one
30149
+ // state has travels away from where it stood, so it gets no hole at all.
30150
+ const arrivingRects = measurePictureRects(areaElement);
30151
+ const holes = [];
30152
+ for (const [target, arrivingRect] of arrivingRects) {
30153
+ const leavingRect = leavingRects.get(target);
30154
+ if (!leavingRect) {
30155
+ continue;
30156
+ }
30157
+ const left =
30158
+ leavingRect.left > arrivingRect.left
30159
+ ? leavingRect.left
30160
+ : arrivingRect.left;
30161
+ const top =
30162
+ leavingRect.top > arrivingRect.top ? leavingRect.top : arrivingRect.top;
30163
+ const right =
30164
+ leavingRect.right < arrivingRect.right
30165
+ ? leavingRect.right
30166
+ : arrivingRect.right;
30167
+ const bottom =
30168
+ leavingRect.bottom < arrivingRect.bottom
30169
+ ? leavingRect.bottom
30170
+ : arrivingRect.bottom;
30171
+ if (right > left && bottom > top) {
30172
+ holes.push({ left, top, right, bottom });
30173
+ }
30174
+ }
30175
+ cutRestWalls(holes, [...arrivingRects.values()]);
30105
30176
  const cssText = `${travelRule("old", namesLeaving, "--navi-route-transition-leave")}${travelRule("new", namesArriving, "--navi-route-transition-enter")}`;
30106
30177
  if (!cssText) {
30107
30178
  return;
@@ -30171,6 +30242,19 @@ const travelRule = (side, names, movementProperty) => {
30171
30242
  return `${selector}{animation-name:${animationName};animation-timing-function:ease;animation-fill-mode:both}`;
30172
30243
  };
30173
30244
 
30245
+ /**
30246
+ * The pictures are up and about to move: what no picture covers heads to the
30247
+ * state arriving, on the same clock.
30248
+ */
30249
+ const startTransitionFurniture = (owner) => {
30250
+ if (owner !== furnitureOwner) {
30251
+ return;
30252
+ }
30253
+ for (const restWall of restWallElements) {
30254
+ restWall.style.opacity = restWallOpacity;
30255
+ }
30256
+ };
30257
+
30174
30258
  const releaseTransitionFurniture = (owner) => {
30175
30259
  if (owner !== furnitureOwner) {
30176
30260
  return;
@@ -30185,6 +30269,7 @@ const releaseTransitionFurniture = (owner) => {
30185
30269
  travelStyleElement = null;
30186
30270
  }
30187
30271
  removeTransitionWalls();
30272
+ removeRestWalls();
30188
30273
  };
30189
30274
 
30190
30275
  // One stand-in per open wall in every picture, walls in document order: they
@@ -30197,25 +30282,11 @@ const paintTransitionWalls = (areaElement) => {
30197
30282
  removeTransitionWalls();
30198
30283
  const sources = document.querySelectorAll(TOP_LAYER_WALL_SELECTOR);
30199
30284
  if (sources.length === 0) {
30200
- return;
30201
- }
30202
- const targets = [areaElement];
30203
- for (const bar of document.querySelectorAll(FIXED_BAR_SELECTOR$1)) {
30204
- if (!areaElement.contains(bar)) {
30205
- targets.push(bar);
30206
- }
30285
+ return sources;
30207
30286
  }
30208
- for (const target of targets) {
30287
+ for (const target of pictureTargets(areaElement)) {
30209
30288
  for (const source of sources) {
30210
- const sourceStyle = getComputedStyle(source);
30211
- const wall = document.createElement("div");
30212
- wall.setAttribute(WALL_ATTRIBUTE, "");
30213
- for (const property of WALL_PROPERTIES) {
30214
- wall.style.setProperty(
30215
- property,
30216
- sourceStyle.getPropertyValue(property),
30217
- );
30218
- }
30289
+ const wall = createWall(source);
30219
30290
  target.appendChild(wall);
30220
30291
  // The target is not necessarily a containing block (the area is a plain
30221
30292
  // box), and made one for the movement it would move whatever the page
@@ -30231,6 +30302,7 @@ const paintTransitionWalls = (areaElement) => {
30231
30302
  wallElements.push(wall);
30232
30303
  }
30233
30304
  }
30305
+ return sources;
30234
30306
  };
30235
30307
 
30236
30308
  const removeTransitionWalls = () => {
@@ -30240,6 +30312,83 @@ const removeTransitionWalls = () => {
30240
30312
  wallElements = [];
30241
30313
  };
30242
30314
 
30315
+ // What is photographed on its own and gets a stand-in in its picture: the
30316
+ // pages, and every bar outside them.
30317
+ const pictureTargets = (areaElement) => {
30318
+ const targets = [areaElement];
30319
+ for (const bar of document.querySelectorAll(FIXED_BAR_SELECTOR$1)) {
30320
+ if (!areaElement.contains(bar)) {
30321
+ targets.push(bar);
30322
+ }
30323
+ }
30324
+ return targets;
30325
+ };
30326
+
30327
+ const createWall = (source) => {
30328
+ const sourceStyle = getComputedStyle(source);
30329
+ const wall = document.createElement("div");
30330
+ wall.setAttribute(WALL_ATTRIBUTE, "");
30331
+ for (const property of WALL_PROPERTIES) {
30332
+ wall.style.setProperty(property, sourceStyle.getPropertyValue(property));
30333
+ }
30334
+ return wall;
30335
+ };
30336
+
30337
+ // One per open wall, over the window, at the opacity of the state they are
30338
+ // painted from. A hole is cut where a picture stands, since the picture has
30339
+ // a stand-in of its own and shows the live document through nowhere — and on
30340
+ // the frames the live document IS shown, the first and the last, a hole is
30341
+ // what keeps the two from being painted on top of each other.
30342
+ const paintRestWalls = (sources, opacity) => {
30343
+ for (const source of sources) {
30344
+ const restWall = createWall(source);
30345
+ restWall.setAttribute(WALL_ATTRIBUTE, "rest");
30346
+ restWall.style.opacity = opacity;
30347
+ document.body.appendChild(restWall);
30348
+ restWallElements.push(restWall);
30349
+ }
30350
+ };
30351
+
30352
+ const measurePictureRects = (areaElement) => {
30353
+ const rects = new Map();
30354
+ for (const target of pictureTargets(areaElement)) {
30355
+ rects.set(target, target.getBoundingClientRect());
30356
+ }
30357
+ return rects;
30358
+ };
30359
+
30360
+ // The holes for the movement, and the ones for its last frame (see the CSS).
30361
+ const cutRestWalls = (holes, holesArriving = null) => {
30362
+ for (const restWall of restWallElements) {
30363
+ restWall.style.setProperty("--wall-holes", holesPolygon(holes));
30364
+ if (holesArriving) {
30365
+ restWall.style.setProperty(
30366
+ "--wall-holes-arriving",
30367
+ holesPolygon(holesArriving),
30368
+ );
30369
+ }
30370
+ }
30371
+ };
30372
+
30373
+ // One evenodd polygon: the window, then each hole entered from and left by
30374
+ // the window's origin, so the bridges between them have no area.
30375
+ const holesPolygon = (holes) => {
30376
+ let polygon = "0 0, 100% 0, 100% 100%, 0 100%, 0 0";
30377
+ for (const { left, top, right, bottom } of holes) {
30378
+ polygon += `, ${left}px ${top}px, ${right}px ${top}px, ${right}px ${bottom}px, ${left}px ${bottom}px, ${left}px ${top}px, 0 0`;
30379
+ }
30380
+ return `polygon(evenodd, ${polygon})`;
30381
+ };
30382
+
30383
+ const removeRestWalls = () => {
30384
+ for (const restWall of restWallElements) {
30385
+ restWall.remove();
30386
+ }
30387
+ restWallElements = [];
30388
+ restWallOpacity = "0";
30389
+ leavingRects = new Map();
30390
+ };
30391
+
30243
30392
  installImportMetaCssBuild(import.meta);
30244
30393
 
30245
30394
  const TRANSITION_WINDOW_CSS = /* css */ `@property --navi-transition-cover-top {
@@ -31836,6 +31985,7 @@ const beginTransition = ({
31836
31985
  // the only place the silent misconfigurations show. They are all about the
31837
31986
  // same thing — a movement playing on pictures that are not the pages.
31838
31987
  const viewTransitionReady = () => {
31988
+ startTransitionFurniture(transition);
31839
31989
  const capturedNames = capturedViewTransitionNames();
31840
31990
  if (areaElements.length > 0) {
31841
31991
  if (!capturedNames.has(AREA_NAME)) {