@saas-ui/modals 2.0.0-next.8 → 2.0.0-rc.22

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/provider.tsx CHANGED
@@ -1,38 +1,59 @@
1
1
  import * as React from 'react'
2
2
 
3
- import { Modal, BaseModalProps } from './modal'
4
- import { Drawer, DrawerProps } from './drawer'
5
- import { ConfirmDialog, ConfirmDialogProps } from './dialog'
6
- import { MenuDialog, MenuDialogProps } from './menu'
7
- import { FormDialog, FormDialogProps } from './form'
8
-
9
- export interface ModalsContextValue {
10
- open: (options: OpenOptions) => ModalId
3
+ import { BaseModalProps } from './modal'
4
+ import { DrawerProps } from './drawer'
5
+ import { ConfirmDialogProps } from './dialog'
6
+ import { MenuDialogProps } from './menu'
7
+ import { FormDialogProps } from './form'
8
+ import { defaultModals } from './default-modals'
9
+ import { FieldValues, FormType } from '@saas-ui/forms'
10
+ import { FormDialogHandler, FormHandler } from './types'
11
+
12
+ export interface ModalsContextValue<
13
+ TModals extends Record<string, React.FC<any>> = Record<string, React.FC<any>>,
14
+ TTypes extends Extract<keyof TModals, string> = Extract<keyof TModals, string>
15
+ > {
16
+ open: <T extends OpenOptions<TTypes>>(
17
+ componentOrOptions: T extends {
18
+ component: infer TComponent extends React.FC<any>
19
+ }
20
+ ? WithModalOptions<React.ComponentPropsWithRef<TComponent>>
21
+ : T extends {
22
+ type: infer TType extends keyof TModals
23
+ }
24
+ ? WithModalOptions<React.ComponentPropsWithRef<TModals[TType]>>
25
+ : T,
26
+ options?: T extends React.FC<any>
27
+ ? WithModalOptions<React.ComponentPropsWithRef<T>>
28
+ : never
29
+ ) => ModalId
11
30
  drawer: (options: DrawerOptions) => ModalId
12
31
  alert: (options: ConfirmDialogOptions) => ModalId
13
32
  confirm: (options: ConfirmDialogOptions) => ModalId
14
33
  menu: (options: MenuDialogOptions) => ModalId
15
- form: (options: FormDialogOptions) => ModalId
34
+ form: FormDialogHandler<TModals['form']>
16
35
  close: (id: ModalId) => void
17
36
  closeAll: () => void
18
37
  }
19
38
 
20
- export const ModalsContext = React.createContext<ModalsContextValue | null>(
21
- null
22
- )
39
+ export const ModalsContext = React.createContext<ModalsContextValue<
40
+ typeof defaultModals
41
+ > | null>(null)
23
42
 
24
- interface ModalsProviderProps {
43
+ export interface ModalsProviderProps<
44
+ TModals extends Record<string, React.FC<any>> = Record<string, React.FC<any>>
45
+ > {
25
46
  children: React.ReactNode
26
- modals?: Record<string, React.FC<any>>
47
+ modals?: TModals
27
48
  }
28
49
 
29
50
  export type ModalId = string | number
30
51
 
52
+ type WithModalOptions<T> = Omit<T, 'isOpen' | 'onClose'> & ModalOptions
53
+
31
54
  interface ModalOptions
32
- extends Omit<BaseModalProps, 'onClose' | 'isOpen' | 'children'> {
55
+ extends Omit<BaseModalProps, 'isOpen' | 'onClose' | 'children'> {
33
56
  onClose?: (args: { force?: boolean }) => Promise<boolean | undefined> | void
34
- body?: React.ReactNode
35
- children?: React.ReactNode
36
57
  [key: string]: any
37
58
  }
38
59
 
@@ -52,23 +73,16 @@ export interface FormDialogOptions
52
73
  extends ModalOptions,
53
74
  Omit<FormDialogProps, 'onClose' | 'isOpen' | 'children'> {}
54
75
 
55
- export interface OpenOptions extends ModalOptions {
56
- type?: ModalTypes
76
+ export interface OpenOptions<TModalTypes extends string> extends ModalOptions {
77
+ type?: TModalTypes
57
78
  scope?: ModalScopes
58
79
  }
59
80
 
60
81
  export type ModalScopes = 'modal' | 'alert'
61
82
 
62
- export type ModalTypes =
63
- | 'modal'
64
- | 'drawer'
65
- | 'alert'
66
- | 'confirm'
67
- | 'menu'
68
- | string
69
-
70
83
  export interface ModalConfig<
71
- TModalOptions extends ModalOptions = ModalOptions
84
+ TModalOptions extends ModalOptions = ModalOptions,
85
+ TModalTypes extends string = string
72
86
  > {
73
87
  /**
74
88
  * The modal id, autogenerated when not set.
@@ -91,7 +105,7 @@ export interface ModalConfig<
91
105
  *
92
106
  * Custom types can be configured using the `modals` prop of `ModalProvider`
93
107
  */
94
- type?: ModalTypes
108
+ type?: TModalTypes
95
109
  /**
96
110
  * Render a custom modal component.
97
111
  * This will ignore the `type` param.
@@ -110,15 +124,6 @@ const initialModalState: ModalConfig = {
110
124
  type: 'modal',
111
125
  }
112
126
 
113
- const defaultModals = {
114
- alert: ConfirmDialog,
115
- confirm: ConfirmDialog,
116
- drawer: Drawer,
117
- modal: Modal,
118
- menu: MenuDialog,
119
- form: FormDialog,
120
- }
121
-
122
127
  export function ModalsProvider({ children, modals }: ModalsProviderProps) {
123
128
  // Note that updating the Set doesn't trigger a re-render,
124
129
  // use in conjuction with setActiveModals
@@ -136,7 +141,7 @@ export function ModalsProvider({ children, modals }: ModalsProviderProps) {
136
141
  ...modals,
137
142
  }
138
143
 
139
- return (type: ModalTypes = 'modal') => {
144
+ return (type = 'modal') => {
140
145
  const component = _modals[type] || _modals.modal
141
146
 
142
147
  return component
@@ -155,14 +160,20 @@ export function ModalsProvider({ children, modals }: ModalsProviderProps) {
155
160
  }))
156
161
  }
157
162
 
158
- const open = <T extends ModalOptions>(
159
- options: T | React.FC<BaseModalProps>
163
+ const open = <T extends OpenOptions<any>>(
164
+ componentOrOptions: any,
165
+ options?: T extends React.FC<any>
166
+ ? WithModalOptions<React.ComponentPropsWithRef<T>>
167
+ : never
160
168
  ): ModalId => {
161
- if (typeof options === 'function') {
162
- const component: React.FC<BaseModalProps> = options
163
- options = {
164
- component,
169
+ let _options: ModalOptions
170
+ if (typeof componentOrOptions === 'function') {
171
+ _options = {
172
+ component: componentOrOptions,
173
+ ...options,
165
174
  } as unknown as T
175
+ } else {
176
+ _options = componentOrOptions
166
177
  }
167
178
 
168
179
  const {
@@ -171,7 +182,7 @@ export function ModalsProvider({ children, modals }: ModalsProviderProps) {
171
182
  scope = 'modal',
172
183
  component,
173
184
  ...props
174
- } = options
185
+ } = _options
175
186
 
176
187
  const modal: ModalConfig<T> = {
177
188
  id,
@@ -188,14 +199,14 @@ export function ModalsProvider({ children, modals }: ModalsProviderProps) {
188
199
  return id
189
200
  }
190
201
 
191
- const drawer = (options: DrawerOptions): ModalId => {
202
+ const drawer = (options: DrawerOptions) => {
192
203
  return open<DrawerOptions>({
193
204
  ...options,
194
205
  type: 'drawer',
195
206
  })
196
207
  }
197
208
 
198
- const alert = (options: ConfirmDialogOptions): ModalId => {
209
+ const alert = (options: ConfirmDialogOptions) => {
199
210
  return open({
200
211
  ...options,
201
212
  scope: 'alert',
@@ -210,7 +221,7 @@ export function ModalsProvider({ children, modals }: ModalsProviderProps) {
210
221
  })
211
222
  }
212
223
 
213
- const confirm = (options: ConfirmDialogOptions): ModalId => {
224
+ const confirm = (options: ConfirmDialogOptions) => {
214
225
  return open<ConfirmDialogOptions>({
215
226
  ...options,
216
227
  scope: 'alert',
@@ -218,15 +229,15 @@ export function ModalsProvider({ children, modals }: ModalsProviderProps) {
218
229
  })
219
230
  }
220
231
 
221
- const menu = (options: MenuDialogOptions): ModalId => {
232
+ const menu = (options: MenuDialogOptions) => {
222
233
  return open<MenuDialogOptions>({
223
234
  ...options,
224
235
  type: 'menu',
225
236
  })
226
237
  }
227
238
 
228
- const form = (options: FormDialogOptions): ModalId => {
229
- return open<FormDialogOptions>({
239
+ const form = (options: any) => {
240
+ return open({
230
241
  ...options,
231
242
  type: 'form',
232
243
  })
@@ -267,6 +278,8 @@ export function ModalsProvider({ children, modals }: ModalsProviderProps) {
267
278
  modal.scope
268
279
  )
269
280
  }
281
+
282
+ closeComplete(id)
270
283
  }
271
284
 
272
285
  const closeComplete = (id?: ModalId | null) => {
package/src/types.ts ADDED
@@ -0,0 +1,83 @@
1
+ import { FormProps, FormType } from '@saas-ui/forms'
2
+ import { ModalId } from './provider'
3
+ import { AnyObjectSchema, YupFormType } from '@saas-ui/forms/yup'
4
+ import { FormDialogFieldOverrides } from './form'
5
+ import { WithFields } from '@saas-ui/forms'
6
+ import { FieldValues } from '@saas-ui/forms'
7
+ import type { z } from 'zod'
8
+ import type { InferType } from 'yup'
9
+ import { ZodFormType } from '@saas-ui/forms/zod'
10
+
11
+ export type FormDialogHandler<T> = T extends YupFormType<
12
+ infer FieldDefs,
13
+ infer ExtraProps,
14
+ infer ExtraOverrides,
15
+ 'yup'
16
+ >
17
+ ? YupHandler<FieldDefs, object, ExtraOverrides & FormDialogFieldOverrides>
18
+ : T extends ZodFormType<
19
+ infer FieldDefs,
20
+ infer ExtraProps,
21
+ infer ExtraOverrides,
22
+ 'zod'
23
+ >
24
+ ? ZodHandler<FieldDefs, object, ExtraOverrides & FormDialogFieldOverrides>
25
+ : T extends FormType<infer FieldDefs, infer ExtraProps, infer ExtraOverrides>
26
+ ? FormHandler<FieldDefs, object, ExtraOverrides & FormDialogFieldOverrides>
27
+ : never
28
+
29
+ export type ZodHandler<
30
+ FieldDefs,
31
+ ExtraProps = object,
32
+ ExtraOverrides = object,
33
+ Type extends 'zod' = 'zod'
34
+ > = <
35
+ TSchema extends z.AnyZodObject = z.AnyZodObject,
36
+ TFieldValues extends z.infer<TSchema> = z.infer<TSchema>,
37
+ TContext extends object = object
38
+ >(
39
+ props: WithFields<
40
+ FormProps<TSchema, TFieldValues, TContext>,
41
+ FieldDefs,
42
+ ExtraOverrides
43
+ > & {
44
+ ref?: React.ForwardedRef<HTMLFormElement>
45
+ } & ExtraProps
46
+ ) => ModalId
47
+
48
+ export type FormHandler<
49
+ FieldDefs,
50
+ ExtraProps = object,
51
+ ExtraOverrides = object
52
+ > = <
53
+ TSchema = unknown,
54
+ TFieldValues extends FieldValues = FieldValues,
55
+ TContext extends object = object
56
+ >(
57
+ props: WithFields<
58
+ FormProps<TSchema, TFieldValues, TContext>,
59
+ FieldDefs,
60
+ ExtraOverrides
61
+ > & {
62
+ ref?: React.ForwardedRef<HTMLFormElement>
63
+ } & ExtraProps
64
+ ) => ModalId
65
+
66
+ export type YupHandler<
67
+ FieldDefs,
68
+ ExtraProps = object,
69
+ ExtraOverrides = object,
70
+ Type extends 'yup' = 'yup'
71
+ > = <
72
+ TSchema extends AnyObjectSchema = AnyObjectSchema,
73
+ TFieldValues extends InferType<TSchema> = InferType<TSchema>, // placeholder
74
+ TContext extends object = object
75
+ >(
76
+ props: WithFields<
77
+ FormProps<TFieldValues, TContext, TSchema>,
78
+ FieldDefs,
79
+ ExtraOverrides
80
+ > & {
81
+ ref?: React.ForwardedRef<HTMLFormElement>
82
+ } & ExtraProps
83
+ ) => ModalId
File without changes