@jsenv/navi 0.29.372 → 0.29.374

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.
@@ -29123,6 +29123,11 @@ const FURNITURE_NAME_PREFIX = "navi-transition-furniture-";
29123
29123
  const TOP_LAYER_WALL_SELECTOR =
29124
29124
  ".navi_dialog:modal, .navi_popover_backdrop:popover-open";
29125
29125
  const WALL_ATTRIBUTE = "data-navi-transition-wall";
29126
+ // Worn by a bar both states have, from the hold on: its two pictures are one
29127
+ // group, and the group is ordered over the pages (route_transition.jsx). Only
29128
+ // a bar — a popup's class is written by layout/popup_css.js, and a second rule
29129
+ // on the same property would replace it.
29130
+ const SHARED_ATTRIBUTE = "data-navi-transition-furniture-shared";
29126
29131
  // What the wall paints, resolved on the matched element in both cases (the
29127
29132
  // dialog for its ::backdrop, the popover's wall for itself): the same two
29128
29133
  // properties, copied onto the stand-in.
@@ -29131,7 +29136,11 @@ const WALL_PROPERTIES = ["--backdrop-background", "--backdrop-filter"];
29131
29136
  // The pictures the wall is painted into: the pages', and every bar's own.
29132
29137
  const FIXED_BAR_SELECTOR$1 = ".navi_fixed_bar";
29133
29138
 
29134
- const TRANSITION_WALL_CSS = /* css */ `[data-navi-transition-wall] {
29139
+ const TRANSITION_FURNITURE_CSS = /* css */ `.navi_fixed_bar[data-navi-transition-furniture-shared] {
29140
+ view-transition-class: navi_furniture_shared;
29141
+ }
29142
+
29143
+ [data-navi-transition-wall] {
29135
29144
  z-index: var(--navi-z-index-top-layer);
29136
29145
  background: var(--backdrop-background);
29137
29146
  backdrop-filter: var(--backdrop-filter);
@@ -29164,7 +29173,7 @@ const TRANSITION_WALL_CSS = /* css */ `[data-navi-transition-wall] {
29164
29173
  // a page that never travels between routes must not carry this sheet, and a
29165
29174
  // build that sees no caller drops the css with the function.
29166
29175
  const installTransitionFurnitureCss = () => {
29167
- import.meta.css = [TRANSITION_WALL_CSS, "@jsenv/navi/src/nav/transition_furniture.js"];
29176
+ import.meta.css = [TRANSITION_FURNITURE_CSS, "@jsenv/navi/src/nav/transition_furniture.js"];
29168
29177
  };
29169
29178
 
29170
29179
  const nameByElement = new WeakMap();
@@ -29226,6 +29235,8 @@ const holdTransitionFurniture = (owner, areaElement) => {
29226
29235
  for (const element of namedElements) {
29227
29236
  if (!element.isConnected) {
29228
29237
  namesLeaving.push(nameByElement.get(element));
29238
+ } else if (element.matches(FIXED_BAR_SELECTOR$1)) {
29239
+ element.setAttribute(SHARED_ATTRIBUTE, "");
29229
29240
  }
29230
29241
  }
29231
29242
  const namesArriving = nameFurnitureAround(areaElement);
@@ -29356,6 +29367,7 @@ const releaseTransitionFurniture = (owner) => {
29356
29367
  furnitureOwner = null;
29357
29368
  for (const element of namedElements) {
29358
29369
  element.style.removeProperty(NAME_PROPERTY$1);
29370
+ element.removeAttribute(SHARED_ATTRIBUTE);
29359
29371
  }
29360
29372
  namedElements = new Set();
29361
29373
  if (travelStyleElement) {
@@ -29387,12 +29399,12 @@ const paintTransitionWalls = (areaElement) => {
29387
29399
  // positioned against an ancestor of it: the wall is placed from
29388
29400
  // wherever its containing block turns out to be, by the offset between
29389
29401
  // that box and the target's.
29390
- const targetRect = target.getBoundingClientRect();
29402
+ const targetRect = pictureRect(target);
29391
29403
  const wallRect = wall.getBoundingClientRect();
29392
29404
  wall.style.left = `${targetRect.left - wallRect.left}px`;
29393
29405
  wall.style.top = `${targetRect.top - wallRect.top}px`;
29394
- wall.style.width = `${targetRect.width}px`;
29395
- wall.style.height = `${targetRect.height}px`;
29406
+ wall.style.width = `${targetRect.right - targetRect.left}px`;
29407
+ wall.style.height = `${targetRect.bottom - targetRect.top}px`;
29396
29408
  wallElements.push(wall);
29397
29409
  }
29398
29410
  }
@@ -29446,11 +29458,45 @@ const paintRestWalls = (sources, opacity) => {
29446
29458
  const measurePictureRects = (areaElement) => {
29447
29459
  const rects = new Map();
29448
29460
  for (const target of pictureTargets(areaElement)) {
29449
- rects.set(target, target.getBoundingClientRect());
29461
+ rects.set(target, pictureRect(target));
29450
29462
  }
29451
29463
  return rects;
29452
29464
  };
29453
29465
 
29466
+ // What the picture holds, which is what the wall covers at rest: a bar's
29467
+ // picture carries what its content paints outside its box (a button standing
29468
+ // up out of a tab bar), so its rectangle is taken with its descendants'. The
29469
+ // pages' is their own box — the movement cuts them at it anyway.
29470
+ const pictureRect = (target) => {
29471
+ const rect = target.getBoundingClientRect();
29472
+ let { left, top, right, bottom } = rect;
29473
+ if (!target.matches(FIXED_BAR_SELECTOR$1)) {
29474
+ return { left, top, right, bottom };
29475
+ }
29476
+ for (const descendant of target.querySelectorAll("*")) {
29477
+ if (descendant.hasAttribute(WALL_ATTRIBUTE)) {
29478
+ continue;
29479
+ }
29480
+ const descendantRect = descendant.getBoundingClientRect();
29481
+ if (descendantRect.width === 0 || descendantRect.height === 0) {
29482
+ continue;
29483
+ }
29484
+ if (descendantRect.left < left) {
29485
+ left = descendantRect.left;
29486
+ }
29487
+ if (descendantRect.top < top) {
29488
+ top = descendantRect.top;
29489
+ }
29490
+ if (descendantRect.right > right) {
29491
+ right = descendantRect.right;
29492
+ }
29493
+ if (descendantRect.bottom > bottom) {
29494
+ bottom = descendantRect.bottom;
29495
+ }
29496
+ }
29497
+ return { left, top, right, bottom };
29498
+ };
29499
+
29454
29500
  // The holes for the movement, and the ones for its last frame (see the CSS).
29455
29501
  const cutRestWalls = (holes, holesArriving = null) => {
29456
29502
  for (const restWall of restWallElements) {
@@ -29465,15 +29511,83 @@ const cutRestWalls = (holes, holesArriving = null) => {
29465
29511
  };
29466
29512
 
29467
29513
  // One evenodd polygon: the window, then each hole entered from and left by
29468
- // the window's origin, so the bridges between them have no area.
29514
+ // the window's origin, so the bridges between them have no area. The holes
29515
+ // must not overlap — evenodd fills where two of them do — and they do
29516
+ // overlap as measured: the pages run under the bars by design, so a bar's
29517
+ // rectangle lies inside the area's. Each is cut down to what the ones before
29518
+ // it left.
29469
29519
  const holesPolygon = (holes) => {
29470
29520
  let polygon = "0 0, 100% 0, 100% 100%, 0 100%, 0 0";
29471
- for (const { left, top, right, bottom } of holes) {
29521
+ for (const { left, top, right, bottom } of disjointRects(holes)) {
29472
29522
  polygon += `, ${left}px ${top}px, ${right}px ${top}px, ${right}px ${bottom}px, ${left}px ${bottom}px, ${left}px ${top}px, 0 0`;
29473
29523
  }
29474
29524
  return `polygon(evenodd, ${polygon})`;
29475
29525
  };
29476
29526
 
29527
+ const disjointRects = (rects) => {
29528
+ const result = [];
29529
+ for (const rect of rects) {
29530
+ let pieces = [rect];
29531
+ for (const placed of result) {
29532
+ const remaining = [];
29533
+ for (const piece of pieces) {
29534
+ remaining.push(...subtractRect(piece, placed));
29535
+ }
29536
+ pieces = remaining;
29537
+ }
29538
+ result.push(...pieces);
29539
+ }
29540
+ return result;
29541
+ };
29542
+
29543
+ // What is left of `rect` outside `hole`: up to four rectangles around it.
29544
+ const subtractRect = (rect, hole) => {
29545
+ if (
29546
+ hole.left >= rect.right ||
29547
+ hole.right <= rect.left ||
29548
+ hole.top >= rect.bottom ||
29549
+ hole.bottom <= rect.top
29550
+ ) {
29551
+ return [rect];
29552
+ }
29553
+ const pieces = [];
29554
+ const innerTop = hole.top > rect.top ? hole.top : rect.top;
29555
+ const innerBottom = hole.bottom < rect.bottom ? hole.bottom : rect.bottom;
29556
+ if (hole.top > rect.top) {
29557
+ pieces.push({
29558
+ left: rect.left,
29559
+ top: rect.top,
29560
+ right: rect.right,
29561
+ bottom: hole.top,
29562
+ });
29563
+ }
29564
+ if (hole.bottom < rect.bottom) {
29565
+ pieces.push({
29566
+ left: rect.left,
29567
+ top: hole.bottom,
29568
+ right: rect.right,
29569
+ bottom: rect.bottom,
29570
+ });
29571
+ }
29572
+ if (hole.left > rect.left) {
29573
+ pieces.push({
29574
+ left: rect.left,
29575
+ top: innerTop,
29576
+ right: hole.left,
29577
+ bottom: innerBottom,
29578
+ });
29579
+ }
29580
+ if (hole.right < rect.right) {
29581
+ pieces.push({
29582
+ left: hole.right,
29583
+ top: innerTop,
29584
+ right: rect.right,
29585
+ bottom: innerBottom,
29586
+ });
29587
+ }
29588
+ return pieces;
29589
+ };
29590
+
29477
29591
  const removeRestWalls = () => {
29478
29592
  for (const restWall of restWallElements) {
29479
29593
  restWall.remove();
@@ -30058,10 +30172,14 @@ const css$12 = /* css */`:root[data-navi-route-transition] [data-navi-route-tran
30058
30172
  z-index: 1;
30059
30173
  }
30060
30174
 
30061
- &::view-transition-group(.navi_popup) {
30175
+ &::view-transition-group(.navi_furniture_shared) {
30062
30176
  z-index: 2;
30063
30177
  }
30064
30178
 
30179
+ &::view-transition-group(.navi_popup) {
30180
+ z-index: 3;
30181
+ }
30182
+
30065
30183
  &::view-transition-group(*), &::view-transition-old(*), &::view-transition-new(*) {
30066
30184
  animation-duration: var(--navi-route-transition-duration, .3s);
30067
30185
  }