UNPKG

4.88 kBJavaScriptView Raw
1"use client";
2
3import classNames from 'classnames';
4import useBreakpoint from '@restart/hooks/useBreakpoint';
5import useEventCallback from '@restart/hooks/useEventCallback';
6import * as React from 'react';
7import { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
8import BaseModal from '@restart/ui/Modal';
9import Fade from './Fade';
10import OffcanvasBody from './OffcanvasBody';
11import OffcanvasToggling from './OffcanvasToggling';
12import ModalContext from './ModalContext';
13import NavbarContext from './NavbarContext';
14import OffcanvasHeader from './OffcanvasHeader';
15import OffcanvasTitle from './OffcanvasTitle';
16import { useBootstrapPrefix } from './ThemeProvider';
17import BootstrapModalManager, { getSharedManager } from './BootstrapModalManager';
18import { jsx as _jsx } from "react/jsx-runtime";
19import { Fragment as _Fragment } from "react/jsx-runtime";
20import { jsxs as _jsxs } from "react/jsx-runtime";
21function DialogTransition(props) {
22 return /*#__PURE__*/_jsx(OffcanvasToggling, {
23 ...props
24 });
25}
26function BackdropTransition(props) {
27 return /*#__PURE__*/_jsx(Fade, {
28 ...props
29 });
30}
31const Offcanvas = /*#__PURE__*/React.forwardRef(({
32 bsPrefix,
33 className,
34 children,
35 'aria-labelledby': ariaLabelledby,
36 placement = 'start',
37 responsive,
38 /* BaseModal props */
39
40 show = false,
41 backdrop = true,
42 keyboard = true,
43 scroll = false,
44 onEscapeKeyDown,
45 onShow,
46 onHide,
47 container,
48 autoFocus = true,
49 enforceFocus = true,
50 restoreFocus = true,
51 restoreFocusOptions,
52 onEntered,
53 onExit,
54 onExiting,
55 onEnter,
56 onEntering,
57 onExited,
58 backdropClassName,
59 manager: propsManager,
60 renderStaticNode = false,
61 ...props
62}, ref) => {
63 const modalManager = useRef();
64 bsPrefix = useBootstrapPrefix(bsPrefix, 'offcanvas');
65 const {
66 onToggle
67 } = useContext(NavbarContext) || {};
68 const [showOffcanvas, setShowOffcanvas] = useState(false);
69 const hideResponsiveOffcanvas = useBreakpoint(responsive || 'xs', 'up');
70 useEffect(() => {
71 // Handles the case where screen is resized while the responsive
72 // offcanvas is shown. If `responsive` not provided, just use `show`.
73 setShowOffcanvas(responsive ? show && !hideResponsiveOffcanvas : show);
74 }, [show, responsive, hideResponsiveOffcanvas]);
75 const handleHide = useEventCallback(() => {
76 onToggle == null ? void 0 : onToggle();
77 onHide == null ? void 0 : onHide();
78 });
79 const modalContext = useMemo(() => ({
80 onHide: handleHide
81 }), [handleHide]);
82 function getModalManager() {
83 if (propsManager) return propsManager;
84 if (scroll) {
85 // Have to use a different modal manager since the shared
86 // one handles overflow.
87 if (!modalManager.current) modalManager.current = new BootstrapModalManager({
88 handleContainerOverflow: false
89 });
90 return modalManager.current;
91 }
92 return getSharedManager();
93 }
94 const handleEnter = (node, ...args) => {
95 if (node) node.style.visibility = 'visible';
96 onEnter == null ? void 0 : onEnter(node, ...args);
97 };
98 const handleExited = (node, ...args) => {
99 if (node) node.style.visibility = '';
100 onExited == null ? void 0 : onExited(...args);
101 };
102 const renderBackdrop = useCallback(backdropProps => /*#__PURE__*/_jsx("div", {
103 ...backdropProps,
104 className: classNames(`${bsPrefix}-backdrop`, backdropClassName)
105 }), [backdropClassName, bsPrefix]);
106 const renderDialog = dialogProps => /*#__PURE__*/_jsx("div", {
107 ...dialogProps,
108 ...props,
109 className: classNames(className, responsive ? `${bsPrefix}-${responsive}` : bsPrefix, `${bsPrefix}-${placement}`),
110 "aria-labelledby": ariaLabelledby,
111 children: children
112 });
113 return /*#__PURE__*/_jsxs(_Fragment, {
114 children: [!showOffcanvas && (responsive || renderStaticNode) && renderDialog({}), /*#__PURE__*/_jsx(ModalContext.Provider, {
115 value: modalContext,
116 children: /*#__PURE__*/_jsx(BaseModal, {
117 show: showOffcanvas,
118 ref: ref,
119 backdrop: backdrop,
120 container: container,
121 keyboard: keyboard,
122 autoFocus: autoFocus,
123 enforceFocus: enforceFocus && !scroll,
124 restoreFocus: restoreFocus,
125 restoreFocusOptions: restoreFocusOptions,
126 onEscapeKeyDown: onEscapeKeyDown,
127 onShow: onShow,
128 onHide: handleHide,
129 onEnter: handleEnter,
130 onEntering: onEntering,
131 onEntered: onEntered,
132 onExit: onExit,
133 onExiting: onExiting,
134 onExited: handleExited,
135 manager: getModalManager(),
136 transition: DialogTransition,
137 backdropTransition: BackdropTransition,
138 renderBackdrop: renderBackdrop,
139 renderDialog: renderDialog
140 })
141 })]
142 });
143});
144Offcanvas.displayName = 'Offcanvas';
145export default Object.assign(Offcanvas, {
146 Body: OffcanvasBody,
147 Header: OffcanvasHeader,
148 Title: OffcanvasTitle
149});
\No newline at end of file