@cerberus-design/react 0.13.1-next-e3e9e48 → 0.13.1-next-8c8a5ee

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.
Files changed (36) hide show
  1. package/build/legacy/_tsup-dts-rollup.d.cts +52 -27
  2. package/build/legacy/components/ModalHeader.cjs +0 -1
  3. package/build/legacy/components/ModalHeader.cjs.map +1 -1
  4. package/build/legacy/context/confirm-modal.cjs +36 -43
  5. package/build/legacy/context/confirm-modal.cjs.map +1 -1
  6. package/build/legacy/context/cta-modal.cjs +34 -35
  7. package/build/legacy/context/cta-modal.cjs.map +1 -1
  8. package/build/legacy/context/notification-center.cjs.map +1 -1
  9. package/build/legacy/context/prompt-modal.cjs +0 -1
  10. package/build/legacy/context/prompt-modal.cjs.map +1 -1
  11. package/build/legacy/index.cjs +72 -79
  12. package/build/legacy/index.cjs.map +1 -1
  13. package/build/modern/_tsup-dts-rollup.d.ts +52 -27
  14. package/build/modern/{chunk-KFGI37CO.js → chunk-4D6VIGNQ.js} +38 -44
  15. package/build/modern/chunk-4D6VIGNQ.js.map +1 -0
  16. package/build/modern/{chunk-KUT2YEEQ.js → chunk-5KHGTLFM.js} +1 -1
  17. package/build/modern/chunk-5KHGTLFM.js.map +1 -0
  18. package/build/modern/{chunk-NCUHRVW2.js → chunk-MMHCX2RG.js} +2 -2
  19. package/build/modern/{chunk-J4LOSTEP.js → chunk-MXMVC3ZQ.js} +36 -36
  20. package/build/modern/{chunk-J4LOSTEP.js.map → chunk-MXMVC3ZQ.js.map} +1 -1
  21. package/build/modern/{chunk-ZFAIE47A.js → chunk-XY6WL55R.js} +1 -2
  22. package/build/modern/{chunk-ZFAIE47A.js.map → chunk-XY6WL55R.js.map} +1 -1
  23. package/build/modern/components/ModalHeader.js +1 -1
  24. package/build/modern/context/confirm-modal.js +2 -2
  25. package/build/modern/context/cta-modal.js +2 -2
  26. package/build/modern/context/notification-center.js +1 -1
  27. package/build/modern/context/prompt-modal.js +2 -2
  28. package/build/modern/index.js +5 -5
  29. package/package.json +2 -2
  30. package/src/components/ModalHeader.tsx +0 -1
  31. package/src/context/confirm-modal.tsx +89 -66
  32. package/src/context/cta-modal.tsx +38 -38
  33. package/src/context/notification-center.tsx +1 -0
  34. package/build/modern/chunk-KFGI37CO.js.map +0 -1
  35. package/build/modern/chunk-KUT2YEEQ.js.map +0 -1
  36. /package/build/modern/{chunk-NCUHRVW2.js.map → chunk-MMHCX2RG.js.map} +0 -0
@@ -299,6 +299,27 @@ declare type AvatarProps = (HtmlHTMLAttributes<HTMLDivElement> & AvatarVariantPr
299
299
  export { AvatarProps }
300
300
  export { AvatarProps as AvatarProps_alias_1 }
301
301
 
302
+ /**
303
+ * This module provides a context and hook for the confirm modal.
304
+ * @module
305
+ */
306
+ declare interface BaseConfirmOptions {
307
+ /**
308
+ * The heading of the confirm modal.
309
+ */
310
+ heading: string;
311
+ /**
312
+ * The text for the action button.
313
+ */
314
+ actionText: string;
315
+ /**
316
+ * The text for the cancel button.
317
+ */
318
+ cancelText: string;
319
+ }
320
+ export { BaseConfirmOptions }
321
+ export { BaseConfirmOptions as BaseConfirmOptions_alias_1 }
322
+
302
323
  /**
303
324
  * This module exports the NotificationDescription component.
304
325
  * @module
@@ -640,6 +661,19 @@ declare function defineIcons(icons: DefinedIcons): Required<DefinedIcons>;
640
661
  export { defineIcons }
641
662
  export { defineIcons as defineIcons_alias_1 }
642
663
 
664
+ declare interface DestructiveConfirmOptions extends BaseConfirmOptions {
665
+ /**
666
+ * The kind of confirm modal to show.
667
+ */
668
+ kind?: 'destructive';
669
+ /**
670
+ * The description of the confirm modal. Can only be a string for destructive confirm modals.
671
+ */
672
+ description?: string;
673
+ }
674
+ export { DestructiveConfirmOptions }
675
+ export { DestructiveConfirmOptions as DestructiveConfirmOptions_alias_1 }
676
+
643
677
  export { DistanceMeasurement }
644
678
 
645
679
  export { DndContext }
@@ -1669,6 +1703,23 @@ declare type NavTriggerRef = RefObject<HTMLButtonElement>;
1669
1703
  export { NavTriggerRef }
1670
1704
  export { NavTriggerRef as NavTriggerRef_alias_1 }
1671
1705
 
1706
+ declare interface NonDestructiveConfirmModalOptions extends BaseConfirmOptions {
1707
+ /**
1708
+ * The kind of confirm modal to show.
1709
+ * @default 'non-destructive'
1710
+ */
1711
+ kind?: 'non-destructive';
1712
+ /**
1713
+ * The description of the confirm modal. Can be a ReactNode for non-destructive kind if you need to display text links.
1714
+ * @example
1715
+ * ```tsx
1716
+ * description: <>Use a Fragment because we put the content within a Paragraph tag.</>
1717
+ */
1718
+ description?: ReactNode;
1719
+ }
1720
+ export { NonDestructiveConfirmModalOptions }
1721
+ export { NonDestructiveConfirmModalOptions as NonDestructiveConfirmModalOptions_alias_1 }
1722
+
1672
1723
  declare type NonIndeterminateProgressBarProps = {
1673
1724
  /**
1674
1725
  * A unique identifier for the progress bar. Required for accessibility.
@@ -2138,33 +2189,7 @@ declare function Show(props: PropsWithChildren<ShowProps>): ReactNode;
2138
2189
  export { Show }
2139
2190
  export { Show as Show_alias_1 }
2140
2191
 
2141
- /**
2142
- * This module provides a context and hook for the confirm modal.
2143
- * @module
2144
- */
2145
- declare interface ShowConfirmModalOptions {
2146
- /**
2147
- * The kind of confirm modal to show.
2148
- * @default 'non-destructive'
2149
- */
2150
- kind?: 'destructive' | 'non-destructive';
2151
- /**
2152
- * The heading of the confirm modal.
2153
- */
2154
- heading: string;
2155
- /**
2156
- * The description of the confirm modal.
2157
- */
2158
- description?: string;
2159
- /**
2160
- * The text for the action button.
2161
- */
2162
- actionText: string;
2163
- /**
2164
- * The text for the cancel button.
2165
- */
2166
- cancelText: string;
2167
- }
2192
+ declare type ShowConfirmModalOptions = NonDestructiveConfirmModalOptions | DestructiveConfirmOptions;
2168
2193
  export { ShowConfirmModalOptions }
2169
2194
  export { ShowConfirmModalOptions as ShowConfirmModalOptions_alias_1 }
2170
2195
 
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-K2PSHGS7.js";
4
4
  import {
5
5
  ModalHeader
6
- } from "./chunk-ZFAIE47A.js";
6
+ } from "./chunk-XY6WL55R.js";
7
7
  import {
8
8
  ModalHeading
9
9
  } from "./chunk-2UXE5PDG.js";
@@ -43,6 +43,7 @@ import {
43
43
  } from "react";
44
44
  import { css } from "@cerberus/styled-system/css";
45
45
  import { hstack } from "@cerberus/styled-system/patterns";
46
+ import { HStack, VStack } from "@cerberus/styled-system/jsx";
46
47
  import { jsx, jsxs } from "react/jsx-runtime";
47
48
  var ConfirmModalContext = createContext(null);
48
49
  function ConfirmModal(props) {
@@ -51,9 +52,10 @@ function ConfirmModal(props) {
51
52
  const [content, setContent] = useState(null);
52
53
  const focusTrap = trapFocus(modalRef);
53
54
  const ConfirmIcon = $cerberusIcons.confirmModal;
55
+ const kind = content?.kind ?? "non-destructive";
54
56
  const palette = useMemo(
55
- () => content?.kind === "destructive" ? "danger" : "action",
56
- [content]
57
+ () => kind === "destructive" ? "danger" : "action",
58
+ [kind]
57
59
  );
58
60
  const handleChoice = useCallback(
59
61
  (e) => {
@@ -69,7 +71,7 @@ function ConfirmModal(props) {
69
71
  const handleShow = useCallback(
70
72
  (options) => {
71
73
  return new Promise((resolve) => {
72
- setContent({ ...options, kind: options.kind || "non-destructive" });
74
+ setContent({ ...options });
73
75
  show();
74
76
  resolveRef.current = resolve;
75
77
  });
@@ -84,7 +86,7 @@ function ConfirmModal(props) {
84
86
  );
85
87
  return /* @__PURE__ */ jsxs(ConfirmModalContext.Provider, { value, children: [
86
88
  props.children,
87
- /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsxs(Modal, { onKeyDown: focusTrap, ref: modalRef, children: [
89
+ /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(Modal, { onKeyDown: focusTrap, ref: modalRef, children: /* @__PURE__ */ jsxs(VStack, { gap: "xl", w: "full", children: [
88
90
  /* @__PURE__ */ jsxs(ModalHeader, { children: [
89
91
  /* @__PURE__ */ jsx(
90
92
  "div",
@@ -122,44 +124,36 @@ function ConfirmModal(props) {
122
124
  /* @__PURE__ */ jsx(ModalHeading, { children: content?.heading }),
123
125
  /* @__PURE__ */ jsx(ModalDescription, { children: content?.description })
124
126
  ] }),
125
- /* @__PURE__ */ jsxs(
126
- "div",
127
- {
128
- className: hstack({
129
- gap: "4"
130
- }),
131
- children: [
132
- /* @__PURE__ */ jsx(
133
- Button,
134
- {
135
- autoFocus: true,
136
- className: css({
137
- w: "1/2"
138
- }),
139
- name: "confirm",
140
- onClick: handleChoice,
141
- palette,
142
- value: "true",
143
- children: content?.actionText
144
- }
145
- ),
146
- /* @__PURE__ */ jsx(
147
- Button,
148
- {
149
- className: css({
150
- w: "1/2"
151
- }),
152
- name: "cancel",
153
- onClick: handleChoice,
154
- usage: "outlined",
155
- value: "false",
156
- children: content?.cancelText
157
- }
158
- )
159
- ]
160
- }
161
- )
162
- ] }) })
127
+ /* @__PURE__ */ jsxs(HStack, { gap: "4", w: "full", children: [
128
+ /* @__PURE__ */ jsx(
129
+ Button,
130
+ {
131
+ autoFocus: true,
132
+ className: css({
133
+ w: "1/2"
134
+ }),
135
+ name: "confirm",
136
+ onClick: handleChoice,
137
+ palette,
138
+ value: "true",
139
+ children: content?.actionText
140
+ }
141
+ ),
142
+ /* @__PURE__ */ jsx(
143
+ Button,
144
+ {
145
+ className: css({
146
+ w: "1/2"
147
+ }),
148
+ name: "cancel",
149
+ onClick: handleChoice,
150
+ usage: "outlined",
151
+ value: "false",
152
+ children: content?.cancelText
153
+ }
154
+ )
155
+ ] })
156
+ ] }) }) })
163
157
  ] });
164
158
  }
165
159
  function useConfirmModal() {
@@ -176,4 +170,4 @@ export {
176
170
  ConfirmModal,
177
171
  useConfirmModal
178
172
  };
179
- //# sourceMappingURL=chunk-KFGI37CO.js.map
173
+ //# sourceMappingURL=chunk-4D6VIGNQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/context/confirm-modal.tsx"],"sourcesContent":["'use client'\n\nimport {\n createContext,\n useCallback,\n useContext,\n useMemo,\n useRef,\n useState,\n type MouseEvent,\n type PropsWithChildren,\n type ReactNode,\n} from 'react'\nimport { Portal } from '../components/Portal'\nimport { Button } from '../components/Button'\nimport { css } from '@cerberus/styled-system/css'\nimport { hstack } from '@cerberus/styled-system/patterns'\nimport { $cerberusIcons } from '../config/defineIcons'\nimport { trapFocus } from '../aria-helpers/trap-focus.aria'\nimport { Show } from '../components/Show'\nimport { Modal } from '../components/Modal'\nimport { useModal } from '../hooks/useModal'\nimport { ModalHeader } from '../components/ModalHeader'\nimport { ModalHeading } from '../components/ModalHeading'\nimport { ModalDescription } from '../components/ModalDescription'\nimport { Avatar } from '../components/Avatar'\nimport { HStack, VStack } from '@cerberus/styled-system/jsx'\n\n/**\n * This module provides a context and hook for the confirm modal.\n * @module\n */\n\nexport interface BaseConfirmOptions {\n /**\n * The heading of the confirm modal.\n */\n heading: string\n /**\n * The text for the action button.\n */\n actionText: string\n /**\n * The text for the cancel button.\n */\n cancelText: string\n}\n\nexport interface DestructiveConfirmOptions extends BaseConfirmOptions {\n /**\n * The kind of confirm modal to show.\n */\n kind?: 'destructive'\n /**\n * The description of the confirm modal. Can only be a string for destructive confirm modals.\n */\n description?: string\n}\n\nexport interface NonDestructiveConfirmModalOptions extends BaseConfirmOptions {\n /**\n * The kind of confirm modal to show.\n * @default 'non-destructive'\n */\n kind?: 'non-destructive'\n /**\n * The description of the confirm modal. Can be a ReactNode for non-destructive kind if you need to display text links.\n * @example\n * ```tsx\n * description: <>Use a Fragment because we put the content within a Paragraph tag.</>\n */\n description?: ReactNode\n}\n\nexport type ShowConfirmModalOptions =\n | NonDestructiveConfirmModalOptions\n | DestructiveConfirmOptions\n\nexport type ShowResult =\n | ((value: boolean | PromiseLike<boolean>) => void)\n | null\n\nexport interface ConfirmModalValue {\n show: (options: ShowConfirmModalOptions) => Promise<boolean>\n}\n\nconst ConfirmModalContext = createContext<ConfirmModalValue | null>(null)\n\nexport interface ConfirmModalProviderProps {}\n\n/**\n * Provides a confirm modal to the app.\n * @see https://cerberus.digitalu.design/react/confirm-modal\n * @example\n * ```tsx\n * // Wrap the Provider around the root of the feature.\n * <ConfirmModal>\n * <SomeFeatureSection />\n * </ConfirmModal>\n *\n * // Use the hook to show the confirm modal.\n * const confirm = useConfirmModal()\n *\n * const handleClick = useCallback(async () => {\n * const userConsent = await confirm.show({\n * heading: 'Add new payment method?',\n * description:\n * 'This will add a new payment method to your account to be billed for future purchases.',\n * actionText: 'Yes, add payment method',\n * cancelText: 'No, cancel',\n * })\n * setConsent(userConsent)\n * }, [confirm])\n * ```\n */\nexport function ConfirmModal(\n props: PropsWithChildren<ConfirmModalProviderProps>,\n) {\n const { modalRef, show, close } = useModal()\n const resolveRef = useRef<ShowResult>(null)\n const [content, setContent] = useState<ShowConfirmModalOptions | null>(null)\n const focusTrap = trapFocus(modalRef)\n const ConfirmIcon = $cerberusIcons.confirmModal\n const kind = content?.kind ?? 'non-destructive'\n\n const palette = useMemo(\n () => (kind === 'destructive' ? 'danger' : 'action'),\n [kind],\n )\n\n const handleChoice = useCallback(\n (e: MouseEvent<HTMLButtonElement>) => {\n const target = e.currentTarget as HTMLButtonElement\n if (target.value === 'true') {\n resolveRef.current?.(true)\n }\n resolveRef.current?.(false)\n close()\n },\n [close],\n )\n\n const handleShow = useCallback(\n (options: ShowConfirmModalOptions) => {\n return new Promise<boolean>((resolve) => {\n setContent({ ...options })\n show()\n resolveRef.current = resolve\n })\n },\n [show],\n )\n\n const value = useMemo(\n () => ({\n show: handleShow,\n }),\n [handleShow],\n )\n\n return (\n <ConfirmModalContext.Provider value={value}>\n {props.children}\n\n <Portal>\n <Modal onKeyDown={focusTrap} ref={modalRef}>\n <VStack gap=\"xl\" w=\"full\">\n <ModalHeader>\n <div\n className={hstack({\n justify: 'center',\n w: 'full',\n })}\n >\n <Show\n when={palette === 'danger'}\n fallback={\n <Avatar\n ariaLabel=\"\"\n gradient=\"charon-light\"\n icon={<ConfirmIcon size={24} />}\n src=\"\"\n />\n }\n >\n <Avatar\n ariaLabel=\"\"\n gradient=\"hades-dark\"\n icon={<ConfirmIcon size={24} />}\n src=\"\"\n />\n </Show>\n </div>\n <ModalHeading>{content?.heading}</ModalHeading>\n <ModalDescription>{content?.description}</ModalDescription>\n </ModalHeader>\n\n <HStack gap=\"4\" w=\"full\">\n <Button\n autoFocus\n className={css({\n w: '1/2',\n })}\n name=\"confirm\"\n onClick={handleChoice}\n palette={palette}\n value=\"true\"\n >\n {content?.actionText}\n </Button>\n <Button\n className={css({\n w: '1/2',\n })}\n name=\"cancel\"\n onClick={handleChoice}\n usage=\"outlined\"\n value=\"false\"\n >\n {content?.cancelText}\n </Button>\n </HStack>\n </VStack>\n </Modal>\n </Portal>\n </ConfirmModalContext.Provider>\n )\n}\n\nexport function useConfirmModal(): ConfirmModalValue {\n const context = useContext(ConfirmModalContext)\n if (context === null) {\n throw new Error(\n 'useConfirmModal must be used within a ConfirmModal Provider',\n )\n }\n return context\n}\n"],"mappings":"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","names":[]}
@@ -159,4 +159,4 @@ export {
159
159
  NotificationCenter,
160
160
  useNotificationCenter
161
161
  };
162
- //# sourceMappingURL=chunk-KUT2YEEQ.js.map
162
+ //# sourceMappingURL=chunk-5KHGTLFM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/context/notification-center.tsx"],"sourcesContent":["'use client'\n\nimport {\n createContext,\n useCallback,\n useContext,\n useMemo,\n useState,\n type MouseEvent,\n type PropsWithChildren,\n type ReactNode,\n} from 'react'\nimport { Show } from '../components/Show'\nimport { NotificationHeading } from '../components/NotificationHeading'\nimport { NotificationDescription } from '../components/NotificationDescription'\nimport { Notification } from '../components/Notification'\nimport { animateIn, vstack } from '@cerberus/styled-system/patterns'\nimport { Portal, type PortalProps } from '../components/Portal'\nimport { notification } from '@cerberus/styled-system/recipes'\nimport { Button } from '../components/Button'\nimport { cx } from '@cerberus/styled-system/css'\n\n/**\n * This module provides a context and hook for notifications.\n * @module\n */\n\nexport interface NotifyOptions {\n /**\n * The palette of the notification.\n * @default 'info'\n */\n palette: 'info' | 'success' | 'warning' | 'danger'\n /**\n * The heading of the notification.\n */\n heading: string\n /**\n * The unique id of the notification.\n */\n id?: string\n /**\n * The description of the notification.\n */\n description?: ReactNode\n /**\n * The action to take when the notification is closed\n */\n onClose?: () => void\n}\n\nexport interface NotificationsValue {\n notify: (options: NotifyOptions) => void\n}\n\nconst NotificationsContext = createContext<NotificationsValue | null>(null)\n\nexport interface NotificationsProviderProps extends PortalProps {}\n\n/**\n * Provides a notification center to the app.\n * @see https://cerberus.digitalu.design/react/notification\n * @example\n * ```tsx\n * // Wrap the Provider around the root of the feature.\n * <Notifications>\n * <SomeFeatureSection />\n * </Notifications>\n *\n * // Use the hook to show a notification.\n * const notify = useNotifications()\n *\n * const handleClick = useCallback(() => {\n * notify({\n * palette: 'info',\n * heading: 'New feature!',\n * description: 'We have added a new feature to the app.',\n * })\n * }, [notify])\n * ```\n */\nexport function NotificationCenter(\n props: PropsWithChildren<NotificationsProviderProps>,\n) {\n const [activeNotifications, setActiveNotifications] = useState<\n NotifyOptions[]\n >([])\n const styles = notification()\n\n const handleNotify = useCallback((options: NotifyOptions) => {\n setActiveNotifications((prev) => {\n const id = `${options.palette}:${prev.length + 1}`\n return [...prev, { ...options, id }]\n })\n }, [])\n\n const handleClose = useCallback((e: MouseEvent<HTMLButtonElement>) => {\n const target = e.currentTarget as HTMLButtonElement\n setActiveNotifications((prev) => {\n const item = prev.find((option) => option.id === target.value)\n if (item?.onClose) item.onClose()\n return prev.filter((option) => option.id !== target.value)\n })\n }, [])\n\n const handleCloseAll = useCallback(() => {\n setActiveNotifications((prev) => {\n prev.forEach((item) => {\n if (item.onClose) item.onClose()\n })\n return []\n })\n }, [])\n\n const value = useMemo(\n () => ({\n notify: handleNotify,\n }),\n [handleNotify],\n )\n\n // For some reason, the vstack pattern alignItems is not registering here.\n // So we are forcing it with the style prop.\n\n return (\n <NotificationsContext.Provider value={value}>\n {props.children}\n\n <Show when={activeNotifications.length > 0}>\n <Portal container={props.container}>\n <div className={styles.center}>\n <Show when={activeNotifications.length >= 4}>\n <Button\n className={cx(styles.closeAll, animateIn())}\n onClick={handleCloseAll}\n palette=\"action\"\n shape=\"rounded\"\n size=\"sm\"\n usage=\"ghost\"\n >\n Close all\n </Button>\n </Show>\n\n <div\n className={vstack({\n alignItems: 'flex-end',\n gap: '4',\n })}\n style={{\n alignItems: 'flex-end',\n }}\n >\n {activeNotifications.map((option) => (\n <MatchNotification\n key={option.id}\n {...option}\n onClose={handleClose}\n />\n ))}\n </div>\n </div>\n </Portal>\n </Show>\n </NotificationsContext.Provider>\n )\n}\n\ninterface MatchNotificationProps extends Omit<NotifyOptions, 'onClose'> {\n onClose: (e: MouseEvent<HTMLButtonElement>) => void\n key: string | undefined\n}\n\nfunction MatchNotification(props: MatchNotificationProps) {\n const { palette, id, onClose, heading, description } = props\n\n switch (palette) {\n case 'success':\n return (\n <Notification\n id={id!}\n key={id}\n onClose={onClose}\n open\n palette=\"success\"\n >\n <NotificationHeading palette=\"success\">{heading}</NotificationHeading>\n <NotificationDescription palette=\"success\">\n {description}\n </NotificationDescription>\n </Notification>\n )\n\n case 'warning':\n return (\n <Notification\n id={id!}\n key={id}\n onClose={onClose}\n open\n palette=\"warning\"\n >\n <NotificationHeading palette=\"warning\">{heading}</NotificationHeading>\n <NotificationDescription palette=\"warning\">\n {description}\n </NotificationDescription>\n </Notification>\n )\n\n case 'danger':\n return (\n <Notification id={id!} key={id} onClose={onClose} open palette=\"danger\">\n <NotificationHeading palette=\"danger\">{heading}</NotificationHeading>\n <NotificationDescription palette=\"danger\">\n {description}\n </NotificationDescription>\n </Notification>\n )\n\n case 'info':\n default:\n return (\n <Notification id={id!} key={id} onClose={onClose} open palette=\"info\">\n <NotificationHeading palette=\"info\">{heading}</NotificationHeading>\n <NotificationDescription palette=\"info\">\n {description}\n </NotificationDescription>\n </Notification>\n )\n }\n}\n\n/**\n * The hook to use the NotificationCenter.\n * @returns The notify method to trigger a notification.\n * @example\n * ```tsx\n * const {notify} = useNotificationCenter()\n * notify({\n * palette: 'info',\n * heading: 'New feature',\n * description: 'We have added a new feature to the app.',\n * })\n * ```\n */\nexport function useNotificationCenter(): NotificationsValue {\n const context = useContext(NotificationsContext)\n if (!context) {\n throw new Error(\n 'useNotificationCenter must be used within a NotificationsProvider',\n )\n }\n return context\n}\n"],"mappings":"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","names":[]}
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-K2PSHGS7.js";
4
4
  import {
5
5
  ModalHeader
6
- } from "./chunk-ZFAIE47A.js";
6
+ } from "./chunk-XY6WL55R.js";
7
7
  import {
8
8
  ModalHeading
9
9
  } from "./chunk-2UXE5PDG.js";
@@ -240,4 +240,4 @@ export {
240
240
  PromptModal,
241
241
  usePromptModal
242
242
  };
243
- //# sourceMappingURL=chunk-NCUHRVW2.js.map
243
+ //# sourceMappingURL=chunk-MMHCX2RG.js.map
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-K2PSHGS7.js";
4
4
  import {
5
5
  ModalHeader
6
- } from "./chunk-ZFAIE47A.js";
6
+ } from "./chunk-XY6WL55R.js";
7
7
  import {
8
8
  ModalHeading
9
9
  } from "./chunk-2UXE5PDG.js";
@@ -101,42 +101,42 @@ function CTAModal(props) {
101
101
  children: /* @__PURE__ */ jsx(IconButton, { ariaLabel: "Close modal", onClick: close, children: /* @__PURE__ */ jsx(CloseIcon, {}) })
102
102
  }
103
103
  ),
104
- /* @__PURE__ */ jsxs(ModalHeader, { children: [
105
- /* @__PURE__ */ jsx(HStack, { justify: "center", w: "full", children: /* @__PURE__ */ jsx(
106
- Avatar,
107
- {
108
- ariaLabel: "",
109
- gradient: "charon-light",
110
- icon: /* @__PURE__ */ jsx(
111
- Show,
112
- {
113
- when: Boolean(confirmIcon),
114
- fallback: /* @__PURE__ */ jsx(FallbackIcon, { size: 24 }),
115
- children: confirmIcon
116
- }
117
- ),
118
- src: ""
119
- }
120
- ) }),
121
- /* @__PURE__ */ jsxs(VStack, { gap: "lg", w: "full", children: [
104
+ /* @__PURE__ */ jsxs(VStack, { gap: "xl", w: "full", children: [
105
+ /* @__PURE__ */ jsx(ModalHeader, { children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", w: "full", children: [
106
+ /* @__PURE__ */ jsx(
107
+ Avatar,
108
+ {
109
+ ariaLabel: "",
110
+ gradient: "charon-light",
111
+ icon: /* @__PURE__ */ jsx(
112
+ Show,
113
+ {
114
+ when: Boolean(confirmIcon),
115
+ fallback: /* @__PURE__ */ jsx(FallbackIcon, { size: 24 }),
116
+ children: confirmIcon
117
+ }
118
+ ),
119
+ src: ""
120
+ }
121
+ ),
122
122
  /* @__PURE__ */ jsx(ModalHeading, { children: content?.heading }),
123
123
  /* @__PURE__ */ jsx(ModalDescription, { children: content?.description })
124
- ] })
125
- ] }),
126
- /* @__PURE__ */ jsx(HStack, { gap: "md", pt: "sm", w: "full", children: /* @__PURE__ */ jsx(Show, { when: Boolean(content?.actions?.length), children: content?.actions?.map((action, index) => /* @__PURE__ */ jsx(
127
- Button,
128
- {
129
- "data-index": index,
130
- className: css({
131
- w: "1/2"
132
- }),
133
- onClick: handleActionClick,
134
- shape: "rounded",
135
- usage: "outlined",
136
- children: action.text
137
- },
138
- index
139
- )) }) })
124
+ ] }) }),
125
+ /* @__PURE__ */ jsx(HStack, { gap: "md", w: "full", children: /* @__PURE__ */ jsx(Show, { when: Boolean(content?.actions?.length), children: content?.actions?.map((action, index) => /* @__PURE__ */ jsx(
126
+ Button,
127
+ {
128
+ "data-index": index,
129
+ className: css({
130
+ w: "1/2"
131
+ }),
132
+ onClick: handleActionClick,
133
+ shape: "rounded",
134
+ usage: "outlined",
135
+ children: action.text
136
+ },
137
+ index
138
+ )) }) })
139
+ ] })
140
140
  ] }) })
141
141
  ] });
142
142
  }
@@ -152,4 +152,4 @@ export {
152
152
  CTAModal,
153
153
  useCTAModal
154
154
  };
155
- //# sourceMappingURL=chunk-J4LOSTEP.js.map
155
+ //# sourceMappingURL=chunk-MXMVC3ZQ.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/context/cta-modal.tsx"],"sourcesContent":["'use client'\n\nimport {\n createContext,\n useCallback,\n useContext,\n useMemo,\n useState,\n type ButtonHTMLAttributes,\n type MouseEvent,\n type PropsWithChildren,\n type ReactNode,\n} from 'react'\nimport { Portal } from '../components/Portal'\nimport { Button } from '../components/Button'\nimport { $cerberusIcons } from '../config/defineIcons'\nimport { trapFocus } from '../aria-helpers/trap-focus.aria'\nimport { Show } from '../components/Show'\nimport { Modal } from '../components/Modal'\nimport { useModal } from '../hooks/useModal'\nimport { ModalHeader } from '../components/ModalHeader'\nimport { ModalHeading } from '../components/ModalHeading'\nimport { ModalDescription } from '../components/ModalDescription'\nimport { Avatar } from '../components/Avatar'\nimport { HStack } from '@cerberus/styled-system/jsx'\nimport { IconButton } from '../components/IconButton'\nimport { css } from '@cerberus/styled-system/css'\nimport { VStack } from '@cerberus/styled-system/jsx'\n\n/**\n * This module provides a context and hook for the cta modal.\n * @module\n */\n\nexport interface ShowCTAModalOptions {\n /**\n * The heading of the cta modal.\n */\n heading: string\n /**\n * The description of the cta modal.\n */\n description?: string\n /**\n * The icon used for the modal Avatar.\n */\n icon?: ReactNode\n /**\n * The actions for the cta modal. Max of 2 actions.\n */\n actions: {\n text: string\n onClick: Required<ButtonHTMLAttributes<HTMLButtonElement>['onClick']>\n }[]\n}\n\nexport interface CTAModalValue {\n show: (options: ShowCTAModalOptions) => void\n}\n\nconst CTAModalContext = createContext<CTAModalValue | null>(null)\n\nexport interface CTAModalProviderProps {}\n\n/**\n * Provides a CTA modal to the app.\n * @see https://cerberus.digitalu.design/react/cta-modal\n * @example\n * ```tsx\n * // Wrap the Provider around the root of the feature.\n * <CTAModal>\n * <SomeFeatureSection />\n * </CTAModal>\n *\n * // Use the hook to show the cta modal.\n * const cta = useCTAModal()\n *\n * const handleClick = useCallback(async () => {\n * const userConsent = await cta.show({\n * heading: 'Create or copy a Cohort',\n * description:\n * 'Create a new cohort or copy and existing one.',\n * icon: <Copy size={24} />,\n * actions: [\n * {\n * text: 'Create Cohort',\n * onClick: () => {},\n * {\n * text: 'Copy Cohort',\n * onClick: () => {}\n * }\n * })\n * setConsent(userConsent)\n * }, [cta])\n * ```\n */\nexport function CTAModal(props: PropsWithChildren<CTAModalProviderProps>) {\n const { modalRef, show, close } = useModal()\n const [content, setContent] = useState<ShowCTAModalOptions | null>(null)\n const focusTrap = trapFocus(modalRef)\n const FallbackIcon = $cerberusIcons.confirmModal\n const confirmIcon = content?.icon as ReactNode\n const { close: CloseIcon } = $cerberusIcons\n\n const handleShow = useCallback(\n (options: ShowCTAModalOptions) => {\n const maxActions = 2\n if (options.actions.length > maxActions) {\n throw new Error(\n `CTA Modal only supports a maximum of ${maxActions} actions.`,\n )\n }\n setContent({ ...options })\n show()\n },\n [show],\n )\n\n const handleActionClick = useCallback(\n (event: MouseEvent<HTMLButtonElement>) => {\n const index = event.currentTarget.getAttribute('data-index')\n const action = content?.actions[Number(index)]\n if (typeof action?.onClick === 'function') {\n action.onClick(event)\n }\n close()\n },\n [content, close],\n )\n\n const value = useMemo(\n () => ({\n show: handleShow,\n }),\n [handleShow],\n )\n\n return (\n <CTAModalContext.Provider value={value}>\n {props.children}\n\n <Portal>\n <Modal onKeyDown={focusTrap} ref={modalRef}>\n <span\n className={css({\n padding: 'md',\n position: 'absolute',\n right: 0,\n top: 0,\n zIndex: 'decorator',\n })}\n >\n <IconButton ariaLabel=\"Close modal\" onClick={close}>\n <CloseIcon />\n </IconButton>\n </span>\n\n <ModalHeader>\n <HStack justify=\"center\" w=\"full\">\n <Avatar\n ariaLabel=\"\"\n gradient=\"charon-light\"\n icon={\n <Show\n when={Boolean(confirmIcon)}\n fallback={<FallbackIcon size={24} />}\n >\n {confirmIcon}\n </Show>\n }\n src=\"\"\n />\n </HStack>\n <VStack gap=\"lg\" w=\"full\">\n <ModalHeading>{content?.heading}</ModalHeading>\n <ModalDescription>{content?.description}</ModalDescription>\n </VStack>\n </ModalHeader>\n\n <HStack gap=\"md\" pt=\"sm\" w=\"full\">\n <Show when={Boolean(content?.actions?.length)}>\n {content?.actions?.map((action, index) => (\n <Button\n data-index={index}\n className={css({\n w: '1/2',\n })}\n key={index}\n onClick={handleActionClick}\n shape=\"rounded\"\n usage=\"outlined\"\n >\n {action.text}\n </Button>\n ))}\n </Show>\n </HStack>\n </Modal>\n </Portal>\n </CTAModalContext.Provider>\n )\n}\n\nexport function useCTAModal(): CTAModalValue {\n const context = useContext(CTAModalContext)\n if (context === null) {\n throw new Error('useCTAModal must be used within a CTAModal Provider')\n }\n return context\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/context/cta-modal.tsx"],"sourcesContent":["'use client'\n\nimport {\n createContext,\n useCallback,\n useContext,\n useMemo,\n useState,\n type ButtonHTMLAttributes,\n type MouseEvent,\n type PropsWithChildren,\n type ReactNode,\n} from 'react'\nimport { Portal } from '../components/Portal'\nimport { Button } from '../components/Button'\nimport { $cerberusIcons } from '../config/defineIcons'\nimport { trapFocus } from '../aria-helpers/trap-focus.aria'\nimport { Show } from '../components/Show'\nimport { Modal } from '../components/Modal'\nimport { useModal } from '../hooks/useModal'\nimport { ModalHeader } from '../components/ModalHeader'\nimport { ModalHeading } from '../components/ModalHeading'\nimport { ModalDescription } from '../components/ModalDescription'\nimport { Avatar } from '../components/Avatar'\nimport { HStack } from '@cerberus/styled-system/jsx'\nimport { IconButton } from '../components/IconButton'\nimport { css } from '@cerberus/styled-system/css'\nimport { VStack } from '@cerberus/styled-system/jsx'\n\n/**\n * This module provides a context and hook for the cta modal.\n * @module\n */\n\nexport interface ShowCTAModalOptions {\n /**\n * The heading of the cta modal.\n */\n heading: string\n /**\n * The description of the cta modal.\n */\n description?: string\n /**\n * The icon used for the modal Avatar.\n */\n icon?: ReactNode\n /**\n * The actions for the cta modal. Max of 2 actions.\n */\n actions: {\n text: string\n onClick: Required<ButtonHTMLAttributes<HTMLButtonElement>['onClick']>\n }[]\n}\n\nexport interface CTAModalValue {\n show: (options: ShowCTAModalOptions) => void\n}\n\nconst CTAModalContext = createContext<CTAModalValue | null>(null)\n\nexport interface CTAModalProviderProps {}\n\n/**\n * Provides a CTA modal to the app.\n * @see https://cerberus.digitalu.design/react/cta-modal\n * @example\n * ```tsx\n * // Wrap the Provider around the root of the feature.\n * <CTAModal>\n * <SomeFeatureSection />\n * </CTAModal>\n *\n * // Use the hook to show the cta modal.\n * const cta = useCTAModal()\n *\n * const handleClick = useCallback(async () => {\n * const userConsent = await cta.show({\n * heading: 'Create or copy a Cohort',\n * description:\n * 'Create a new cohort or copy and existing one.',\n * icon: <Copy size={24} />,\n * actions: [\n * {\n * text: 'Create Cohort',\n * onClick: () => {},\n * {\n * text: 'Copy Cohort',\n * onClick: () => {}\n * }\n * })\n * setConsent(userConsent)\n * }, [cta])\n * ```\n */\nexport function CTAModal(props: PropsWithChildren<CTAModalProviderProps>) {\n const { modalRef, show, close } = useModal()\n const [content, setContent] = useState<ShowCTAModalOptions | null>(null)\n const focusTrap = trapFocus(modalRef)\n const FallbackIcon = $cerberusIcons.confirmModal\n const confirmIcon = content?.icon as ReactNode\n const { close: CloseIcon } = $cerberusIcons\n\n const handleShow = useCallback(\n (options: ShowCTAModalOptions) => {\n const maxActions = 2\n if (options.actions.length > maxActions) {\n throw new Error(\n `CTA Modal only supports a maximum of ${maxActions} actions.`,\n )\n }\n setContent({ ...options })\n show()\n },\n [show],\n )\n\n const handleActionClick = useCallback(\n (event: MouseEvent<HTMLButtonElement>) => {\n const index = event.currentTarget.getAttribute('data-index')\n const action = content?.actions[Number(index)]\n if (typeof action?.onClick === 'function') {\n action.onClick(event)\n }\n close()\n },\n [content, close],\n )\n\n const value = useMemo(\n () => ({\n show: handleShow,\n }),\n [handleShow],\n )\n\n return (\n <CTAModalContext.Provider value={value}>\n {props.children}\n\n <Portal>\n <Modal onKeyDown={focusTrap} ref={modalRef}>\n <span\n className={css({\n padding: 'md',\n position: 'absolute',\n right: 0,\n top: 0,\n zIndex: 'decorator',\n })}\n >\n <IconButton ariaLabel=\"Close modal\" onClick={close}>\n <CloseIcon />\n </IconButton>\n </span>\n\n <VStack gap=\"xl\" w=\"full\">\n <ModalHeader>\n <VStack gap=\"lg\" w=\"full\">\n <Avatar\n ariaLabel=\"\"\n gradient=\"charon-light\"\n icon={\n <Show\n when={Boolean(confirmIcon)}\n fallback={<FallbackIcon size={24} />}\n >\n {confirmIcon}\n </Show>\n }\n src=\"\"\n />\n <ModalHeading>{content?.heading}</ModalHeading>\n <ModalDescription>{content?.description}</ModalDescription>\n </VStack>\n </ModalHeader>\n\n <HStack gap=\"md\" w=\"full\">\n <Show when={Boolean(content?.actions?.length)}>\n {content?.actions?.map((action, index) => (\n <Button\n data-index={index}\n className={css({\n w: '1/2',\n })}\n key={index}\n onClick={handleActionClick}\n shape=\"rounded\"\n usage=\"outlined\"\n >\n {action.text}\n </Button>\n ))}\n </Show>\n </HStack>\n </VStack>\n </Modal>\n </Portal>\n </CTAModalContext.Provider>\n )\n}\n\nexport function useCTAModal(): CTAModalValue {\n const context = useContext(CTAModalContext)\n if (context === null) {\n throw new Error('useCTAModal must be used within a CTAModal Provider')\n }\n return context\n}\n"],"mappings":"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","names":[]}
@@ -12,7 +12,6 @@ function ModalHeader(props) {
12
12
  vstack({
13
13
  alignItems: "flex-start",
14
14
  gap: "md",
15
- mb: "md",
16
15
  position: "relative"
17
16
  })
18
17
  )
@@ -23,4 +22,4 @@ function ModalHeader(props) {
23
22
  export {
24
23
  ModalHeader
25
24
  };
26
- //# sourceMappingURL=chunk-ZFAIE47A.js.map
25
+ //# sourceMappingURL=chunk-XY6WL55R.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/ModalHeader.tsx"],"sourcesContent":["import { cx } from '@cerberus/styled-system/css'\nimport { vstack } from '@cerberus/styled-system/patterns'\nimport type { HTMLAttributes } from 'react'\n\n/**\n * This module contains the ModalHeader component for a customizable modal.\n * @module\n */\n\nexport type ModalHeaderProps = HTMLAttributes<HTMLDivElement>\n\n/**\n * The ModalHeader component is a header element for a customizable modal.\n * @see https://cerberus.digitalu.design/react/modal\n * @example\n * ```tsx\n * <Modal>\n * <ModalHeader>\n * <h2>Modal Heading</h2>\n * </ModalHeader>\n * </Modal>\n * ```\n */\nexport function ModalHeader(props: ModalHeaderProps) {\n return (\n <div\n {...props}\n className={cx(\n props.className,\n vstack({\n alignItems: 'flex-start',\n gap: 'md',\n mb: 'md',\n position: 'relative',\n }),\n )}\n />\n )\n}\n"],"mappings":";AAAA,SAAS,UAAU;AACnB,SAAS,cAAc;AAwBnB;AAFG,SAAS,YAAY,OAAyB;AACnD,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ,WAAW;AAAA,QACT,MAAM;AAAA,QACN,OAAO;AAAA,UACL,YAAY;AAAA,UACZ,KAAK;AAAA,UACL,IAAI;AAAA,UACJ,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AAAA;AAAA,EACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/components/ModalHeader.tsx"],"sourcesContent":["import { cx } from '@cerberus/styled-system/css'\nimport { vstack } from '@cerberus/styled-system/patterns'\nimport type { HTMLAttributes } from 'react'\n\n/**\n * This module contains the ModalHeader component for a customizable modal.\n * @module\n */\n\nexport type ModalHeaderProps = HTMLAttributes<HTMLDivElement>\n\n/**\n * The ModalHeader component is a header element for a customizable modal.\n * @see https://cerberus.digitalu.design/react/modal\n * @example\n * ```tsx\n * <Modal>\n * <ModalHeader>\n * <h2>Modal Heading</h2>\n * </ModalHeader>\n * </Modal>\n * ```\n */\nexport function ModalHeader(props: ModalHeaderProps) {\n return (\n <div\n {...props}\n className={cx(\n props.className,\n vstack({\n alignItems: 'flex-start',\n gap: 'md',\n position: 'relative',\n }),\n )}\n />\n )\n}\n"],"mappings":";AAAA,SAAS,UAAU;AACnB,SAAS,cAAc;AAwBnB;AAFG,SAAS,YAAY,OAAyB;AACnD,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ,WAAW;AAAA,QACT,MAAM;AAAA,QACN,OAAO;AAAA,UACL,YAAY;AAAA,UACZ,KAAK;AAAA,UACL,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AAAA;AAAA,EACF;AAEJ;","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ModalHeader
3
- } from "../chunk-ZFAIE47A.js";
3
+ } from "../chunk-XY6WL55R.js";
4
4
  export {
5
5
  ModalHeader
6
6
  };
@@ -2,9 +2,9 @@
2
2
  import {
3
3
  ConfirmModal,
4
4
  useConfirmModal
5
- } from "../chunk-KFGI37CO.js";
5
+ } from "../chunk-4D6VIGNQ.js";
6
6
  import "../chunk-K2PSHGS7.js";
7
- import "../chunk-ZFAIE47A.js";
7
+ import "../chunk-XY6WL55R.js";
8
8
  import "../chunk-2UXE5PDG.js";
9
9
  import "../chunk-BE4EOU2P.js";
10
10
  import "../chunk-Q7BRMIBR.js";
@@ -2,9 +2,9 @@
2
2
  import {
3
3
  CTAModal,
4
4
  useCTAModal
5
- } from "../chunk-J4LOSTEP.js";
5
+ } from "../chunk-MXMVC3ZQ.js";
6
6
  import "../chunk-K2PSHGS7.js";
7
- import "../chunk-ZFAIE47A.js";
7
+ import "../chunk-XY6WL55R.js";
8
8
  import "../chunk-2UXE5PDG.js";
9
9
  import "../chunk-BE4EOU2P.js";
10
10
  import "../chunk-Q7BRMIBR.js";
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  NotificationCenter,
4
4
  useNotificationCenter
5
- } from "../chunk-KUT2YEEQ.js";
5
+ } from "../chunk-5KHGTLFM.js";
6
6
  import "../chunk-K2PSHGS7.js";
7
7
  import "../chunk-7SGPJM66.js";
8
8
  import "../chunk-XEW6TJJ4.js";
@@ -2,9 +2,9 @@
2
2
  import {
3
3
  PromptModal,
4
4
  usePromptModal
5
- } from "../chunk-NCUHRVW2.js";
5
+ } from "../chunk-MMHCX2RG.js";
6
6
  import "../chunk-K2PSHGS7.js";
7
- import "../chunk-ZFAIE47A.js";
7
+ import "../chunk-XY6WL55R.js";
8
8
  import "../chunk-2UXE5PDG.js";
9
9
  import "../chunk-NKM6PISB.js";
10
10
  import "../chunk-NMF2HYWO.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  PromptModal,
3
3
  usePromptModal
4
- } from "./chunk-NCUHRVW2.js";
4
+ } from "./chunk-MMHCX2RG.js";
5
5
  import {
6
6
  ThemeProvider,
7
7
  useThemeContext
@@ -15,15 +15,15 @@ import {
15
15
  import {
16
16
  ConfirmModal,
17
17
  useConfirmModal
18
- } from "./chunk-KFGI37CO.js";
18
+ } from "./chunk-4D6VIGNQ.js";
19
19
  import {
20
20
  CTAModal,
21
21
  useCTAModal
22
- } from "./chunk-J4LOSTEP.js";
22
+ } from "./chunk-MXMVC3ZQ.js";
23
23
  import {
24
24
  NotificationCenter,
25
25
  useNotificationCenter
26
- } from "./chunk-KUT2YEEQ.js";
26
+ } from "./chunk-5KHGTLFM.js";
27
27
  import {
28
28
  TabPanel
29
29
  } from "./chunk-AYIRV5CL.js";
@@ -70,7 +70,7 @@ import {
70
70
  } from "./chunk-UKPF7JOB.js";
71
71
  import {
72
72
  ModalHeader
73
- } from "./chunk-ZFAIE47A.js";
73
+ } from "./chunk-XY6WL55R.js";
74
74
  import {
75
75
  ModalHeading
76
76
  } from "./chunk-2UXE5PDG.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cerberus-design/react",
3
- "version": "0.13.1-next-e3e9e48",
3
+ "version": "0.13.1-next-8c8a5ee",
4
4
  "description": "The Cerberus Design React component library.",
5
5
  "browserslist": "> 0.25%, not dead",
6
6
  "sideEffects": false,
@@ -27,7 +27,7 @@
27
27
  "react-dom": "^18",
28
28
  "tsup": "^8.1.0",
29
29
  "@cerberus-design/configs": "0.0.0",
30
- "@cerberus-design/styled-system": "0.13.1-next-e3e9e48"
30
+ "@cerberus-design/styled-system": "0.13.1-next-8c8a5ee"
31
31
  },
32
32
  "publishConfig": {
33
33
  "access": "public"
@@ -30,7 +30,6 @@ export function ModalHeader(props: ModalHeaderProps) {
30
30
  vstack({
31
31
  alignItems: 'flex-start',
32
32
  gap: 'md',
33
- mb: 'md',
34
33
  position: 'relative',
35
34
  }),
36
35
  )}