@cerberus-design/react 0.6.1-next-2d28489 → 0.6.1-next-fa4208e

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 (92) hide show
  1. package/build/legacy/_tsup-dts-rollup.d.ts +119 -9
  2. package/build/legacy/chunk-2F5TB2EV.js +25 -0
  3. package/build/legacy/chunk-2F5TB2EV.js.map +1 -0
  4. package/build/legacy/{chunk-7ISHDUYN.js → chunk-5GEC53G7.js} +4 -4
  5. package/build/legacy/{chunk-JJGZRBIR.js → chunk-CU7HXAKM.js} +4 -4
  6. package/build/legacy/chunk-D3ZXZA3U.js +155 -0
  7. package/build/legacy/chunk-D3ZXZA3U.js.map +1 -0
  8. package/build/legacy/{chunk-SNSBODYR.js → chunk-DGPLSWFJ.js} +55 -71
  9. package/build/legacy/chunk-DGPLSWFJ.js.map +1 -0
  10. package/build/legacy/chunk-G3JEWPLM.js +29 -0
  11. package/build/legacy/chunk-G3JEWPLM.js.map +1 -0
  12. package/build/legacy/chunk-OGSAAB6K.js +12 -0
  13. package/build/legacy/chunk-OGSAAB6K.js.map +1 -0
  14. package/build/legacy/chunk-TPFNVGYA.js +21 -0
  15. package/build/legacy/chunk-TPFNVGYA.js.map +1 -0
  16. package/build/legacy/chunk-TZNYJ3G7.js +25 -0
  17. package/build/legacy/chunk-TZNYJ3G7.js.map +1 -0
  18. package/build/legacy/chunk-UPODPCRD.js +12 -0
  19. package/build/legacy/chunk-UPODPCRD.js.map +1 -0
  20. package/build/legacy/components/Input.js +2 -2
  21. package/build/legacy/components/Label.js +2 -2
  22. package/build/legacy/components/Modal.js +7 -0
  23. package/build/legacy/components/Modal.js.map +1 -0
  24. package/build/legacy/components/ModalDescription.js +7 -0
  25. package/build/legacy/components/ModalDescription.js.map +1 -0
  26. package/build/legacy/components/ModalHeader.js +7 -0
  27. package/build/legacy/components/ModalHeader.js.map +1 -0
  28. package/build/legacy/components/ModalHeading.js +7 -0
  29. package/build/legacy/components/ModalHeading.js.map +1 -0
  30. package/build/legacy/components/ModalIcon.js +7 -0
  31. package/build/legacy/components/ModalIcon.js.map +1 -0
  32. package/build/legacy/context/confirm-modal.js +7 -3
  33. package/build/legacy/context/prompt-modal.js +10 -7
  34. package/build/legacy/hooks/useModal.js +8 -0
  35. package/build/legacy/hooks/useModal.js.map +1 -0
  36. package/build/legacy/index.js +59 -39
  37. package/build/modern/_tsup-dts-rollup.d.ts +119 -9
  38. package/build/modern/chunk-2F5TB2EV.js +25 -0
  39. package/build/modern/chunk-2F5TB2EV.js.map +1 -0
  40. package/build/modern/{chunk-7ISHDUYN.js → chunk-5GEC53G7.js} +4 -4
  41. package/build/modern/chunk-C5HLLGME.js +23 -0
  42. package/build/modern/chunk-C5HLLGME.js.map +1 -0
  43. package/build/modern/{chunk-JJGZRBIR.js → chunk-CU7HXAKM.js} +4 -4
  44. package/build/modern/chunk-G3JEWPLM.js +29 -0
  45. package/build/modern/chunk-G3JEWPLM.js.map +1 -0
  46. package/build/modern/chunk-OGSAAB6K.js +12 -0
  47. package/build/modern/chunk-OGSAAB6K.js.map +1 -0
  48. package/build/modern/chunk-TAVCJ54A.js +154 -0
  49. package/build/modern/chunk-TAVCJ54A.js.map +1 -0
  50. package/build/modern/chunk-TPFNVGYA.js +21 -0
  51. package/build/modern/chunk-TPFNVGYA.js.map +1 -0
  52. package/build/modern/chunk-UPODPCRD.js +12 -0
  53. package/build/modern/chunk-UPODPCRD.js.map +1 -0
  54. package/build/modern/{chunk-FZ75OJLJ.js → chunk-WWG5QWXY.js} +54 -69
  55. package/build/modern/chunk-WWG5QWXY.js.map +1 -0
  56. package/build/modern/components/Input.js +2 -2
  57. package/build/modern/components/Label.js +2 -2
  58. package/build/modern/components/Modal.js +7 -0
  59. package/build/modern/components/Modal.js.map +1 -0
  60. package/build/modern/components/ModalDescription.js +7 -0
  61. package/build/modern/components/ModalDescription.js.map +1 -0
  62. package/build/modern/components/ModalHeader.js +7 -0
  63. package/build/modern/components/ModalHeader.js.map +1 -0
  64. package/build/modern/components/ModalHeading.js +7 -0
  65. package/build/modern/components/ModalHeading.js.map +1 -0
  66. package/build/modern/components/ModalIcon.js +7 -0
  67. package/build/modern/components/ModalIcon.js.map +1 -0
  68. package/build/modern/context/confirm-modal.js +7 -3
  69. package/build/modern/context/prompt-modal.js +10 -7
  70. package/build/modern/hooks/useModal.js +8 -0
  71. package/build/modern/hooks/useModal.js.map +1 -0
  72. package/build/modern/index.js +59 -39
  73. package/package.json +2 -2
  74. package/src/components/Modal.tsx +37 -0
  75. package/src/components/ModalDescription.tsx +23 -0
  76. package/src/components/ModalHeader.tsx +37 -0
  77. package/src/components/ModalHeading.tsx +23 -0
  78. package/src/components/ModalIcon.tsx +28 -0
  79. package/src/context/confirm-modal.tsx +50 -70
  80. package/src/context/prompt-modal.tsx +41 -63
  81. package/src/hooks/useModal.ts +34 -0
  82. package/src/index.ts +6 -0
  83. package/build/legacy/chunk-BLJ4SRAF.js +0 -167
  84. package/build/legacy/chunk-BLJ4SRAF.js.map +0 -1
  85. package/build/legacy/chunk-SNSBODYR.js.map +0 -1
  86. package/build/modern/chunk-4GURONLE.js +0 -165
  87. package/build/modern/chunk-4GURONLE.js.map +0 -1
  88. package/build/modern/chunk-FZ75OJLJ.js.map +0 -1
  89. /package/build/legacy/{chunk-7ISHDUYN.js.map → chunk-5GEC53G7.js.map} +0 -0
  90. /package/build/legacy/{chunk-JJGZRBIR.js.map → chunk-CU7HXAKM.js.map} +0 -0
  91. /package/build/modern/{chunk-7ISHDUYN.js.map → chunk-5GEC53G7.js.map} +0 -0
  92. /package/build/modern/{chunk-JJGZRBIR.js.map → chunk-CU7HXAKM.js.map} +0 -0
@@ -0,0 +1,34 @@
1
+ 'use client'
2
+
3
+ import { useCallback, useMemo, useRef, type RefObject } from 'react'
4
+
5
+ /**
6
+ * This module provides a hook for using a custom modal.
7
+ * @module
8
+ */
9
+
10
+ interface UseModalReturnValue {
11
+ modalRef: RefObject<HTMLDialogElement>
12
+ show: () => void
13
+ close: () => void
14
+ }
15
+
16
+ export function useModal(): UseModalReturnValue {
17
+ const modalRef = useRef<HTMLDialogElement | null>(null)
18
+
19
+ const show = useCallback(() => {
20
+ modalRef.current?.showModal()
21
+ }, [])
22
+
23
+ const close = useCallback(() => {
24
+ modalRef.current?.close()
25
+ }, [])
26
+
27
+ return useMemo(() => {
28
+ return {
29
+ modalRef,
30
+ show,
31
+ close,
32
+ }
33
+ }, [modalRef, show, close])
34
+ }
package/src/index.ts CHANGED
@@ -11,6 +11,11 @@ export * from './components/FeatureFlag'
11
11
  export * from './components/IconButton'
12
12
  export * from './components/Input'
13
13
  export * from './components/Label'
14
+ export * from './components/Modal'
15
+ export * from './components/ModalHeader'
16
+ export * from './components/ModalHeading'
17
+ export * from './components/ModalDescription'
18
+ export * from './components/ModalIcon'
14
19
  export * from './components/NavMenuTrigger'
15
20
  export * from './components/NavMenuList'
16
21
  export * from './components/NavMenuLink'
@@ -36,6 +41,7 @@ export * from './context/theme'
36
41
 
37
42
  // hooks
38
43
 
44
+ export * from './hooks/useModal'
39
45
  export * from './hooks/useTheme'
40
46
  export * from './hooks/useToggle'
41
47
 
@@ -1,167 +0,0 @@
1
- import {
2
- Portal
3
- } from "./chunk-4CAT3FHV.js";
4
- import {
5
- Button
6
- } from "./chunk-2ATICEW3.js";
7
- import {
8
- Show
9
- } from "./chunk-4O4QFF4S.js";
10
- import {
11
- trapFocus
12
- } from "./chunk-KESKDLX6.js";
13
- import {
14
- $cerberusIcons
15
- } from "./chunk-6TXQZ3PB.js";
16
-
17
- // src/context/confirm-modal.tsx
18
- import {
19
- createContext,
20
- useCallback,
21
- useContext,
22
- useMemo,
23
- useRef,
24
- useState
25
- } from "react";
26
- import { css, cx } from "@cerberus-design/styled-system/css";
27
- import { circle, hstack, vstack } from "@cerberus-design/styled-system/patterns";
28
- import {
29
- confirmModal
30
- } from "@cerberus-design/styled-system/recipes";
31
- import { jsx, jsxs } from "react/jsx-runtime";
32
- var ConfirmModalContext = createContext(null);
33
- function ConfirmModal(props) {
34
- const dialogRef = useRef(null);
35
- const resolveRef = useRef(null);
36
- const [content, setContent] = useState(null);
37
- const focusTrap = trapFocus(dialogRef);
38
- const palette = useMemo(
39
- () => (content == null ? void 0 : content.kind) === "destructive" ? "danger" : "action",
40
- [content]
41
- );
42
- const styles = confirmModal({ palette });
43
- const handleChoice = useCallback((e) => {
44
- var _a, _b, _c;
45
- const target = e.currentTarget;
46
- if (target.value === "true") {
47
- (_a = resolveRef.current) == null ? void 0 : _a.call(resolveRef, true);
48
- }
49
- (_b = resolveRef.current) == null ? void 0 : _b.call(resolveRef, false);
50
- (_c = dialogRef == null ? void 0 : dialogRef.current) == null ? void 0 : _c.close();
51
- }, []);
52
- const handleShow = useCallback((options) => {
53
- return new Promise((resolve) => {
54
- var _a;
55
- setContent({ ...options, kind: options.kind || "non-destructive" });
56
- (_a = dialogRef == null ? void 0 : dialogRef.current) == null ? void 0 : _a.showModal();
57
- resolveRef.current = resolve;
58
- });
59
- }, []);
60
- const value = useMemo(
61
- () => ({
62
- show: handleShow
63
- }),
64
- [handleShow]
65
- );
66
- return /* @__PURE__ */ jsxs(ConfirmModalContext.Provider, { value, children: [
67
- props.children,
68
- /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsxs("dialog", { className: styles.dialog, onKeyDown: focusTrap, ref: dialogRef, children: [
69
- /* @__PURE__ */ jsxs(
70
- "div",
71
- {
72
- className: vstack({
73
- alignItems: "flex-start",
74
- gap: "4",
75
- mb: "8"
76
- }),
77
- children: [
78
- /* @__PURE__ */ jsx(ConfirmModalIcon, { palette }),
79
- /* @__PURE__ */ jsx("h2", { className: styles.heading, children: content == null ? void 0 : content.heading }),
80
- /* @__PURE__ */ jsx("p", { className: styles.description, children: content == null ? void 0 : content.description })
81
- ]
82
- }
83
- ),
84
- /* @__PURE__ */ jsxs(
85
- "div",
86
- {
87
- className: hstack({
88
- justifyContent: "stretch",
89
- gap: "4"
90
- }),
91
- children: [
92
- /* @__PURE__ */ jsx(
93
- Button,
94
- {
95
- autoFocus: true,
96
- className: css({
97
- w: "1/2"
98
- }),
99
- name: "confirm",
100
- onClick: handleChoice,
101
- palette,
102
- value: "true",
103
- children: content == null ? void 0 : content.actionText
104
- }
105
- ),
106
- /* @__PURE__ */ jsx(
107
- Button,
108
- {
109
- className: css({
110
- w: "1/2"
111
- }),
112
- name: "cancel",
113
- onClick: handleChoice,
114
- usage: "outlined",
115
- value: "false",
116
- children: content == null ? void 0 : content.cancelText
117
- }
118
- )
119
- ]
120
- }
121
- )
122
- ] }) })
123
- ] });
124
- }
125
- function ConfirmModalIcon(props) {
126
- const InfoIcon = $cerberusIcons.confirmModal;
127
- return /* @__PURE__ */ jsx(
128
- Show,
129
- {
130
- when: props.palette === "danger",
131
- fallback: /* @__PURE__ */ jsx("div", { className: cx(confirmModal().icon, circle()), children: /* @__PURE__ */ jsx(InfoIcon, { size: 24 }) }),
132
- children: /* @__PURE__ */ jsx(
133
- "div",
134
- {
135
- className: cx(
136
- confirmModal({
137
- palette: "danger"
138
- }).icon,
139
- circle({
140
- bgColor: "danger.surface.initial"
141
- })
142
- ),
143
- style: {
144
- color: "var(--cerberus-colors-danger-text-100)"
145
- },
146
- children: /* @__PURE__ */ jsx(InfoIcon, { size: 24 })
147
- }
148
- )
149
- }
150
- );
151
- }
152
- function useConfirmModal() {
153
- const context = useContext(ConfirmModalContext);
154
- if (context === null) {
155
- throw new Error(
156
- "useConfirmModal must be used within a ConfirmModal Provider"
157
- );
158
- }
159
- return context;
160
- }
161
-
162
- export {
163
- ConfirmModal,
164
- ConfirmModalIcon,
165
- useConfirmModal
166
- };
167
- //# sourceMappingURL=chunk-BLJ4SRAF.js.map
@@ -1 +0,0 @@
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} from 'react'\nimport { Portal } from '../components/Portal'\nimport { Button } from '../components/Button'\nimport { css, cx } from '@cerberus-design/styled-system/css'\nimport { circle, hstack, vstack } from '@cerberus-design/styled-system/patterns'\nimport { $cerberusIcons } from '../config/defineIcons'\nimport {\n confirmModal,\n type ConfirmModalVariantProps,\n} from '@cerberus-design/styled-system/recipes'\nimport { trapFocus } from '../aria-helpers/trap-focus.aria'\nimport { Show } from '../components/Show'\n\n/**\n * This module provides a context and hook for the confirm modal.\n * @module\n */\n\nexport interface ShowConfirmModalOptions {\n kind?: 'destructive' | 'non-destructive'\n heading: string\n description?: string\n actionText: string\n cancelText: string\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 * @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 dialogRef = useRef<HTMLDialogElement>(null)\n const resolveRef = useRef<ShowResult>(null)\n const [content, setContent] = useState<ShowConfirmModalOptions | null>(null)\n const focusTrap = trapFocus(dialogRef)\n\n const palette = useMemo(\n () => (content?.kind === 'destructive' ? 'danger' : 'action'),\n [content],\n )\n const styles = confirmModal({ palette })\n\n const handleChoice = useCallback((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 dialogRef?.current?.close()\n }, [])\n\n const handleShow = useCallback((options: ShowConfirmModalOptions) => {\n return new Promise<boolean>((resolve) => {\n setContent({ ...options, kind: options.kind || 'non-destructive' })\n dialogRef?.current?.showModal()\n resolveRef.current = resolve\n })\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 <dialog className={styles.dialog} onKeyDown={focusTrap} ref={dialogRef}>\n <div\n className={vstack({\n alignItems: 'flex-start',\n gap: '4',\n mb: '8',\n })}\n >\n <ConfirmModalIcon palette={palette} />\n <h2 className={styles.heading}>{content?.heading}</h2>\n <p className={styles.description}>{content?.description}</p>\n </div>\n\n <div\n className={hstack({\n justifyContent: 'stretch',\n gap: '4',\n })}\n >\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 </div>\n </dialog>\n </Portal>\n </ConfirmModalContext.Provider>\n )\n}\n\n// This is to help show the variant styles for the icon since Panda is\n// not syncing correctly for the danger variant.\nexport function ConfirmModalIcon(props: ConfirmModalVariantProps) {\n const InfoIcon = $cerberusIcons.confirmModal\n return (\n <Show\n when={props.palette === 'danger'}\n fallback={\n <div className={cx(confirmModal().icon, circle())}>\n <InfoIcon size={24} />\n </div>\n }\n >\n <div\n className={cx(\n confirmModal({\n palette: 'danger',\n }).icon,\n circle({\n bgColor: 'danger.surface.initial',\n }),\n )}\n style={{\n color: 'var(--cerberus-colors-danger-text-100)',\n }}\n >\n <InfoIcon size={24} />\n </div>\n </Show>\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":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/context/prompt-modal.tsx"],"sourcesContent":["'use client'\n\nimport {\n createContext,\n useCallback,\n useContext,\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type MouseEvent,\n type PropsWithChildren,\n} from 'react'\nimport { Portal } from '../components/Portal'\nimport { Button } from '../components/Button'\nimport { css, cx } from '@cerberus-design/styled-system/css'\nimport { circle, hstack, vstack } from '@cerberus-design/styled-system/patterns'\nimport {\n confirmModal,\n type ConfirmModalVariantProps,\n} from '@cerberus-design/styled-system/recipes'\nimport { trapFocus } from '../aria-helpers/trap-focus.aria'\nimport { Input } from '../components/Input'\nimport { Field } from './field'\nimport { Label } from '../components/Label'\nimport { ConfirmModalIcon } from './confirm-modal'\nimport { $cerberusIcons } from '../config/defineIcons'\nimport { Show } from '../components/Show'\n\n/**\n * This module provides a context and hook for the prompt modal.\n * @module\n */\n\nexport interface ShowPromptModalOptions {\n kind?: 'destructive' | 'non-destructive'\n heading: string\n description?: string\n key: string\n actionText: string\n cancelText: string\n}\nexport type PromptShowResult =\n | ((value: string | PromiseLike<string>) => void)\n | null\n\nexport interface PromptModalValue {\n show: (options: ShowPromptModalOptions) => Promise<string>\n}\n\nconst PromptModalContext = createContext<PromptModalValue | null>(null)\n\nexport interface PromptModalProviderProps {}\n\n/**\n * Provides a prompt modal to the app.\n * @example\n * ```tsx\n * // Wrap the Provider around the root of the feature.\n * <PromptModal>\n * <SomeFeatureSection />\n * </PromptModal>\n *\n * // Use the hook to show the prompt modal.\n * const prompt = usePromptModal()\n *\n * const handleClick = useCallback(async () => {\n * const accepted = await prompt.show({\n * kind: 'destructive',\n * heading: 'Delete channel?',\n * description:\n * 'This will permanently delete a channel on your account. There is no going back.',\n * key: CHANNEL_NAME,\n * actionText: 'Yes, delete channel',\n * cancelText: 'No, cancel',\n * })\n * // do something with accepted\n * }, [prompt])\n * ```\n */\nexport function PromptModal(\n props: PropsWithChildren<PromptModalProviderProps>,\n) {\n const dialogRef = useRef<HTMLDialogElement>(null)\n const resolveRef = useRef<PromptShowResult>(null)\n const [content, setContent] = useState<ShowPromptModalOptions | null>(null)\n const [inputValue, setInputValue] = useState<string>('')\n const focusTrap = trapFocus(dialogRef)\n\n const isValid = useMemo(\n () => inputValue === content?.key,\n [inputValue, content],\n )\n\n const palette = useMemo(\n () => (content?.kind === 'destructive' ? 'danger' : 'action'),\n [content],\n )\n const styles = confirmModal({ palette })\n\n const handleChange = useCallback(\n (e: ChangeEvent<HTMLInputElement>) => {\n setInputValue(e.currentTarget.value)\n },\n [content],\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?.(inputValue)\n }\n dialogRef?.current?.close()\n },\n [inputValue],\n )\n\n const handleShow = useCallback((options: ShowPromptModalOptions) => {\n return new Promise<string>((resolve) => {\n setContent({ ...options, kind: options.kind || 'non-destructive' })\n dialogRef?.current?.showModal()\n resolveRef.current = resolve\n })\n }, [])\n\n const value = useMemo(\n () => ({\n show: handleShow,\n }),\n [handleShow],\n )\n\n return (\n <PromptModalContext.Provider value={value}>\n {props.children}\n\n <Portal>\n <dialog className={styles.dialog} onKeyDown={focusTrap} ref={dialogRef}>\n <div\n className={vstack({\n alignItems: 'flex-start',\n gap: '4',\n })}\n >\n <ConfirmModalIcon palette={palette} />\n <h2 className={styles.heading}>{content?.heading}</h2>\n <p className={styles.description}>{content?.description}</p>\n </div>\n\n <div\n className={vstack({\n alignItems: 'flex-start',\n mt: '4',\n mb: '8',\n })}\n >\n <Field invalid={!isValid}>\n <Label htmlFor=\"confirm\" size=\"md\">\n Type\n <strong\n className={css({\n textTransform: 'uppercase',\n })}\n >\n {content?.key}\n </strong>\n to confirm\n </Label>\n <Input\n id=\"confirm\"\n name=\"confirm\"\n onChange={handleChange}\n type=\"text\"\n />\n </Field>\n </div>\n\n <div\n className={hstack({\n justifyContent: 'stretch',\n gap: '4',\n })}\n >\n <Button\n autoFocus\n className={css({\n w: '1/2',\n })}\n disabled={!isValid}\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 </div>\n </dialog>\n </Portal>\n </PromptModalContext.Provider>\n )\n}\n\n// This is to help show the variant styles for the icon since Panda is\n// not syncing correctly for the danger variant.\nexport function PromptModalIcon(props: ConfirmModalVariantProps) {\n const PromptIcon = $cerberusIcons.promptModal\n return (\n <Show\n when={props.palette === 'danger'}\n fallback={\n <div className={cx(confirmModal().icon, circle())}>\n <PromptIcon size={24} />\n </div>\n }\n >\n <div\n className={cx(\n confirmModal({\n palette: 'danger',\n }).icon,\n circle({\n bgColor: 'danger.surface.initial',\n }),\n )}\n style={{\n color: 'var(--cerberus-colors-danger-text-100)',\n }}\n >\n <PromptIcon size={24} />\n </div>\n </Show>\n )\n}\n\nexport function usePromptModal(): PromptModalValue {\n const context = useContext(PromptModalContext)\n if (context === null) {\n throw new Error('usePromptModal must be used within a PromptModal Provider')\n }\n return context\n}\n"],"mappings":"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","names":[]}
@@ -1,165 +0,0 @@
1
- import {
2
- Portal
3
- } from "./chunk-4CAT3FHV.js";
4
- import {
5
- Button
6
- } from "./chunk-2ATICEW3.js";
7
- import {
8
- Show
9
- } from "./chunk-4O4QFF4S.js";
10
- import {
11
- trapFocus
12
- } from "./chunk-JIZQFTW6.js";
13
- import {
14
- $cerberusIcons
15
- } from "./chunk-6TXQZ3PB.js";
16
-
17
- // src/context/confirm-modal.tsx
18
- import {
19
- createContext,
20
- useCallback,
21
- useContext,
22
- useMemo,
23
- useRef,
24
- useState
25
- } from "react";
26
- import { css, cx } from "@cerberus-design/styled-system/css";
27
- import { circle, hstack, vstack } from "@cerberus-design/styled-system/patterns";
28
- import {
29
- confirmModal
30
- } from "@cerberus-design/styled-system/recipes";
31
- import { jsx, jsxs } from "react/jsx-runtime";
32
- var ConfirmModalContext = createContext(null);
33
- function ConfirmModal(props) {
34
- const dialogRef = useRef(null);
35
- const resolveRef = useRef(null);
36
- const [content, setContent] = useState(null);
37
- const focusTrap = trapFocus(dialogRef);
38
- const palette = useMemo(
39
- () => content?.kind === "destructive" ? "danger" : "action",
40
- [content]
41
- );
42
- const styles = confirmModal({ palette });
43
- const handleChoice = useCallback((e) => {
44
- const target = e.currentTarget;
45
- if (target.value === "true") {
46
- resolveRef.current?.(true);
47
- }
48
- resolveRef.current?.(false);
49
- dialogRef?.current?.close();
50
- }, []);
51
- const handleShow = useCallback((options) => {
52
- return new Promise((resolve) => {
53
- setContent({ ...options, kind: options.kind || "non-destructive" });
54
- dialogRef?.current?.showModal();
55
- resolveRef.current = resolve;
56
- });
57
- }, []);
58
- const value = useMemo(
59
- () => ({
60
- show: handleShow
61
- }),
62
- [handleShow]
63
- );
64
- return /* @__PURE__ */ jsxs(ConfirmModalContext.Provider, { value, children: [
65
- props.children,
66
- /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsxs("dialog", { className: styles.dialog, onKeyDown: focusTrap, ref: dialogRef, children: [
67
- /* @__PURE__ */ jsxs(
68
- "div",
69
- {
70
- className: vstack({
71
- alignItems: "flex-start",
72
- gap: "4",
73
- mb: "8"
74
- }),
75
- children: [
76
- /* @__PURE__ */ jsx(ConfirmModalIcon, { palette }),
77
- /* @__PURE__ */ jsx("h2", { className: styles.heading, children: content?.heading }),
78
- /* @__PURE__ */ jsx("p", { className: styles.description, children: content?.description })
79
- ]
80
- }
81
- ),
82
- /* @__PURE__ */ jsxs(
83
- "div",
84
- {
85
- className: hstack({
86
- justifyContent: "stretch",
87
- gap: "4"
88
- }),
89
- children: [
90
- /* @__PURE__ */ jsx(
91
- Button,
92
- {
93
- autoFocus: true,
94
- className: css({
95
- w: "1/2"
96
- }),
97
- name: "confirm",
98
- onClick: handleChoice,
99
- palette,
100
- value: "true",
101
- children: content?.actionText
102
- }
103
- ),
104
- /* @__PURE__ */ jsx(
105
- Button,
106
- {
107
- className: css({
108
- w: "1/2"
109
- }),
110
- name: "cancel",
111
- onClick: handleChoice,
112
- usage: "outlined",
113
- value: "false",
114
- children: content?.cancelText
115
- }
116
- )
117
- ]
118
- }
119
- )
120
- ] }) })
121
- ] });
122
- }
123
- function ConfirmModalIcon(props) {
124
- const InfoIcon = $cerberusIcons.confirmModal;
125
- return /* @__PURE__ */ jsx(
126
- Show,
127
- {
128
- when: props.palette === "danger",
129
- fallback: /* @__PURE__ */ jsx("div", { className: cx(confirmModal().icon, circle()), children: /* @__PURE__ */ jsx(InfoIcon, { size: 24 }) }),
130
- children: /* @__PURE__ */ jsx(
131
- "div",
132
- {
133
- className: cx(
134
- confirmModal({
135
- palette: "danger"
136
- }).icon,
137
- circle({
138
- bgColor: "danger.surface.initial"
139
- })
140
- ),
141
- style: {
142
- color: "var(--cerberus-colors-danger-text-100)"
143
- },
144
- children: /* @__PURE__ */ jsx(InfoIcon, { size: 24 })
145
- }
146
- )
147
- }
148
- );
149
- }
150
- function useConfirmModal() {
151
- const context = useContext(ConfirmModalContext);
152
- if (context === null) {
153
- throw new Error(
154
- "useConfirmModal must be used within a ConfirmModal Provider"
155
- );
156
- }
157
- return context;
158
- }
159
-
160
- export {
161
- ConfirmModal,
162
- ConfirmModalIcon,
163
- useConfirmModal
164
- };
165
- //# sourceMappingURL=chunk-4GURONLE.js.map
@@ -1 +0,0 @@
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} from 'react'\nimport { Portal } from '../components/Portal'\nimport { Button } from '../components/Button'\nimport { css, cx } from '@cerberus-design/styled-system/css'\nimport { circle, hstack, vstack } from '@cerberus-design/styled-system/patterns'\nimport { $cerberusIcons } from '../config/defineIcons'\nimport {\n confirmModal,\n type ConfirmModalVariantProps,\n} from '@cerberus-design/styled-system/recipes'\nimport { trapFocus } from '../aria-helpers/trap-focus.aria'\nimport { Show } from '../components/Show'\n\n/**\n * This module provides a context and hook for the confirm modal.\n * @module\n */\n\nexport interface ShowConfirmModalOptions {\n kind?: 'destructive' | 'non-destructive'\n heading: string\n description?: string\n actionText: string\n cancelText: string\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 * @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 dialogRef = useRef<HTMLDialogElement>(null)\n const resolveRef = useRef<ShowResult>(null)\n const [content, setContent] = useState<ShowConfirmModalOptions | null>(null)\n const focusTrap = trapFocus(dialogRef)\n\n const palette = useMemo(\n () => (content?.kind === 'destructive' ? 'danger' : 'action'),\n [content],\n )\n const styles = confirmModal({ palette })\n\n const handleChoice = useCallback((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 dialogRef?.current?.close()\n }, [])\n\n const handleShow = useCallback((options: ShowConfirmModalOptions) => {\n return new Promise<boolean>((resolve) => {\n setContent({ ...options, kind: options.kind || 'non-destructive' })\n dialogRef?.current?.showModal()\n resolveRef.current = resolve\n })\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 <dialog className={styles.dialog} onKeyDown={focusTrap} ref={dialogRef}>\n <div\n className={vstack({\n alignItems: 'flex-start',\n gap: '4',\n mb: '8',\n })}\n >\n <ConfirmModalIcon palette={palette} />\n <h2 className={styles.heading}>{content?.heading}</h2>\n <p className={styles.description}>{content?.description}</p>\n </div>\n\n <div\n className={hstack({\n justifyContent: 'stretch',\n gap: '4',\n })}\n >\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 </div>\n </dialog>\n </Portal>\n </ConfirmModalContext.Provider>\n )\n}\n\n// This is to help show the variant styles for the icon since Panda is\n// not syncing correctly for the danger variant.\nexport function ConfirmModalIcon(props: ConfirmModalVariantProps) {\n const InfoIcon = $cerberusIcons.confirmModal\n return (\n <Show\n when={props.palette === 'danger'}\n fallback={\n <div className={cx(confirmModal().icon, circle())}>\n <InfoIcon size={24} />\n </div>\n }\n >\n <div\n className={cx(\n confirmModal({\n palette: 'danger',\n }).icon,\n circle({\n bgColor: 'danger.surface.initial',\n }),\n )}\n style={{\n color: 'var(--cerberus-colors-danger-text-100)',\n }}\n >\n <InfoIcon size={24} />\n </div>\n </Show>\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":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/context/prompt-modal.tsx"],"sourcesContent":["'use client'\n\nimport {\n createContext,\n useCallback,\n useContext,\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type MouseEvent,\n type PropsWithChildren,\n} from 'react'\nimport { Portal } from '../components/Portal'\nimport { Button } from '../components/Button'\nimport { css, cx } from '@cerberus-design/styled-system/css'\nimport { circle, hstack, vstack } from '@cerberus-design/styled-system/patterns'\nimport {\n confirmModal,\n type ConfirmModalVariantProps,\n} from '@cerberus-design/styled-system/recipes'\nimport { trapFocus } from '../aria-helpers/trap-focus.aria'\nimport { Input } from '../components/Input'\nimport { Field } from './field'\nimport { Label } from '../components/Label'\nimport { ConfirmModalIcon } from './confirm-modal'\nimport { $cerberusIcons } from '../config/defineIcons'\nimport { Show } from '../components/Show'\n\n/**\n * This module provides a context and hook for the prompt modal.\n * @module\n */\n\nexport interface ShowPromptModalOptions {\n kind?: 'destructive' | 'non-destructive'\n heading: string\n description?: string\n key: string\n actionText: string\n cancelText: string\n}\nexport type PromptShowResult =\n | ((value: string | PromiseLike<string>) => void)\n | null\n\nexport interface PromptModalValue {\n show: (options: ShowPromptModalOptions) => Promise<string>\n}\n\nconst PromptModalContext = createContext<PromptModalValue | null>(null)\n\nexport interface PromptModalProviderProps {}\n\n/**\n * Provides a prompt modal to the app.\n * @example\n * ```tsx\n * // Wrap the Provider around the root of the feature.\n * <PromptModal>\n * <SomeFeatureSection />\n * </PromptModal>\n *\n * // Use the hook to show the prompt modal.\n * const prompt = usePromptModal()\n *\n * const handleClick = useCallback(async () => {\n * const accepted = await prompt.show({\n * kind: 'destructive',\n * heading: 'Delete channel?',\n * description:\n * 'This will permanently delete a channel on your account. There is no going back.',\n * key: CHANNEL_NAME,\n * actionText: 'Yes, delete channel',\n * cancelText: 'No, cancel',\n * })\n * // do something with accepted\n * }, [prompt])\n * ```\n */\nexport function PromptModal(\n props: PropsWithChildren<PromptModalProviderProps>,\n) {\n const dialogRef = useRef<HTMLDialogElement>(null)\n const resolveRef = useRef<PromptShowResult>(null)\n const [content, setContent] = useState<ShowPromptModalOptions | null>(null)\n const [inputValue, setInputValue] = useState<string>('')\n const focusTrap = trapFocus(dialogRef)\n\n const isValid = useMemo(\n () => inputValue === content?.key,\n [inputValue, content],\n )\n\n const palette = useMemo(\n () => (content?.kind === 'destructive' ? 'danger' : 'action'),\n [content],\n )\n const styles = confirmModal({ palette })\n\n const handleChange = useCallback(\n (e: ChangeEvent<HTMLInputElement>) => {\n setInputValue(e.currentTarget.value)\n },\n [content],\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?.(inputValue)\n }\n dialogRef?.current?.close()\n },\n [inputValue],\n )\n\n const handleShow = useCallback((options: ShowPromptModalOptions) => {\n return new Promise<string>((resolve) => {\n setContent({ ...options, kind: options.kind || 'non-destructive' })\n dialogRef?.current?.showModal()\n resolveRef.current = resolve\n })\n }, [])\n\n const value = useMemo(\n () => ({\n show: handleShow,\n }),\n [handleShow],\n )\n\n return (\n <PromptModalContext.Provider value={value}>\n {props.children}\n\n <Portal>\n <dialog className={styles.dialog} onKeyDown={focusTrap} ref={dialogRef}>\n <div\n className={vstack({\n alignItems: 'flex-start',\n gap: '4',\n })}\n >\n <ConfirmModalIcon palette={palette} />\n <h2 className={styles.heading}>{content?.heading}</h2>\n <p className={styles.description}>{content?.description}</p>\n </div>\n\n <div\n className={vstack({\n alignItems: 'flex-start',\n mt: '4',\n mb: '8',\n })}\n >\n <Field invalid={!isValid}>\n <Label htmlFor=\"confirm\" size=\"md\">\n Type\n <strong\n className={css({\n textTransform: 'uppercase',\n })}\n >\n {content?.key}\n </strong>\n to confirm\n </Label>\n <Input\n id=\"confirm\"\n name=\"confirm\"\n onChange={handleChange}\n type=\"text\"\n />\n </Field>\n </div>\n\n <div\n className={hstack({\n justifyContent: 'stretch',\n gap: '4',\n })}\n >\n <Button\n autoFocus\n className={css({\n w: '1/2',\n })}\n disabled={!isValid}\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 </div>\n </dialog>\n </Portal>\n </PromptModalContext.Provider>\n )\n}\n\n// This is to help show the variant styles for the icon since Panda is\n// not syncing correctly for the danger variant.\nexport function PromptModalIcon(props: ConfirmModalVariantProps) {\n const PromptIcon = $cerberusIcons.promptModal\n return (\n <Show\n when={props.palette === 'danger'}\n fallback={\n <div className={cx(confirmModal().icon, circle())}>\n <PromptIcon size={24} />\n </div>\n }\n >\n <div\n className={cx(\n confirmModal({\n palette: 'danger',\n }).icon,\n circle({\n bgColor: 'danger.surface.initial',\n }),\n )}\n style={{\n color: 'var(--cerberus-colors-danger-text-100)',\n }}\n >\n <PromptIcon size={24} />\n </div>\n </Show>\n )\n}\n\nexport function usePromptModal(): PromptModalValue {\n const context = useContext(PromptModalContext)\n if (context === null) {\n throw new Error('usePromptModal must be used within a PromptModal Provider')\n }\n return context\n}\n"],"mappings":"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","names":[]}