@saas-ui/modals 2.0.0-next.2 → 2.0.0-next.21

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/index.mjs CHANGED
@@ -1,7 +1,9 @@
1
- import * as React from 'react';
2
- import { createStylesContext, forwardRef, useMenuContext, useMenuList, useMultiStyleConfig, chakra, ModalFooter, ModalBody, Button, AlertDialog, AlertDialogOverlay, AlertDialogContent, AlertDialogHeader, AlertDialogBody, AlertDialogFooter, ButtonGroup, Drawer as Drawer$1, DrawerOverlay, DrawerContent, DrawerHeader, DrawerCloseButton, DrawerBody, DrawerFooter, Modal as Modal$1, ModalOverlay, ModalContent, ModalHeader, ModalCloseButton, Menu } from '@chakra-ui/react';
3
- import { runIfFn } from '@saas-ui/react-utils';
4
- import { Form, Fields, SubmitButton } from '@saas-ui/forms';
1
+ import * as React2 from 'react';
2
+ import { createStylesContext, forwardRef, useMenuContext, useMenuList, useMultiStyleConfig, useBreakpointValue, chakra, ModalFooter, AlertDialog, AlertDialogOverlay, AlertDialogContent, AlertDialogHeader, AlertDialogBody, AlertDialogFooter, ButtonGroup, Button, Drawer as Drawer$1, DrawerOverlay, DrawerContent, DrawerHeader, DrawerCloseButton, DrawerFooter, DrawerBody, Modal as Modal$1, ModalOverlay, ModalContent, ModalHeader, ModalCloseButton, ModalBody, Menu } from '@chakra-ui/react';
3
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
4
+ import { runIfFn } from '@chakra-ui/utils';
5
+ import { runIfFn as runIfFn$1 } from '@saas-ui/react-utils';
6
+ import { AutoFields, SubmitButton, Form } from '@saas-ui/forms';
5
7
 
6
8
  // src/dialog.tsx
7
9
  var ConfirmDialog = (props) => {
@@ -22,52 +24,81 @@ var ConfirmDialog = (props) => {
22
24
  children,
23
25
  ...rest
24
26
  } = props;
25
- const cancelRef = React.useRef(null);
26
- const confirmRef = React.useRef(null);
27
- return /* @__PURE__ */ React.createElement(AlertDialog, {
28
- isOpen,
29
- onClose,
30
- ...rest,
31
- leastDestructiveRef: leastDestructiveFocus === "cancel" ? cancelRef : confirmRef
32
- }, /* @__PURE__ */ React.createElement(AlertDialogOverlay, null, /* @__PURE__ */ React.createElement(AlertDialogContent, null, /* @__PURE__ */ React.createElement(AlertDialogHeader, null, title), /* @__PURE__ */ React.createElement(AlertDialogBody, null, children), /* @__PURE__ */ React.createElement(AlertDialogFooter, null, /* @__PURE__ */ React.createElement(ButtonGroup, {
33
- ...buttonGroupProps
34
- }, /* @__PURE__ */ React.createElement(Button, {
35
- ref: cancelRef,
36
- ...cancelProps,
37
- onClick: () => {
38
- onCancel == null ? void 0 : onCancel();
39
- closeOnCancel && onClose();
40
- }
41
- }, (cancelProps == null ? void 0 : cancelProps.children) || cancelLabel), /* @__PURE__ */ React.createElement(Button, {
42
- ref: confirmRef,
43
- ...confirmProps,
44
- onClick: () => {
45
- onConfirm == null ? void 0 : onConfirm();
46
- closeOnConfirm && onClose();
27
+ const cancelRef = React2.useRef(null);
28
+ const confirmRef = React2.useRef(null);
29
+ return /* @__PURE__ */ jsx(
30
+ AlertDialog,
31
+ {
32
+ isOpen,
33
+ onClose,
34
+ ...rest,
35
+ leastDestructiveRef: leastDestructiveFocus === "cancel" ? cancelRef : confirmRef,
36
+ children: /* @__PURE__ */ jsx(AlertDialogOverlay, { children: /* @__PURE__ */ jsxs(AlertDialogContent, { children: [
37
+ /* @__PURE__ */ jsx(AlertDialogHeader, { children: title }),
38
+ /* @__PURE__ */ jsx(AlertDialogBody, { children }),
39
+ /* @__PURE__ */ jsx(AlertDialogFooter, { children: /* @__PURE__ */ jsxs(ButtonGroup, { ...buttonGroupProps, children: [
40
+ /* @__PURE__ */ jsx(
41
+ Button,
42
+ {
43
+ ref: cancelRef,
44
+ ...cancelProps,
45
+ onClick: () => {
46
+ onCancel == null ? void 0 : onCancel();
47
+ closeOnCancel && onClose();
48
+ },
49
+ children: (cancelProps == null ? void 0 : cancelProps.children) || cancelLabel
50
+ }
51
+ ),
52
+ /* @__PURE__ */ jsx(
53
+ Button,
54
+ {
55
+ ref: confirmRef,
56
+ ...confirmProps,
57
+ onClick: () => {
58
+ onConfirm == null ? void 0 : onConfirm();
59
+ closeOnConfirm && onClose();
60
+ },
61
+ children: (confirmProps == null ? void 0 : confirmProps.children) || confirmLabel
62
+ }
63
+ )
64
+ ] }) })
65
+ ] }) })
47
66
  }
48
- }, (confirmProps == null ? void 0 : confirmProps.children) || confirmLabel))))));
67
+ );
49
68
  };
50
69
  var BaseDrawer = (props) => {
51
70
  const {
52
71
  title,
53
72
  children,
73
+ footer,
54
74
  isOpen,
55
75
  onClose,
56
76
  hideCloseButton,
57
77
  hideOverlay,
78
+ headerProps,
79
+ contentProps,
80
+ footerProps,
58
81
  ...rest
59
82
  } = props;
60
- return /* @__PURE__ */ React.createElement(Drawer$1, {
61
- isOpen,
62
- onClose,
63
- ...rest
64
- }, !hideOverlay && /* @__PURE__ */ React.createElement(DrawerOverlay, null), /* @__PURE__ */ React.createElement(DrawerContent, null, /* @__PURE__ */ React.createElement(DrawerHeader, null, title), !hideCloseButton && /* @__PURE__ */ React.createElement(DrawerCloseButton, null), children));
83
+ return /* @__PURE__ */ jsxs(Drawer$1, { isOpen, onClose, ...rest, children: [
84
+ !hideOverlay && /* @__PURE__ */ jsx(DrawerOverlay, {}),
85
+ /* @__PURE__ */ jsxs(DrawerContent, { ...contentProps, children: [
86
+ title && /* @__PURE__ */ jsx(DrawerHeader, { ...headerProps, children: title }),
87
+ !hideCloseButton && /* @__PURE__ */ jsx(DrawerCloseButton, {}),
88
+ runIfFn(children, {
89
+ isOpen,
90
+ onClose
91
+ }),
92
+ footer && /* @__PURE__ */ jsx(DrawerFooter, { ...footerProps, children: footer })
93
+ ] })
94
+ ] });
65
95
  };
66
96
  var Drawer = (props) => {
67
- const { footer, children, ...rest } = props;
68
- return /* @__PURE__ */ React.createElement(BaseDrawer, {
69
- ...rest
70
- }, /* @__PURE__ */ React.createElement(DrawerBody, null, children), footer && /* @__PURE__ */ React.createElement(DrawerFooter, null, footer));
97
+ const { children, isOpen, onClose, ...rest } = props;
98
+ return /* @__PURE__ */ jsx(BaseDrawer, { isOpen, onClose, ...rest, children: /* @__PURE__ */ jsx(DrawerBody, { children: runIfFn(children, {
99
+ isOpen,
100
+ onClose
101
+ }) }) });
71
102
  };
72
103
  var BaseModal = (props) => {
73
104
  const {
@@ -78,31 +109,45 @@ var BaseModal = (props) => {
78
109
  onClose,
79
110
  hideCloseButton,
80
111
  hideOverlay,
112
+ headerProps,
113
+ contentProps,
114
+ footerProps,
81
115
  ...rest
82
116
  } = props;
83
- return /* @__PURE__ */ React.createElement(Modal$1, {
84
- isOpen,
85
- onClose,
86
- ...rest
87
- }, !hideOverlay && /* @__PURE__ */ React.createElement(ModalOverlay, null), /* @__PURE__ */ React.createElement(ModalContent, null, title && /* @__PURE__ */ React.createElement(ModalHeader, null, title), !hideCloseButton && /* @__PURE__ */ React.createElement(ModalCloseButton, null), children, footer && /* @__PURE__ */ React.createElement(ModalFooter, null, footer)));
117
+ return /* @__PURE__ */ jsxs(Modal$1, { isOpen, onClose, ...rest, children: [
118
+ !hideOverlay && /* @__PURE__ */ jsx(ModalOverlay, {}),
119
+ /* @__PURE__ */ jsxs(ModalContent, { ...contentProps, children: [
120
+ title && /* @__PURE__ */ jsx(ModalHeader, { ...headerProps, children: title }),
121
+ !hideCloseButton && /* @__PURE__ */ jsx(ModalCloseButton, {}),
122
+ runIfFn(children, {
123
+ isOpen,
124
+ onClose
125
+ }),
126
+ footer && /* @__PURE__ */ jsx(ModalFooter, { ...footerProps, children: footer })
127
+ ] })
128
+ ] });
88
129
  };
89
130
  var Modal = (props) => {
90
- const { children, ...rest } = props;
91
- return /* @__PURE__ */ React.createElement(BaseModal, {
92
- ...rest
93
- }, /* @__PURE__ */ React.createElement(ModalBody, null, children));
131
+ const { children, isOpen, onClose, ...rest } = props;
132
+ return /* @__PURE__ */ jsx(BaseModal, { ...rest, isOpen, onClose, children: /* @__PURE__ */ jsx(ModalBody, { children: runIfFn(children, {
133
+ isOpen,
134
+ onClose
135
+ }) }) });
94
136
  };
95
137
  var [StylesProvider] = createStylesContext("SuiMenuDialog");
96
138
  var MenuDialog = (props) => {
97
139
  const { onClose, onCloseComplete, ...rest } = props;
98
- return /* @__PURE__ */ React.createElement(Menu, {
99
- variant: "dialog",
100
- onClose: () => {
101
- onClose == null ? void 0 : onClose();
102
- onCloseComplete == null ? void 0 : onCloseComplete();
103
- },
104
- ...rest
105
- });
140
+ return /* @__PURE__ */ jsx(
141
+ Menu,
142
+ {
143
+ variant: "dialog",
144
+ onClose: () => {
145
+ onClose == null ? void 0 : onClose();
146
+ onCloseComplete == null ? void 0 : onCloseComplete();
147
+ },
148
+ ...rest
149
+ }
150
+ );
106
151
  };
107
152
  var MenuDialogList = forwardRef(
108
153
  (props, forwardedRef) => {
@@ -112,106 +157,126 @@ var MenuDialogList = forwardRef(
112
157
  footer,
113
158
  initialFocusRef,
114
159
  hideCloseButton,
115
- motionPreset,
160
+ motionPreset = "slideInBottom",
161
+ isCentered: isCenteredProp,
116
162
  ...rest
117
163
  } = props;
118
164
  const { isOpen, onClose, menuRef } = useMenuContext();
119
165
  const { ref, ...ownProps } = useMenuList(rest, forwardedRef);
120
166
  const styles = useMultiStyleConfig("Menu", props);
121
- return /* @__PURE__ */ React.createElement(BaseModal, {
122
- isOpen,
123
- onClose,
124
- initialFocusRef: initialFocusRef || menuRef,
125
- title,
126
- hideCloseButton,
127
- motionPreset
128
- }, /* @__PURE__ */ React.createElement(StylesProvider, {
129
- value: styles
130
- }, /* @__PURE__ */ React.createElement(chakra.div, {
131
- ...ownProps,
132
- ref,
133
- __css: {
134
- outline: 0,
135
- maxHeight: "80vh",
136
- overflowY: "auto",
137
- ...styles.list,
138
- boxShadow: "none",
139
- border: 0
167
+ const isCentered = useBreakpointValue({ base: true, md: false });
168
+ return /* @__PURE__ */ jsxs(
169
+ BaseModal,
170
+ {
171
+ isOpen,
172
+ onClose,
173
+ initialFocusRef: initialFocusRef || menuRef,
174
+ title,
175
+ hideCloseButton,
176
+ motionPreset,
177
+ isCentered: isCenteredProp != null ? isCenteredProp : isCentered,
178
+ contentProps: { mx: 4 },
179
+ children: [
180
+ /* @__PURE__ */ jsx(StylesProvider, { value: styles, children: /* @__PURE__ */ jsx(
181
+ chakra.div,
182
+ {
183
+ ...ownProps,
184
+ ref,
185
+ __css: {
186
+ outline: 0,
187
+ maxHeight: "80vh",
188
+ // can override this in theme
189
+ overflowY: "auto",
190
+ // can override this in theme
191
+ ...styles.list,
192
+ boxShadow: "none",
193
+ border: 0,
194
+ _dark: {
195
+ /* @ts-expect-error */
196
+ ...styles.list._dark || {},
197
+ boxShadow: "none"
198
+ }
199
+ }
200
+ }
201
+ ) }),
202
+ footer && /* @__PURE__ */ jsx(ModalFooter, { children: footer })
203
+ ]
140
204
  }
141
- })), footer && /* @__PURE__ */ React.createElement(ModalFooter, null, footer));
205
+ );
142
206
  }
143
207
  );
144
- var FormDialog = forwardRef(
145
- (props, ref) => {
146
- const {
147
- children,
148
- schema,
149
- resolver,
150
- fieldResolver,
151
- defaultValues,
152
- values,
153
- context,
154
- onChange,
155
- onSubmit,
156
- onError,
157
- mode,
158
- reValidateMode,
159
- shouldFocusError = true,
160
- shouldUnregister,
161
- shouldUseNativeValidation,
162
- criteriaMode,
163
- delayError = 100,
164
- cancelLabel = "Cancel",
165
- submitLabel = "Submit",
166
- footer,
167
- isOpen,
168
- onClose,
169
- ...rest
170
- } = props;
171
- const formProps = {
172
- ref,
173
- schema,
174
- resolver,
175
- defaultValues,
176
- values,
177
- context,
178
- onChange,
179
- onSubmit,
180
- onError,
181
- mode,
182
- reValidateMode,
183
- shouldFocusError,
184
- shouldUnregister,
185
- shouldUseNativeValidation,
186
- criteriaMode,
187
- delayError
188
- };
189
- return /* @__PURE__ */ React.createElement(BaseModal, {
190
- isOpen,
191
- onClose,
192
- ...rest
193
- }, /* @__PURE__ */ React.createElement(Form, {
194
- ...formProps,
195
- ref
196
- }, (form) => /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(ModalBody, null, runIfFn(children, form) || /* @__PURE__ */ React.createElement(Fields, {
197
- schema,
198
- fieldResolver,
199
- focusFirstField: true
200
- })), footer || /* @__PURE__ */ React.createElement(ModalFooter, null, /* @__PURE__ */ React.createElement(Button, {
201
- variant: "ghost",
202
- mr: 3,
203
- onClick: onClose
204
- }, cancelLabel), /* @__PURE__ */ React.createElement(SubmitButton, null, submitLabel)))));
205
- }
206
- );
207
- var ModalsContext = React.createContext(
208
- null
209
- );
210
- var initialModalState = {
211
- id: null,
212
- props: null,
213
- type: "modal"
208
+ var useFormProps = (props) => {
209
+ const {
210
+ schema,
211
+ resolver,
212
+ fieldResolver,
213
+ defaultValues,
214
+ values,
215
+ context,
216
+ onChange,
217
+ onSubmit,
218
+ onError,
219
+ mode,
220
+ reValidateMode,
221
+ shouldFocusError = true,
222
+ shouldUnregister,
223
+ shouldUseNativeValidation,
224
+ criteriaMode,
225
+ delayError = 100,
226
+ fields,
227
+ ...modalProps
228
+ } = props;
229
+ const formProps = {
230
+ schema,
231
+ resolver,
232
+ defaultValues,
233
+ values,
234
+ context,
235
+ onChange,
236
+ onSubmit,
237
+ onError,
238
+ mode,
239
+ reValidateMode,
240
+ shouldFocusError,
241
+ shouldUnregister,
242
+ shouldUseNativeValidation,
243
+ criteriaMode,
244
+ delayError,
245
+ fields
246
+ };
247
+ return { modalProps, formProps, fields };
214
248
  };
249
+ function createFormDialog(Form2) {
250
+ const Dialog = forwardRef((props, ref) => {
251
+ const { isOpen, onClose, footer, children, ...rest } = props;
252
+ const { modalProps, formProps, fields } = useFormProps(rest);
253
+ return /* @__PURE__ */ jsx(BaseModal, { ...modalProps, isOpen, onClose, children: /* @__PURE__ */ jsx(Form2, { ref, ...formProps, children: (form) => {
254
+ var _a, _b;
255
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
256
+ /* @__PURE__ */ jsx(ModalBody, { children: runIfFn$1(children, form) || /* @__PURE__ */ jsx(AutoFields, {}) }),
257
+ footer || /* @__PURE__ */ jsxs(ModalFooter, { children: [
258
+ /* @__PURE__ */ jsx(
259
+ Button,
260
+ {
261
+ variant: "ghost",
262
+ mr: 3,
263
+ onClick: onClose,
264
+ ...fields == null ? void 0 : fields.cancel,
265
+ children: (_b = (_a = fields == null ? void 0 : fields.cancel) == null ? void 0 : _a.children) != null ? _b : "Cancel"
266
+ }
267
+ ),
268
+ /* @__PURE__ */ jsx(SubmitButton, { ...fields == null ? void 0 : fields.submit })
269
+ ] })
270
+ ] });
271
+ } }) });
272
+ });
273
+ Dialog.displayName = `${Form2.displayName || Form2.name}Dialog`;
274
+ Dialog.id = Form2.id;
275
+ return Dialog;
276
+ }
277
+ var FormDialog = createFormDialog(Form);
278
+
279
+ // src/default-modals.ts
215
280
  var defaultModals = {
216
281
  alert: ConfirmDialog,
217
282
  confirm: ConfirmDialog,
@@ -220,12 +285,18 @@ var defaultModals = {
220
285
  menu: MenuDialog,
221
286
  form: FormDialog
222
287
  };
288
+ var ModalsContext = React2.createContext(null);
289
+ var initialModalState = {
290
+ id: null,
291
+ props: null,
292
+ type: "modal"
293
+ };
223
294
  function ModalsProvider({ children, modals }) {
224
- const _instances = React.useMemo(() => /* @__PURE__ */ new Set(), []);
225
- const [activeModals, setActiveModals] = React.useState({
295
+ const _instances = React2.useMemo(() => /* @__PURE__ */ new Set(), []);
296
+ const [activeModals, setActiveModals] = React2.useState({
226
297
  modal: initialModalState
227
298
  });
228
- const getModalComponent = React.useMemo(() => {
299
+ const getModalComponent = React2.useMemo(() => {
229
300
  const _modals = {
230
301
  ...defaultModals,
231
302
  ...modals
@@ -246,12 +317,15 @@ function ModalsProvider({ children, modals }) {
246
317
  [scope]: modal
247
318
  }));
248
319
  };
249
- const open = (options) => {
250
- if (typeof options === "function") {
251
- const component2 = options;
252
- options = {
253
- component: component2
320
+ const open = (componentOrOptions, options) => {
321
+ let _options;
322
+ if (typeof componentOrOptions === "function") {
323
+ _options = {
324
+ component: componentOrOptions,
325
+ ...options
254
326
  };
327
+ } else {
328
+ _options = componentOrOptions;
255
329
  }
256
330
  const {
257
331
  id = _instances.size + 1,
@@ -259,7 +333,7 @@ function ModalsProvider({ children, modals }) {
259
333
  scope = "modal",
260
334
  component,
261
335
  ...props
262
- } = options;
336
+ } = _options;
263
337
  const modal = {
264
338
  id,
265
339
  props,
@@ -339,10 +413,12 @@ function ModalsProvider({ children, modals }) {
339
413
  id: null,
340
414
  props: null,
341
415
  type: modal.type
416
+ // Keep type same as last modal type to make sure the animation isn't interrupted
342
417
  },
343
418
  modal.scope
344
419
  );
345
420
  }
421
+ closeComplete(id);
346
422
  };
347
423
  const closeComplete = (id) => {
348
424
  const modals2 = [...Array.from(_instances)];
@@ -371,31 +447,48 @@ function ModalsProvider({ children, modals }) {
371
447
  close,
372
448
  closeAll
373
449
  };
374
- const content = React.useMemo(
450
+ const content = React2.useMemo(
375
451
  () => Object.entries(activeModals).map(([scope, config]) => {
376
452
  const Component = config.component || getModalComponent(config.type);
377
453
  const { title, body, children: children2, ...props } = config.props || {};
378
- return /* @__PURE__ */ React.createElement(Component, {
379
- key: scope,
380
- title,
381
- children: body || children2,
382
- ...props,
383
- isOpen: !!config.isOpen,
384
- onClose: () => close(config.id),
385
- onCloseComplete: () => closeComplete(config.id)
386
- });
454
+ return /* @__PURE__ */ jsx(
455
+ Component,
456
+ {
457
+ title,
458
+ children: body || children2,
459
+ ...props,
460
+ isOpen: !!config.isOpen,
461
+ onClose: () => close(config.id),
462
+ onCloseComplete: () => closeComplete(config.id)
463
+ },
464
+ scope
465
+ );
387
466
  }),
388
467
  [activeModals]
389
468
  );
390
- return /* @__PURE__ */ React.createElement(ModalsContext.Provider, {
391
- value: context
392
- }, content, children);
469
+ return /* @__PURE__ */ jsxs(ModalsContext.Provider, { value: context, children: [
470
+ content,
471
+ children
472
+ ] });
393
473
  }
394
- var useModalsContext = () => React.useContext(ModalsContext);
474
+ var useModalsContext = () => React2.useContext(ModalsContext);
395
475
  var useModals = () => {
396
476
  return useModalsContext();
397
477
  };
478
+ var createModals = (options) => {
479
+ const modals = {
480
+ ...defaultModals,
481
+ ...options.modals
482
+ };
483
+ const Provider = (props) => {
484
+ return /* @__PURE__ */ jsx(ModalsProvider, { children: props.children, modals });
485
+ };
486
+ return {
487
+ ModalsProvider: Provider,
488
+ useModals
489
+ };
490
+ };
398
491
 
399
- export { BaseDrawer, BaseModal, ConfirmDialog, Drawer, FormDialog, MenuDialog, MenuDialogList, Modal, ModalsContext, ModalsProvider, useModals, useModalsContext };
492
+ export { BaseDrawer, BaseModal, ConfirmDialog, Drawer, FormDialog, MenuDialog, MenuDialogList, Modal, ModalsContext, ModalsProvider, createFormDialog, createModals, useModals, useModalsContext };
400
493
  //# sourceMappingURL=out.js.map
401
494
  //# sourceMappingURL=index.mjs.map