@cerberus-design/react 0.11.1-next-2ed68bd → 0.11.1-next-c28b077

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 (100) hide show
  1. package/build/legacy/_tsup-dts-rollup.d.cts +79 -0
  2. package/build/legacy/components/Admonition.cjs +1 -1
  3. package/build/legacy/components/Admonition.cjs.map +1 -1
  4. package/build/legacy/components/Avatar.cjs +1 -1
  5. package/build/legacy/components/Avatar.cjs.map +1 -1
  6. package/build/legacy/components/Checkbox.cjs +1 -1
  7. package/build/legacy/components/Checkbox.cjs.map +1 -1
  8. package/build/legacy/components/FileStatus.cjs +1 -1
  9. package/build/legacy/components/FileStatus.cjs.map +1 -1
  10. package/build/legacy/components/FileUploader.cjs +1 -1
  11. package/build/legacy/components/FileUploader.cjs.map +1 -1
  12. package/build/legacy/components/Input.cjs +1 -1
  13. package/build/legacy/components/Input.cjs.map +1 -1
  14. package/build/legacy/components/ModalHeader.cjs +2 -1
  15. package/build/legacy/components/ModalHeader.cjs.map +1 -1
  16. package/build/legacy/components/Notification.cjs +3 -3
  17. package/build/legacy/components/Notification.cjs.map +1 -1
  18. package/build/legacy/components/Select.cjs +1 -1
  19. package/build/legacy/components/Select.cjs.map +1 -1
  20. package/build/legacy/components/Tag.cjs +3 -3
  21. package/build/legacy/components/Tag.cjs.map +1 -1
  22. package/build/legacy/components/Toggle.cjs +1 -1
  23. package/build/legacy/components/Toggle.cjs.map +1 -1
  24. package/build/legacy/config/cerbIcons.cjs +1 -1
  25. package/build/legacy/config/cerbIcons.cjs.map +1 -1
  26. package/build/legacy/config/defineIcons.cjs +1 -1
  27. package/build/legacy/config/defineIcons.cjs.map +1 -1
  28. package/build/legacy/context/confirm-modal.cjs +3 -2
  29. package/build/legacy/context/confirm-modal.cjs.map +1 -1
  30. package/build/legacy/context/cta-modal.cjs +567 -0
  31. package/build/legacy/context/cta-modal.cjs.map +1 -0
  32. package/build/legacy/context/notification-center.cjs +3 -3
  33. package/build/legacy/context/notification-center.cjs.map +1 -1
  34. package/build/legacy/context/prompt-modal.cjs +3 -2
  35. package/build/legacy/context/prompt-modal.cjs.map +1 -1
  36. package/build/legacy/index.cjs +201 -88
  37. package/build/legacy/index.cjs.map +1 -1
  38. package/build/modern/_tsup-dts-rollup.d.ts +79 -0
  39. package/build/modern/{chunk-RDQHHCFR.js → chunk-5OSUZUR4.js} +2 -2
  40. package/build/modern/{chunk-KLUBAM4U.js → chunk-7SGPJM66.js} +4 -4
  41. package/build/modern/chunk-7SGPJM66.js.map +1 -0
  42. package/build/modern/{chunk-3NE6C66J.js → chunk-C7UVOGPZ.js} +5 -5
  43. package/build/modern/{chunk-TMR7JGMP.js → chunk-F27AAKQ3.js} +3 -3
  44. package/build/modern/chunk-F27AAKQ3.js.map +1 -0
  45. package/build/modern/{chunk-BOCAJC3S.js → chunk-F72ZABKX.js} +2 -2
  46. package/build/modern/chunk-JVIFMN67.js +155 -0
  47. package/build/modern/chunk-JVIFMN67.js.map +1 -0
  48. package/build/modern/{chunk-KF6V5JLW.js → chunk-N4QTLDVM.js} +3 -3
  49. package/build/modern/{chunk-MDIUFBDX.js → chunk-NB6DV4VA.js} +2 -2
  50. package/build/modern/{chunk-UJKS4DDN.js → chunk-NKM6PISB.js} +2 -2
  51. package/build/modern/{chunk-YWCTMLLO.js → chunk-NMNONSHU.js} +2 -2
  52. package/build/modern/{chunk-X4Y4WTRU.js → chunk-PJGUYNKD.js} +4 -4
  53. package/build/modern/{chunk-ZX6DBC2Z.js → chunk-SPZYPRZ6.js} +2 -2
  54. package/build/modern/{chunk-FT7DFRHQ.js → chunk-VERRHMW4.js} +2 -2
  55. package/build/modern/{chunk-HCB5NQ5J.js → chunk-W4DXACNV.js} +3 -3
  56. package/build/modern/{chunk-PA5EB7EO.js → chunk-XL4JREDT.js} +2 -2
  57. package/build/modern/{chunk-6EJXHRAP.js → chunk-ZBMA5G54.js} +3 -3
  58. package/build/modern/{chunk-ULYQLKWA.js → chunk-ZFAIE47A.js} +3 -2
  59. package/build/modern/{chunk-ULYQLKWA.js.map → chunk-ZFAIE47A.js.map} +1 -1
  60. package/build/modern/components/Admonition.js +4 -4
  61. package/build/modern/components/Avatar.js +3 -3
  62. package/build/modern/components/Checkbox.js +3 -3
  63. package/build/modern/components/FileStatus.js +4 -4
  64. package/build/modern/components/FileUploader.js +4 -4
  65. package/build/modern/components/Input.js +3 -3
  66. package/build/modern/components/ModalHeader.js +1 -1
  67. package/build/modern/components/Notification.js +3 -3
  68. package/build/modern/components/Select.js +3 -3
  69. package/build/modern/components/Tag.js +3 -3
  70. package/build/modern/components/Toggle.js +3 -3
  71. package/build/modern/config/cerbIcons.js +1 -1
  72. package/build/modern/config/defineIcons.js +2 -2
  73. package/build/modern/context/confirm-modal.js +5 -5
  74. package/build/modern/context/cta-modal.js +25 -0
  75. package/build/modern/context/cta-modal.js.map +1 -0
  76. package/build/modern/context/notification-center.js +4 -4
  77. package/build/modern/context/prompt-modal.js +6 -6
  78. package/build/modern/index.js +22 -16
  79. package/build/modern/index.js.map +1 -1
  80. package/package.json +2 -2
  81. package/src/components/ModalHeader.tsx +1 -0
  82. package/src/components/Notification.tsx +2 -2
  83. package/src/config/cerbIcons.ts +2 -2
  84. package/src/context/cta-modal.tsx +210 -0
  85. package/src/index.ts +1 -0
  86. package/build/modern/chunk-KLUBAM4U.js.map +0 -1
  87. package/build/modern/chunk-TMR7JGMP.js.map +0 -1
  88. /package/build/modern/{chunk-RDQHHCFR.js.map → chunk-5OSUZUR4.js.map} +0 -0
  89. /package/build/modern/{chunk-3NE6C66J.js.map → chunk-C7UVOGPZ.js.map} +0 -0
  90. /package/build/modern/{chunk-BOCAJC3S.js.map → chunk-F72ZABKX.js.map} +0 -0
  91. /package/build/modern/{chunk-KF6V5JLW.js.map → chunk-N4QTLDVM.js.map} +0 -0
  92. /package/build/modern/{chunk-MDIUFBDX.js.map → chunk-NB6DV4VA.js.map} +0 -0
  93. /package/build/modern/{chunk-UJKS4DDN.js.map → chunk-NKM6PISB.js.map} +0 -0
  94. /package/build/modern/{chunk-YWCTMLLO.js.map → chunk-NMNONSHU.js.map} +0 -0
  95. /package/build/modern/{chunk-X4Y4WTRU.js.map → chunk-PJGUYNKD.js.map} +0 -0
  96. /package/build/modern/{chunk-ZX6DBC2Z.js.map → chunk-SPZYPRZ6.js.map} +0 -0
  97. /package/build/modern/{chunk-FT7DFRHQ.js.map → chunk-VERRHMW4.js.map} +0 -0
  98. /package/build/modern/{chunk-HCB5NQ5J.js.map → chunk-W4DXACNV.js.map} +0 -0
  99. /package/build/modern/{chunk-PA5EB7EO.js.map → chunk-XL4JREDT.js.map} +0 -0
  100. /package/build/modern/{chunk-6EJXHRAP.js.map → chunk-ZBMA5G54.js.map} +0 -0
@@ -0,0 +1,210 @@
1
+ 'use client'
2
+
3
+ import {
4
+ createContext,
5
+ useCallback,
6
+ useContext,
7
+ useMemo,
8
+ useState,
9
+ type ButtonHTMLAttributes,
10
+ type MouseEvent,
11
+ type PropsWithChildren,
12
+ type ReactNode,
13
+ } from 'react'
14
+ import { Portal } from '../components/Portal'
15
+ import { Button } from '../components/Button'
16
+ import { $cerberusIcons } from '../config/defineIcons'
17
+ import { trapFocus } from '../aria-helpers/trap-focus.aria'
18
+ import { Show } from '../components/Show'
19
+ import { Modal } from '../components/Modal'
20
+ import { useModal } from '../hooks/useModal'
21
+ import { ModalHeader } from '../components/ModalHeader'
22
+ import { ModalHeading } from '../components/ModalHeading'
23
+ import { ModalDescription } from '../components/ModalDescription'
24
+ import { Avatar } from '../components/Avatar'
25
+ import { HStack } from '@cerberus/styled-system/jsx'
26
+ import { IconButton } from '../components/IconButton'
27
+ import { css } from '@cerberus/styled-system/css'
28
+ import { VStack } from '@cerberus/styled-system/jsx'
29
+
30
+ /**
31
+ * This module provides a context and hook for the cta modal.
32
+ * @module
33
+ */
34
+
35
+ export interface ShowCTAModalOptions {
36
+ /**
37
+ * The heading of the cta modal.
38
+ */
39
+ heading: string
40
+ /**
41
+ * The description of the cta modal.
42
+ */
43
+ description?: string
44
+ /**
45
+ * The icon used for the modal Avatar.
46
+ */
47
+ icon?: ReactNode
48
+ /**
49
+ * The actions for the cta modal. Max of 2 actions.
50
+ */
51
+ actions: {
52
+ text: string
53
+ onClick: Required<ButtonHTMLAttributes<HTMLButtonElement>['onClick']>
54
+ }[]
55
+ }
56
+
57
+ export interface CTAModalValue {
58
+ show: (options: ShowCTAModalOptions) => void
59
+ }
60
+
61
+ const CTAModalContext = createContext<CTAModalValue | null>(null)
62
+
63
+ export interface CTAModalProviderProps {}
64
+
65
+ /**
66
+ * Provides a CTA modal to the app.
67
+ * @see https://cerberus.digitalu.design/react/cta-modal
68
+ * @example
69
+ * ```tsx
70
+ * // Wrap the Provider around the root of the feature.
71
+ * <CTAModal>
72
+ * <SomeFeatureSection />
73
+ * </CTAModal>
74
+ *
75
+ * // Use the hook to show the cta modal.
76
+ * const cta = useCTAModal()
77
+ *
78
+ * const handleClick = useCallback(async () => {
79
+ * const userConsent = await cta.show({
80
+ * heading: 'Create or copy a Cohort',
81
+ * description:
82
+ * 'Create a new cohort or copy and existing one.',
83
+ * icon: <Copy size={24} />,
84
+ * actions: [
85
+ * {
86
+ * text: 'Create Cohort',
87
+ * onClick: () => {},
88
+ * {
89
+ * text: 'Copy Cohort',
90
+ * onClick: () => {}
91
+ * }
92
+ * })
93
+ * setConsent(userConsent)
94
+ * }, [cta])
95
+ * ```
96
+ */
97
+ export function CTAModal(props: PropsWithChildren<CTAModalProviderProps>) {
98
+ const { modalRef, show, close } = useModal()
99
+ const [content, setContent] = useState<ShowCTAModalOptions | null>(null)
100
+ const focusTrap = trapFocus(modalRef)
101
+ const FallbackIcon = $cerberusIcons.confirmModal
102
+ const confirmIcon = content?.icon as ReactNode
103
+ const { close: CloseIcon } = $cerberusIcons
104
+
105
+ const handleShow = useCallback(
106
+ (options: ShowCTAModalOptions) => {
107
+ const maxActions = 2
108
+ if (options.actions.length > maxActions) {
109
+ throw new Error(
110
+ `CTA Modal only supports a maximum of ${maxActions} actions.`,
111
+ )
112
+ }
113
+ setContent({ ...options })
114
+ show()
115
+ },
116
+ [show],
117
+ )
118
+
119
+ const handleActionClick = useCallback(
120
+ (event: MouseEvent<HTMLButtonElement>) => {
121
+ const index = event.currentTarget.getAttribute('data-index')
122
+ const action = content?.actions[Number(index)]
123
+ if (typeof action?.onClick === 'function') {
124
+ action.onClick(event)
125
+ }
126
+ close()
127
+ },
128
+ [content, close],
129
+ )
130
+
131
+ const value = useMemo(
132
+ () => ({
133
+ show: handleShow,
134
+ }),
135
+ [handleShow],
136
+ )
137
+
138
+ return (
139
+ <CTAModalContext.Provider value={value}>
140
+ {props.children}
141
+
142
+ <Portal>
143
+ <Modal onKeyDown={focusTrap} ref={modalRef}>
144
+ <span
145
+ className={css({
146
+ padding: 'md',
147
+ position: 'absolute',
148
+ right: 0,
149
+ top: 0,
150
+ zIndex: 'decorator',
151
+ })}
152
+ >
153
+ <IconButton ariaLabel="Close modal" onClick={close}>
154
+ <CloseIcon />
155
+ </IconButton>
156
+ </span>
157
+
158
+ <ModalHeader>
159
+ <HStack justify="center" w="full">
160
+ <Avatar
161
+ ariaLabel=""
162
+ gradient="charon-light"
163
+ icon={
164
+ <Show
165
+ when={Boolean(confirmIcon)}
166
+ fallback={<FallbackIcon size={24} />}
167
+ >
168
+ {confirmIcon}
169
+ </Show>
170
+ }
171
+ src=""
172
+ />
173
+ </HStack>
174
+ <VStack gap="lg" w="full">
175
+ <ModalHeading>{content?.heading}</ModalHeading>
176
+ <ModalDescription>{content?.description}</ModalDescription>
177
+ </VStack>
178
+ </ModalHeader>
179
+
180
+ <HStack gap="md" pt="sm" w="full">
181
+ <Show when={Boolean(content?.actions?.length)}>
182
+ {content?.actions?.map((action, index) => (
183
+ <Button
184
+ data-index={index}
185
+ className={css({
186
+ w: '1/2',
187
+ })}
188
+ key={index}
189
+ onClick={handleActionClick}
190
+ shape="rounded"
191
+ usage="outlined"
192
+ >
193
+ {action.text}
194
+ </Button>
195
+ ))}
196
+ </Show>
197
+ </HStack>
198
+ </Modal>
199
+ </Portal>
200
+ </CTAModalContext.Provider>
201
+ )
202
+ }
203
+
204
+ export function useCTAModal(): CTAModalValue {
205
+ const context = useContext(CTAModalContext)
206
+ if (context === null) {
207
+ throw new Error('useCTAModal must be used within a CTAModal Provider')
208
+ }
209
+ return context
210
+ }
package/src/index.ts CHANGED
@@ -52,6 +52,7 @@ export * from './components/Show'
52
52
  // context
53
53
 
54
54
  export * from './context/confirm-modal'
55
+ export * from './context/cta-modal'
55
56
  export * from './context/feature-flags'
56
57
  export * from './context/field'
57
58
  export * from './context/navMenu'
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/components/Notification.tsx"],"sourcesContent":["'use client'\n\nimport { cx } from '@cerberus/styled-system/css'\nimport { hstack, vstack } from '@cerberus/styled-system/patterns'\nimport {\n notification,\n type NotificationVariantProps,\n} from '@cerberus/styled-system/recipes'\nimport {\n useRef,\n type DialogHTMLAttributes,\n type PropsWithChildren,\n type MouseEvent,\n} from 'react'\nimport { Close } from '@cerberus/icons'\nimport { $cerberusIcons } from '../config/defineIcons'\nimport type { IconType } from '../config/cerbIcons'\nimport { trapFocus } from '../aria-helpers/trap-focus.aria'\n\n/**\n * This module exports the Notification component.\n * @module\n */\n\nfunction MatchNotificationIcon(props: NotificationVariantProps) {\n const palette = props.palette || 'info'\n const key = `${palette}Notification` as keyof typeof $cerberusIcons\n const Icon = $cerberusIcons[key] as IconType\n return <Icon />\n}\n\nexport interface NotificationBaseProps\n extends Omit<DialogHTMLAttributes<HTMLDialogElement>, 'onClose'> {\n /**\n * The unique id of the notification. Required for the onClose callback.\n */\n id: string\n /**\n * Called when the close button is clicked.\n */\n onClose?: (e: MouseEvent<HTMLButtonElement>) => void\n}\nexport type NotificationProps = NotificationBaseProps & NotificationVariantProps\n\n/**\n * A static Notification component that displays a message to the user. This\n * is typically only used when not utilizing the NotificationCenter.\n * @see https://cerberus.digitalu.design/react/notification\n * @memberof module:NotificationCenter\n * @example\n * ```tsx\n * <Notification id=\"info:1\" open>\n * <NotificationHeading>Info Notification</NotificationHeading>\n * <NotificationDescription>\n * This is a description with a <a href=\"#\">link</a> in the message.\n * </NotificationDescription>\n * </Notification>\n * ```\n */\nexport function Notification(props: PropsWithChildren<NotificationProps>) {\n const { children, palette, onClose, ...nativeProps } = props\n const ref = useRef<HTMLDialogElement>(null)\n const onKeyDown = trapFocus(ref)\n const styles = notification({ palette })\n\n return (\n <dialog\n {...nativeProps}\n className={cx(\n nativeProps.className,\n hstack({\n position: 'relative',\n gap: '4',\n }),\n styles.dialog,\n )}\n onKeyDown={onKeyDown}\n ref={ref}\n >\n <span className={styles.icon}>\n <MatchNotificationIcon palette={palette} />\n </span>\n\n <div\n className={vstack({\n alignItems: 'flex-start',\n gap: '0',\n py: '2',\n })}\n >\n {children}\n </div>\n\n <button\n aria-label=\"Close\"\n className={styles.close}\n onClick={onClose}\n value={props.id}\n >\n <Close />\n </button>\n </dialog>\n )\n}\n"],"mappings":";;;;;;;;AAEA,SAAS,UAAU;AACnB,SAAS,QAAQ,cAAc;AAC/B;AAAA,EACE;AAAA,OAEK;AACP;AAAA,EACE;AAAA,OAIK;AACP,SAAS,aAAa;AAcb,cAsCL,YAtCK;AAJT,SAAS,sBAAsB,OAAiC;AAC9D,QAAM,UAAU,MAAM,WAAW;AACjC,QAAM,MAAM,GAAG,OAAO;AACtB,QAAM,OAAO,eAAe,GAAG;AAC/B,SAAO,oBAAC,QAAK;AACf;AA8BO,SAAS,aAAa,OAA6C;AACxE,QAAM,EAAE,UAAU,SAAS,SAAS,GAAG,YAAY,IAAI;AACvD,QAAM,MAAM,OAA0B,IAAI;AAC1C,QAAM,YAAY,UAAU,GAAG;AAC/B,QAAM,SAAS,aAAa,EAAE,QAAQ,CAAC;AAEvC,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ,WAAW;AAAA,QACT,YAAY;AAAA,QACZ,OAAO;AAAA,UACL,UAAU;AAAA,UACV,KAAK;AAAA,QACP,CAAC;AAAA,QACD,OAAO;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MAEA;AAAA,4BAAC,UAAK,WAAW,OAAO,MACtB,8BAAC,yBAAsB,SAAkB,GAC3C;AAAA,QAEA;AAAA,UAAC;AAAA;AAAA,YACC,WAAW,OAAO;AAAA,cAChB,YAAY;AAAA,cACZ,KAAK;AAAA,cACL,IAAI;AAAA,YACN,CAAC;AAAA,YAEA;AAAA;AAAA,QACH;AAAA,QAEA;AAAA,UAAC;AAAA;AAAA,YACC,cAAW;AAAA,YACX,WAAW,OAAO;AAAA,YAClB,SAAS;AAAA,YACT,OAAO,MAAM;AAAA,YAEb,8BAAC,SAAM;AAAA;AAAA,QACT;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/config/cerbIcons.ts"],"sourcesContent":["import {\n Checkmark,\n CheckmarkOutline,\n ChevronDown,\n CloseFilled,\n CloudUpload,\n Information,\n Restart,\n TrashCan,\n UserFilled,\n Warning,\n WarningAlt,\n WarningFilled,\n type CarbonIconType,\n} from '@cerberus/icons'\nimport type { ElementType } from 'react'\nimport { CheckmarkIcon, IndeterminateIcon } from './icons/checkbox.icons'\nimport { AnimatingUploadIcon } from '../components/AnimatingUploadIcon'\n\nexport type IconType = CarbonIconType | ElementType\n\nexport interface DefinedIcons {\n avatar?: IconType\n checkbox?: IconType\n close?: IconType\n confirmModal?: IconType\n delete?: IconType\n promptModal?: IconType\n waitingFileUploader?: IconType\n fileUploader?: IconType\n indeterminate?: IconType\n infoNotification?: IconType\n successNotification?: IconType\n warningNotification?: IconType\n dangerNotification?: IconType\n invalid: IconType\n invalidAlt?: IconType\n redo?: IconType\n selectArrow?: IconType\n toggleChecked?: IconType\n}\n\nexport const defaultIcons: DefinedIcons = {\n avatar: UserFilled,\n checkbox: CheckmarkIcon,\n close: CloseFilled,\n confirmModal: Information,\n delete: TrashCan,\n promptModal: Information,\n waitingFileUploader: CloudUpload,\n fileUploader: AnimatingUploadIcon,\n indeterminate: IndeterminateIcon,\n infoNotification: Information,\n successNotification: CheckmarkOutline,\n warningNotification: WarningAlt,\n dangerNotification: WarningFilled,\n invalid: WarningFilled,\n invalidAlt: Warning,\n redo: Restart,\n selectArrow: ChevronDown,\n toggleChecked: Checkmark,\n}\n"],"mappings":";;;;;;;;;AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AA4BA,IAAM,eAA6B;AAAA,EACxC,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,OAAO;AAAA,EACP,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,aAAa;AAAA,EACb,qBAAqB;AAAA,EACrB,cAAc;AAAA,EACd,eAAe;AAAA,EACf,kBAAkB;AAAA,EAClB,qBAAqB;AAAA,EACrB,qBAAqB;AAAA,EACrB,oBAAoB;AAAA,EACpB,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,aAAa;AAAA,EACb,eAAe;AACjB;","names":[]}