@inertiaui/modal-react 0.1.0 → 0.1.2
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/inertiaui-modal.js +4544 -4504
- package/dist/inertiaui-modal.umd.cjs +20 -20
- package/package.json +1 -1
- package/src/HeadlessModal.jsx +88 -0
- package/src/Modal.jsx +86 -119
- package/src/inertiauiModal.js +4 -2
package/package.json
CHANGED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { useMemo, useState, forwardRef, useImperativeHandle, useEffect } from 'react'
|
|
2
|
+
import { getConfig, getConfigByType } from './config'
|
|
3
|
+
import { useModalIndex } from './ModalRenderer.jsx'
|
|
4
|
+
import { useModalStack } from './ModalRoot.jsx'
|
|
5
|
+
import ModalRenderer from './ModalRenderer'
|
|
6
|
+
|
|
7
|
+
const HeadlessModal = forwardRef(({ name, children, ...props }, ref) => {
|
|
8
|
+
const modalIndex = useModalIndex()
|
|
9
|
+
const { stack, registerLocalModal, removeLocalModal } = useModalStack()
|
|
10
|
+
|
|
11
|
+
const [localModalContext, setLocalModalContext] = useState(null)
|
|
12
|
+
const modalContext = useMemo(() => (name ? localModalContext : stack[modalIndex]))
|
|
13
|
+
|
|
14
|
+
const modalPropsSlideover = useMemo(() => modalContext?.modalProps.slideover ?? props.slideover ?? getConfig('type') === 'slideover', [props.slideover])
|
|
15
|
+
|
|
16
|
+
const modalProps = useMemo(
|
|
17
|
+
() => ({
|
|
18
|
+
slideover: modalPropsSlideover,
|
|
19
|
+
closeButton: props.closeButton ?? getConfigByType(modalPropsSlideover, 'closeButton'),
|
|
20
|
+
closeExplicitly: props.closeExplicitly ?? getConfigByType(modalPropsSlideover, 'closeExplicitly'),
|
|
21
|
+
maxWidth: props.maxWidth ?? getConfigByType(modalPropsSlideover, 'maxWidth'),
|
|
22
|
+
paddingClasses: props.paddingClasses ?? getConfigByType(modalPropsSlideover, 'paddingClasses'),
|
|
23
|
+
panelClasses: props.panelClasses ?? getConfigByType(modalPropsSlideover, 'panelClasses'),
|
|
24
|
+
position: props.position ?? getConfigByType(modalPropsSlideover, 'position'),
|
|
25
|
+
...modalContext?.modalProps,
|
|
26
|
+
}),
|
|
27
|
+
[props, modalContext?.modalProps],
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
if (name) {
|
|
32
|
+
let removeListeners = null
|
|
33
|
+
|
|
34
|
+
registerLocalModal(name, (localContext) => {
|
|
35
|
+
removeListeners = localContext.registerEventListenersFromProps(props)
|
|
36
|
+
setLocalModalContext(localContext)
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
return () => {
|
|
40
|
+
removeListeners?.()
|
|
41
|
+
removeListeners = null
|
|
42
|
+
removeLocalModal(name)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return modalContext.registerEventListenersFromProps(props)
|
|
47
|
+
}, [name])
|
|
48
|
+
|
|
49
|
+
useImperativeHandle(
|
|
50
|
+
ref,
|
|
51
|
+
() => ({
|
|
52
|
+
afterLeave: () => modalContext.afterLeave(),
|
|
53
|
+
close: () => modalContext.close(),
|
|
54
|
+
emit: (...args) => modalContext.emit(...args),
|
|
55
|
+
getChildModal: () => modalContext.getChildModal(),
|
|
56
|
+
getParentModal: () => modalContext.getParentModal(),
|
|
57
|
+
modalContext,
|
|
58
|
+
modalProps,
|
|
59
|
+
reload: () => modalContext.reload(),
|
|
60
|
+
}),
|
|
61
|
+
[modalContext],
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
modalContext && (
|
|
66
|
+
<>
|
|
67
|
+
{typeof children === 'function'
|
|
68
|
+
? children({
|
|
69
|
+
afterLeave: modalContext.afterLeave,
|
|
70
|
+
close: modalContext.close,
|
|
71
|
+
emit: modalContext.emit,
|
|
72
|
+
getChildModal: modalContext.getChildModal,
|
|
73
|
+
getParentModal: modalContext.getParentModal,
|
|
74
|
+
modalContext,
|
|
75
|
+
modalProps,
|
|
76
|
+
reload: modalContext.reload,
|
|
77
|
+
})
|
|
78
|
+
: children}
|
|
79
|
+
|
|
80
|
+
{/* Next modal in the stack */}
|
|
81
|
+
{stack[modalContext.index + 1] && <ModalRenderer index={modalContext.index + 1} />}
|
|
82
|
+
</>
|
|
83
|
+
)
|
|
84
|
+
)
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
HeadlessModal.displayName = 'HeadlessModal'
|
|
88
|
+
export default HeadlessModal
|
package/src/Modal.jsx
CHANGED
|
@@ -1,135 +1,102 @@
|
|
|
1
1
|
import { Dialog, Transition, TransitionChild } from '@headlessui/react'
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import { useModalIndex } from './ModalRenderer.jsx'
|
|
5
|
-
import { useModalStack } from './ModalRoot.jsx'
|
|
2
|
+
import { forwardRef, useRef, useImperativeHandle } from 'react'
|
|
3
|
+
import HeadlessModal from './HeadlessModal'
|
|
6
4
|
import ModalContent from './ModalContent'
|
|
7
|
-
import ModalRenderer from './ModalRenderer'
|
|
8
5
|
import SlideoverContent from './SlideoverContent'
|
|
9
6
|
|
|
10
7
|
const Modal = forwardRef(({ name, children, ...props }, ref) => {
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const [localModalContext, setLocalModalContext] = useState(null)
|
|
15
|
-
const modalContext = useMemo(() => (name ? localModalContext : stack[modalIndex]))
|
|
16
|
-
|
|
17
|
-
const modalPropsSlideover = useMemo(() => modalContext?.modalProps.slideover ?? props.slideover ?? getConfig('type') === 'slideover', [props.slideover])
|
|
18
|
-
|
|
19
|
-
const modalProps = useMemo(
|
|
20
|
-
() => ({
|
|
21
|
-
slideover: modalPropsSlideover,
|
|
22
|
-
closeButton: props.closeButton ?? getConfigByType(modalPropsSlideover, 'closeButton'),
|
|
23
|
-
closeExplicitly: props.closeExplicitly ?? getConfigByType(modalPropsSlideover, 'closeExplicitly'),
|
|
24
|
-
maxWidth: props.maxWidth ?? getConfigByType(modalPropsSlideover, 'maxWidth'),
|
|
25
|
-
paddingClasses: props.paddingClasses ?? getConfigByType(modalPropsSlideover, 'paddingClasses'),
|
|
26
|
-
panelClasses: props.panelClasses ?? getConfigByType(modalPropsSlideover, 'panelClasses'),
|
|
27
|
-
position: props.position ?? getConfigByType(modalPropsSlideover, 'position'),
|
|
28
|
-
...modalContext?.modalProps,
|
|
29
|
-
}),
|
|
30
|
-
[props, modalContext?.modalProps],
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
const Content = useMemo(() => (modalProps.slideover ? SlideoverContent : ModalContent), [modalProps.slideover])
|
|
34
|
-
|
|
35
|
-
useEffect(() => {
|
|
36
|
-
if (name) {
|
|
37
|
-
let removeListeners = null
|
|
38
|
-
|
|
39
|
-
registerLocalModal(name, (localContext) => {
|
|
40
|
-
removeListeners = localContext.registerEventListenersFromProps(props)
|
|
41
|
-
setLocalModalContext(localContext)
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
return () => {
|
|
45
|
-
removeListeners?.()
|
|
46
|
-
removeListeners = null
|
|
47
|
-
removeLocalModal(name)
|
|
48
|
-
}
|
|
8
|
+
const renderChildren = (contentProps) => {
|
|
9
|
+
if (typeof children === 'function') {
|
|
10
|
+
return children(contentProps)
|
|
49
11
|
}
|
|
50
12
|
|
|
51
|
-
return
|
|
52
|
-
}
|
|
13
|
+
return children
|
|
14
|
+
}
|
|
53
15
|
|
|
54
|
-
|
|
55
|
-
ref,
|
|
56
|
-
() => ({
|
|
57
|
-
close: () => modalContext.close(),
|
|
58
|
-
emit: (...args) => modalContext.emit(...args),
|
|
59
|
-
getChildModal: () => modalContext.getChildModal(),
|
|
60
|
-
getParentModal: () => modalContext.getParentModal(),
|
|
61
|
-
modalContext: modalContext,
|
|
62
|
-
reload: () => modalContext.reload(),
|
|
63
|
-
}),
|
|
64
|
-
[modalContext],
|
|
65
|
-
)
|
|
16
|
+
const headlessModalRef = useRef(null)
|
|
66
17
|
|
|
67
|
-
|
|
68
|
-
if (!modalProps.closeExplicitly) {
|
|
69
|
-
modalContext.close()
|
|
70
|
-
}
|
|
71
|
-
}
|
|
18
|
+
useImperativeHandle(ref, () => headlessModalRef.current, [headlessModalRef])
|
|
72
19
|
|
|
73
20
|
return (
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
data-inertiaui-modal-id={modalContext.id}
|
|
84
|
-
data-inertiaui-modal-index={modalContext.index}
|
|
21
|
+
<HeadlessModal
|
|
22
|
+
ref={headlessModalRef}
|
|
23
|
+
name={name}
|
|
24
|
+
{...props}
|
|
25
|
+
>
|
|
26
|
+
{({ afterLeave, close, emit, getChildModal, getParentModal, modalContext, modalProps, reload }) => (
|
|
27
|
+
<Transition
|
|
28
|
+
appear={true}
|
|
29
|
+
show={modalContext.open ?? false}
|
|
85
30
|
>
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
leave="transition transform ease-in-out duration-300"
|
|
93
|
-
leaveFrom="opacity-100"
|
|
94
|
-
leaveTo="opacity-0"
|
|
95
|
-
>
|
|
96
|
-
{modalContext.onTopOfStack ? (
|
|
97
|
-
<div
|
|
98
|
-
className="im-backdrop fixed inset-0 z-30 bg-black/75"
|
|
99
|
-
aria-hidden="true"
|
|
100
|
-
/>
|
|
101
|
-
) : (
|
|
102
|
-
<div />
|
|
103
|
-
)}
|
|
104
|
-
</TransitionChild>
|
|
105
|
-
) : null}
|
|
106
|
-
|
|
107
|
-
{/* On multiple modals, only show a backdrop for the modal that is on top of the stack */}
|
|
108
|
-
{modalContext.index > 0 && modalContext.onTopOfStack ? <div className="im-backdrop fixed inset-0 z-30 bg-black/75" /> : null}
|
|
109
|
-
|
|
110
|
-
{/* The modal/slideover content itself */}
|
|
111
|
-
<Content
|
|
112
|
-
modalContext={modalContext}
|
|
113
|
-
modalProps={modalProps}
|
|
31
|
+
<Dialog
|
|
32
|
+
as="div"
|
|
33
|
+
className="im-dialog relative z-20"
|
|
34
|
+
onClose={() => (modalProps.closeExplicitly ? null : close())}
|
|
35
|
+
data-inertiaui-modal-id={modalContext.id}
|
|
36
|
+
data-inertiaui-modal-index={modalContext.index}
|
|
114
37
|
>
|
|
115
|
-
{
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
38
|
+
{/* Only transition the backdrop for the first modal in the stack */}
|
|
39
|
+
{modalContext.index === 0 ? (
|
|
40
|
+
<TransitionChild
|
|
41
|
+
enter="transition transform ease-in-out duration-300"
|
|
42
|
+
enterFrom="opacity-0"
|
|
43
|
+
enterTo="opacity-100"
|
|
44
|
+
leave="transition transform ease-in-out duration-300"
|
|
45
|
+
leaveFrom="opacity-100"
|
|
46
|
+
leaveTo="opacity-0"
|
|
47
|
+
>
|
|
48
|
+
{modalContext.onTopOfStack ? (
|
|
49
|
+
<div
|
|
50
|
+
className="im-backdrop fixed inset-0 z-30 bg-black/75"
|
|
51
|
+
aria-hidden="true"
|
|
52
|
+
/>
|
|
53
|
+
) : (
|
|
54
|
+
<div />
|
|
55
|
+
)}
|
|
56
|
+
</TransitionChild>
|
|
57
|
+
) : null}
|
|
58
|
+
|
|
59
|
+
{/* On multiple modals, only show a backdrop for the modal that is on top of the stack */}
|
|
60
|
+
{modalContext.index > 0 && modalContext.onTopOfStack ? <div className="im-backdrop fixed inset-0 z-30 bg-black/75" /> : null}
|
|
61
|
+
|
|
62
|
+
{/* The modal/slideover content itself */}
|
|
63
|
+
{modalProps.slideover ? (
|
|
64
|
+
<SlideoverContent
|
|
65
|
+
modalContext={modalContext}
|
|
66
|
+
modalProps={modalProps}
|
|
67
|
+
>
|
|
68
|
+
{renderChildren({
|
|
69
|
+
afterLeave,
|
|
70
|
+
close,
|
|
71
|
+
emit,
|
|
72
|
+
getChildModal,
|
|
73
|
+
getParentModal,
|
|
74
|
+
modalContext,
|
|
75
|
+
modalProps,
|
|
76
|
+
reload,
|
|
77
|
+
})}
|
|
78
|
+
</SlideoverContent>
|
|
79
|
+
) : (
|
|
80
|
+
<ModalContent
|
|
81
|
+
modalContext={modalContext}
|
|
82
|
+
modalProps={modalProps}
|
|
83
|
+
>
|
|
84
|
+
{renderChildren({
|
|
85
|
+
afterLeave,
|
|
86
|
+
close,
|
|
87
|
+
emit,
|
|
88
|
+
getChildModal,
|
|
89
|
+
getParentModal,
|
|
90
|
+
modalContext,
|
|
91
|
+
modalProps,
|
|
92
|
+
reload,
|
|
93
|
+
})}
|
|
94
|
+
</ModalContent>
|
|
95
|
+
)}
|
|
96
|
+
</Dialog>
|
|
97
|
+
</Transition>
|
|
98
|
+
)}
|
|
99
|
+
</HeadlessModal>
|
|
133
100
|
)
|
|
134
101
|
})
|
|
135
102
|
|
package/src/inertiauiModal.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { getConfig, putConfig, resetConfig } from './config.js'
|
|
2
|
+
import { useModalIndex } from './ModalRenderer.jsx'
|
|
3
|
+
import { useModalStack, ModalRoot, ModalStackProvider } from './ModalRoot.jsx'
|
|
4
|
+
import HeadlessModal from './HeadlessModal.jsx'
|
|
2
5
|
import Modal from './Modal.jsx'
|
|
3
6
|
import ModalLink from './ModalLink.jsx'
|
|
4
|
-
import { useModalStack, ModalRoot, ModalStackProvider } from './ModalRoot.jsx'
|
|
5
7
|
|
|
6
|
-
export {
|
|
8
|
+
export { getConfig, putConfig, resetConfig, useModalStack, useModalIndex, HeadlessModal, Modal, ModalLink, ModalRoot, ModalStackProvider }
|