@jsenv/navi 0.27.54 → 0.27.55

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.
@@ -1,4 +1,4 @@
1
- import { installImportMetaCssBuild } from "./jsenv_navi_side_effects.js";
1
+ import { installImportMetaCssBuild, windowWidthSignal } from "./jsenv_navi_side_effects.js";
2
2
  import { isValidElement, createContext, h, toChildArray, render, Fragment, cloneElement } from "preact";
3
3
  import { useErrorBoundary, useLayoutEffect, useEffect, useContext, useMemo, useRef, useState, useCallback, useId } from "preact/hooks";
4
4
  import { jsxs, jsx, Fragment as Fragment$1 } from "preact/jsx-runtime";
@@ -35356,12 +35356,6 @@ const renderSafe = (value) => {
35356
35356
 
35357
35357
  const PickerContext = createContext();
35358
35358
 
35359
- const windowWidthSignal = signal(window.innerWidth);
35360
-
35361
- window.addEventListener("resize", () => {
35362
- windowWidthSignal.value = window.innerWidth;
35363
- });
35364
-
35365
35359
  /**
35366
35360
  * Mirrors what browsers do when navigating to a page:
35367
35361
  * 1. Focus the first element with [navi-autofocus] (but not [navi-autofocus="fallback"]) inside the container
@@ -35638,12 +35632,17 @@ const Dialog = props => {
35638
35632
  pseudoClasses: DIALOG_PSEUDO_CLASSES,
35639
35633
  onMouseDown: e => {
35640
35634
  rest.onMouseDown?.(e);
35641
- // The <dialog> element covers the full viewport; clicking the backdrop
35642
- // hits the dialog itself (not any child). Close when that happens.
35635
+ // Detect backdrop click: the click must land outside the dialog's
35636
+ // bounding rect. Checking coordinates is necessary because clicking
35637
+ // on the dialog's own padding also sets e.target === ref.current.
35643
35638
  if (!pointerTrap && e.button === 0 && e.target === ref.current) {
35644
- onRequestClose(e, {
35645
- isClickOutside: true
35646
- });
35639
+ const rect = ref.current.getBoundingClientRect();
35640
+ const isBackdrop = e.clientX < rect.left || e.clientX > rect.right || e.clientY < rect.top || e.clientY > rect.bottom;
35641
+ if (isBackdrop) {
35642
+ onRequestClose(e, {
35643
+ isClickOutside: true
35644
+ });
35645
+ }
35647
35646
  }
35648
35647
  },
35649
35648
  onCancel: e => {
@@ -35902,11 +35901,21 @@ installImportMetaCssBuild(import.meta);const css$p = /* css */`
35902
35901
  /* Shared by popover and dialog */
35903
35902
  --picker-popup-background-color: var(--picker-background-color);
35904
35903
  --picker-popup-border-radius: var(--picker-border-radius);
35904
+ --picker-popup-border-width: var(--picker-border-width);
35905
35905
  /* Popover */
35906
- --picker-popover-max-height: 300px;
35906
+ --picker-popover-max-height: 300px; /* soft: user-configurable preferred max-height */
35907
+ --picker-popover-maxmax-height: calc(0.95 * var(--navi-vvh));
35908
+ --picker-popover-maxmax-width: calc(0.95 * var(--navi-vvw));
35909
+ /* --picker-popover-max-width: soft, leave unset to rely on maxmax */
35907
35910
  /* Dialog */
35908
- --picker-dialog-max-width: 95dvw;
35909
- --picker-dialog-max-height: 95dvh;
35911
+ --picker-dialog-margin: 3dvw; /* min gap between dialog edges and viewport */
35912
+ --picker-dialog-maxmax-width: calc(
35913
+ var(--navi-vvw) - 2 * var(--picker-dialog-margin)
35914
+ );
35915
+ --picker-dialog-maxmax-height: calc(
35916
+ var(--navi-vvh) - 2 * var(--picker-dialog-margin)
35917
+ );
35918
+ --picker-dialog-border-width: 0px; /* Dialog do not need border like popover (they stand out more) */
35910
35919
 
35911
35920
  /* popover */
35912
35921
  &[aria-haspopup="listbox"] {
@@ -35914,11 +35923,15 @@ installImportMetaCssBuild(import.meta);const css$p = /* css */`
35914
35923
  position: absolute;
35915
35924
  inset: unset;
35916
35925
  min-width: var(--anchor-width, 0px);
35917
- max-width: 95vw;
35926
+ max-width: min(
35927
+ var(--picker-popover-max-width, var(--picker-popover-maxmax-width)),
35928
+ var(--picker-popover-maxmax-width)
35929
+ );
35918
35930
  /* max-height covers the placeholder + list; the list scrolls internally */
35919
35931
  max-height: min(
35920
35932
  var(--picker-popover-max-height),
35921
- var(--space-available, 95dvh)
35933
+ var(--space-available, var(--picker-popover-maxmax-height)),
35934
+ var(--picker-popover-maxmax-height)
35922
35935
  );
35923
35936
  margin: 0;
35924
35937
  padding: 0;
@@ -36012,11 +36025,18 @@ installImportMetaCssBuild(import.meta);const css$p = /* css */`
36012
36025
  &[aria-haspopup="dialog"] {
36013
36026
  .navi_picker_dialog {
36014
36027
  min-width: var(--anchor-width, 0px);
36015
- max-width: var(--picker-dialog-max-width);
36016
- max-height: var(--picker-dialog-max-height);
36028
+ max-width: min(
36029
+ var(--picker-dialog-max-width, var(--picker-dialog-maxmax-width)),
36030
+ var(--picker-dialog-maxmax-width)
36031
+ );
36032
+ max-height: min(
36033
+ var(--picker-dialog-max-height, var(--picker-dialog-maxmax-height)),
36034
+ var(--picker-dialog-maxmax-height)
36035
+ );
36017
36036
  padding: 0;
36018
36037
  background: var(--picker-popup-background-color);
36019
- border: var(--picker-border-width) solid var(--x-picker-border-color);
36038
+ border: var(--picker-dialog-border-width) solid
36039
+ var(--x-picker-border-color);
36020
36040
  border-radius: var(--picker-popup-border-radius);
36021
36041
  outline-width: var(--picker-outline-width);
36022
36042
  outline-color: var(--picker-outline-color);
@@ -36028,10 +36048,10 @@ installImportMetaCssBuild(import.meta);const css$p = /* css */`
36028
36048
  /* overscroll-behavior: contain; */
36029
36049
 
36030
36050
  &[data-expand-x] {
36031
- width: var(--picker-dialog-max-width);
36051
+ width: var(--picker-dialog-maxmax-width);
36032
36052
  }
36033
36053
  &[data-expand-y] {
36034
- height: var(--picker-dialog-max-height);
36054
+ height: var(--picker-dialog-maxmax-height);
36035
36055
  }
36036
36056
 
36037
36057
  &[open] {
@@ -36396,11 +36416,14 @@ const PickerCustom = props => {
36396
36416
  };
36397
36417
  }
36398
36418
  });
36419
+ const isWithinPopup = el => {
36420
+ const popupEl = popupRef.current;
36421
+ return el === popupEl || popupEl.contains(el);
36422
+ };
36399
36423
  Object.assign(pickerProps, {
36400
36424
  eventReactionDefinitions: {
36401
36425
  mouseDown: e => {
36402
- const popupEl = popupRef.current;
36403
- if (popupEl && popupEl.contains(e.target)) {
36426
+ if (isWithinPopup(e.target)) {
36404
36427
  return null;
36405
36428
  }
36406
36429
  if (expandedRef.current) {
@@ -36421,8 +36444,7 @@ const PickerCustom = props => {
36421
36444
  };
36422
36445
  },
36423
36446
  click: e => {
36424
- const popupEl = popupRef.current;
36425
- if (popupEl && popupEl.contains(e.target)) {
36447
+ if (isWithinPopup(e.target)) {
36426
36448
  return null;
36427
36449
  }
36428
36450
  // When a label is clicked it transfers focus to the select
@@ -40979,6 +41001,7 @@ const PickerStyleCSSVars = {
40979
41001
  "popoverMaxHeight": "--picker-popover-max-height",
40980
41002
  "popupBackgroundColor": "--picker-popup-background-color",
40981
41003
  "popupBorderRadius": "--picker-popup-border-radius",
41004
+ "dialogBorderWidth": "--picker-dialog-border-width",
40982
41005
  "padding": "--picker-padding",
40983
41006
  "paddingX": "--picker-padding-x",
40984
41007
  "paddingY": "--picker-padding-y",