@jsenv/navi 0.30.28 → 0.30.30

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.
@@ -13987,7 +13987,7 @@ const CLICK_TO_EXPAND_SELECTOR = "summary, [aria-expanded]";
13987
13987
  // A popup is written inside whatever opened it, but it is not part of it on
13988
13988
  // screen: a control inside a popup must not be read as a click on the region
13989
13989
  // the popup happens to be nested in.
13990
- const POPUP_SELECTOR = "[navi-control='popover'], [navi-control='dialog']";
13990
+ const POPUP_SELECTOR$1 = "[navi-control='popover'], [navi-control='dialog']";
13991
13991
 
13992
13992
  /**
13993
13993
  * Cancels `event` when the control consumed a click that a surrounding
@@ -14025,7 +14025,7 @@ const findClickToExpandRegion = (element) => {
14025
14025
  while (ancestor) {
14026
14026
  // Tested first: a popup carries `aria-expanded` of its own, so it would
14027
14027
  // otherwise pass for the region containing its own content.
14028
- if (ancestor.matches(POPUP_SELECTOR)) {
14028
+ if (ancestor.matches(POPUP_SELECTOR$1)) {
14029
14029
  return null;
14030
14030
  }
14031
14031
  if (ancestor.matches(CLICK_TO_EXPAND_SELECTOR)) {
@@ -45048,6 +45048,17 @@ const resolveClosestExpandable = (el) => {
45048
45048
  }
45049
45049
  return expandableRepeatedBy(expandable) || expandable;
45050
45050
  };
45051
+ // The popup a decision taken inside it answers (a clear, a send). A section
45052
+ // revealed in the page flow (<Expandable>, data-in-flow) is not one: it belongs
45053
+ // to whatever holds it, a page or a popup, so the walk goes through it.
45054
+ const POPUP_SELECTOR = "[aria-expanded]:not([data-in-flow])";
45055
+ const resolveClosestPopup = (el) => {
45056
+ const popup = el.closest(POPUP_SELECTOR);
45057
+ if (!popup) {
45058
+ return null;
45059
+ }
45060
+ return expandableRepeatedBy(popup) || popup;
45061
+ };
45051
45062
  // A control's host repeats the aria-expanded of its root, beside its role, for
45052
45063
  // assistive tech to read (a picker's <input>, a combobox or a button). The root
45053
45064
  // is the expandable: the host is a leaf the walk lands on only when it is the
@@ -45064,16 +45075,16 @@ const expandableRepeatedBy = (el) => {
45064
45075
  }
45065
45076
  return null;
45066
45077
  };
45067
- // The surface a send is decided on: the expandable holding the CONTROL that
45068
- // sends, never one that control is itself. A picker's own root carries
45069
- // aria-expanded for its popup, and a confirm picker pressed as a whole (see
45078
+ // The surface a send is decided on: the popup holding the CONTROL that sends,
45079
+ // never one that control is itself. A picker's own root carries aria-expanded
45080
+ // for its popup, and a confirm picker pressed as a whole (see
45070
45081
  // picker_confirm.jsx) sends from its input: what it answers is the surface
45071
45082
  // around the picker, not the picker. Same for a popup told to send upward
45072
45083
  // once it has closed (data-after-send="--navi-send"): the surface above it.
45073
- const resolveExpandableAround = (source) => {
45084
+ const resolvePopupAround = (source) => {
45074
45085
  const sender = findControlRoot(source) || source;
45075
45086
  const parent = sender.parentElement;
45076
- return parent ? resolveClosestExpandable(parent) : null;
45087
+ return parent ? resolveClosestPopup(parent) : null;
45077
45088
  };
45078
45089
  // An element carrying navi-command-proxy-for="anchorId" stands in for that
45079
45090
  // other element as the command's source when the source is forwarded to
@@ -45099,16 +45110,14 @@ const resolveClosestControlWithAction = (el) => {
45099
45110
  return findClosestControlWithAction(el);
45100
45111
  };
45101
45112
  // Both can enclose the send's source: a form inside a dialog is a control with
45102
- // an action, inside an expandable. The nearer one owns the send — a button
45103
- // inside that form means "submit this form", not "confirm the dialog around
45104
- // it", and the same button placed directly in the dialog means the opposite.
45105
- const resolveClosestSendTarget = (expandable, controlWithAction) => {
45106
- if (!expandable || !controlWithAction) {
45107
- return expandable || controlWithAction;
45113
+ // an action, inside a popup. The nearer one owns the send — a button inside
45114
+ // that form means "submit this form", not "confirm the dialog around it", and
45115
+ // the same button placed directly in the dialog means the opposite.
45116
+ const resolveClosestSendTarget = (popup, controlWithAction) => {
45117
+ if (!popup || !controlWithAction) {
45118
+ return popup || controlWithAction;
45108
45119
  }
45109
- return expandable.contains(controlWithAction)
45110
- ? controlWithAction
45111
- : expandable;
45120
+ return popup.contains(controlWithAction) ? controlWithAction : popup;
45112
45121
  };
45113
45122
 
45114
45123
  // An id that names something that is not a control — a layout box, a label, a
@@ -45310,9 +45319,10 @@ const clearCommand = (source, event) => {
45310
45319
  }
45311
45320
  // Only what is open: the clear cross of a picker sits on the closed
45312
45321
  // trigger, with nothing to close. A clear pressed INSIDE an open popup is
45313
- // the one this is for: it answers the popup, so the popup goes away.
45314
- const expandable = resolveClosestExpandable(source);
45315
- if (expandable?.getAttribute("aria-expanded") !== "true") {
45322
+ // the one this is for: it answers the popup, so the popup goes away. An
45323
+ // open section of the page is answered by nothing pressed in it.
45324
+ const popup = resolveClosestPopup(source);
45325
+ if (popup?.getAttribute("aria-expanded") !== "true") {
45316
45326
  return;
45317
45327
  }
45318
45328
  // Asked of the popup itself, not resolved again from the source: a
@@ -45320,7 +45330,7 @@ const clearCommand = (source, event) => {
45320
45330
  // picker names the input it empties), and a close resolved from it would
45321
45331
  // aim at that input's picker — busy with the send it was just handed —
45322
45332
  // rather than at the popup the cross is in.
45323
- triggerNaviCommand(expandable, "--navi-close", clearEvent, {
45333
+ triggerNaviCommand(popup, "--navi-close", clearEvent, {
45324
45334
  optional: true,
45325
45335
  });
45326
45336
  };
@@ -45364,7 +45374,8 @@ const resetCommand = (source, event) => {
45364
45374
  * same act, a level down. A popup opened from another popup answers for
45365
45375
  * itself only — say `data-after-send="--navi-send"` on the sending control
45366
45376
  * to make the decision travel up to the surface holding it;
45367
- * - the document: nothing. A form on a page stays where it is.
45377
+ * - the document: nothing. A form on a page stays where it is, open
45378
+ * <Expandable> sections around it included (see resolveClosestPopup).
45368
45379
  */
45369
45380
  // What follows a send that went through — and it is asked of the button that
45370
45381
  // sent before the form it sent, because a form with two submit buttons has two
@@ -45395,7 +45406,7 @@ const resolveAfterSend = (target, requester, surface) => {
45395
45406
  // the target: a popup that IS the send target is handled on its own (see the
45396
45407
  // aria-expanded branch in sendCommand), and must not answer twice.
45397
45408
  const resolveSendSurface = (target) =>
45398
- target.parentElement?.closest(`[data-slide], [aria-expanded]`);
45409
+ target.parentElement?.closest(`[data-slide], ${POPUP_SELECTOR}`);
45399
45410
  // What follows a send is caused by the send, not by the gesture: the send
45400
45411
  // answered the gesture and may have prevented it (an Enter must not also click
45401
45412
  // the submit button, nor activate the trigger of the popup it closed), and a
@@ -45408,11 +45419,10 @@ const createSentEvent = (event) => {
45408
45419
  };
45409
45420
 
45410
45421
  const sendCommand = (source, event, { requester }) => {
45411
- const expandable = resolveExpandableAround(source);
45412
45422
  const target =
45413
45423
  resolveExplicitTarget(source) ||
45414
45424
  resolveClosestSendTarget(
45415
- expandable,
45425
+ resolvePopupAround(source),
45416
45426
  resolveClosestControlWithAction(source),
45417
45427
  );
45418
45428
  if (!target) {
@@ -45423,7 +45433,7 @@ const sendCommand = (source, event, { requester }) => {
45423
45433
  // looking at, and a decision just taken there is a reason to leave it. The
45424
45434
  // NEAREST surface answers, and only that one — a form inside a slide inside a
45425
45435
  // dialog goes back a slide, it does not also close the dialog.
45426
- // send inside expandable — the control itself when it sends from its host,
45436
+ // send inside popup — the control itself when it sends from its host,
45427
45437
  // whose aria-expanded is its root's (see expandableRepeatedBy)
45428
45438
  if (
45429
45439
  target.getAttribute("aria-expanded") === "true" &&
@@ -63056,7 +63066,11 @@ const Expandable = props => {
63056
63066
  return jsx(Box, {
63057
63067
  ref: rootRef,
63058
63068
  baseClassName: "navi_expandable",
63059
- "aria-expanded": opened ? "true" : "false",
63069
+ "aria-expanded": opened ? "true" : "false"
63070
+ // Read by commands.js: open or not, this is no popup — a clear or a send
63071
+ // pressed inside does not close it (see resolveClosestPopup).
63072
+ ,
63073
+ "data-in-flow": "",
63060
63074
  "data-layout": isColumn ? "column" : undefined,
63061
63075
  "data-open-direction": revealDirection,
63062
63076
  "data-animation": animation ? "" : undefined,
@@ -63151,6 +63165,7 @@ const ExpandableUI = ({
63151
63165
  role: "button",
63152
63166
  tabIndex: 0,
63153
63167
  "aria-expanded": opened,
63168
+ "data-in-flow": "",
63154
63169
  "aria-controls": contentId,
63155
63170
  onClick: onUIClick,
63156
63171
  onPointerDown: onUIPointerDown,