@allxsmith/bestax-bulma 5.28.0 → 5.29.0
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.
- package/dist/esm/components/Dialog.js +8 -4
- package/dist/esm/components/Dialog.js.map +1 -1
- package/dist/esm/components/HoverCard.js.map +1 -1
- package/dist/esm/components/Modal.js +19 -11
- package/dist/esm/components/Modal.js.map +1 -1
- package/dist/esm/components/Popover.js.map +1 -1
- package/dist/esm/components/Sidebar.js +12 -3
- package/dist/esm/components/Sidebar.js.map +1 -1
- package/dist/esm/components/Toast.js +5 -3
- package/dist/esm/components/Toast.js.map +1 -1
- package/dist/esm/elements/Notification.js +3 -1
- package/dist/esm/elements/Notification.js.map +1 -1
- package/dist/esm/form/DateInputBase.js.map +1 -1
- package/dist/esm/form/DateRangeInputBase.js.map +1 -1
- package/dist/esm/form/DateTimeInputBase.js.map +1 -1
- package/dist/esm/form/TimeInputBase.js.map +1 -1
- package/dist/esm/form/_pickerInternals/PickerPopover.js +3 -1
- package/dist/esm/form/_pickerInternals/PickerPopover.js.map +1 -1
- package/dist/esm/helpers/Config.js +5 -2
- package/dist/esm/helpers/Config.js.map +1 -1
- package/dist/esm/helpers/portal.js +30 -5
- package/dist/esm/helpers/portal.js.map +1 -1
- package/dist/index.cjs +76 -27
- package/dist/index.cjs.map +1 -1
- package/dist/types/components/HoverCard.d.ts +14 -12
- package/dist/types/components/Modal.d.ts +2 -1
- package/dist/types/components/Popover.d.ts +8 -7
- package/dist/types/form/DateInputBase.d.ts +4 -1
- package/dist/types/form/DateRangeInputBase.d.ts +4 -1
- package/dist/types/form/DateTimeInputBase.d.ts +4 -1
- package/dist/types/form/TimeInputBase.d.ts +2 -1
- package/dist/types/helpers/Config.d.ts +34 -3
- package/dist/types/helpers/portal.d.ts +27 -5
- package/dist/types-cjs/components/HoverCard.d.ts +14 -12
- package/dist/types-cjs/components/Modal.d.ts +2 -1
- package/dist/types-cjs/components/Popover.d.ts +8 -7
- package/dist/types-cjs/form/DateInputBase.d.ts +4 -1
- package/dist/types-cjs/form/DateRangeInputBase.d.ts +4 -1
- package/dist/types-cjs/form/DateTimeInputBase.d.ts +4 -1
- package/dist/types-cjs/form/TimeInputBase.d.ts +2 -1
- package/dist/types-cjs/helpers/Config.d.ts +34 -3
- package/dist/types-cjs/helpers/portal.d.ts +27 -5
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"portal.js","sources":["../../../src/helpers/portal.tsx"],"sourcesContent":["import React from 'react';\nimport { createPortal } from 'react-dom';\nimport { useIsHydrated } from './useIsHydrated';\n\n/**\n * Resolves a portal target: an `HTMLElement` is used directly, a non-empty\n * `string` is treated as a `document.querySelector` selector (falling back to\n * `document.body` when it matches nothing), and any falsy value — `undefined`\n * or the empty string — resolves to `document.body`.\n *\n * The empty string is deliberately treated as \"no target\" rather than passed\n * through: `document.querySelector('')` throws a `SyntaxError`, and callers\n * building a selector from state can easily hand us `''`.\n *\n * @function resolvePortalContainer\n * @param container - The requested portal target, if any.\n * @returns The resolved DOM node to portal into.\n */\nexport function resolvePortalContainer(\n container?: string | HTMLElement\n): HTMLElement {\n if (!container) {\n return document.body;\n }\n if (typeof container === 'string') {\n return (\n (document.querySelector(container) as HTMLElement | null) ?? document.body\n );\n }\n return container;\n}\n\n/**\n * Props for the Portal component.\n */\nexport interface PortalProps {\n /** Content to render into the container. */\n children?: React.ReactNode;\n /**\n * Where the content goes: an element, or a `document.querySelector`\n * selector. Omitted
|
|
1
|
+
{"version":3,"file":"portal.js","sources":["../../../src/helpers/portal.tsx"],"sourcesContent":["import React from 'react';\nimport { createPortal } from 'react-dom';\nimport { useIsHydrated } from './useIsHydrated';\nimport { useConfig } from './Config';\n\n/**\n * Resolves a portal target: an `HTMLElement` is used directly, a non-empty\n * `string` is treated as a `document.querySelector` selector (falling back to\n * `document.body` when it matches nothing), and any falsy value — `undefined`\n * or the empty string — resolves to `document.body`.\n *\n * The empty string is deliberately treated as \"no target\" rather than passed\n * through: `document.querySelector('')` throws a `SyntaxError`, and callers\n * building a selector from state can easily hand us `''`.\n *\n * @function resolvePortalContainer\n * @param container - The requested portal target, if any.\n * @returns The resolved DOM node to portal into.\n */\nexport function resolvePortalContainer(\n container?: string | HTMLElement\n): HTMLElement {\n if (!container) {\n return document.body;\n }\n if (typeof container === 'string') {\n return (\n (document.querySelector(container) as HTMLElement | null) ?? document.body\n );\n }\n return container;\n}\n\n/**\n * Where a component's portal goes, as a function to call when the portal is\n * created: the target the component was given, else the `portalContainer` a\n * `ConfigProvider` sets, else `document.body`, each read as\n * `resolvePortalContainer` reads it. A component that portals resolves its\n * target through this, so the provider's default reaches it.\n *\n * The hook only reads context, so it is safe to call on the server, ahead of\n * any early return. The function it returns reads the DOM, so call it only\n * where the portal is created, which the server never reaches.\n *\n * @function usePortalContainer\n * @returns A function that takes the component's own target, if any, and\n * returns the DOM node to portal into.\n */\nexport function usePortalContainer(): (\n container?: string | HTMLElement\n) => HTMLElement {\n const { portalContainer } = useConfig();\n return container => resolvePortalContainer(container || portalContainer);\n}\n\n/**\n * Props for the Portal component.\n */\nexport interface PortalProps {\n /** Content to render into the container. */\n children?: React.ReactNode;\n /**\n * Where the content goes: an element, or a `document.querySelector`\n * selector. Omitted or empty, it goes to the `portalContainer` a\n * `ConfigProvider` sets, and to `document.body` when none is set. A\n * selector that matches nothing means `document.body` too. A selector is\n * looked up again on each render, so the\n * content follows the target when it changes. Moving to another target\n * remounts the children and resets their state, which includes a selector\n * that only starts matching after the content has shown in `document.body`.\n * Render the target first, or pass the element once you have it.\n */\n container?: string | HTMLElement;\n /**\n * Render the children in place instead, on the server as well as the\n * client. Lets a component that portals only sometimes keep a single code\n * path.\n * @defaultValue false\n */\n disabled?: boolean;\n}\n\n/**\n * Renders its children into another part of the page, `document.body` unless `container` or a `ConfigProvider` says otherwise, so floating content escapes an ancestor's `overflow`, `transform` or stacking context.\n *\n * React's server renderer can't render a portal, so `Portal` renders nothing\n * on the server and during hydration, and mounts its children in the commit\n * that follows. The first client render then matches the server markup. In an app\n * without server rendering it portals on the first render.\n *\n * React context, such as `ConfigProvider`'s class prefix, reaches the\n * portaled children, and their React events bubble through the React tree.\n * CSS inheritance follows the DOM instead: a scoped (non-`isRoot`) `Theme`\n * sets its variables on a wrapper element the portaled content has left, so\n * that content sees the page-level theme, and styles scoped to a shadow root\n * don't reach `document.body` at all. To keep them, portal into an element\n * inside the themed area or the shadow root: pass it as `container`, or as\n * the `portalContainer` of a `ConfigProvider` around that area. The second\n * also reaches what the library's components portal, such as Popover's\n * `appendToBody` panel or a `Modal` with `portal`.\n *\n * Tab order and focus follow the DOM too. Content portaled from inside a\n * focus trap is no longer inside the trapped element, so the trap neither\n * reaches it nor holds focus there: render nested overlays inside the\n * trapped element, or give them a trap of their own. To trap portaled\n * content, put `useFocusTrap`'s ref on the element inside the `Portal`.\n *\n * @function\n * @param {PortalProps} props - Props for the Portal component.\n * @returns The portal, the children in place when `disabled`, or nothing\n * before hydration.\n *\n * @example\n * <Portal>\n * <div className=\"box\">Rendered at the end of document.body</div>\n * </Portal>\n *\n * @example\n * // Into a dedicated overlay root\n * <Portal container=\"#overlays\">\n * <CommandPalette />\n * </Portal>\n */\nexport function Portal({ children, container, disabled = false }: PortalProps) {\n const hydrated = useIsHydrated();\n const resolveContainer = usePortalContainer();\n if (disabled) return <>{children}</>;\n if (!hydrated) return null;\n return createPortal(children, resolveContainer(container));\n}\n"],"names":["_jsx","_Fragment"],"mappings":";;;;;;AAKA;;;;;;;;;;;;;AAaG;AACG,SAAU,sBAAsB,CACpC,SAAgC,EAAA;IAEhC,IAAI,CAAC,SAAS,EAAE;QACd,OAAO,QAAQ,CAAC,IAAI;IACtB;AACA,IAAA,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE;AACjC,QAAA,QACG,QAAQ,CAAC,aAAa,CAAC,SAAS,CAAwB,IAAI,QAAQ,CAAC,IAAI;IAE9E;AACA,IAAA,OAAO,SAAS;AAClB;AAEA;;;;;;;;;;;;;;AAcG;SACa,kBAAkB,GAAA;AAGhC,IAAA,MAAM,EAAE,eAAe,EAAE,GAAG,SAAS,EAAE;IACvC,OAAO,SAAS,IAAI,sBAAsB,CAAC,SAAS,IAAI,eAAe,CAAC;AAC1E;AA6BA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCG;AACG,SAAU,MAAM,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,GAAG,KAAK,EAAe,EAAA;AAC3E,IAAA,MAAM,QAAQ,GAAG,aAAa,EAAE;AAChC,IAAA,MAAM,gBAAgB,GAAG,kBAAkB,EAAE;AAC7C,IAAA,IAAI,QAAQ;QAAE,OAAOA,GAAA,CAAAC,QAAA,EAAA,EAAA,QAAA,EAAG,QAAQ,EAAA,CAAI;AACpC,IAAA,IAAI,CAAC,QAAQ;AAAE,QAAA,OAAO,IAAI;IAC1B,OAAO,YAAY,CAAC,QAAQ,EAAE,gBAAgB,CAAC,SAAS,CAAC,CAAC;AAC5D;;"}
|
package/dist/index.cjs
CHANGED
|
@@ -16,6 +16,9 @@ const useConfig = () => React.useContext(ConfigContext);
|
|
|
16
16
|
/**
|
|
17
17
|
* ConfigProvider injects configuration into all child components via React context.
|
|
18
18
|
*
|
|
19
|
+
* A nested provider replaces the outer one's settings rather than adding to
|
|
20
|
+
* them, so inside it any setting it leaves out is back to its default.
|
|
21
|
+
*
|
|
19
22
|
* @function
|
|
20
23
|
* @param {ConfigProviderProps} props - Provider props.
|
|
21
24
|
* @returns {JSX.Element} The context provider wrapping children.
|
|
@@ -25,8 +28,8 @@ const useConfig = () => React.useContext(ConfigContext);
|
|
|
25
28
|
* <App />
|
|
26
29
|
* </ConfigProvider>
|
|
27
30
|
*/
|
|
28
|
-
const ConfigProvider = ({ classPrefix, iconLibrary, children, }) => {
|
|
29
|
-
return (jsxRuntime.jsx(ConfigContext.Provider, { value: { classPrefix, iconLibrary }, children: children }));
|
|
31
|
+
const ConfigProvider = ({ classPrefix, iconLibrary, portalContainer, children, }) => {
|
|
32
|
+
return (jsxRuntime.jsx(ConfigContext.Provider, { value: { classPrefix, iconLibrary, portalContainer }, children: children }));
|
|
30
33
|
};
|
|
31
34
|
/**
|
|
32
35
|
* Utility hook to get the configured class prefix string.
|
|
@@ -2934,7 +2937,26 @@ function resolvePortalContainer(container) {
|
|
|
2934
2937
|
return container;
|
|
2935
2938
|
}
|
|
2936
2939
|
/**
|
|
2937
|
-
*
|
|
2940
|
+
* Where a component's portal goes, as a function to call when the portal is
|
|
2941
|
+
* created: the target the component was given, else the `portalContainer` a
|
|
2942
|
+
* `ConfigProvider` sets, else `document.body`, each read as
|
|
2943
|
+
* `resolvePortalContainer` reads it. A component that portals resolves its
|
|
2944
|
+
* target through this, so the provider's default reaches it.
|
|
2945
|
+
*
|
|
2946
|
+
* The hook only reads context, so it is safe to call on the server, ahead of
|
|
2947
|
+
* any early return. The function it returns reads the DOM, so call it only
|
|
2948
|
+
* where the portal is created, which the server never reaches.
|
|
2949
|
+
*
|
|
2950
|
+
* @function usePortalContainer
|
|
2951
|
+
* @returns A function that takes the component's own target, if any, and
|
|
2952
|
+
* returns the DOM node to portal into.
|
|
2953
|
+
*/
|
|
2954
|
+
function usePortalContainer() {
|
|
2955
|
+
const { portalContainer } = useConfig();
|
|
2956
|
+
return container => resolvePortalContainer(container || portalContainer);
|
|
2957
|
+
}
|
|
2958
|
+
/**
|
|
2959
|
+
* Renders its children into another part of the page, `document.body` unless `container` or a `ConfigProvider` says otherwise, so floating content escapes an ancestor's `overflow`, `transform` or stacking context.
|
|
2938
2960
|
*
|
|
2939
2961
|
* React's server renderer can't render a portal, so `Portal` renders nothing
|
|
2940
2962
|
* on the server and during hydration, and mounts its children in the commit
|
|
@@ -2945,8 +2967,12 @@ function resolvePortalContainer(container) {
|
|
|
2945
2967
|
* portaled children, and their React events bubble through the React tree.
|
|
2946
2968
|
* CSS inheritance follows the DOM instead: a scoped (non-`isRoot`) `Theme`
|
|
2947
2969
|
* sets its variables on a wrapper element the portaled content has left, so
|
|
2948
|
-
* that content sees the page-level theme
|
|
2949
|
-
*
|
|
2970
|
+
* that content sees the page-level theme, and styles scoped to a shadow root
|
|
2971
|
+
* don't reach `document.body` at all. To keep them, portal into an element
|
|
2972
|
+
* inside the themed area or the shadow root: pass it as `container`, or as
|
|
2973
|
+
* the `portalContainer` of a `ConfigProvider` around that area. The second
|
|
2974
|
+
* also reaches what the library's components portal, such as Popover's
|
|
2975
|
+
* `appendToBody` panel or a `Modal` with `portal`.
|
|
2950
2976
|
*
|
|
2951
2977
|
* Tab order and focus follow the DOM too. Content portaled from inside a
|
|
2952
2978
|
* focus trap is no longer inside the trapped element, so the trap neither
|
|
@@ -2972,11 +2998,12 @@ function resolvePortalContainer(container) {
|
|
|
2972
2998
|
*/
|
|
2973
2999
|
function Portal({ children, container, disabled = false }) {
|
|
2974
3000
|
const hydrated = useIsHydrated();
|
|
3001
|
+
const resolveContainer = usePortalContainer();
|
|
2975
3002
|
if (disabled)
|
|
2976
3003
|
return jsxRuntime.jsx(jsxRuntime.Fragment, { children: children });
|
|
2977
3004
|
if (!hydrated)
|
|
2978
3005
|
return null;
|
|
2979
|
-
return reactDom.createPortal(children,
|
|
3006
|
+
return reactDom.createPortal(children, resolveContainer(container));
|
|
2980
3007
|
}
|
|
2981
3008
|
|
|
2982
3009
|
/**
|
|
@@ -3131,7 +3158,7 @@ const ModalClose = ({ className, size = 'large', variant = 'delete', ...props })
|
|
|
3131
3158
|
* @see {@link https://bulma.io/documentation/components/modal/ | Bulma Modal documentation}
|
|
3132
3159
|
*/
|
|
3133
3160
|
const ModalRoot = React.forwardRef(function ModalRoot({ active, isActive, onClose, className, textColor, bgColor, modalCardTitle, modalCardFoot, type, children, closeOnEscape = true, lockScroll = true, portal = false, role, 'aria-modal': ariaModalProp, ...props }, ref) {
|
|
3134
|
-
const { classPrefix } = useConfig();
|
|
3161
|
+
const { classPrefix, portalContainer } = useConfig();
|
|
3135
3162
|
const { bulmaHelperClasses, rest } = useBulmaClasses({
|
|
3136
3163
|
color: textColor,
|
|
3137
3164
|
backgroundColor: bgColor,
|
|
@@ -3181,10 +3208,17 @@ const ModalRoot = React.forwardRef(function ModalRoot({ active, isActive, onClos
|
|
|
3181
3208
|
// hydrating render have to stay inline and only move into the portal once
|
|
3182
3209
|
// we're past hydration.
|
|
3183
3210
|
const onClient = useIsHydrated();
|
|
3184
|
-
|
|
3185
|
-
//
|
|
3186
|
-
//
|
|
3211
|
+
const resolveContainer = usePortalContainer();
|
|
3212
|
+
// Moving into the portal, or from one portal target to another, remounts
|
|
3213
|
+
// the modal's subtree, so any effect holding a DOM node from before the move
|
|
3214
|
+
// is holding a detached one. Effects that touch the modal's nodes key on
|
|
3215
|
+
// this, on `portal` and on `defaultTarget`, so they re-run against the new
|
|
3216
|
+
// tree.
|
|
3187
3217
|
const isPortaled = Boolean(portal) && onClient;
|
|
3218
|
+
// The configured `portalContainer` only places a modal portaled with
|
|
3219
|
+
// `portal` set to `true`. In place, or with a target of its own, a change
|
|
3220
|
+
// to it moves nothing, so it mustn't re-run the effects either.
|
|
3221
|
+
const defaultTarget = isPortaled && portal === true ? portalContainer : undefined;
|
|
3188
3222
|
useScrollLock(isModalActive && lockScroll);
|
|
3189
3223
|
// Record open order so keyboard handling only applies to the topmost modal.
|
|
3190
3224
|
React.useEffect(() => {
|
|
@@ -3264,11 +3298,12 @@ const ModalRoot = React.forwardRef(function ModalRoot({ active, isActive, onClos
|
|
|
3264
3298
|
previouslyFocusedRef.current?.focus?.();
|
|
3265
3299
|
};
|
|
3266
3300
|
// `isPortaled` flips once when a hydrated portal modal moves out of the
|
|
3267
|
-
// inline tree
|
|
3268
|
-
//
|
|
3269
|
-
//
|
|
3270
|
-
//
|
|
3271
|
-
|
|
3301
|
+
// inline tree, and `portal` or `defaultTarget` changing moves a portaled
|
|
3302
|
+
// one to another target; re-running rebinds focus onto the remounted
|
|
3303
|
+
// nodes. The cleanup above restores focus to the pre-open element first
|
|
3304
|
+
// (the detached subtree has left focus on <body>), so the re-run re-records
|
|
3305
|
+
// the same element and restore-on-close still lands in the right place.
|
|
3306
|
+
}, [isModalActive, isPortaled, portal, defaultTarget]);
|
|
3272
3307
|
// Check if children contain compound components
|
|
3273
3308
|
const hasCompoundComponents = React.Children.toArray(children).some(child => React.isValidElement(child) &&
|
|
3274
3309
|
(child.type === ModalBackground ||
|
|
@@ -3305,7 +3340,7 @@ const ModalRoot = React.forwardRef(function ModalRoot({ active, isActive, onClos
|
|
|
3305
3340
|
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" }))] }));
|
|
3306
3341
|
}
|
|
3307
3342
|
if (isPortaled) {
|
|
3308
|
-
const target =
|
|
3343
|
+
const target = resolveContainer(typeof portal === 'boolean' ? undefined : portal);
|
|
3309
3344
|
return reactDom.createPortal(modalElement, target);
|
|
3310
3345
|
}
|
|
3311
3346
|
return modalElement;
|
|
@@ -6658,6 +6693,11 @@ const Steps = withSubComponents(StepsComponent, { Step }, 'Steps');
|
|
|
6658
6693
|
*/
|
|
6659
6694
|
const SidebarComponent = React.forwardRef(({ isOpen, onClose, position = 'left', width = '260px', isFullwidth, fullWidth, overlay = true, overlayClose = true, escapeClose = true, canCancel = true, children, inline = false, className, style, ...props }, ref) => {
|
|
6660
6695
|
const { bulmaHelperClasses, rest } = useBulmaClasses(props);
|
|
6696
|
+
const resolveContainer = usePortalContainer();
|
|
6697
|
+
const { portalContainer } = useConfig();
|
|
6698
|
+
// Where the configured default puts the sidebar. An `inline` one doesn't
|
|
6699
|
+
// portal, so a change to the default moves nothing.
|
|
6700
|
+
const defaultTarget = inline ? undefined : portalContainer;
|
|
6661
6701
|
const sidebarRef = React.useRef(null);
|
|
6662
6702
|
// Cleanup returned by a consumer's callback ref on attach, held until detach.
|
|
6663
6703
|
const consumerCleanupRef = React.useRef(null);
|
|
@@ -6689,7 +6729,9 @@ const SidebarComponent = React.forwardRef(({ isOpen, onClose, position = 'left',
|
|
|
6689
6729
|
// Prevent body scroll when sidebar is open. Ref-counted through the shared
|
|
6690
6730
|
// helper so an overlapping Modal/Dialog/Loading doesn't unlock underneath.
|
|
6691
6731
|
useScrollLock(isOpen && overlay);
|
|
6692
|
-
// Focus trap (basic - focus sidebar when opened)
|
|
6732
|
+
// Focus trap (basic - focus sidebar when opened). A different
|
|
6733
|
+
// `defaultTarget` remounts the portaled sidebar, so it focuses the new
|
|
6734
|
+
// nodes then too.
|
|
6693
6735
|
React.useEffect(() => {
|
|
6694
6736
|
if (isOpen) {
|
|
6695
6737
|
const element = sidebarRef.current;
|
|
@@ -6704,7 +6746,7 @@ const SidebarComponent = React.forwardRef(({ isOpen, onClose, position = 'left',
|
|
|
6704
6746
|
}
|
|
6705
6747
|
}
|
|
6706
6748
|
}
|
|
6707
|
-
}, [isOpen]);
|
|
6749
|
+
}, [isOpen, defaultTarget]);
|
|
6708
6750
|
// Use combined ref
|
|
6709
6751
|
const combinedRef = React.useCallback((node) => {
|
|
6710
6752
|
sidebarRef.current =
|
|
@@ -6759,7 +6801,7 @@ const SidebarComponent = React.forwardRef(({ isOpen, onClose, position = 'left',
|
|
|
6759
6801
|
}
|
|
6760
6802
|
// Render to portal for proper stacking
|
|
6761
6803
|
if (typeof document !== 'undefined') {
|
|
6762
|
-
return reactDom.createPortal(sidebarContent,
|
|
6804
|
+
return reactDom.createPortal(sidebarContent, resolveContainer());
|
|
6763
6805
|
}
|
|
6764
6806
|
return null;
|
|
6765
6807
|
});
|
|
@@ -6887,6 +6929,7 @@ function groupIntoPositionStacks(items, positionOf, containerPosition, order) {
|
|
|
6887
6929
|
*/
|
|
6888
6930
|
const Toast = React.forwardRef(({ message, type = 'default', actionType, position = 'top-right', duration = 2000, indefinite = false, dismissible = true, closable = false, rounded = false, pauseOnHover = false, cancelable = true, actionText, cancelText, onAction, onClose, container, inline = false, className, ...props }, ref) => {
|
|
6889
6931
|
const { bulmaHelperClasses, rest } = useBulmaClasses(props);
|
|
6932
|
+
const resolveContainer = usePortalContainer();
|
|
6890
6933
|
const [isVisible, setIsVisible] = React.useState(true);
|
|
6891
6934
|
const [isPaused, setIsPaused] = React.useState(false);
|
|
6892
6935
|
const toastRef = React.useRef(null);
|
|
@@ -7012,7 +7055,7 @@ const Toast = React.forwardRef(({ message, type = 'default', actionType, positio
|
|
|
7012
7055
|
}
|
|
7013
7056
|
const toastContent = jsxRuntime.jsx("div", { className: containerClasses, children: toastElement });
|
|
7014
7057
|
if (typeof document !== 'undefined') {
|
|
7015
|
-
return reactDom.createPortal(toastContent,
|
|
7058
|
+
return reactDom.createPortal(toastContent, resolveContainer(container));
|
|
7016
7059
|
}
|
|
7017
7060
|
return null;
|
|
7018
7061
|
});
|
|
@@ -7169,6 +7212,7 @@ const ToastContainer = ({ position = 'top-right' }) => {
|
|
|
7169
7212
|
// Starts from the toasts already showing instead of an empty list, then
|
|
7170
7213
|
// follows changes.
|
|
7171
7214
|
const toastList = React.useSyncExternalStore(toast.subscribe, getVisibleToasts, getServerToasts);
|
|
7215
|
+
const resolveContainer = usePortalContainer();
|
|
7172
7216
|
if (typeof document === 'undefined' || toastList.length === 0) {
|
|
7173
7217
|
return null;
|
|
7174
7218
|
}
|
|
@@ -7176,7 +7220,7 @@ const ToastContainer = ({ position = 'top-right' }) => {
|
|
|
7176
7220
|
return reactDom.createPortal(stacks.map(stack => (jsxRuntime.jsx("div", { className: `toast-container is-${stack.position}`, children: stack.items.map(t => {
|
|
7177
7221
|
const { queue: _queue, ...toastProps } = t.props;
|
|
7178
7222
|
return (jsxRuntime.jsx(Toast, { ...toastProps, position: stack.position, onClose: () => toast.close(t.id) }, t.id));
|
|
7179
|
-
}) }, stack.key))),
|
|
7223
|
+
}) }, stack.key))), resolveContainer());
|
|
7180
7224
|
};
|
|
7181
7225
|
|
|
7182
7226
|
/**
|
|
@@ -7233,11 +7277,14 @@ const Dialog = React.forwardRef(({ isOpen, title, message, type = 'default', con
|
|
|
7233
7277
|
handleCancel();
|
|
7234
7278
|
}
|
|
7235
7279
|
}, [canCancel, handleCancel]);
|
|
7236
|
-
// Moving into the portal
|
|
7237
|
-
// included
|
|
7238
|
-
// nodes, exactly as the Modal's own focus
|
|
7280
|
+
// Moving into the portal, or from one portal target to another, remounts
|
|
7281
|
+
// the Modal's subtree, these buttons included, so the focus effect below
|
|
7282
|
+
// has to re-run against the new nodes, exactly as the Modal's own focus
|
|
7283
|
+
// effect does, on the same inputs.
|
|
7239
7284
|
const isHydrated = useIsHydrated();
|
|
7240
7285
|
const isPortaled = Boolean(portal) && isHydrated;
|
|
7286
|
+
const { portalContainer } = useConfig();
|
|
7287
|
+
const defaultTarget = isPortaled && portal === true ? portalContainer : undefined;
|
|
7241
7288
|
// Focus management — Dialog picks a specific button rather than the
|
|
7242
7289
|
// Modal's default (first focusable/root); this effect runs after the
|
|
7243
7290
|
// inner Modal's own focus-on-open effect, so it wins.
|
|
@@ -7246,7 +7293,7 @@ const Dialog = React.forwardRef(({ isOpen, title, message, type = 'default', con
|
|
|
7246
7293
|
const buttonToFocus = focusCancel && showCancel ? cancelRef.current : confirmRef.current;
|
|
7247
7294
|
buttonToFocus?.focus();
|
|
7248
7295
|
}
|
|
7249
|
-
}, [isOpen, focusCancel, showCancel, isPortaled]);
|
|
7296
|
+
}, [isOpen, focusCancel, showCancel, isPortaled, portal, defaultTarget]);
|
|
7250
7297
|
// Use combined ref
|
|
7251
7298
|
const combinedRef = React.useCallback((node) => {
|
|
7252
7299
|
dialogRef.current =
|
|
@@ -8881,6 +8928,7 @@ const NotificationContainer = ({ position = 'top-right' }) => {
|
|
|
8881
8928
|
// the server render and the hydrating one render nothing, and the container
|
|
8882
8929
|
// portals in from the render after hydration.
|
|
8883
8930
|
const isHydrated = useIsHydrated();
|
|
8931
|
+
const resolveContainer = usePortalContainer();
|
|
8884
8932
|
// The notifications the status region announces. Danger and warning
|
|
8885
8933
|
// announce themselves.
|
|
8886
8934
|
const politeItems = React.useMemo(() => items.filter(item => !isUrgentColor(item.options.color)), [items]);
|
|
@@ -8913,7 +8961,7 @@ const NotificationContainer = ({ position = 'top-right' }) => {
|
|
|
8913
8961
|
return null;
|
|
8914
8962
|
}
|
|
8915
8963
|
const stacks = groupIntoPositionStacks(items, item => item.options.position, position, notificationStackOrder);
|
|
8916
|
-
return reactDom.createPortal(jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [stacks.map(stack => (jsxRuntime.jsx("div", { style: notificationStackStyle(stack.position), children: stack.items.map(item => (jsxRuntime.jsx(NotificationItem, { instance: item, onClose: notification.close, registerMessage: registerMessage }, item.id))) }, stack.key))), jsxRuntime.jsx(StatusRegion, { items: politeItems, describe: describe })] }),
|
|
8964
|
+
return reactDom.createPortal(jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [stacks.map(stack => (jsxRuntime.jsx("div", { style: notificationStackStyle(stack.position), children: stack.items.map(item => (jsxRuntime.jsx(NotificationItem, { instance: item, onClose: notification.close, registerMessage: registerMessage }, item.id))) }, stack.key))), jsxRuntime.jsx(StatusRegion, { items: politeItems, describe: describe })] }), resolveContainer());
|
|
8917
8965
|
};
|
|
8918
8966
|
|
|
8919
8967
|
/**
|
|
@@ -13840,6 +13888,7 @@ Calendar.displayName = 'Calendar';
|
|
|
13840
13888
|
const isBrowser = typeof window !== 'undefined';
|
|
13841
13889
|
const PickerPopover = ({ isOpen, onClose, anchorRef, children, position = 'bottom-left', appendToBody = false, className, trapFocus = true, closeOnClickOutside = true, closeOnEscape = true, ariaLabel, ariaLabelledBy, role = 'dialog', id, restoreFocusRef, initialFocusSelector, }) => {
|
|
13842
13890
|
const panelRef = React.useRef(null);
|
|
13891
|
+
const resolveContainer = usePortalContainer();
|
|
13843
13892
|
// Read as the trap turns on, once the panel's content has rendered.
|
|
13844
13893
|
const initialFocusRef = React.useMemo(() => initialFocusSelector === undefined
|
|
13845
13894
|
? undefined
|
|
@@ -13916,7 +13965,7 @@ const PickerPopover = ({ isOpen, onClose, anchorRef, children, position = 'botto
|
|
|
13916
13965
|
: {};
|
|
13917
13966
|
const panel = (jsxRuntime.jsx("div", { ref: panelRef, id: id, role: role, "aria-modal": role === 'dialog' ? 'false' : undefined, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, tabIndex: -1, className: classNames(panelClass, className), style: style, children: children }));
|
|
13918
13967
|
if (appendToBody && isBrowser) {
|
|
13919
|
-
return reactDom.createPortal(panel,
|
|
13968
|
+
return reactDom.createPortal(panel, resolveContainer());
|
|
13920
13969
|
}
|
|
13921
13970
|
return panel;
|
|
13922
13971
|
};
|