@jsenv/navi 0.29.75 → 0.29.77

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.
@@ -60,7 +60,9 @@ const css$12 = /* css */`
60
60
  what the page positioned itself, which loses to DOM order otherwise
61
61
  (a sticky part is written before what scrolls under it). Box applies
62
62
  it by default, isolated, and lets a call site write auto back:
63
- --box-header-z-index / --box-footer-z-index.
63
+ --box-header-z-index / --box-footer-z-index. <Box sticky> gets it from
64
+ the prop itself, for the same reason and with the same way out (an
65
+ explicit zIndex, "auto" included).
64
66
 
65
67
  "While stuck" is the condition the name states, and it costs something
66
68
  to ignore: a sticky part at rest is a block in the flow with nothing
@@ -16935,6 +16937,28 @@ const DIMENSION_PROPS = {
16935
16937
  return { transform: `scaleZ(${value})` };
16936
16938
  },
16937
16939
  };
16940
+ const applyPositionSticky = applyToCssPropWhenTruthy(
16941
+ "position",
16942
+ "sticky",
16943
+ "static",
16944
+ );
16945
+ // A sticky box is one something scrolls under, which is what
16946
+ // --navi-z-index-sticky names; without it the box is a positioned element at
16947
+ // z-index: auto and loses to anything the page raised — a Group member holding
16948
+ // focus (2) is seen passing in front of a sticky submit bar. Like Box's own
16949
+ // header/footer, the band applies always and not only while stuck: a box
16950
+ // written by an app is the generic case, it cannot read its own stuck state
16951
+ // (see docs/z_index.md), and dropping to auto loses to a single
16952
+ // position: relative. An explicit zIndex (including zIndex="auto") wins.
16953
+ const stickyZIndex = (styleContext) => {
16954
+ if (
16955
+ styleContext.styles.zIndex !== undefined ||
16956
+ styleContext.remainingProps.zIndex !== undefined
16957
+ ) {
16958
+ return null;
16959
+ }
16960
+ return { zIndex: "var(--navi-z-index-sticky)" };
16961
+ };
16938
16962
  const POSITION_PROPS = {
16939
16963
  // For row, selfAlignX uses auto margins for positioning
16940
16964
  // NOTE: Auto margins only work effectively for positioning individual items.
@@ -17002,11 +17026,22 @@ const POSITION_PROPS = {
17002
17026
  }
17003
17027
  return undefined;
17004
17028
  },
17005
- position: PASS_THROUGH,
17029
+ position: (value, styleContext) => {
17030
+ if (value === "sticky") {
17031
+ return { position: "sticky", ...stickyZIndex(styleContext) };
17032
+ }
17033
+ return { position: value };
17034
+ },
17006
17035
  absolute: applyToCssPropWhenTruthy("position", "absolute", "static"),
17007
17036
  relative: applyToCssPropWhenTruthy("position", "relative", "static"),
17008
17037
  fixed: applyToCssPropWhenTruthy("position", "fixed", "static"),
17009
- sticky: applyToCssPropWhenTruthy("position", "sticky", "static"),
17038
+ sticky: (value, styleContext) => {
17039
+ const positionStyles = applyPositionSticky(value, styleContext);
17040
+ if (!value) {
17041
+ return positionStyles;
17042
+ }
17043
+ return { ...positionStyles, ...stickyZIndex(styleContext) };
17044
+ },
17010
17045
  zIndex: PASS_THROUGH,
17011
17046
  // Keeps the zIndex values used inside this box local to it — see
17012
17047
  // docs/z_index.md: a z-index that opens no stacking context competes with
@@ -30219,6 +30254,29 @@ const css$X = /* css */`
30219
30254
  outline-color: var(--dialog-outline-color);
30220
30255
  outline-offset: 0;
30221
30256
  box-shadow: var(--dialog-box-shadow);
30257
+
30258
+ /* A gesture landing on the dialog belongs to the dialog: what it cannot
30259
+ scroll (a short body, an axis with nowhere to go) must not travel to
30260
+ whatever is behind. */
30261
+ overscroll-behavior: none;
30262
+
30263
+ /* Docking answers a different question than --dialog-max-width: a sheet
30264
+ spans its container's full width, flush against the two side edges —
30265
+ that shape IS the mode — while the caller's ceiling was an answer about
30266
+ the *centered* box ("do not sprawl on a wide window"). Applying it here
30267
+ turns the sheet into a small floating box that no longer touches the
30268
+ edges it was docked to, so it is dropped out of the clamp entirely; the
30269
+ container ceiling still holds. --dialog-min-width needs no such rule:
30270
+ the floor is below the full width a docked dialog takes, so it stops
30271
+ mattering on its own. Height is untouched — a sheet is content-tall, not
30272
+ container-tall (expandY cancels docking outright), so --dialog-max-height
30273
+ still means what it meant. */
30274
+ &[data-docked] {
30275
+ --x-dialog-max-width: min(
30276
+ var(--container-position-remaining-width, var(--dialog-maxmax-width)),
30277
+ var(--dialog-maxmax-width)
30278
+ );
30279
+ }
30222
30280
  /* The clamped max, not --dialog-maxmax-*: that one is the viewport minus
30223
30281
  the spacing, which is only the real ceiling for layer="top". A local
30224
30282
  dialog is confined to its positioned ancestor, whose size reaches here
@@ -30459,7 +30517,15 @@ const css$X = /* css */`
30459
30517
  * from where the finger just tapped, and size alone would dock a narrow
30460
30518
  * desktop window, which is still a mouse. It supplies defaults for
30461
30519
  * `positionArea`, `marginWithContainer`, `expandX` and `scrollCapture`, so
30462
- * any of them can still be pinned explicitly. Ignored entirely when `expandY`
30520
+ * any of them can still be pinned explicitly including `expandX={false}`,
30521
+ * which opts the docked dialog out of the full-width stretch and leaves it a
30522
+ * floating box at the bottom. It also withdraws `maxWidth` while docked: a
30523
+ * sheet is container-wide by definition, and a `maxWidth` is an answer about
30524
+ * the *centered* shape, so the two can be stated together (`maxWidth="16rem"
30525
+ * dockedOnSmallTouchScreen`) and each applies where it means something.
30526
+ * `minWidth` needs no such rule — its floor is below the full width — and
30527
+ * `maxHeight`/`minHeight` keep applying, a sheet being content-tall.
30528
+ * Ignored entirely when `expandY`
30463
30529
  * (or `expand`) is set: a dialog already filling the height is on the bottom
30464
30530
  * edge docking would bring it to, so docking could only take away the shape
30465
30531
  * the caller asked for. Re-resolves live as the pointer
@@ -30481,7 +30547,10 @@ const css$X = /* css */`
30481
30547
  * @param {boolean} [props.expand] - Shorthand for both `expandX` and `expandY`.
30482
30548
  * @param {boolean} [props.expandX] - Stretches the dialog to the full width its
30483
30549
  * container allows (`--dialog-maxmax-width`). Set by
30484
- * `dockedOnSmallTouchScreen` on a small touch screen.
30550
+ * `dockedOnSmallTouchScreen` on a small touch screen — so passing `false`
30551
+ * here also opts out of *that* stretch, leaving a docked dialog a floating
30552
+ * box instead of a flush sheet. To keep the sheet flush and merely cap the
30553
+ * centered shape, use `maxWidth`: docking withdraws it on its own.
30485
30554
  * @param {boolean} [props.expandY] - Same, vertically
30486
30555
  * (`--dialog-maxmax-height`). Cancels `dockedOnSmallTouchScreen`.
30487
30556
  * @param {string|number} [props.marginWithContainer="3appw"] - Minimum gap kept
@@ -30540,7 +30609,9 @@ const css$X = /* css */`
30540
30609
  * so it can never push the dialog past `--dialog-maxmax-width` (the
30541
30610
  * viewport/container-spacing ceiling) regardless of how large a value is
30542
30611
  * passed.
30543
- * @param {string} [props.maxWidth] - Maps to `--dialog-max-width`.
30612
+ * @param {string} [props.maxWidth] - Maps to `--dialog-max-width`. Describes
30613
+ * the centered shape only: a dialog docked by `dockedOnSmallTouchScreen`
30614
+ * ignores it and stays container-wide.
30544
30615
  * @param {string} [props.minHeight] - Maps to `--dialog-min-height`, same
30545
30616
  * clamping as `minWidth`.
30546
30617
  * @param {string} [props.maxHeight] - Maps to `--dialog-max-height`.
@@ -31059,7 +31130,11 @@ const useDialogProps = props => {
31059
31130
  }));
31060
31131
  }
31061
31132
  if (scrollCapture) {
31062
- addCleanup(trapScrollInside(dialogEl));
31133
+ // A modal dialog always has its own ::backdrop; the custom renderer has
31134
+ // the backdrop element when it renders one.
31135
+ addCleanup(trapScrollInside(dialogEl, {
31136
+ backdrop: isModal || backdropEl
31137
+ }));
31063
31138
  } else if (!isModal) {
31064
31139
  // A local dialog is confined to its positioned ancestor, and so is its
31065
31140
  // backdrop (inset: 0 covers the scrollport, not the scrolled content):
@@ -31458,6 +31533,10 @@ const useDialogProps = props => {
31458
31533
  // scrolling area, so it says so once, here.
31459
31534
  "overflow": "auto",
31460
31535
  "data-layer": layer,
31536
+ // The sheet shape is live in CSS, not just a set of resolved defaults:
31537
+ // it is what withdraws the caller's --dialog-max-width (see the stylesheet
31538
+ // above), which is an answer about the centered box only.
31539
+ "data-docked": isDocked ? "" : undefined,
31461
31540
  "data-expand-x": expandX ? "" : undefined,
31462
31541
  "data-expand-y": expandY ? "" : undefined,
31463
31542
  "data-flush-top": flushEdges.top ? "" : undefined,
@@ -32592,7 +32671,9 @@ const usePopoverProps = props => {
32592
32671
  // here.
32593
32672
  };
32594
32673
  if (scrollCapture) {
32595
- addCleanup(trapScrollInside(popoverEl));
32674
+ addCleanup(trapScrollInside(popoverEl, {
32675
+ backdrop: backdropEl
32676
+ }));
32596
32677
  }
32597
32678
  if (focusCapture) {
32598
32679
  addCleanup(trapFocusInside(popoverEl, {
@@ -65867,6 +65948,8 @@ const css$l = /* css */`
65867
65948
  * positionArea?: string,
65868
65949
  * popupWidthFitContent?: boolean,
65869
65950
  * popoverMaxHeight?: number | string,
65951
+ * dialogMinWidth?: number | string,
65952
+ * dialogMinHeight?: number | string,
65870
65953
  * dialogMaxWidth?: number | string,
65871
65954
  * dialogMaxHeight?: number | string,
65872
65955
  * dialogExpand?: boolean,
@@ -65916,7 +65999,8 @@ const css$l = /* css */`
65916
65999
  * popover; a dialog keeps Dialog's own "center".
65917
66000
  *
65918
66001
  * Every other prop the Picker's popup answers to is forwarded as-is —
65919
- * `dockedOnSmallTouchScreen`, `dialogExpand*`, `dialogMaxWidth`/`Height`,
66002
+ * `dockedOnSmallTouchScreen`, `dialogExpand*`, `dialogMinWidth`/`Height`,
66003
+ * `dialogMaxWidth`/`Height`,
65920
66004
  * `marginWithContainer`, `popoverMode`, `popoverSpacing`, `popupLayer`,
65921
66005
  * `popupWidthFitContent`, `popoverMaxHeight`, `backdropVariant`,
65922
66006
  * `pointerInteractionOutsideEffect`, `escapeEffect`, `closeOnFocusOut`,
@@ -66121,7 +66205,7 @@ const SplitButton = props => {
66121
66205
  // What the Picker's popup answers to — Picker's own popup props, named here so
66122
66206
  // a caller reaches all of them through the split button (see picker.jsx's JSDoc
66123
66207
  // for what each one says).
66124
- const POPUP_PROP_SET = new Set(["mode", "popupLayer", "positionArea", "popoverMode", "popoverSpacing", "popupWidthFitContent", "popoverMaxHeight", "dialogMaxWidth", "dialogMaxHeight", "dialogExpand", "dialogExpandX", "dialogExpandY", "dockedOnSmallTouchScreen", "marginWithContainer", "backdropVariant", "pointerInteractionOutsideEffect", "escapeEffect", "closeOnFocusOut", "scrollCapture", "focusCapture", "popupBackgroundColor", "popupBorderRadius", "animation"]);
66208
+ const POPUP_PROP_SET = new Set(["mode", "popupLayer", "positionArea", "popoverMode", "popoverSpacing", "popupWidthFitContent", "popoverMaxHeight", "dialogMinWidth", "dialogMinHeight", "dialogMaxWidth", "dialogMaxHeight", "dialogExpand", "dialogExpandX", "dialogExpandY", "dockedOnSmallTouchScreen", "marginWithContainer", "backdropVariant", "pointerInteractionOutsideEffect", "escapeEffect", "closeOnFocusOut", "scrollCapture", "focusCapture", "popupBackgroundColor", "popupBorderRadius", "animation"]);
66125
66209
  const splitPopupProps = props => {
66126
66210
  const popupProps = {};
66127
66211
  const boxProps = {};