@inertiaui/modal-react 3.1.0 → 3.1.1

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/src/Modal.tsx CHANGED
@@ -1,10 +1,11 @@
1
+ import { lockScroll, markAriaHidden } from '@inertiaui/vanilla'
1
2
  import { forwardRef, useRef, useImperativeHandle, useState, useEffect, useCallback, useMemo, ReactNode } from 'react'
2
3
  import { createPortal } from 'react-dom'
4
+
5
+ import { getConfig } from './config'
3
6
  import HeadlessModal, { HeadlessModalRef } from './HeadlessModal'
4
7
  import ModalContent from './ModalContent'
5
8
  import SlideoverContent from './SlideoverContent'
6
- import { lockScroll, markAriaHidden } from '@inertiaui/vanilla'
7
- import { getConfig } from './config'
8
9
  import type { Modal as ModalType, ReloadOptions } from './types'
9
10
 
10
11
  interface ModalConfig {
@@ -61,158 +62,145 @@ interface BackdropTransitionProps {
61
62
  onAfterAppear?: () => void
62
63
  }
63
64
 
64
- const Modal = forwardRef<HeadlessModalRef, ModalProps>(
65
- (allProps, ref) => {
66
- const { name, children, onFocus, onBlur, onClose, onSuccess, onAfterLeave, ...props } = allProps as ModalBaseProps & Record<string, unknown>
67
- const renderChildren = (contentProps: ModalRenderProps) => {
68
- if (typeof children === 'function') {
69
- return children(contentProps)
70
- }
71
-
72
- return children
65
+ const Modal = forwardRef<HeadlessModalRef, ModalProps>((allProps, ref) => {
66
+ const { name, children, onFocus, onBlur, onClose, onSuccess, onAfterLeave, ...props } = allProps as ModalBaseProps & Record<string, unknown>
67
+ const renderChildren = (contentProps: ModalRenderProps) => {
68
+ if (typeof children === 'function') {
69
+ return children(contentProps)
73
70
  }
74
71
 
75
- const headlessModalRef = useRef<HeadlessModalRef>(null)
76
- const cleanupScrollLockRef = useRef<(() => void) | null>(null)
77
- const cleanupAriaHiddenRef = useRef<(() => void) | null>(null)
78
- const [rendered, setRendered] = useState(false)
79
- const useNativeDialog = useMemo(() => getConfig('useNativeDialog') as boolean, [])
72
+ return children
73
+ }
80
74
 
81
- useImperativeHandle(ref, () => headlessModalRef.current!, [headlessModalRef])
82
-
83
- // Cleanup on unmount
84
- useEffect(() => {
85
- return () => {
86
- cleanupScrollLockRef.current?.()
87
- cleanupAriaHiddenRef.current?.()
88
- }
89
- }, [])
75
+ const headlessModalRef = useRef<HeadlessModalRef>(null)
76
+ const cleanupScrollLockRef = useRef<(() => void) | null>(null)
77
+ const cleanupAriaHiddenRef = useRef<(() => void) | null>(null)
78
+ const [rendered, setRendered] = useState(false)
79
+ const useNativeDialog = useMemo(() => getConfig('useNativeDialog') as boolean, [])
90
80
 
91
- const handleSuccess = useCallback(() => {
92
- onSuccess?.()
93
- if (!cleanupScrollLockRef.current) {
94
- cleanupScrollLockRef.current = lockScroll()
95
- cleanupAriaHiddenRef.current = markAriaHidden(getConfig('appElement') as string)
96
- }
97
- }, [onSuccess])
81
+ useImperativeHandle(ref, () => headlessModalRef.current!, [headlessModalRef])
98
82
 
99
- const handleClose = useCallback(() => {
100
- onClose?.()
83
+ // Cleanup on unmount
84
+ useEffect(() => {
85
+ return () => {
101
86
  cleanupScrollLockRef.current?.()
102
87
  cleanupAriaHiddenRef.current?.()
103
- cleanupScrollLockRef.current = null
104
- cleanupAriaHiddenRef.current = null
105
- }, [onClose])
88
+ }
89
+ }, [])
106
90
 
107
- const handleAfterLeave = useCallback(() => {
108
- onAfterLeave?.()
109
- }, [onAfterLeave])
91
+ const handleSuccess = useCallback(() => {
92
+ onSuccess?.()
93
+ if (!cleanupScrollLockRef.current) {
94
+ cleanupScrollLockRef.current = lockScroll()
95
+ cleanupAriaHiddenRef.current = markAriaHidden(getConfig('appElement') as string)
96
+ }
97
+ }, [onSuccess])
110
98
 
111
- return (
112
- <HeadlessModal
113
- ref={headlessModalRef}
114
- name={name}
115
- onFocus={onFocus ?? undefined}
116
- onBlur={onBlur ?? undefined}
117
- onClose={handleClose}
118
- onSuccess={handleSuccess}
119
- {...props}
120
- >
121
- {({
122
- afterLeave,
123
- close,
124
- config,
125
- emit,
126
- getChildModal,
127
- getParentModal,
128
- id,
129
- index,
130
- isOpen,
131
- modalContext,
132
- onTopOfStack,
133
- reload,
134
- setOpen,
135
- shouldRender,
136
- ...extraProps
137
- }) => (
138
- <ModalPortal>
139
- <div
140
- className="im-dialog relative z-20"
141
- data-inertiaui-modal-id={id}
142
- data-inertiaui-modal-index={index}
143
- aria-hidden={!onTopOfStack}
144
- >
145
- {/* Only render backdrop for the first modal (non-native dialog mode) */}
146
- {/* Native dialog uses ::backdrop pseudo-element instead */}
147
- {index === 0 && !useNativeDialog && (
148
- <BackdropTransition
149
- show={isOpen}
150
- appear={!rendered}
151
- onAfterAppear={() => setRendered(true)}
152
- />
153
- )}
99
+ const handleClose = useCallback(() => {
100
+ onClose?.()
101
+ cleanupScrollLockRef.current?.()
102
+ cleanupAriaHiddenRef.current?.()
103
+ cleanupScrollLockRef.current = null
104
+ cleanupAriaHiddenRef.current = null
105
+ }, [onClose])
154
106
 
155
- {/* The modal/slideover content itself */}
156
- {config.slideover ? (
157
- <SlideoverContent
158
- modalContext={modalContext}
159
- config={config}
160
- useNativeDialog={useNativeDialog}
161
- isFirstModal={index === 0}
162
- onAfterLeave={handleAfterLeave}
163
- >
164
- {renderChildren({
165
- ...extraProps,
166
- afterLeave,
167
- close,
168
- config,
169
- emit,
170
- getChildModal,
171
- getParentModal,
172
- id,
173
- index,
174
- isOpen,
175
- modalContext,
176
- onTopOfStack,
177
- reload,
178
- setOpen,
179
- shouldRender,
180
- })}
181
- </SlideoverContent>
182
- ) : (
183
- <ModalContent
184
- modalContext={modalContext}
185
- config={config}
186
- useNativeDialog={useNativeDialog}
187
- isFirstModal={index === 0}
188
- onAfterLeave={handleAfterLeave}
189
- >
190
- {renderChildren({
191
- ...extraProps,
192
- afterLeave,
193
- close,
194
- config,
195
- emit,
196
- getChildModal,
197
- getParentModal,
198
- id,
199
- index,
200
- isOpen,
201
- modalContext,
202
- onTopOfStack,
203
- reload,
204
- setOpen,
205
- shouldRender,
206
- })}
207
- </ModalContent>
208
- )}
209
- </div>
210
- </ModalPortal>
211
- )}
212
- </HeadlessModal>
213
- )
214
- },
215
- )
107
+ const handleAfterLeave = useCallback(() => {
108
+ onAfterLeave?.()
109
+ }, [onAfterLeave])
110
+
111
+ return (
112
+ <HeadlessModal
113
+ ref={headlessModalRef}
114
+ name={name}
115
+ onFocus={onFocus ?? undefined}
116
+ onBlur={onBlur ?? undefined}
117
+ onClose={handleClose}
118
+ onSuccess={handleSuccess}
119
+ {...props}
120
+ >
121
+ {({
122
+ afterLeave,
123
+ close,
124
+ config,
125
+ emit,
126
+ getChildModal,
127
+ getParentModal,
128
+ id,
129
+ index,
130
+ isOpen,
131
+ modalContext,
132
+ onTopOfStack,
133
+ reload,
134
+ setOpen,
135
+ shouldRender,
136
+ ...extraProps
137
+ }) => (
138
+ <ModalPortal>
139
+ <div className="im-dialog relative z-20" data-inertiaui-modal-id={id} data-inertiaui-modal-index={index} aria-hidden={!onTopOfStack}>
140
+ {/* Only render backdrop for the first modal (non-native dialog mode) */}
141
+ {/* Native dialog uses ::backdrop pseudo-element instead */}
142
+ {index === 0 && !useNativeDialog && <BackdropTransition show={isOpen} appear={!rendered} onAfterAppear={() => setRendered(true)} />}
143
+
144
+ {/* The modal/slideover content itself */}
145
+ {config.slideover ? (
146
+ <SlideoverContent
147
+ modalContext={modalContext}
148
+ config={config}
149
+ useNativeDialog={useNativeDialog}
150
+ isFirstModal={index === 0}
151
+ onAfterLeave={handleAfterLeave}
152
+ >
153
+ {renderChildren({
154
+ ...extraProps,
155
+ afterLeave,
156
+ close,
157
+ config,
158
+ emit,
159
+ getChildModal,
160
+ getParentModal,
161
+ id,
162
+ index,
163
+ isOpen,
164
+ modalContext,
165
+ onTopOfStack,
166
+ reload,
167
+ setOpen,
168
+ shouldRender,
169
+ })}
170
+ </SlideoverContent>
171
+ ) : (
172
+ <ModalContent
173
+ modalContext={modalContext}
174
+ config={config}
175
+ useNativeDialog={useNativeDialog}
176
+ isFirstModal={index === 0}
177
+ onAfterLeave={handleAfterLeave}
178
+ >
179
+ {renderChildren({
180
+ ...extraProps,
181
+ afterLeave,
182
+ close,
183
+ config,
184
+ emit,
185
+ getChildModal,
186
+ getParentModal,
187
+ id,
188
+ index,
189
+ isOpen,
190
+ modalContext,
191
+ onTopOfStack,
192
+ reload,
193
+ setOpen,
194
+ shouldRender,
195
+ })}
196
+ </ModalContent>
197
+ )}
198
+ </div>
199
+ </ModalPortal>
200
+ )}
201
+ </HeadlessModal>
202
+ )
203
+ })
216
204
 
217
205
  // Simple portal component
218
206
  function ModalPortal({ children }: { children: ReactNode }) {
@@ -1,7 +1,8 @@
1
+ import { createFocusTrap, onEscapeKey, animate, cancelAnimations } from '@inertiaui/vanilla'
2
+ import clsx from 'clsx'
1
3
  import { useState, useEffect, useRef, useCallback, useMemo, ReactNode, SyntheticEvent, MouseEvent } from 'react'
4
+
2
5
  import CloseButton from './CloseButton'
3
- import clsx from 'clsx'
4
- import { createFocusTrap, onEscapeKey, animate, cancelAnimations } from '@inertiaui/vanilla'
5
6
  import { getMaxWidthClass } from './constants'
6
7
  import type { Modal } from './types'
7
8
 
@@ -26,8 +27,8 @@ interface ModalContentProps {
26
27
 
27
28
  const ModalContent = ({ modalContext, config, useNativeDialog, isFirstModal, onAfterLeave, children }: ModalContentProps) => {
28
29
  const [isRendered, setIsRendered] = useState(false)
29
- const [isVisible, setIsVisible] = useState(false) // For backdrop sync
30
- const [entered, setEntered] = useState(false) // After animation completes
30
+ const [isVisible, setIsVisible] = useState(false) // For backdrop sync
31
+ const [entered, setEntered] = useState(false) // After animation completes
31
32
  const wrapperRef = useRef<HTMLDivElement>(null)
32
33
  const dialogRef = useRef<HTMLDialogElement>(null)
33
34
  const nativeWrapperRef = useRef<HTMLDivElement>(null)
@@ -230,12 +231,9 @@ const ModalContent = ({ modalContext, config, useNativeDialog, isFirstModal, onA
230
231
  // ============ Render ============
231
232
 
232
233
  const renderContent = () => (
233
- <div
234
- className={`im-modal-content relative ${config.paddingClasses} ${config.panelClasses}`}
235
- data-inertiaui-modal-entered={entered}
236
- >
234
+ <div className={`im-modal-content relative ${config.paddingClasses} ${config.panelClasses}`} data-inertiaui-modal-entered={entered}>
237
235
  {config.closeButton && (
238
- <div className="absolute right-0 top-0 pr-3 pt-3">
236
+ <div className="absolute top-0 right-0 pt-3 pr-3">
239
237
  <CloseButton onClick={modalContext.close} />
240
238
  </div>
241
239
  )}
@@ -268,7 +266,11 @@ const ModalContent = ({ modalContext, config, useNativeDialog, isFirstModal, onA
268
266
  >
269
267
  <div
270
268
  ref={nativeWrapperRef}
271
- className={clsx('im-modal-wrapper w-full transition-[filter] duration-300', modalContext.onTopOfStack ? '' : 'blur-xs', maxWidthClass)}
269
+ className={clsx(
270
+ 'im-modal-wrapper w-full transition-[filter] duration-300',
271
+ modalContext.onTopOfStack ? '' : 'blur-xs',
272
+ maxWidthClass,
273
+ )}
272
274
  >
273
275
  {renderContent()}
274
276
  </div>
@@ -282,10 +284,7 @@ const ModalContent = ({ modalContext, config, useNativeDialog, isFirstModal, onA
282
284
  if (!isRendered) return null
283
285
 
284
286
  return (
285
- <div
286
- className="im-modal-container fixed inset-0 z-40 overflow-y-auto p-4"
287
- onMouseDown={handleClickOutside}
288
- >
287
+ <div className="im-modal-container fixed inset-0 z-40 overflow-y-auto p-4" onMouseDown={handleClickOutside}>
289
288
  <div
290
289
  className={clsx('im-modal-positioner flex min-h-full justify-center', {
291
290
  'items-start': config.position === 'top',
package/src/ModalLink.tsx CHANGED
@@ -1,9 +1,10 @@
1
+ import type { RequestPayload } from '@inertiajs/core'
1
2
  import { useCallback, useState, useEffect, useMemo, useRef, ReactNode, ElementType, MouseEvent } from 'react'
2
- import { useModalStack, modalPropNames, prefetch as prefetchModal } from './ModalRoot'
3
- import { only, rejectNullValues, isStandardDomEvent } from './helpers'
3
+
4
4
  import { getConfig } from './config'
5
+ import { only, rejectNullValues, isStandardDomEvent } from './helpers'
6
+ import { useModalStack, modalPropNames, prefetch as prefetchModal } from './ModalRoot'
5
7
  import type { Modal, PrefetchOption, HttpMethod } from './types'
6
- import type { RequestPayload } from '@inertiajs/core'
7
8
 
8
9
  interface ModalLinkProps {
9
10
  href: string
@@ -1,4 +1,5 @@
1
1
  import React, { useMemo, createElement } from 'react'
2
+
2
3
  import { useModalStack } from './ModalRoot'
3
4
  import type { ModalRendererProps } from './types'
4
5
 
package/src/ModalRoot.tsx CHANGED
@@ -1,11 +1,12 @@
1
- import { createElement, useEffect, useLayoutEffect, useState, useRef, useReducer, ReactNode, ComponentType } from 'react'
2
- import { except, kebabCase, generateId, sameUrlPath, parseResponseData } from './helpers'
3
- import { ResponseCache } from './cache'
4
- import { router, usePage, progress, http } from '@inertiajs/react'
5
1
  import { mergeDataIntoQueryString, type RequestPayload, type HttpResponse, type HttpRequestConfig } from '@inertiajs/core'
2
+ import { router, usePage, progress, http } from '@inertiajs/react'
3
+ import { createElement, useEffect, useLayoutEffect, useState, useRef, useReducer, ReactNode, ComponentType } from 'react'
6
4
  import { createContext, useContext } from 'react'
7
- import ModalRenderer from './ModalRenderer'
5
+
6
+ import { ResponseCache } from './cache'
8
7
  import { getConfig } from './config'
8
+ import { except, kebabCase, generateId, sameUrlPath, parseResponseData } from './helpers'
9
+ import ModalRenderer from './ModalRenderer'
9
10
  import type {
10
11
  Modal,
11
12
  ModalConfig,
@@ -346,7 +347,7 @@ export const ModalStackProvider = ({ children }: ModalStackProviderProps) => {
346
347
  data: method === 'get' ? undefined : data,
347
348
  params: method === 'get' ? data : undefined,
348
349
  headers: {
349
- ...(options.headers ?? {}),
350
+ ...options.headers,
350
351
  Accept: 'text/html, application/xhtml+xml',
351
352
  'X-Inertia': 'true',
352
353
  'X-Inertia-Partial-Component': this.response.component,
@@ -376,12 +377,7 @@ export const ModalStackProvider = ({ children }: ModalStackProviderProps) => {
376
377
  }
377
378
 
378
379
  const isValidModalResponse = (data: unknown): data is ModalResponseData => {
379
- return (
380
- typeof data === 'object' &&
381
- data !== null &&
382
- 'component' in data &&
383
- typeof (data as ModalResponseData).component === 'string'
384
- )
380
+ return typeof data === 'object' && data !== null && 'component' in data && typeof (data as ModalResponseData).component === 'string'
385
381
  }
386
382
 
387
383
  const pushFromResponseData = (
@@ -399,9 +395,9 @@ export const ModalStackProvider = ({ children }: ModalStackProviderProps) => {
399
395
  )
400
396
  }
401
397
 
402
- return router.resolveComponent(responseData.component).then((component) =>
403
- push(component as ComponentType, responseData, config, onClose, onAfterLeave),
404
- )
398
+ return router
399
+ .resolveComponent(responseData.component)
400
+ .then((component) => push(component as ComponentType, responseData, config, onClose, onAfterLeave))
405
401
  }
406
402
 
407
403
  const loadDeferredProps = (modal: Modal) => {
@@ -665,10 +661,7 @@ export const renderApp = (App: ComponentType<{ children: (props: RenderInertiaAp
665
661
  return Component.layout
666
662
  .slice()
667
663
  .reverse()
668
- .reduce(
669
- (acc, Layout) => createElement(Layout as ComponentType<Record<string, unknown>>, props, acc),
670
- child as ReactNode,
671
- )
664
+ .reduce((acc, Layout) => createElement(Layout as ComponentType<Record<string, unknown>>, props, acc), child as ReactNode)
672
665
  }
673
666
 
674
667
  return child
@@ -715,14 +708,18 @@ export const ModalRoot = ({ children }: ModalRootProps) => {
715
708
  // Register interceptor in useLayoutEffect (fires during commit, before microtasks).
716
709
  // Inertia 3 loads deferred props during page.set() microtasks which fire after commit
717
710
  // but before useEffect — useLayoutEffect ensures the interceptor is registered in time.
718
- useLayoutEffect(() => http.onRequest((config: HttpRequestConfig) => {
719
- const baseUrlValue = baseUrl ?? pageRef.current.props._inertiaui_modal?.baseUrl ?? null
720
- if (baseUrlValue) {
721
- config.headers = config.headers ?? {}
722
- config.headers['X-InertiaUI-Modal-Base-Url'] = baseUrlValue
723
- }
724
- return config
725
- }), [])
711
+ useLayoutEffect(
712
+ () =>
713
+ http.onRequest((config: HttpRequestConfig) => {
714
+ const baseUrlValue = baseUrl ?? pageRef.current.props._inertiaui_modal?.baseUrl ?? null
715
+ if (baseUrlValue) {
716
+ config.headers = config.headers ?? {}
717
+ config.headers['X-InertiaUI-Modal-Base-Url'] = baseUrlValue
718
+ }
719
+ return config
720
+ }),
721
+ [],
722
+ )
726
723
 
727
724
  useEffect(() => router.on('start', () => (isNavigatingRef.current = true)), [])
728
725
  useEffect(() => router.on('finish', () => (isNavigatingRef.current = false)), [])
@@ -831,9 +828,7 @@ export const ModalRoot = ({ children }: ModalRootProps) => {
831
828
  // If there's no previous modal but we have modals in the stack (opened via XHR),
832
829
  // check if the new modal matches any open modal and update its props
833
830
  if (!previousModal && context && context.stack.length > 0) {
834
- const existingModal = context.stack.find(
835
- (m) => m.response?.component === newModal.component && sameUrlPath(m.response?.url, newModal.url),
836
- )
831
+ const existingModal = context.stack.find((m) => m.response?.component === newModal.component && sameUrlPath(m.response?.url, newModal.url))
837
832
  if (existingModal) {
838
833
  existingModal.updateProps(newModal.props ?? {})
839
834
  }
@@ -847,4 +842,3 @@ export const ModalRoot = ({ children }: ModalRootProps) => {
847
842
  </>
848
843
  )
849
844
  }
850
-
@@ -1,7 +1,8 @@
1
+ import { createFocusTrap, onEscapeKey, animate, cancelAnimations } from '@inertiaui/vanilla'
2
+ import clsx from 'clsx'
1
3
  import { useState, useEffect, useRef, useCallback, useMemo, ReactNode, SyntheticEvent, MouseEvent } from 'react'
4
+
2
5
  import CloseButton from './CloseButton'
3
- import clsx from 'clsx'
4
- import { createFocusTrap, onEscapeKey, animate, cancelAnimations } from '@inertiaui/vanilla'
5
6
  import { getMaxWidthClass } from './constants'
6
7
  import type { Modal } from './types'
7
8
 
@@ -26,8 +27,8 @@ interface SlideoverContentProps {
26
27
 
27
28
  const SlideoverContent = ({ modalContext, config, useNativeDialog, isFirstModal, onAfterLeave, children }: SlideoverContentProps) => {
28
29
  const [isRendered, setIsRendered] = useState(false)
29
- const [isVisible, setIsVisible] = useState(false) // For backdrop sync
30
- const [entered, setEntered] = useState(false) // After animation completes
30
+ const [isVisible, setIsVisible] = useState(false) // For backdrop sync
31
+ const [entered, setEntered] = useState(false) // After animation completes
31
32
  const wrapperRef = useRef<HTMLDivElement>(null)
32
33
  const dialogRef = useRef<HTMLDialogElement>(null)
33
34
  const nativeWrapperRef = useRef<HTMLDivElement>(null)
@@ -240,12 +241,9 @@ const SlideoverContent = ({ modalContext, config, useNativeDialog, isFirstModal,
240
241
  // ============ Render ============
241
242
 
242
243
  const renderContent = () => (
243
- <div
244
- className={`im-slideover-content relative ${config.paddingClasses} ${config.panelClasses}`}
245
- data-inertiaui-modal-entered={entered}
246
- >
244
+ <div className={`im-slideover-content relative ${config.paddingClasses} ${config.panelClasses}`} data-inertiaui-modal-entered={entered}>
247
245
  {config.closeButton && (
248
- <div className="absolute right-0 top-0 pr-3 pt-3">
246
+ <div className="absolute top-0 right-0 pt-3 pr-3">
249
247
  <CloseButton onClick={modalContext.close} />
250
248
  </div>
251
249
  )}
@@ -268,7 +266,7 @@ const SlideoverContent = ({ modalContext, config, useNativeDialog, isFirstModal,
268
266
  onCancel={handleCancel}
269
267
  onClick={handleDialogClick}
270
268
  >
271
- <div className="im-slideover-container fixed inset-0 overflow-y-auto overflow-x-hidden">
269
+ <div className="im-slideover-container fixed inset-0 overflow-x-hidden overflow-y-auto">
272
270
  <div
273
271
  className={clsx('im-slideover-positioner flex min-h-full items-center', {
274
272
  'justify-start rtl:justify-end': config?.position === 'left',
@@ -277,7 +275,11 @@ const SlideoverContent = ({ modalContext, config, useNativeDialog, isFirstModal,
277
275
  >
278
276
  <div
279
277
  ref={nativeWrapperRef}
280
- className={clsx('im-slideover-wrapper w-full transition-[filter] duration-300', modalContext.onTopOfStack ? '' : 'blur-xs', maxWidthClass)}
278
+ className={clsx(
279
+ 'im-slideover-wrapper w-full transition-[filter] duration-300',
280
+ modalContext.onTopOfStack ? '' : 'blur-xs',
281
+ maxWidthClass,
282
+ )}
281
283
  >
282
284
  {renderContent()}
283
285
  </div>
@@ -291,10 +293,7 @@ const SlideoverContent = ({ modalContext, config, useNativeDialog, isFirstModal,
291
293
  if (!isRendered) return null
292
294
 
293
295
  return (
294
- <div
295
- className="im-slideover-container fixed inset-0 z-40 overflow-y-auto overflow-x-hidden"
296
- onMouseDown={handleClickOutside}
297
- >
296
+ <div className="im-slideover-container fixed inset-0 z-40 overflow-x-hidden overflow-y-auto" onMouseDown={handleClickOutside}>
298
297
  <div
299
298
  className={clsx('im-slideover-positioner flex min-h-full items-center', {
300
299
  'justify-start rtl:justify-end': config?.position === 'left',
@@ -1,7 +1,8 @@
1
1
  // See: https://github.com/inertiajs/inertia/blob/48bcd21fb7daf467d0df1bfde2408f161f94a579/packages/react/src/WhenVisible.ts
2
2
  import { createElement, useCallback, useEffect, useRef, useState, ReactNode, ElementType } from 'react'
3
- import useModal from './useModal'
3
+
4
4
  import type { ReloadOptions } from './types'
5
+ import useModal from './useModal'
5
6
 
6
7
  interface WhenVisibleProps {
7
8
  children: ReactNode
package/src/cache.ts CHANGED
@@ -36,7 +36,10 @@ export class ResponseCache<T> {
36
36
  })
37
37
 
38
38
  if (cacheFor > 0) {
39
- this.timers.set(key, setTimeout(() => this.delete(key), cacheFor))
39
+ this.timers.set(
40
+ key,
41
+ setTimeout(() => this.delete(key), cacheFor),
42
+ )
40
43
  }
41
44
  }
42
45
 
package/src/config.ts CHANGED
@@ -61,8 +61,8 @@ class Config {
61
61
  navigate: key.navigate ?? defaultConfig.navigate,
62
62
  useNativeDialog: key.useNativeDialog ?? defaultConfig.useNativeDialog,
63
63
  appElement: key.appElement !== undefined ? key.appElement : defaultConfig.appElement,
64
- modal: { ...defaultConfig.modal, ...(key.modal ?? {}) },
65
- slideover: { ...defaultConfig.slideover, ...(key.slideover ?? {}) },
64
+ modal: { ...defaultConfig.modal, ...key.modal },
65
+ slideover: { ...defaultConfig.slideover, ...key.slideover },
66
66
  }
67
67
  return
68
68
  }
@@ -95,5 +95,4 @@ const configInstance = new Config()
95
95
  export const resetConfig = (): void => configInstance.reset()
96
96
  export const putConfig = (key: string | Partial<ModalConfig>, value?: unknown): void => configInstance.put(key, value)
97
97
  export const getConfig = (key?: string): unknown => configInstance.get(key)
98
- export const getConfigByType = (isSlideover: boolean, key: string): unknown =>
99
- configInstance.get(isSlideover ? `slideover.${key}` : `modal.${key}`)
98
+ export const getConfigByType = (isSlideover: boolean, key: string): unknown => configInstance.get(isSlideover ? `slideover.${key}` : `modal.${key}`)
@@ -1,14 +1,15 @@
1
+ import * as dialogUtils from '@inertiaui/vanilla'
1
2
  import { createElement } from 'react'
3
+
2
4
  import { getConfig, putConfig, resetConfig } from './config'
3
- import { useModalIndex } from './ModalRenderer'
4
- import { useModalStack, ModalRoot, ModalStackProvider, renderApp, initFromPageProps, modalPropNames, prefetch } from './ModalRoot'
5
- import useModal from './useModal'
6
5
  import Deferred from './Deferred'
7
6
  import HeadlessModal from './HeadlessModal'
8
7
  import Modal from './Modal'
9
8
  import ModalLink from './ModalLink'
9
+ import { useModalIndex } from './ModalRenderer'
10
+ import { useModalStack, ModalRoot, ModalStackProvider, renderApp, initFromPageProps, modalPropNames, prefetch } from './ModalRoot'
11
+ import useModal from './useModal'
10
12
  import WhenVisible from './WhenVisible'
11
- import * as dialogUtils from '@inertiaui/vanilla'
12
13
 
13
14
  // Types
14
15
  export type {
@@ -34,12 +35,12 @@ export type { ModalTypeConfig } from './config'
34
35
 
35
36
  export type { CleanupFunction, FocusTrapOptions, EscapeKeyOptions } from '@inertiaui/vanilla'
36
37
 
37
- const setPageLayout = <T extends { default: { layout?: (page: React.ReactNode) => React.ReactNode } }>(
38
- layout: React.ComponentType<{ children?: React.ReactNode }>,
39
- ) => (module: T): T => {
40
- module.default.layout = (page) => createElement(layout, { children: page })
41
- return module
42
- }
38
+ const setPageLayout =
39
+ <T extends { default: { layout?: (page: React.ReactNode) => React.ReactNode } }>(layout: React.ComponentType<{ children?: React.ReactNode }>) =>
40
+ (module: T): T => {
41
+ module.default.layout = (page) => createElement(layout, { children: page })
42
+ return module
43
+ }
43
44
 
44
45
  export {
45
46
  Deferred,