@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.
- package/build/legacy/_tsup-dts-rollup.d.cts +52 -27
- package/build/legacy/components/ModalHeader.cjs +0 -1
- package/build/legacy/components/ModalHeader.cjs.map +1 -1
- package/build/legacy/context/confirm-modal.cjs +36 -43
- package/build/legacy/context/confirm-modal.cjs.map +1 -1
- package/build/legacy/context/cta-modal.cjs +34 -35
- package/build/legacy/context/cta-modal.cjs.map +1 -1
- package/build/legacy/context/notification-center.cjs.map +1 -1
- package/build/legacy/context/prompt-modal.cjs +0 -1
- package/build/legacy/context/prompt-modal.cjs.map +1 -1
- package/build/legacy/index.cjs +72 -79
- package/build/legacy/index.cjs.map +1 -1
- package/build/modern/_tsup-dts-rollup.d.ts +52 -27
- package/build/modern/{chunk-KFGI37CO.js → chunk-4D6VIGNQ.js} +38 -44
- package/build/modern/chunk-4D6VIGNQ.js.map +1 -0
- package/build/modern/{chunk-KUT2YEEQ.js → chunk-5KHGTLFM.js} +1 -1
- package/build/modern/chunk-5KHGTLFM.js.map +1 -0
- package/build/modern/{chunk-NCUHRVW2.js → chunk-MMHCX2RG.js} +2 -2
- package/build/modern/{chunk-J4LOSTEP.js → chunk-MXMVC3ZQ.js} +36 -36
- package/build/modern/{chunk-J4LOSTEP.js.map → chunk-MXMVC3ZQ.js.map} +1 -1
- package/build/modern/{chunk-ZFAIE47A.js → chunk-XY6WL55R.js} +1 -2
- package/build/modern/{chunk-ZFAIE47A.js.map → chunk-XY6WL55R.js.map} +1 -1
- package/build/modern/components/ModalHeader.js +1 -1
- package/build/modern/context/confirm-modal.js +2 -2
- package/build/modern/context/cta-modal.js +2 -2
- package/build/modern/context/notification-center.js +1 -1
- package/build/modern/context/prompt-modal.js +2 -2
- package/build/modern/index.js +5 -5
- package/package.json +2 -2
- package/src/components/ModalHeader.tsx +0 -1
- package/src/context/confirm-modal.tsx +89 -66
- package/src/context/cta-modal.tsx +38 -38
- package/src/context/notification-center.tsx +1 -0
- package/build/modern/chunk-KFGI37CO.js.map +0 -1
- package/build/modern/chunk-KUT2YEEQ.js.map +0 -1
- /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-
|
|
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
|
-
() =>
|
|
56
|
-
[
|
|
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
|
|
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__ */
|
|
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
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
),
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
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-
|
|
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":[]}
|
|
@@ -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-
|
|
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-
|
|
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-
|
|
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(
|
|
105
|
-
/* @__PURE__ */ jsx(
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
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
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
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-
|
|
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 <
|
|
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-
|
|
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
|
|
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":[]}
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
import {
|
|
3
3
|
ConfirmModal,
|
|
4
4
|
useConfirmModal
|
|
5
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-4D6VIGNQ.js";
|
|
6
6
|
import "../chunk-K2PSHGS7.js";
|
|
7
|
-
import "../chunk-
|
|
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-
|
|
5
|
+
} from "../chunk-MXMVC3ZQ.js";
|
|
6
6
|
import "../chunk-K2PSHGS7.js";
|
|
7
|
-
import "../chunk-
|
|
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
|
PromptModal,
|
|
4
4
|
usePromptModal
|
|
5
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-MMHCX2RG.js";
|
|
6
6
|
import "../chunk-K2PSHGS7.js";
|
|
7
|
-
import "../chunk-
|
|
7
|
+
import "../chunk-XY6WL55R.js";
|
|
8
8
|
import "../chunk-2UXE5PDG.js";
|
|
9
9
|
import "../chunk-NKM6PISB.js";
|
|
10
10
|
import "../chunk-NMF2HYWO.js";
|
package/build/modern/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
PromptModal,
|
|
3
3
|
usePromptModal
|
|
4
|
-
} from "./chunk-
|
|
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-
|
|
18
|
+
} from "./chunk-4D6VIGNQ.js";
|
|
19
19
|
import {
|
|
20
20
|
CTAModal,
|
|
21
21
|
useCTAModal
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-MXMVC3ZQ.js";
|
|
23
23
|
import {
|
|
24
24
|
NotificationCenter,
|
|
25
25
|
useNotificationCenter
|
|
26
|
-
} from "./chunk-
|
|
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-
|
|
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-
|
|
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-
|
|
30
|
+
"@cerberus-design/styled-system": "0.13.1-next-8c8a5ee"
|
|
31
31
|
},
|
|
32
32
|
"publishConfig": {
|
|
33
33
|
"access": "public"
|