@allxsmith/bestax-bulma 5.67.2 → 5.67.4

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.
Files changed (96) hide show
  1. package/dist/bestax.css +1 -1
  2. package/dist/bestax.css.map +1 -1
  3. package/dist/esm/components/Card.js +3 -14
  4. package/dist/esm/components/Card.js.map +1 -1
  5. package/dist/esm/components/Command.js +14 -3
  6. package/dist/esm/components/Command.js.map +1 -1
  7. package/dist/esm/components/ContextMenu.js +10 -10
  8. package/dist/esm/components/ContextMenu.js.map +1 -1
  9. package/dist/esm/components/Dialog.js +7 -3
  10. package/dist/esm/components/Dialog.js.map +1 -1
  11. package/dist/esm/components/HoverCard.js +2 -2
  12. package/dist/esm/components/HoverCard.js.map +1 -1
  13. package/dist/esm/components/Menu.js +2 -1
  14. package/dist/esm/components/Menu.js.map +1 -1
  15. package/dist/esm/components/Modal.js +11 -9
  16. package/dist/esm/components/Modal.js.map +1 -1
  17. package/dist/esm/components/Popover.js +2 -2
  18. package/dist/esm/components/Popover.js.map +1 -1
  19. package/dist/esm/components/Tabs.js +4 -3
  20. package/dist/esm/components/Tabs.js.map +1 -1
  21. package/dist/esm/elements/CopyButton.js +6 -3
  22. package/dist/esm/elements/CopyButton.js.map +1 -1
  23. package/dist/esm/elements/IconButton.js +3 -2
  24. package/dist/esm/elements/IconButton.js.map +1 -1
  25. package/dist/esm/elements/Stat.js +3 -2
  26. package/dist/esm/elements/Stat.js.map +1 -1
  27. package/dist/esm/form/ColorInputBase.js.map +1 -1
  28. package/dist/esm/form/Combobox.js +2 -2
  29. package/dist/esm/form/Combobox.js.map +1 -1
  30. package/dist/esm/form/DateInputBase.js.map +1 -1
  31. package/dist/esm/form/DateRangeInputBase.js.map +1 -1
  32. package/dist/esm/form/DateTimeInputBase.js.map +1 -1
  33. package/dist/esm/form/Field.js +6 -6
  34. package/dist/esm/form/Field.js.map +1 -1
  35. package/dist/esm/form/TimeInputBase.js.map +1 -1
  36. package/dist/esm/form/TreeSelect.js.map +1 -1
  37. package/dist/esm/form/_pickerInternals/Calendar.js +19 -12
  38. package/dist/esm/form/_pickerInternals/Calendar.js.map +1 -1
  39. package/dist/esm/form/_pickerInternals/PickerPopover.js +3 -3
  40. package/dist/esm/form/_pickerInternals/PickerPopover.js.map +1 -1
  41. package/dist/esm/helpers/Config.js.map +1 -1
  42. package/dist/esm/helpers/elementType.js +42 -0
  43. package/dist/esm/helpers/elementType.js.map +1 -0
  44. package/dist/esm/helpers/portal.js +57 -1
  45. package/dist/esm/helpers/portal.js.map +1 -1
  46. package/dist/esm/helpers/useAnchoredPosition.js +23 -12
  47. package/dist/esm/helpers/useAnchoredPosition.js.map +1 -1
  48. package/dist/esm/helpers/withSubComponents.js +1 -1
  49. package/dist/esm/helpers/withSubComponents.js.map +1 -1
  50. package/dist/esm/layout/AppFrame.js +4 -3
  51. package/dist/esm/layout/AppFrame.js.map +1 -1
  52. package/dist/esm/layout/Splitter.js +3 -2
  53. package/dist/esm/layout/Splitter.js.map +1 -1
  54. package/dist/extras.css +1 -1
  55. package/dist/extras.css.map +1 -1
  56. package/dist/index.cjs +196 -81
  57. package/dist/index.cjs.map +1 -1
  58. package/dist/types/components/HoverCard.d.ts +9 -8
  59. package/dist/types/components/Popover.d.ts +6 -5
  60. package/dist/types/form/ColorInputBase.d.ts +2 -1
  61. package/dist/types/form/Combobox.d.ts +6 -7
  62. package/dist/types/form/DateInputBase.d.ts +6 -2
  63. package/dist/types/form/DateRangeInputBase.d.ts +6 -2
  64. package/dist/types/form/DateTimeInputBase.d.ts +6 -2
  65. package/dist/types/form/TimeInputBase.d.ts +2 -1
  66. package/dist/types/form/TreeSelect.d.ts +1 -1
  67. package/dist/types/helpers/Config.d.ts +6 -3
  68. package/dist/types/helpers/elementType.d.ts +20 -0
  69. package/dist/types/helpers/portal.d.ts +44 -0
  70. package/dist/types/helpers/useAnchoredPosition.d.ts +3 -1
  71. package/dist/types/helpers/withSubComponents.d.ts +1 -1
  72. package/dist/types-cjs/components/HoverCard.d.ts +9 -8
  73. package/dist/types-cjs/components/Popover.d.ts +6 -5
  74. package/dist/types-cjs/form/ColorInputBase.d.ts +2 -1
  75. package/dist/types-cjs/form/Combobox.d.ts +6 -7
  76. package/dist/types-cjs/form/DateInputBase.d.ts +6 -2
  77. package/dist/types-cjs/form/DateRangeInputBase.d.ts +6 -2
  78. package/dist/types-cjs/form/DateTimeInputBase.d.ts +6 -2
  79. package/dist/types-cjs/form/TimeInputBase.d.ts +2 -1
  80. package/dist/types-cjs/form/TreeSelect.d.ts +1 -1
  81. package/dist/types-cjs/helpers/Config.d.ts +6 -3
  82. package/dist/types-cjs/helpers/elementType.d.ts +20 -0
  83. package/dist/types-cjs/helpers/portal.d.ts +44 -0
  84. package/dist/types-cjs/helpers/useAnchoredPosition.d.ts +3 -1
  85. package/dist/types-cjs/helpers/withSubComponents.d.ts +1 -1
  86. package/dist/versions/bestax-no-dark-mode.css +1 -1
  87. package/dist/versions/bestax-no-dark-mode.css.map +1 -1
  88. package/dist/versions/bestax-no-helpers-prefixed.css +1 -1
  89. package/dist/versions/bestax-no-helpers-prefixed.css.map +1 -1
  90. package/dist/versions/bestax-no-helpers.css +1 -1
  91. package/dist/versions/bestax-no-helpers.css.map +1 -1
  92. package/dist/versions/bestax-prefixed.css +1 -1
  93. package/dist/versions/bestax-prefixed.css.map +1 -1
  94. package/package.json +1 -1
  95. package/src/scss/components/_menu.scss +16 -2
  96. package/src/scss/form/_dateinput.scss +1 -1
package/dist/index.cjs CHANGED
@@ -1369,7 +1369,7 @@ const Column = ({ className, textColor, color: _fieldColor, bgColor, size, sizeM
1369
1369
  *
1370
1370
  * Internal helper — it MUST mutate and return the same function object
1371
1371
  * (`Object.assign`), never wrap the base in a new function: identity checks
1372
- * like `child.type === ModalCard` (Modal) and Field's displayName-based
1372
+ * like `isElementOf(child, ModalCard)` (Modal) and Field's displayName-based
1373
1373
  * child detection rely on the attached component being the same object as
1374
1374
  * the separately exported one.
1375
1375
  *
@@ -2518,6 +2518,42 @@ const Breadcrumb = ({ className, alignment, separator, size, children, ...props
2518
2518
  return (jsxRuntime.jsx("nav", { className: breadcrumbClasses, "aria-label": "breadcrumbs", ...rest, children: jsxRuntime.jsx("ul", { children: children }) }));
2519
2519
  };
2520
2520
 
2521
+ // INTERNAL: deliberately not exported from src/index.ts.
2522
+ /**
2523
+ * Whether `type` is a lazy type, which `React.lazy` returns. The symbol is
2524
+ * looked up here rather than when the module loads, which must do nothing.
2525
+ */
2526
+ const isLazy = (type) => typeof type === 'object' &&
2527
+ type !== null &&
2528
+ type.$$typeof === Symbol.for('react.lazy') &&
2529
+ typeof type._init === 'function';
2530
+ /**
2531
+ * The component an element renders, read through a lazy type.
2532
+ *
2533
+ * A client component written in a React Server Component reaches the client
2534
+ * as a client reference, whose element type is lazy rather than the
2535
+ * component's own function, so `child.type === Part` is never true there
2536
+ * (#1500). This resolves a lazy type the way React does when it renders one:
2537
+ * a module that has loaded gives its component, one still loading throws, so
2538
+ * the caller suspends at the boundary the element itself would have, and one
2539
+ * that failed throws its error. A lazy type without those fields comes back
2540
+ * as it is, so a part goes unrecognized, which is what happened before.
2541
+ */
2542
+ function elementType(element) {
2543
+ let type = element.type;
2544
+ while (isLazy(type))
2545
+ type = type._init(type._payload);
2546
+ return type;
2547
+ }
2548
+ /**
2549
+ * Whether `node` is an element of one of `types`, including one written in a
2550
+ * Server Component. A parent tells its parts apart with this, never by
2551
+ * comparing `child.type`.
2552
+ */
2553
+ function isElementOf(node, ...types) {
2554
+ return React.isValidElement(node) && types.includes(elementType(node));
2555
+ }
2556
+
2521
2557
  /**
2522
2558
  * The runtime mirror of `AnchorOnlyAttributes`, keyed so the two cannot drift.
2523
2559
  *
@@ -2610,17 +2646,7 @@ const mergeBulmaStyles = (helperStyles, style) => helperStyles || style ? { ...h
2610
2646
  * @returns {boolean} True if any child is a Card compound component.
2611
2647
  */
2612
2648
  const hasCompoundComponents = (children) => {
2613
- return React.Children.toArray(children).some(child => {
2614
- if (!React.isValidElement(child))
2615
- return false;
2616
- // Direct comparison with our compound component functions
2617
- return (child.type === CardHeader ||
2618
- child.type === CardContent ||
2619
- child.type === CardImage ||
2620
- child.type === CardFooter ||
2621
- child.type === CardFooterItem ||
2622
- child.type === CardHeaderIcon);
2623
- });
2649
+ return React.Children.toArray(children).some(child => isElementOf(child, CardHeader, CardContent, CardImage, CardFooter, CardFooterItem, CardHeaderIcon));
2624
2650
  };
2625
2651
  /**
2626
2652
  * The `Card` component renders a Bulma-styled card with optional header, image, content, and footer.
@@ -2706,9 +2732,7 @@ const CardHeaderComponent = ({ className, children, centered, color, bgColor, te
2706
2732
  ...props,
2707
2733
  });
2708
2734
  // Check if children contains a CardHeaderTitle component
2709
- const hasHeaderTitle = React.Children.toArray(children).some(child => React.isValidElement(child) &&
2710
- typeof child.type === 'function' &&
2711
- child.type === CardHeaderTitle);
2735
+ const hasHeaderTitle = React.Children.toArray(children).some(child => isElementOf(child, CardHeaderTitle));
2712
2736
  const headerClasses = usePrefixedClassNames('card-header');
2713
2737
  return (jsxRuntime.jsx("header", { className: classNames(headerClasses, bulmaHelperClasses, className), ...rest, children: hasHeaderTitle ? (children) : (jsxRuntime.jsx("div", { className: classNames(prefixedClassNames(classPrefix, 'card-header-title', {
2714
2738
  'is-centered': centered,
@@ -3857,7 +3881,7 @@ function iconOf(node) {
3857
3881
  if (items.length === 0)
3858
3882
  return null;
3859
3883
  const [only] = items;
3860
- if (items.length === 1 && React.isValidElement(only) && only.type === Icon) {
3884
+ if (items.length === 1 && isElementOf(only, Icon)) {
3861
3885
  return only;
3862
3886
  }
3863
3887
  return jsxRuntime.jsx(Icon, { children: items });
@@ -4025,6 +4049,47 @@ function usePortalContainer() {
4025
4049
  const { portalContainer } = useConfig();
4026
4050
  return container => resolvePortalContainer(container || portalContainer);
4027
4051
  }
4052
+ /**
4053
+ * The element the overlay around a popup hands it to portal into, `null`
4054
+ * outside any, and inside one whose element hasn't mounted yet.
4055
+ */
4056
+ const PortalScopeContext = React.createContext(null);
4057
+ /**
4058
+ * INTERNAL, deliberately not exported from `src/index.ts`. Makes `node` where
4059
+ * the popups inside it portal, unless a `ConfigProvider` sets a
4060
+ * `portalContainer`. Modal, Dialog and Command.Dialog wrap their content in
4061
+ * it, each with the element that carries their `aria-modal`, since a screen
4062
+ * reader that honors it hides everything outside that element. The nearest
4063
+ * one wins, so a Dialog's own box wins over the Modal it renders.
4064
+ *
4065
+ * @function PortalScope
4066
+ * @param props - `node`, the element popups portal into, and `children`.
4067
+ * @returns The children, inside the scope.
4068
+ */
4069
+ function PortalScope({ node, children, }) {
4070
+ return (jsxRuntime.jsx(PortalScopeContext.Provider, { value: node, children: children }));
4071
+ }
4072
+ /**
4073
+ * INTERNAL. Where a popup portals, a panel a component opens against
4074
+ * something on the page, such as Popover's: the `portalContainer` a
4075
+ * `ConfigProvider` sets, else the overlay it's in (see `PortalScope`), else
4076
+ * `undefined`, which `resolvePortalContainer` reads as `document.body`.
4077
+ *
4078
+ * The overlay's element only exists once it has mounted, so a popup open as
4079
+ * the overlay first renders mounts in `document.body`, and moves into the
4080
+ * overlay in the update that follows, before the browser paints. Moving
4081
+ * remounts it, as any change of portal target does. It isn't held back
4082
+ * instead, because the popups measure their panel against the trigger as
4083
+ * they open, and a panel that isn't there yet is never placed.
4084
+ *
4085
+ * @function usePopupContainer
4086
+ * @returns The popup's container, `undefined` for `document.body`.
4087
+ */
4088
+ function usePopupContainer() {
4089
+ const { portalContainer } = useConfig();
4090
+ const scope = React.useContext(PortalScopeContext);
4091
+ return portalContainer || scope || undefined;
4092
+ }
4028
4093
  /**
4029
4094
  * Reads Modal's `portal` prop (`boolean | string | HTMLElement`) for a
4030
4095
  * component that takes it: whether the content is in its portal yet, and
@@ -4114,6 +4179,20 @@ function Portal({ children, container, disabled = false }) {
4114
4179
  const target = resolveContainer(container);
4115
4180
  return reactDom.createPortal(jsxRuntime.jsx(LocalePortalScope, { target: target, children: children }), target);
4116
4181
  }
4182
+ /**
4183
+ * INTERNAL. `Portal` for a popup, into the container `usePopupContainer`
4184
+ * names, so a popup opened inside a Modal, Dialog or Command.Dialog stays
4185
+ * inside it. `disabled` renders the children in place, as `Portal`'s does.
4186
+ *
4187
+ * @function PopupPortal
4188
+ * @param props - The children, and `disabled`.
4189
+ * @returns The portal, the children in place when `disabled`, or nothing
4190
+ * before hydration.
4191
+ */
4192
+ function PopupPortal({ children, disabled = false, }) {
4193
+ const container = usePopupContainer();
4194
+ return (jsxRuntime.jsx(Portal, { disabled: disabled, container: container, children: children }));
4195
+ }
4117
4196
 
4118
4197
  /**
4119
4198
  * How long after an item appears its announcement is written, in ms. The wait
@@ -4634,9 +4713,12 @@ const CopyButton = React.forwardRef(function CopyButton({ value, duration = 2000
4634
4713
  // the button takes focus or a click, rather than once as it mounts,
4635
4714
  // since Modal and Sidebar keep their content mounted while closed, and
4636
4715
  // only an open one is `aria-modal`. A region that moves starts empty, so
4637
- // it doesn't say the last outcome again. This lookup can go once the
4638
- // overlays hand their content their own root as its portal container
4639
- // (#1471).
4716
+ // it doesn't say the last outcome again. The popups inside a Modal,
4717
+ // Dialog or Command.Dialog portal into it on their own, but this lookup
4718
+ // stays: it finds a modal dialog the library didn't render too, such as
4719
+ // a `<dialog>` opened with `showModal()`, and unlike theirs, it wins over
4720
+ // a `portalContainer`, since a live region outside the dialog says
4721
+ // nothing.
4640
4722
  const [dialog, setDialog] = React.useState(null);
4641
4723
  const placeRegion = (button) => {
4642
4724
  const next = closestModalDialog(button);
@@ -5117,7 +5199,7 @@ const MenuItem = React.forwardRef(function MenuItem(itemProps, ref) {
5117
5199
  const labelChildren = [];
5118
5200
  const nestedMenuLists = [];
5119
5201
  React.Children.forEach(children, child => {
5120
- if (React.isValidElement(child) && child.type === MenuList) {
5202
+ if (isElementOf(child, MenuList)) {
5121
5203
  nestedMenuLists.push(child);
5122
5204
  }
5123
5205
  else {
@@ -6101,12 +6183,16 @@ const ModalRoot = React.forwardRef(function ModalRoot({ active, isActive, onClos
6101
6183
  const modalRootRef = React.useRef(null);
6102
6184
  // Cleanup returned by a consumer's callback ref on attach, held until detach.
6103
6185
  const consumerCleanupRef = React.useRef(null);
6186
+ // The root, as state, for the popups inside to portal into: outside it,
6187
+ // its `aria-modal` hides them from screen readers.
6188
+ const [scopeNode, setScopeNode] = React.useState(null);
6104
6189
  // The forwarded ref and the internal one must both see the node: focus
6105
6190
  // management and the Tab trap read `modalRootRef`, while consumers expect
6106
6191
  // their own ref to resolve.
6107
6192
  const combinedRef = React.useCallback((node) => {
6108
6193
  modalRootRef.current =
6109
6194
  node;
6195
+ setScopeNode(node);
6110
6196
  if (typeof ref === 'function') {
6111
6197
  // React 19 lets a callback ref return a cleanup function and detaches
6112
6198
  // by running it instead of calling the ref with `null`; React 18
@@ -6221,11 +6307,7 @@ const ModalRoot = React.forwardRef(function ModalRoot({ active, isActive, onClos
6221
6307
  // the same element and restore-on-close still lands in the right place.
6222
6308
  }, [isModalActive, isPortaled, portal, defaultTarget]);
6223
6309
  // Check if children contain compound components
6224
- const hasCompoundComponents = React.Children.toArray(children).some(child => React.isValidElement(child) &&
6225
- (child.type === ModalBackground ||
6226
- child.type === ModalContent ||
6227
- child.type === ModalCard ||
6228
- child.type === ModalClose));
6310
+ const hasCompoundComponents = React.Children.toArray(children).some(child => isElementOf(child, ModalBackground, ModalContent, ModalCard, ModalClose));
6229
6311
  // Generate Bulma classes with prefix
6230
6312
  const bulmaClasses = usePrefixedClassNames('modal', {
6231
6313
  'is-active': isModalActive,
@@ -6255,8 +6337,9 @@ const ModalRoot = React.forwardRef(function ModalRoot({ active, isActive, onClos
6255
6337
  isModalCard = !!modalCardTitle || !!modalCardFoot;
6256
6338
  modalElement = (jsxRuntime.jsxs("div", { className: modalClasses, ref: combinedRef, role: resolvedRole, "aria-modal": resolvedAriaModal, "aria-labelledby": titleId, tabIndex: -1, ...rest, "data-testid": "modal", children: [jsxRuntime.jsx("div", { className: prefixedClassNames(classPrefix, 'modal-background'), onClick: onClose, "data-testid": "modal-background" }), isModalCard ? (jsxRuntime.jsxs("div", { className: prefixedClassNames(classPrefix, 'modal-card'), children: [modalCardTitle && (jsxRuntime.jsxs("header", { className: prefixedClassNames(classPrefix, 'modal-card-head'), children: [jsxRuntime.jsx("p", { id: titleId, className: prefixedClassNames(classPrefix, 'modal-card-title'), children: modalCardTitle }), onClose && (jsxRuntime.jsx("button", { className: deleteClass, "aria-label": "close", onClick: onClose, type: "button", "data-testid": "modal-close" }))] })), jsxRuntime.jsx("section", { className: prefixedClassNames(classPrefix, 'modal-card-body'), "data-testid": "modal-body", children: children }), modalCardFoot && (jsxRuntime.jsx("footer", { className: prefixedClassNames(classPrefix, 'modal-card-foot'), children: modalCardFoot }))] })) : (jsxRuntime.jsx("div", { className: prefixedClassNames(classPrefix, 'modal-content'), "data-testid": "modal-content", children: children })), (!isModalCard || (!modalCardTitle && onClose)) && onClose && (jsxRuntime.jsx("button", { className: prefixedClassNames(classPrefix, 'modal-close', 'is-large'), "aria-label": "close", onClick: onClose, type: "button", "data-testid": "modal-close-float" }))] }));
6257
6339
  }
6258
- // In both forms, so a `Modal.Close` anywhere inside closes this modal.
6259
- modalElement = (jsxRuntime.jsx(ModalCloseContext.Provider, { value: onClose, children: modalElement }));
6340
+ // In both forms, so a `Modal.Close` anywhere inside closes this modal, and
6341
+ // a popup anywhere inside portals into it.
6342
+ modalElement = (jsxRuntime.jsx(ModalCloseContext.Provider, { value: onClose, children: jsxRuntime.jsx(PortalScope, { node: scopeNode, children: modalElement }) }));
6260
6343
  return (jsxRuntime.jsx(Portal, { disabled: !isPortaled, container: container, children: modalElement }));
6261
6344
  });
6262
6345
  const Modal = withSubComponents(ModalRoot, {
@@ -7020,7 +7103,7 @@ const TabsComponent = ({ align, size, isFullwidth, isFullWidth, fullwidth, boxed
7020
7103
  tabStop = enabledTabs.length > 0 ? enabledTabs[0].index : null;
7021
7104
  // Check if children include TabsContent
7022
7105
  const childArray = React.Children.toArray(children);
7023
- const hasContent = childArray.some(child => React.isValidElement(child) && child.type === TabsContent);
7106
+ const hasContent = childArray.some(child => isElementOf(child, TabsContent));
7024
7107
  const contextValue = {
7025
7108
  activeTab,
7026
7109
  setActiveTab,
@@ -7057,7 +7140,7 @@ const TabsComponent = ({ align, size, isFullwidth, isFullWidth, fullwidth, boxed
7057
7140
  const listChildren = [];
7058
7141
  const contentChildren = [];
7059
7142
  childArray.forEach(child => {
7060
- if (React.isValidElement(child) && child.type === TabsContent) {
7143
+ if (isElementOf(child, TabsContent)) {
7061
7144
  contentChildren.push(child);
7062
7145
  }
7063
7146
  else {
@@ -7071,7 +7154,7 @@ const TabsComponent = ({ align, size, isFullwidth, isFullWidth, fullwidth, boxed
7071
7154
  const listChildren = [];
7072
7155
  const contentChildren = [];
7073
7156
  childArray.forEach(child => {
7074
- if (React.isValidElement(child) && child.type === TabsContent) {
7157
+ if (isElementOf(child, TabsContent)) {
7075
7158
  contentChildren.push(child);
7076
7159
  }
7077
7160
  else {
@@ -8563,7 +8646,9 @@ const samePosition = (a, b) => a.position === b.position &&
8563
8646
  * anchor changes size, so a fixed panel follows its anchor and its own
8564
8647
  * content. Those measure once in the next frame, however many arrive before
8565
8648
  * it. With `followContent` it also measures after each render. A
8566
- * measurement that changes nothing doesn't render again.
8649
+ * measurement that changes nothing doesn't render again. A panel that's
8650
+ * replaced while it's open, as a portal moving to another target replaces
8651
+ * it, is watched from the next measurement on.
8567
8652
  *
8568
8653
  * The first measurement happens in a layout effect, so the panel is placed
8569
8654
  * before it paints. It needs both elements on the page while `active` is
@@ -8587,11 +8672,25 @@ function useAnchoredPosition(anchorRef, panelRef, { active, position, fixed, off
8587
8672
  return undefined;
8588
8673
  const view = (anchorRef.current ?? panelRef.current)?.ownerDocument.defaultView ??
8589
8674
  window;
8675
+ // The panel's content can change size without the component holding the
8676
+ // hook rendering, as an image loading or a child's own state does, and
8677
+ // so can the anchor. Set up below, once `update` exists.
8678
+ let resizes = null;
8679
+ // The panel being watched. A portal that moves to another target
8680
+ // remounts the panel, as a popup that opens with the dialog it's in
8681
+ // does, so each measurement watches the one that's there now.
8682
+ let watched = null;
8590
8683
  const update = () => {
8591
8684
  const anchor = anchorRef.current;
8592
8685
  const panel = panelRef.current;
8593
8686
  if (!anchor || !panel)
8594
8687
  return;
8688
+ if (panel !== watched) {
8689
+ if (watched)
8690
+ resizes?.unobserve(watched);
8691
+ resizes?.observe(panel);
8692
+ watched = panel;
8693
+ }
8595
8694
  const rect = anchor.getBoundingClientRect();
8596
8695
  const measured = panel.getBoundingClientRect();
8597
8696
  // The width the panel has once it's at least as wide as the anchor.
@@ -8622,8 +8721,6 @@ function useAnchoredPosition(anchorRef, panelRef, { active, position, fixed, off
8622
8721
  : { position: corner };
8623
8722
  setResolved(prev => (samePosition(prev, next) ? prev : next));
8624
8723
  };
8625
- updateRef.current = update;
8626
- update();
8627
8724
  // A scroll, a resize or a change in size measures in the next frame,
8628
8725
  // once however many of them ask.
8629
8726
  let frame = 0;
@@ -8635,17 +8732,14 @@ function useAnchoredPosition(anchorRef, panelRef, { active, position, fixed, off
8635
8732
  update();
8636
8733
  });
8637
8734
  };
8735
+ const Observer = view.ResizeObserver;
8736
+ resizes = typeof Observer === 'undefined' ? null : new Observer(schedule);
8737
+ if (anchorRef.current)
8738
+ resizes?.observe(anchorRef.current);
8739
+ updateRef.current = update;
8740
+ update();
8638
8741
  view.addEventListener('resize', schedule, { passive: true });
8639
8742
  view.addEventListener('scroll', schedule, { passive: true, capture: true });
8640
- // The panel's content can change size without the component holding the
8641
- // hook rendering, as an image loading or a child's own state does, and
8642
- // so can the anchor.
8643
- const Observer = view.ResizeObserver;
8644
- const resizes = typeof Observer === 'undefined' ? null : new Observer(schedule);
8645
- for (const element of [anchorRef.current, panelRef.current]) {
8646
- if (element)
8647
- resizes?.observe(element);
8648
- }
8649
8743
  return () => {
8650
8744
  updateRef.current = null;
8651
8745
  view.cancelAnimationFrame(frame);
@@ -8887,7 +8981,7 @@ const PopoverComponent = ({ trigger, children, open: controlledOpen, defaultOpen
8887
8981
  'is-start-aligned': position === undefined,
8888
8982
  'is-portal': appendToBody,
8889
8983
  }), contentClassName);
8890
- return (jsxRuntime.jsxs("div", { className: rootClasses, ...rest, ref: rootRef, children: [clonedTrigger, isOpen && (jsxRuntime.jsx(Portal, { disabled: !appendToBody, children: jsxRuntime.jsx(PopoverPanel, { panelRef: panelRef, titleId: titleId, ariaLabel: ariaLabel, close: close, id: panelId, className: panelClasses, style: appendToBody
8984
+ return (jsxRuntime.jsxs("div", { className: rootClasses, ...rest, ref: rootRef, children: [clonedTrigger, isOpen && (jsxRuntime.jsx(PopupPortal, { disabled: !appendToBody, children: jsxRuntime.jsx(PopoverPanel, { panelRef: panelRef, titleId: titleId, ariaLabel: ariaLabel, close: close, id: panelId, className: panelClasses, style: appendToBody
8891
8985
  ? {
8892
8986
  position: 'fixed',
8893
8987
  top: resolved.top,
@@ -9080,7 +9174,7 @@ const HoverCard = ({ trigger, children, open: controlledOpen, defaultOpen = fals
9080
9174
  [`is-${resolved.position}`]: true,
9081
9175
  'is-portal': appendToBody,
9082
9176
  }), contentClassName);
9083
- return (jsxRuntime.jsxs("span", { className: rootClasses, ...attrs, onPointerEnter: chain$1(onPointerEnter, hover.onPointerEnter), onPointerOver: chain$1(onPointerOver, hover.onPointerOver), onPointerLeave: chain$1(onPointerLeave, hover.onPointerLeave), onFocus: chain$1(onFocus, hover.onFocus), onBlur: chain$1(onBlur, hover.onBlur), onPointerDown: chain$1(onPointerDown, hover.onPointerDown), onPointerUp: chain$1(onPointerUp, hover.onPointerUp), ref: rootRef, children: [clonedTrigger, isOpen && (jsxRuntime.jsx(Portal, { disabled: !appendToBody, children: jsxRuntime.jsx("div", { ref: cardRef, id: cardId, className: cardClasses, style: appendToBody
9177
+ return (jsxRuntime.jsxs("span", { className: rootClasses, ...attrs, onPointerEnter: chain$1(onPointerEnter, hover.onPointerEnter), onPointerOver: chain$1(onPointerOver, hover.onPointerOver), onPointerLeave: chain$1(onPointerLeave, hover.onPointerLeave), onFocus: chain$1(onFocus, hover.onFocus), onBlur: chain$1(onBlur, hover.onBlur), onPointerDown: chain$1(onPointerDown, hover.onPointerDown), onPointerUp: chain$1(onPointerUp, hover.onPointerUp), ref: rootRef, children: [clonedTrigger, isOpen && (jsxRuntime.jsx(PopupPortal, { disabled: !appendToBody, children: jsxRuntime.jsx("div", { ref: cardRef, id: cardId, className: cardClasses, style: appendToBody
9084
9178
  ? {
9085
9179
  position: 'fixed',
9086
9180
  top: resolved.top,
@@ -9274,14 +9368,15 @@ function chain(own, ours) {
9274
9368
  *
9275
9369
  * Shift+F10 and the context menu key open it too, where the browser fires
9276
9370
  * `contextmenu` for them, which Windows and Linux do. The menu is Dropdown's
9277
- * markup, portaled into the `portalContainer` a `ConfigProvider` sets, or
9278
- * the end of the trigger's own document's `<body>`, so it never has server
9279
- * markup. It opens below and to the right of the point, flips above or to
9371
+ * markup, portaled, so it never has server markup: into the
9372
+ * `portalContainer` a `ConfigProvider` sets, else the `Modal`, `Dialog` or
9373
+ * `Command.Dialog` it's in, where screen readers that honor the dialog's
9374
+ * `aria-modal` reach it, else the end of the trigger's own document's
9375
+ * `<body>`. It opens below and to the right of the point, flips above or to
9280
9376
  * the left where there's no room, moves in where it fits neither way, and
9281
9377
  * scrolls inside when it's taller than the viewport. It doesn't follow the
9282
- * trigger, since scrolling closes it. Inside a `Modal` or a shadow root,
9283
- * point `portalContainer` inside it, so screen readers that honor
9284
- * `aria-modal` reach the menu and the shadow root's styles apply.
9378
+ * trigger, since scrolling closes it. Inside a shadow root, point
9379
+ * `portalContainer` inside it, so the shadow root's styles apply.
9285
9380
  *
9286
9381
  * Opening moves focus to the first enabled item. The arrow keys, Home, End
9287
9382
  * and typing move between items, and Enter and Space activate one. Escape,
@@ -9305,7 +9400,7 @@ function chain(own, ours) {
9305
9400
  */
9306
9401
  const ContextMenuComponent = ({ trigger, children, onOpenChange, closeOnClick = true, disabled = false, className, onKeyDown, onClick, onContextMenu, ...props }) => {
9307
9402
  const { bulmaHelperClasses, rest } = useBulmaClasses(props);
9308
- const { portalContainer } = useConfig();
9403
+ const popupContainer = usePopupContainer();
9309
9404
  const [menu, setMenu] = React.useState(null);
9310
9405
  // Turning `disabled` on closes it.
9311
9406
  if (disabled && menu)
@@ -9462,7 +9557,7 @@ const ContextMenuComponent = ({ trigger, children, onOpenChange, closeOnClick =
9462
9557
  });
9463
9558
  const menuClasses = classNames(usePrefixedClassNames('dropdown-menu'), bulmaHelperClasses, className);
9464
9559
  const contentClasses = usePrefixedClassNames('dropdown-content');
9465
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [clonedTrigger, menu && (jsxRuntime.jsx(Portal, { container: portalContainer || menu.doc.body, children: jsxRuntime.jsx("div", { ref: boxRef, className: boxClasses, style: {
9560
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [clonedTrigger, menu && (jsxRuntime.jsx(Portal, { container: popupContainer || menu.doc.body, children: jsxRuntime.jsx("div", { ref: boxRef, className: boxClasses, style: {
9466
9561
  top: placed?.top ?? menu.point.y,
9467
9562
  left: placed?.left ?? menu.point.x,
9468
9563
  }, children: jsxRuntime.jsx("div", { ...rest, ref: menuRef, role: "menu", tabIndex: -1, className: menuClasses, onKeyDown: handleKeyDown, onClick: handleClick, onContextMenu: handleContextMenu, children: jsxRuntime.jsx("div", { className: contentClasses, children: children }) }) }) }))] }));
@@ -10419,6 +10514,9 @@ const Dialog = React.forwardRef(({ isOpen, title, message, type = 'default', con
10419
10514
  const dialogRef = React.useRef(null);
10420
10515
  // Cleanup returned by a consumer's callback ref on attach, held until detach.
10421
10516
  const consumerCleanupRef = React.useRef(null);
10517
+ // The box, as state, for the popups in the message to portal into. It's
10518
+ // what carries `aria-modal`, rather than the Modal's root around it.
10519
+ const [scopeNode, setScopeNode] = React.useState(null);
10422
10520
  const confirmRef = React.useRef(null);
10423
10521
  const cancelRef = React.useRef(null);
10424
10522
  // Handle cancel
@@ -10455,6 +10553,7 @@ const Dialog = React.forwardRef(({ isOpen, title, message, type = 'default', con
10455
10553
  const combinedRef = React.useCallback((node) => {
10456
10554
  dialogRef.current =
10457
10555
  node;
10556
+ setScopeNode(node);
10458
10557
  if (typeof ref === 'function') {
10459
10558
  // React 19 lets a callback ref return a cleanup function and detaches by
10460
10559
  // running it instead of calling the ref with `null`; React 18 discards the
@@ -10520,7 +10619,7 @@ const Dialog = React.forwardRef(({ isOpen, title, message, type = 'default', con
10520
10619
  if (!isOpen) {
10521
10620
  return null;
10522
10621
  }
10523
- return (jsxRuntime.jsxs(Modal, { isActive: isOpen, onClose: handleCancel, role: "presentation", portal: portal, children: [jsxRuntime.jsx(Modal.Background, { onClick: handleBackgroundClick }), jsxRuntime.jsxs("div", { ref: combinedRef, className: combinedClasses, role: "alertdialog", "aria-modal": "true", "aria-labelledby": title ? 'dialog-title' : undefined, "aria-describedby": "dialog-message", ...rest, children: [title && (jsxRuntime.jsxs("div", { className: headerClass, children: [displayIcon && jsxRuntime.jsx("span", { className: iconClass, children: displayIcon }), jsxRuntime.jsx("h3", { id: "dialog-title", className: titleClass, children: title })] })), jsxRuntime.jsx("div", { id: "dialog-message", className: bodyClass, children: message }), jsxRuntime.jsxs("div", { className: footerClass, children: [showCancel && (jsxRuntime.jsx("button", { ref: cancelRef, type: "button", className: cancelButtonClass, onClick: handleCancel, children: cancelText })), jsxRuntime.jsx("button", { ref: confirmRef, type: "button", className: confirmButtonClass, onClick: handleConfirm, children: confirmText })] })] })] }));
10622
+ return (jsxRuntime.jsxs(Modal, { isActive: isOpen, onClose: handleCancel, role: "presentation", portal: portal, children: [jsxRuntime.jsx(Modal.Background, { onClick: handleBackgroundClick }), jsxRuntime.jsx(PortalScope, { node: scopeNode, children: jsxRuntime.jsxs("div", { ref: combinedRef, className: combinedClasses, role: "alertdialog", "aria-modal": "true", "aria-labelledby": title ? 'dialog-title' : undefined, "aria-describedby": "dialog-message", ...rest, children: [title && (jsxRuntime.jsxs("div", { className: headerClass, children: [displayIcon && (jsxRuntime.jsx("span", { className: iconClass, children: displayIcon })), jsxRuntime.jsx("h3", { id: "dialog-title", className: titleClass, children: title })] })), jsxRuntime.jsx("div", { id: "dialog-message", className: bodyClass, children: message }), jsxRuntime.jsxs("div", { className: footerClass, children: [showCancel && (jsxRuntime.jsx("button", { ref: cancelRef, type: "button", className: cancelButtonClass, onClick: handleCancel, children: cancelText })), jsxRuntime.jsx("button", { ref: confirmRef, type: "button", className: confirmButtonClass, onClick: handleConfirm, children: confirmText })] })] }) })] }));
10524
10623
  });
10525
10624
  Dialog.displayName = 'Dialog';
10526
10625
  let dialogListeners = new Set();
@@ -14218,12 +14317,11 @@ const FieldComponent = ({ horizontal, grouped, hasAddons, narrow, label, labelSi
14218
14317
  // like <Field.Label/> + <Field.Body/>).
14219
14318
  let content = children;
14220
14319
  if (horizontal) {
14221
- const isFieldBody = (c) => React.isValidElement(c) &&
14222
- // @ts-expect-error displayName isn't on the public type
14223
- (c.type === FieldBody || c.type?.displayName === 'FieldBody');
14224
- const isFieldLabel = (c) => React.isValidElement(c) &&
14225
- // @ts-expect-error displayName isn't on the public type
14226
- (c.type === FieldLabel || c.type?.displayName === 'FieldLabel');
14320
+ const named = (c, displayName) => React.isValidElement(c) &&
14321
+ elementType(c)?.displayName ===
14322
+ displayName;
14323
+ const isFieldBody = (c) => isElementOf(c, FieldBody) || named(c, 'FieldBody');
14324
+ const isFieldLabel = (c) => isElementOf(c, FieldLabel) || named(c, 'FieldLabel');
14227
14325
  const childArray = React.Children.toArray(children);
14228
14326
  const userProvidedStructure = childArray.some(c => isFieldBody(c) || isFieldLabel(c));
14229
14327
  if (userProvidedStructure) {
@@ -15057,6 +15155,16 @@ const CommandDialog = React.forwardRef(({ open: controlledOpen, defaultOpen = fa
15057
15155
  return () => window.removeEventListener('keydown', onKeyDown);
15058
15156
  }, [shortcut, open, openFromShortcut]);
15059
15157
  const dialogClass = usePrefixedClassNames('command-dialog');
15158
+ // The box, as state, for the popups inside to portal into. It's what
15159
+ // carries `aria-modal`, rather than the Modal's root around it.
15160
+ const [scopeNode, setScopeNode] = React.useState(null);
15161
+ const dialogRef = React.useCallback((node) => {
15162
+ setScopeNode(node);
15163
+ if (typeof ref === 'function')
15164
+ ref(node);
15165
+ else if (ref)
15166
+ ref.current = node;
15167
+ }, [ref]);
15060
15168
  if (!open)
15061
15169
  return null;
15062
15170
  const close = () => setOpen(false);
@@ -15065,9 +15173,9 @@ const CommandDialog = React.forwardRef(({ open: controlledOpen, defaultOpen = fa
15065
15173
  if (closeOnSelect)
15066
15174
  close();
15067
15175
  };
15068
- return (jsxRuntime.jsxs(Modal, { isActive: true, onClose: close, role: "presentation", portal: portal, children: [jsxRuntime.jsx(Modal.Background, { onClick: close }), jsxRuntime.jsx(CommandRoot, { ...props, ref: ref, className: classNames(dialogClass, className), label: label, query: query, onQueryChange: setQuery, onSelect: run, role: "dialog", "aria-modal": "true", "aria-label": ariaLabelledBy === undefined
15069
- ? ariaLabel || label || defaultLabel
15070
- : ariaLabel, "aria-labelledby": ariaLabelledBy })] }));
15176
+ return (jsxRuntime.jsxs(Modal, { isActive: true, onClose: close, role: "presentation", portal: portal, children: [jsxRuntime.jsx(Modal.Background, { onClick: close }), jsxRuntime.jsx(PortalScope, { node: scopeNode, children: jsxRuntime.jsx(CommandRoot, { ...props, ref: dialogRef, className: classNames(dialogClass, className), label: label, query: query, onQueryChange: setQuery, onSelect: run, role: "dialog", "aria-modal": "true", "aria-label": ariaLabelledBy === undefined
15177
+ ? ariaLabel || label || defaultLabel
15178
+ : ariaLabel, "aria-labelledby": ariaLabelledBy }) })] }));
15071
15179
  });
15072
15180
  CommandDialog.displayName = 'CommandDialog';
15073
15181
  /** Command with Input, List, Group, Item, Empty and Dialog sub-components. */
@@ -17582,7 +17690,7 @@ const StatRoot = React.forwardRef(({ className, label, value, format, locale, ch
17582
17690
  // warning below know what's there. A part rendered from inside another
17583
17691
  // component isn't seen.
17584
17692
  const parts = flattenChildren(children);
17585
- const hasPart = (type) => parts.some(part => React.isValidElement(part) && part.type === type);
17693
+ const hasPart = (type) => parts.some(part => isElementOf(part, type));
17586
17694
  const hasValuePart = hasPart(StatValue);
17587
17695
  const labelled = isGiven(label) || hasPart(StatLabel);
17588
17696
  // Without a label, the figure has no name and the values no term.
@@ -20909,7 +21017,7 @@ const ComboboxMenu = ({ children, className, style, onMouseDown, onPointerDownCa
20909
21017
  return jsxRuntime.jsx(jsxRuntime.Fragment, { children: children });
20910
21018
  if (!shown)
20911
21019
  return null;
20912
- return (jsxRuntime.jsx(Portal, { disabled: !appendToBody, children: jsxRuntime.jsx("div", { ...props, ref: panelRef, className: classNames(menuClass, className), style: appendToBody
21020
+ return (jsxRuntime.jsx(PopupPortal, { disabled: !appendToBody, children: jsxRuntime.jsx("div", { ...props, ref: panelRef, className: classNames(menuClass, className), style: appendToBody
20913
21021
  ? {
20914
21022
  ...style,
20915
21023
  position: 'fixed',
@@ -21297,7 +21405,7 @@ function searchTree(data, matches) {
21297
21405
  const isBrowser = typeof window !== 'undefined';
21298
21406
  const PickerPopover = ({ isOpen, onClose, anchorRef, children, position, appendToBody = false, className, trapFocus = true, closeOnClickOutside = true, closeOnEscape = true, ariaLabel, ariaLabelledBy, role = 'dialog', id, restoreFocusRef, initialFocusSelector, localeScope, matchWidth = false, followContent = false, }) => {
21299
21407
  const panelRef = React.useRef(null);
21300
- const resolveContainer = usePortalContainer();
21408
+ const popupContainer = usePopupContainer();
21301
21409
  // A portal has no server-rendered counterpart, so a panel open on the first
21302
21410
  // render stays in place on the server and while hydrating, and moves into
21303
21411
  // its portal once the client takes over, as Modal's `portal` does.
@@ -21404,7 +21512,7 @@ const PickerPopover = ({ isOpen, onClose, anchorRef, children, position, appendT
21404
21512
  e.preventDefault();
21405
21513
  }, children: children }));
21406
21514
  if (isPortaled) {
21407
- const target = resolveContainer();
21515
+ const target = resolvePortalContainer(popupContainer);
21408
21516
  return reactDom.createPortal(jsxRuntime.jsx(LocalePortalScope, { target: target, scope: localeScope, children: panel }), target);
21409
21517
  }
21410
21518
  return panel;
@@ -24685,6 +24793,11 @@ const inWeeks = (days, className) => {
24685
24793
  }
24686
24794
  return rows;
24687
24795
  };
24796
+ /** Sunday-first weekday names, starting from `firstDayOfWeek` instead. */
24797
+ const fromFirstDay = (sundayFirst, firstDayOfWeek) => [
24798
+ ...sundayFirst.slice(firstDayOfWeek),
24799
+ ...sundayFirst.slice(0, firstDayOfWeek),
24800
+ ];
24688
24801
  /** A date's time, or `null` for none, for comparing ranges by value. */
24689
24802
  const timeOf = (d) => d ? d.getTime() : null;
24690
24803
  /**
@@ -24728,15 +24841,18 @@ const Calendar = ({ value, focusedDate, onSelect: onSelectProp, onFocusedDateCha
24728
24841
  const [view, setView] = React.useState(baseView);
24729
24842
  // Nothing before year 1 can be picked or reached, as in HTML's date inputs.
24730
24843
  const min = React.useMemo(() => floorMin(minProp), [minProp]);
24731
- const computedDayNames = React.useMemo(() => {
24732
- if (dayNames && dayNames.length === 7)
24733
- return dayNames;
24734
- const sundayFirst = getDayNames(locale, 'short');
24735
- return [
24736
- ...sundayFirst.slice(firstDayOfWeek),
24737
- ...sundayFirst.slice(0, firstDayOfWeek),
24738
- ];
24739
- }, [dayNames, locale, firstDayOfWeek]);
24844
+ const customDayNames = dayNames && dayNames.length === 7 ? dayNames : null;
24845
+ const computedDayNames = React.useMemo(() => customDayNames ??
24846
+ fromFirstDay(getDayNames(locale, 'short'), firstDayOfWeek), [customDayNames, locale, firstDayOfWeek]);
24847
+ // Each weekday column is named by its full weekday in the locale, so a
24848
+ // screen reader names the column as focus moves across the grid. A server
24849
+ // and a browser can spell those names differently, so they're added only
24850
+ // once the page has hydrated, and never beside day names the caller gave,
24851
+ // which name the columns themselves.
24852
+ const hydrated = useIsHydrated();
24853
+ const weekdayNames = React.useMemo(() => hydrated && !customDayNames
24854
+ ? fromFirstDay(getDayNames(locale, 'long'), firstDayOfWeek)
24855
+ : null, [hydrated, customDayNames, locale, firstDayOfWeek]);
24740
24856
  const computedMonthNames = React.useMemo(() => {
24741
24857
  if (monthNames && monthNames.length === 12)
24742
24858
  return monthNames;
@@ -25023,7 +25139,6 @@ const Calendar = ({ value, focusedDate, onSelect: onSelectProp, onFocusedDateCha
25023
25139
  // server render and the render hydrating it mark no day, month or year,
25024
25140
  // and the commit after marks the browser's own. A calendar mounted after
25025
25141
  // hydration marks it from its first render.
25026
- const hydrated = useIsHydrated();
25027
25142
  const today = hydrated ? new Date() : null;
25028
25143
  const todayYear = today?.getFullYear();
25029
25144
  // The header steps a month at a time over the day grid and a year at a
@@ -25232,7 +25347,7 @@ const Calendar = ({ value, focusedDate, onSelect: onSelectProp, onFocusedDateCha
25232
25347
  return (jsxRuntime.jsxs("div", { className: classNames(calendarClass, className), id: id, children: [jsxRuntime.jsxs("div", { className: headerClass, children: [isYearGranularity ? (jsxRuntime.jsx("span", { className: monthLabelClass, id: labelId, children: monthLabel })) : (jsxRuntime.jsxs("button", { type: "button", className: monthTriggerClass, "aria-haspopup": "listbox", "aria-expanded": view === 'years', disabled: calendarDisabled, onClick: () => {
25233
25348
  setNavYear(null);
25234
25349
  setView(v => (v === 'years' ? baseView : 'years'));
25235
- }, children: [jsxRuntime.jsx("span", { className: monthLabelClass, id: labelId, "aria-live": "polite", children: monthLabel }), jsxRuntime.jsx("svg", { className: monthCaretClass, viewBox: "0 0 12 12", width: "10", height: "10", "aria-hidden": "true", children: jsxRuntime.jsx("path", { d: "M2 4l4 4 4-4", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round" }) })] })), !isYearGranularity && (jsxRuntime.jsxs("div", { className: navGroupClass, children: [jsxRuntime.jsx("button", { type: "button", className: navPrevClass, "aria-label": isDayGranularity ? t.prevMonth : t.prevYear, disabled: calendarDisabled || prevDisabled || view !== baseView, onClick: () => onFocusedDateChange(prevAnchor), children: navArrow('M10 3l-5 5 5 5') }), jsxRuntime.jsx("button", { type: "button", className: navNextClass, "aria-label": isDayGranularity ? t.nextMonth : t.nextYear, disabled: calendarDisabled || nextDisabled || view !== baseView, onClick: () => onFocusedDateChange(nextAnchor), children: navArrow('M6 3l5 5-5 5') })] }))] }), view === 'days' && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: dayNamesRowClass, "aria-hidden": "true", children: computedDayNames.map((name, i) => (jsxRuntime.jsx("div", { className: dayNameClass, children: name }, i))) }), jsxRuntime.jsx("div", { ref: gridRef, role: "grid", "aria-labelledby": labelId, "aria-multiselectable": rangeMode || undefined, "aria-describedby": rangeMode ? rangeSummaryId : undefined, "aria-disabled": calendarDisabled || undefined, "aria-readonly": readOnly || undefined, className: gridClass, onKeyDown: handleKeyDown, onMouseLeave: anchor ? () => setHoverDate(null) : undefined, ...gridFocusHandlers, children: inWeeks(cells.map(cell => {
25350
+ }, children: [jsxRuntime.jsx("span", { className: monthLabelClass, id: labelId, "aria-live": "polite", children: monthLabel }), jsxRuntime.jsx("svg", { className: monthCaretClass, viewBox: "0 0 12 12", width: "10", height: "10", "aria-hidden": "true", children: jsxRuntime.jsx("path", { d: "M2 4l4 4 4-4", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round" }) })] })), !isYearGranularity && (jsxRuntime.jsxs("div", { className: navGroupClass, children: [jsxRuntime.jsx("button", { type: "button", className: navPrevClass, "aria-label": isDayGranularity ? t.prevMonth : t.prevYear, disabled: calendarDisabled || prevDisabled || view !== baseView, onClick: () => onFocusedDateChange(prevAnchor), children: navArrow('M10 3l-5 5 5 5') }), jsxRuntime.jsx("button", { type: "button", className: navNextClass, "aria-label": isDayGranularity ? t.nextMonth : t.nextYear, disabled: calendarDisabled || nextDisabled || view !== baseView, onClick: () => onFocusedDateChange(nextAnchor), children: navArrow('M6 3l5 5-5 5') })] }))] }), view === 'days' && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsxs("div", { ref: gridRef, role: "grid", "aria-labelledby": labelId, "aria-multiselectable": rangeMode || undefined, "aria-describedby": rangeMode ? rangeSummaryId : undefined, "aria-disabled": calendarDisabled || undefined, "aria-readonly": readOnly || undefined, className: gridClass, onKeyDown: handleKeyDown, onMouseLeave: anchor ? () => setHoverDate(null) : undefined, ...gridFocusHandlers, children: [jsxRuntime.jsx("div", { role: "row", className: dayNamesRowClass, children: computedDayNames.map((name, i) => (jsxRuntime.jsx("div", { role: "columnheader", "aria-label": weekdayNames?.[i], className: dayNameClass, children: name }, i))) }), inWeeks(cells.map(cell => {
25236
25351
  const disabled = calendarDisabled || isDateUnselectable(cell.date);
25237
25352
  const time = cell.date.getTime();
25238
25353
  // Range mode. The range on show has its ends filled. Every day
@@ -25295,7 +25410,7 @@ const Calendar = ({ value, focusedDate, onSelect: onSelectProp, onFocusedDateCha
25295
25410
  else
25296
25411
  onSelect?.(cell.date);
25297
25412
  }, style: !display ? { visibility: 'hidden' } : undefined, children: cell.date.getDate() }, cell.date.toISOString()));
25298
- }), weekClass) })] })), view === 'months' && (jsxRuntime.jsx("div", { ref: monthGridRef, role: "grid", "aria-labelledby": labelId, "aria-disabled": calendarDisabled || undefined, "aria-readonly": readOnly || undefined, className: monthsGridClass, onKeyDown: handleMonthKeyDown, ...gridFocusHandlers, children: MONTH_ROWS.map(row => (jsxRuntime.jsx("div", { role: "row", className: monthsRowClass, children: row.map(month => {
25413
+ }), weekClass)] }) })), view === 'months' && (jsxRuntime.jsx("div", { ref: monthGridRef, role: "grid", "aria-labelledby": labelId, "aria-disabled": calendarDisabled || undefined, "aria-readonly": readOnly || undefined, className: monthsGridClass, onKeyDown: handleMonthKeyDown, ...gridFocusHandlers, children: MONTH_ROWS.map(row => (jsxRuntime.jsx("div", { role: "row", className: monthsRowClass, children: row.map(month => {
25299
25414
  const date = makeDate(focusedYear, month);
25300
25415
  const disabled = calendarDisabled || disabledMonths[month];
25301
25416
  const isSelected = !!value && isSameMonth(value, date);
@@ -30115,8 +30230,8 @@ const AppFrameBurger = React.forwardRef(({ className, onClick, ...props }, ref)
30115
30230
  } }));
30116
30231
  });
30117
30232
  AppFrameBurger.displayName = 'AppFrame.Burger';
30118
- const isMain = (child) => React.isValidElement(child) && child.type === AppFrameMain;
30119
- const isNav = (child) => React.isValidElement(child) && child.type === AppFrameNav;
30233
+ const isMain = (child) => isElementOf(child, AppFrameMain);
30234
+ const isNav = (child) => isElementOf(child, AppFrameNav);
30120
30235
  /**
30121
30236
  * The `AppFrame` component lays out an app's pages: a header across the top, a navigation column down the side, the page, and an aside and a footer, with the nav a drawer behind a burger on narrow screens.
30122
30237
  *
@@ -30916,7 +31031,7 @@ const SplitterPane = React.forwardRef(({ className, textColor, bgColor, label: _
30916
31031
  style: state ? { ...style, flex: `${state.size} 1 0px` } : style, hidden: state?.collapsed || rest.hidden, children: children }));
30917
31032
  });
30918
31033
  SplitterPane.displayName = 'Splitter.Pane';
30919
- const isPane = (child) => React.isValidElement(child) && child.type === SplitterPane;
31034
+ const isPane = (child) => isElementOf(child, SplitterPane);
30920
31035
  /** The bounds with pane `i`'s changed, for a move that mustn't snap it shut. */
30921
31036
  const withBound = (bounds, i, change) => bounds.map((bound, j) => (j === i ? { ...bound, ...change } : bound));
30922
31037
  /** The bounds with neither pane beside handle `h` able to shut. */