@cerberus-design/react 0.6.1-next-0345599 → 0.6.1-next-1315bf2

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 (108) hide show
  1. package/build/legacy/_tsup-dts-rollup.d.ts +147 -3
  2. package/build/legacy/aria-helpers/trap-focus.aria.js +7 -0
  3. package/build/legacy/aria-helpers/trap-focus.aria.js.map +1 -0
  4. package/build/legacy/{chunk-3CBN7U25.js → chunk-3TYUA4C7.js} +6 -3
  5. package/build/legacy/chunk-3TYUA4C7.js.map +1 -0
  6. package/build/legacy/chunk-4CAT3FHV.js +11 -0
  7. package/build/legacy/chunk-4CAT3FHV.js.map +1 -0
  8. package/build/legacy/chunk-4M3EUP57.js +22 -0
  9. package/build/legacy/chunk-4M3EUP57.js.map +1 -0
  10. package/build/{modern/chunk-X4YQ27D5.js → legacy/chunk-5RA3ZIXA.js} +2 -2
  11. package/build/legacy/{chunk-5XNLWIZO.js → chunk-EVEEQRH6.js} +2 -2
  12. package/build/legacy/chunk-EVEEQRH6.js.map +1 -0
  13. package/build/{modern/chunk-HE3HFKYU.js → legacy/chunk-JJGZRBIR.js} +2 -2
  14. package/build/legacy/{chunk-HE3HFKYU.js.map → chunk-JJGZRBIR.js.map} +1 -1
  15. package/build/legacy/chunk-KESKDLX6.js +30 -0
  16. package/build/legacy/chunk-KESKDLX6.js.map +1 -0
  17. package/build/{modern/chunk-G2QMBSK5.js → legacy/chunk-PMCYXRAH.js} +2 -2
  18. package/build/legacy/chunk-PMCYXRAH.js.map +1 -0
  19. package/build/legacy/chunk-SCAVVE6E.js +16 -0
  20. package/build/legacy/chunk-SCAVVE6E.js.map +1 -0
  21. package/build/legacy/{chunk-734PGVLT.js → chunk-VLVKNEA5.js} +2 -2
  22. package/build/legacy/chunk-VULPMZUW.js +18 -0
  23. package/build/legacy/chunk-VULPMZUW.js.map +1 -0
  24. package/build/legacy/chunk-YRUUO4AP.js +166 -0
  25. package/build/legacy/chunk-YRUUO4AP.js.map +1 -0
  26. package/build/legacy/components/FeatureFlag.js +10 -0
  27. package/build/legacy/components/FeatureFlag.js.map +1 -0
  28. package/build/legacy/components/Input.js +3 -3
  29. package/build/legacy/components/Label.js +1 -1
  30. package/build/legacy/components/NavMenuList.js +1 -1
  31. package/build/legacy/components/Portal.js +7 -0
  32. package/build/legacy/components/Portal.js.map +1 -0
  33. package/build/legacy/components/Tag.js +1 -1
  34. package/build/legacy/components/Toggle.js +3 -3
  35. package/build/legacy/config/cerbIcons.js +1 -1
  36. package/build/legacy/config/defineIcons.js +2 -2
  37. package/build/legacy/context/confirm-modal.js +16 -0
  38. package/build/legacy/context/confirm-modal.js.map +1 -0
  39. package/build/legacy/context/feature-flags.js +10 -0
  40. package/build/legacy/context/feature-flags.js.map +1 -0
  41. package/build/legacy/index.js +50 -26
  42. package/build/modern/_tsup-dts-rollup.d.ts +147 -3
  43. package/build/modern/aria-helpers/trap-focus.aria.js +7 -0
  44. package/build/modern/aria-helpers/trap-focus.aria.js.map +1 -0
  45. package/build/modern/{chunk-3CBN7U25.js → chunk-3TYUA4C7.js} +6 -3
  46. package/build/modern/chunk-3TYUA4C7.js.map +1 -0
  47. package/build/modern/chunk-4CAT3FHV.js +11 -0
  48. package/build/modern/chunk-4CAT3FHV.js.map +1 -0
  49. package/build/modern/chunk-4M3EUP57.js +22 -0
  50. package/build/modern/chunk-4M3EUP57.js.map +1 -0
  51. package/build/{legacy/chunk-X4YQ27D5.js → modern/chunk-5RA3ZIXA.js} +2 -2
  52. package/build/modern/chunk-BVK6GEDZ.js +164 -0
  53. package/build/modern/chunk-BVK6GEDZ.js.map +1 -0
  54. package/build/modern/chunk-JIZQFTW6.js +29 -0
  55. package/build/modern/chunk-JIZQFTW6.js.map +1 -0
  56. package/build/{legacy/chunk-HE3HFKYU.js → modern/chunk-JJGZRBIR.js} +2 -2
  57. package/build/modern/{chunk-HE3HFKYU.js.map → chunk-JJGZRBIR.js.map} +1 -1
  58. package/build/{legacy/chunk-G2QMBSK5.js → modern/chunk-PMCYXRAH.js} +2 -2
  59. package/build/modern/chunk-PMCYXRAH.js.map +1 -0
  60. package/build/modern/chunk-SCAVVE6E.js +16 -0
  61. package/build/modern/chunk-SCAVVE6E.js.map +1 -0
  62. package/build/modern/{chunk-734PGVLT.js → chunk-VLVKNEA5.js} +2 -2
  63. package/build/modern/chunk-VULPMZUW.js +18 -0
  64. package/build/modern/chunk-VULPMZUW.js.map +1 -0
  65. package/build/modern/{chunk-SLIOCQBZ.js → chunk-Z6IWNVPN.js} +2 -2
  66. package/build/modern/chunk-Z6IWNVPN.js.map +1 -0
  67. package/build/modern/components/FeatureFlag.js +10 -0
  68. package/build/modern/components/FeatureFlag.js.map +1 -0
  69. package/build/modern/components/Input.js +3 -3
  70. package/build/modern/components/Label.js +1 -1
  71. package/build/modern/components/NavMenuList.js +1 -1
  72. package/build/modern/components/Portal.js +7 -0
  73. package/build/modern/components/Portal.js.map +1 -0
  74. package/build/modern/components/Tag.js +1 -1
  75. package/build/modern/components/Toggle.js +3 -3
  76. package/build/modern/config/cerbIcons.js +1 -1
  77. package/build/modern/config/defineIcons.js +2 -2
  78. package/build/modern/context/confirm-modal.js +16 -0
  79. package/build/modern/context/confirm-modal.js.map +1 -0
  80. package/build/modern/context/feature-flags.js +10 -0
  81. package/build/modern/context/feature-flags.js.map +1 -0
  82. package/build/modern/index.js +50 -26
  83. package/package.json +3 -2
  84. package/src/aria-helpers/trap-focus.aria.ts +29 -0
  85. package/src/components/FeatureFlag.tsx +14 -0
  86. package/src/components/Label.tsx +1 -1
  87. package/src/components/NavMenuList.tsx +1 -1
  88. package/src/components/Portal.tsx +22 -0
  89. package/src/components/Tag.tsx +1 -1
  90. package/src/config/cerbIcons.ts +9 -2
  91. package/src/config/defineIcons.ts +6 -3
  92. package/src/context/confirm-modal.tsx +205 -0
  93. package/src/context/feature-flags.tsx +60 -0
  94. package/src/index.ts +5 -0
  95. package/build/legacy/chunk-3CBN7U25.js.map +0 -1
  96. package/build/legacy/chunk-5MNCW677.js +0 -11
  97. package/build/legacy/chunk-5MNCW677.js.map +0 -1
  98. package/build/legacy/chunk-5XNLWIZO.js.map +0 -1
  99. package/build/legacy/chunk-G2QMBSK5.js.map +0 -1
  100. package/build/modern/chunk-3CBN7U25.js.map +0 -1
  101. package/build/modern/chunk-5MNCW677.js +0 -11
  102. package/build/modern/chunk-5MNCW677.js.map +0 -1
  103. package/build/modern/chunk-G2QMBSK5.js.map +0 -1
  104. package/build/modern/chunk-SLIOCQBZ.js.map +0 -1
  105. /package/build/legacy/{chunk-X4YQ27D5.js.map → chunk-5RA3ZIXA.js.map} +0 -0
  106. /package/build/legacy/{chunk-734PGVLT.js.map → chunk-VLVKNEA5.js.map} +0 -0
  107. /package/build/modern/{chunk-X4YQ27D5.js.map → chunk-5RA3ZIXA.js.map} +0 -0
  108. /package/build/modern/{chunk-734PGVLT.js.map → chunk-VLVKNEA5.js.map} +0 -0
@@ -1,3 +1,30 @@
1
+ import {
2
+ Tag
3
+ } from "./chunk-Z6IWNVPN.js";
4
+ import {
5
+ Textarea
6
+ } from "./chunk-TCO46FK7.js";
7
+ import {
8
+ Toggle
9
+ } from "./chunk-VLVKNEA5.js";
10
+ import {
11
+ ConfirmModal,
12
+ useConfirmModal
13
+ } from "./chunk-BVK6GEDZ.js";
14
+ import {
15
+ NavMenuList,
16
+ getPosition
17
+ } from "./chunk-PMCYXRAH.js";
18
+ import {
19
+ NavMenuTrigger
20
+ } from "./chunk-RPZAPUCF.js";
21
+ import {
22
+ NavMenu,
23
+ useNavMenuContext
24
+ } from "./chunk-KJUCHZHV.js";
25
+ import {
26
+ Portal
27
+ } from "./chunk-4CAT3FHV.js";
1
28
  import {
2
29
  Radio
3
30
  } from "./chunk-WE3JNSNO.js";
@@ -11,17 +38,18 @@ import {
11
38
  TabPanel
12
39
  } from "./chunk-67S42J4B.js";
13
40
  import {
14
- Tag
15
- } from "./chunk-SLIOCQBZ.js";
16
- import {
17
- Textarea
18
- } from "./chunk-TCO46FK7.js";
19
- import {
20
- Toggle
21
- } from "./chunk-734PGVLT.js";
41
+ useToggle
42
+ } from "./chunk-QEA6N6TN.js";
22
43
  import {
23
44
  Button
24
45
  } from "./chunk-2ATICEW3.js";
46
+ import {
47
+ FeatureFlag
48
+ } from "./chunk-VULPMZUW.js";
49
+ import {
50
+ FeatureFlags,
51
+ useFeatureFlags
52
+ } from "./chunk-4M3EUP57.js";
25
53
  import {
26
54
  FieldMessage
27
55
  } from "./chunk-VGHVH2T3.js";
@@ -30,10 +58,10 @@ import {
30
58
  } from "./chunk-SLHX5K6I.js";
31
59
  import {
32
60
  Input
33
- } from "./chunk-X4YQ27D5.js";
61
+ } from "./chunk-5RA3ZIXA.js";
34
62
  import {
35
63
  Label
36
- } from "./chunk-HE3HFKYU.js";
64
+ } from "./chunk-JJGZRBIR.js";
37
65
  import {
38
66
  Field,
39
67
  useFieldContext
@@ -41,17 +69,6 @@ import {
41
69
  import {
42
70
  NavMenuLink
43
71
  } from "./chunk-6DIGPXAD.js";
44
- import {
45
- NavMenuList,
46
- getPosition
47
- } from "./chunk-G2QMBSK5.js";
48
- import {
49
- NavMenuTrigger
50
- } from "./chunk-RPZAPUCF.js";
51
- import {
52
- NavMenu,
53
- useNavMenuContext
54
- } from "./chunk-KJUCHZHV.js";
55
72
  import {
56
73
  Show
57
74
  } from "./chunk-4O4QFF4S.js";
@@ -67,11 +84,14 @@ import {
67
84
  TabsContext,
68
85
  useTabsContext
69
86
  } from "./chunk-7KJIZIAU.js";
87
+ import {
88
+ trapFocus
89
+ } from "./chunk-JIZQFTW6.js";
70
90
  import {
71
91
  $cerberusIcons,
72
92
  defineIcons
73
- } from "./chunk-3CBN7U25.js";
74
- import "./chunk-5MNCW677.js";
93
+ } from "./chunk-3TYUA4C7.js";
94
+ import "./chunk-SCAVVE6E.js";
75
95
  import {
76
96
  MODE_KEY,
77
97
  THEME_KEY,
@@ -79,12 +99,12 @@ import {
79
99
  useTheme,
80
100
  useThemeContext
81
101
  } from "./chunk-SXXWC6UD.js";
82
- import {
83
- useToggle
84
- } from "./chunk-QEA6N6TN.js";
85
102
  export {
86
103
  $cerberusIcons,
87
104
  Button,
105
+ ConfirmModal,
106
+ FeatureFlag,
107
+ FeatureFlags,
88
108
  Field,
89
109
  FieldMessage,
90
110
  IconButton,
@@ -95,6 +115,7 @@ export {
95
115
  NavMenuLink,
96
116
  NavMenuList,
97
117
  NavMenuTrigger,
118
+ Portal,
98
119
  Radio,
99
120
  Show,
100
121
  THEME_KEY,
@@ -110,6 +131,9 @@ export {
110
131
  createNavTriggerProps,
111
132
  defineIcons,
112
133
  getPosition,
134
+ trapFocus,
135
+ useConfirmModal,
136
+ useFeatureFlags,
113
137
  useFieldContext,
114
138
  useNavMenuContext,
115
139
  useTabsContext,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cerberus-design/react",
3
- "version": "0.6.1-next-0345599",
3
+ "version": "0.6.1-next-1315bf2",
4
4
  "description": "The Cerberus Design React component library.",
5
5
  "browserslist": "> 0.25%, not dead",
6
6
  "sideEffects": false,
@@ -18,11 +18,12 @@
18
18
  "devDependencies": {
19
19
  "@microsoft/api-extractor": "^7.46.2",
20
20
  "@types/react": "^18",
21
+ "@types/react-dom": "^18",
21
22
  "react": "^18",
22
23
  "react-dom": "^18",
23
24
  "tsup": "^8.1.0",
24
25
  "@cerberus-design/configs": "0.0.0",
25
- "@cerberus-design/styled-system": "0.6.1-next-0345599"
26
+ "@cerberus-design/styled-system": "0.6.1-next-1315bf2"
26
27
  },
27
28
  "publishConfig": {
28
29
  "access": "public"
@@ -0,0 +1,29 @@
1
+ import type { KeyboardEvent, KeyboardEventHandler, RefObject } from 'react'
2
+
3
+ export function trapFocus(
4
+ modalRef: RefObject<HTMLDialogElement>,
5
+ ): KeyboardEventHandler<HTMLDialogElement> {
6
+ const focusableElements =
7
+ 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
8
+ const focusable = Array.from(
9
+ modalRef.current?.querySelectorAll(focusableElements) ?? [],
10
+ )
11
+ const firstFocusable = focusable[0] as HTMLElement
12
+ const lastFocusable = focusable[focusable.length - 1] as HTMLElement
13
+
14
+ return function handleKeyDown(event: KeyboardEvent<HTMLDialogElement>) {
15
+ if (event.key === 'Tab') {
16
+ if (event.shiftKey) {
17
+ if (document.activeElement === firstFocusable) {
18
+ lastFocusable.focus()
19
+ event.preventDefault()
20
+ }
21
+ } else {
22
+ if (document.activeElement === lastFocusable) {
23
+ firstFocusable.focus()
24
+ event.preventDefault()
25
+ }
26
+ }
27
+ }
28
+ }
29
+ }
@@ -0,0 +1,14 @@
1
+ 'use client'
2
+
3
+ import type { PropsWithChildren } from 'react'
4
+ import { useFeatureFlags } from '../context/feature-flags'
5
+ import { Show } from './Show'
6
+
7
+ export interface FeatureFlagProps {
8
+ flag: string
9
+ }
10
+
11
+ export function FeatureFlag(props: PropsWithChildren<FeatureFlagProps>) {
12
+ const showContent = useFeatureFlags(props.flag)
13
+ return <Show when={showContent}>{props.children}</Show>
14
+ }
@@ -51,7 +51,7 @@ export function Label(props: PropsWithChildren<LabelProps>) {
51
51
  <Show when={required}>
52
52
  <span
53
53
  className={css({
54
- color: 'neutral.text.100',
54
+ color: 'page.text.100',
55
55
  fontSize: 'inherit',
56
56
  })}
57
57
  >
@@ -37,7 +37,7 @@ export function getPosition(position: Positions): GetPositionResult {
37
37
 
38
38
  const navListStyles = vstack({
39
39
  alignItems: 'flex-start',
40
- bgColor: 'neutral.surface.100',
40
+ bgColor: 'page.surface.100',
41
41
  boxShadow: 'lg',
42
42
  gap: '2',
43
43
  opacity: '0',
@@ -0,0 +1,22 @@
1
+ import type { PropsWithChildren } from 'react'
2
+ import { createPortal } from 'react-dom'
3
+
4
+ /**
5
+ * This module is the Portal component.
6
+ * @module
7
+ */
8
+
9
+ export interface PortalProps {
10
+ container?: Element | DocumentFragment
11
+ key?: null | string
12
+ }
13
+
14
+ /**
15
+ * The Portal component is used to render children into a DOM node that exists outside the DOM hierarchy of the parent component.
16
+ * @param container - The props for the Portal component.
17
+ * @returns ReactPortal
18
+ */
19
+ export function Portal(props: PropsWithChildren<PortalProps>) {
20
+ const container = props.container || document.body
21
+ return createPortal(props.children, container, props.key)
22
+ }
@@ -37,7 +37,7 @@ export type TagProps = StaticTagProps | ClickableTagProps
37
37
  */
38
38
  export function Tag(props: PropsWithChildren<TagProps>): JSX.Element {
39
39
  const { shape: initShape, gradient, onClick, usage, ...nativeProps } = props
40
- const palette = props?.palette ?? 'neutral'
40
+ const palette = props?.palette ?? 'page'
41
41
  const isClosable = Boolean(onClick)
42
42
  const shape = isClosable ? 'pill' : initShape
43
43
  const closableStyles = isClosable ? closableCss : ''
@@ -1,12 +1,19 @@
1
- import { Checkmark, WarningFilled, type CarbonIconType } from '@cerberus/icons'
1
+ import {
2
+ Checkmark,
3
+ Information,
4
+ WarningFilled,
5
+ type CarbonIconType,
6
+ } from '@cerberus/icons'
2
7
  import type { ElementType } from 'react'
3
8
 
4
9
  export interface DefinedIcons {
10
+ confirmModal?: CarbonIconType | ElementType
5
11
  invalid: CarbonIconType | ElementType
6
- toggleChecked: CarbonIconType | ElementType
12
+ toggleChecked?: CarbonIconType | ElementType
7
13
  }
8
14
 
9
15
  export const defaultIcons: DefinedIcons = {
16
+ confirmModal: Information,
10
17
  invalid: WarningFilled,
11
18
  toggleChecked: Checkmark,
12
19
  }
@@ -8,12 +8,15 @@ function _validateIconsProperties(icons: DefinedIcons) {
8
8
  }
9
9
  }
10
10
 
11
- export function defineIcons(icons: DefinedIcons): DefinedIcons {
11
+ export function defineIcons(icons: DefinedIcons): Required<DefinedIcons> {
12
12
  _validateIconsProperties(icons)
13
- $cerberusIcons = icons
13
+ $cerberusIcons = {
14
+ ...defaultIcons,
15
+ ...icons,
16
+ } as Required<DefinedIcons>
14
17
  return $cerberusIcons
15
18
  }
16
19
 
17
20
  // Default icons
18
21
 
19
- export let $cerberusIcons: DefinedIcons = defaultIcons
22
+ export let $cerberusIcons = defaultIcons as Required<DefinedIcons>
@@ -0,0 +1,205 @@
1
+ 'use client'
2
+
3
+ import {
4
+ createContext,
5
+ useCallback,
6
+ useContext,
7
+ useMemo,
8
+ useRef,
9
+ useState,
10
+ type MouseEvent,
11
+ type PropsWithChildren,
12
+ } from 'react'
13
+ import { Portal } from '../components/Portal'
14
+ import { Button } from '../components/Button'
15
+ import { css, cx } from '@cerberus-design/styled-system/css'
16
+ import { circle, hstack, vstack } from '@cerberus-design/styled-system/patterns'
17
+ import { $cerberusIcons } from '../config/defineIcons'
18
+ import {
19
+ confirmModal,
20
+ type ConfirmModalVariantProps,
21
+ } from '@cerberus-design/styled-system/recipes'
22
+ import { trapFocus } from '../aria-helpers/trap-focus.aria'
23
+ import { Show } from '../components/Show'
24
+
25
+ /**
26
+ * This module provides a context and hook for the confirm modal.
27
+ * @module
28
+ */
29
+
30
+ export interface ShowConfirmModalOptions {
31
+ kind?: 'destructive' | 'non-destructive'
32
+ heading: string
33
+ description?: string
34
+ actionText: string
35
+ cancelText: string
36
+ }
37
+ export type ShowResult =
38
+ | ((value: boolean | PromiseLike<boolean>) => void)
39
+ | null
40
+
41
+ export interface ConfirmModalValue {
42
+ show: (options: ShowConfirmModalOptions) => Promise<boolean>
43
+ }
44
+
45
+ const ConfirmModalContext = createContext<ConfirmModalValue | null>(null)
46
+
47
+ export interface ConfirmModalProviderProps {}
48
+
49
+ /**
50
+ * Provides a confirm modal to the app.
51
+ * @example
52
+ * ```tsx
53
+ * // Wrap the Provider around the root of the feature.
54
+ * <ConfirmModal>
55
+ * <SomeFeatureSection />
56
+ * </ConfirmModal>
57
+ *
58
+ * // Use the hook to show the confirm modal.
59
+ * const confirm = useConfirmModal()
60
+ *
61
+ * const handleClick = useCallback(async () => {
62
+ * const userConsent = await confirm.show({
63
+ * heading: 'Add new payment method?',
64
+ * description:
65
+ * 'This will add a new payment method to your account to be billed for future purchases.',
66
+ * actionText: 'Yes, add payment method',
67
+ * cancelText: 'No, cancel',
68
+ * })
69
+ * setConsent(userConsent)
70
+ * }, [confirm])
71
+ * ```
72
+ */
73
+ export function ConfirmModal(
74
+ props: PropsWithChildren<ConfirmModalProviderProps>,
75
+ ) {
76
+ const dialogRef = useRef<HTMLDialogElement>(null)
77
+ const resolveRef = useRef<ShowResult>(null)
78
+ const [content, setContent] = useState<ShowConfirmModalOptions | null>(null)
79
+ const focusTrap = trapFocus(dialogRef)
80
+
81
+ const palette = useMemo(
82
+ () => (content?.kind === 'destructive' ? 'danger' : 'action'),
83
+ [content],
84
+ )
85
+ const styles = confirmModal({ palette })
86
+
87
+ const handleChoice = useCallback((e: MouseEvent<HTMLButtonElement>) => {
88
+ const target = e.currentTarget as HTMLButtonElement
89
+ if (target.value === 'true') {
90
+ resolveRef.current?.(true)
91
+ }
92
+ resolveRef.current?.(false)
93
+ dialogRef?.current?.close()
94
+ }, [])
95
+
96
+ const handleShow = useCallback((options: ShowConfirmModalOptions) => {
97
+ return new Promise<boolean>((resolve) => {
98
+ setContent({ ...options, kind: options.kind || 'non-destructive' })
99
+ dialogRef?.current?.showModal()
100
+ resolveRef.current = resolve
101
+ })
102
+ }, [])
103
+
104
+ const value = useMemo(
105
+ () => ({
106
+ show: handleShow,
107
+ }),
108
+ [handleShow],
109
+ )
110
+
111
+ return (
112
+ <ConfirmModalContext.Provider value={value}>
113
+ {props.children}
114
+
115
+ <Portal>
116
+ <dialog className={styles.dialog} onKeyDown={focusTrap} ref={dialogRef}>
117
+ <div
118
+ className={vstack({
119
+ alignItems: 'flex-start',
120
+ gap: '4',
121
+ mb: '8',
122
+ })}
123
+ >
124
+ <ConfirmModalIcon palette={palette} />
125
+ <h2 className={styles.heading}>{content?.heading}</h2>
126
+ <p className={styles.description}>{content?.description}</p>
127
+ </div>
128
+
129
+ <div
130
+ className={hstack({
131
+ justifyContent: 'stretch',
132
+ gap: '4',
133
+ })}
134
+ >
135
+ <Button
136
+ autoFocus
137
+ className={css({
138
+ w: '1/2',
139
+ })}
140
+ name="confirm"
141
+ onClick={handleChoice}
142
+ palette={palette}
143
+ value="true"
144
+ >
145
+ {content?.actionText}
146
+ </Button>
147
+ <Button
148
+ className={css({
149
+ w: '1/2',
150
+ })}
151
+ name="cancel"
152
+ onClick={handleChoice}
153
+ usage="outlined"
154
+ value="false"
155
+ >
156
+ {content?.cancelText}
157
+ </Button>
158
+ </div>
159
+ </dialog>
160
+ </Portal>
161
+ </ConfirmModalContext.Provider>
162
+ )
163
+ }
164
+
165
+ // This is to help show the variant styles for the icon since Panda is
166
+ // not syncing correctly for the danger variant.
167
+ function ConfirmModalIcon(props: ConfirmModalVariantProps) {
168
+ const InfoIcon = $cerberusIcons.confirmModal
169
+ return (
170
+ <Show
171
+ when={props.palette === 'danger'}
172
+ fallback={
173
+ <div className={cx(confirmModal().icon, circle())}>
174
+ <InfoIcon />
175
+ </div>
176
+ }
177
+ >
178
+ <div
179
+ className={cx(
180
+ confirmModal({
181
+ palette: 'danger',
182
+ }).icon,
183
+ circle({
184
+ bgColor: 'danger.surface.initial',
185
+ }),
186
+ )}
187
+ style={{
188
+ color: 'var(--cerberus-colors-danger-text-100)',
189
+ }}
190
+ >
191
+ <InfoIcon />
192
+ </div>
193
+ </Show>
194
+ )
195
+ }
196
+
197
+ export function useConfirmModal(): ConfirmModalValue {
198
+ const context = useContext(ConfirmModalContext)
199
+ if (context === null) {
200
+ throw new Error(
201
+ 'useConfirmModal must be used within a ConfirmModal Provider',
202
+ )
203
+ }
204
+ return context
205
+ }
@@ -0,0 +1,60 @@
1
+ 'use client'
2
+
3
+ import { createContext, useContext, type PropsWithChildren } from 'react'
4
+
5
+ /**
6
+ * This module provides a context and hook for feature flags.
7
+ * @module
8
+ */
9
+
10
+ export interface FeatureFlagValue {
11
+ [key: string]: boolean
12
+ }
13
+
14
+ const FeatureFlagContext = createContext<FeatureFlagValue | null>(null)
15
+
16
+ export interface FeatureFlagProviderProps {
17
+ flags: FeatureFlagValue
18
+ }
19
+
20
+ /**
21
+ * Provides feature flags to the application.
22
+ * @param flags - The flags data for the provider.
23
+ * @example
24
+ * ```tsx
25
+ * // This should be a JSON file or a server response.
26
+ * const flags = {
27
+ * featureOne: true,
28
+ * featureTwo: false
29
+ * }
30
+ *
31
+ * // Wrap the Provider around the root of your application.
32
+ * <FeatureFlags flags={flags}>
33
+ * <FeatureFlag flag="featureOne">
34
+ * This is visible.
35
+ * </FeatureFlag>
36
+ * <FeatureFlag flag="featureTwo">
37
+ * This is hidden.
38
+ * </FeatureFlag>
39
+ * </FeatureFlags>
40
+ * ```
41
+ */
42
+ export function FeatureFlags(
43
+ props: PropsWithChildren<FeatureFlagProviderProps>,
44
+ ) {
45
+ return (
46
+ <FeatureFlagContext.Provider value={props.flags}>
47
+ {props.children}
48
+ </FeatureFlagContext.Provider>
49
+ )
50
+ }
51
+
52
+ export function useFeatureFlags(key: string): boolean {
53
+ const context = useContext(FeatureFlagContext)
54
+ if (context === null) {
55
+ throw new Error(
56
+ 'useFeatureFlag must be used within a FeatureFlags Provider',
57
+ )
58
+ }
59
+ return context[key] ?? false
60
+ }
package/src/index.ts CHANGED
@@ -7,12 +7,14 @@
7
7
 
8
8
  export * from './components/Button'
9
9
  export * from './components/FieldMessage'
10
+ export * from './components/FeatureFlag'
10
11
  export * from './components/IconButton'
11
12
  export * from './components/Input'
12
13
  export * from './components/Label'
13
14
  export * from './components/NavMenuTrigger'
14
15
  export * from './components/NavMenuList'
15
16
  export * from './components/NavMenuLink'
17
+ export * from './components/Portal'
16
18
  export * from './components/Radio'
17
19
  export * from './components/Tab'
18
20
  export * from './components/TabList'
@@ -24,6 +26,8 @@ export * from './components/Show'
24
26
 
25
27
  // context
26
28
 
29
+ export * from './context/confirm-modal'
30
+ export * from './context/feature-flags'
27
31
  export * from './context/field'
28
32
  export * from './context/navMenu'
29
33
  export * from './context/tabs'
@@ -38,6 +42,7 @@ export * from './hooks/useToggle'
38
42
 
39
43
  export * from './aria-helpers/nav-menu.aria'
40
44
  export * from './aria-helpers/tabs.aria'
45
+ export * from './aria-helpers/trap-focus.aria'
41
46
 
42
47
  // utils
43
48
 
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/config/defineIcons.ts"],"sourcesContent":["import { defaultIcons, type DefinedIcons } from './cerbIcons'\n\nfunction _validateIconsProperties(icons: DefinedIcons) {\n if (!icons.invalid) {\n throw new Error(\n 'The an invalid property must be defined in your custom icons library.',\n )\n }\n}\n\nexport function defineIcons(icons: DefinedIcons): DefinedIcons {\n _validateIconsProperties(icons)\n $cerberusIcons = icons\n return $cerberusIcons\n}\n\n// Default icons\n\nexport let $cerberusIcons: DefinedIcons = defaultIcons\n"],"mappings":";;;;;AAEA,SAAS,yBAAyB,OAAqB;AACrD,MAAI,CAAC,MAAM,SAAS;AAClB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,YAAY,OAAmC;AAC7D,2BAAyB,KAAK;AAC9B,mBAAiB;AACjB,SAAO;AACT;AAIO,IAAI,iBAA+B;","names":[]}
@@ -1,11 +0,0 @@
1
- // src/config/cerbIcons.ts
2
- import { Checkmark, WarningFilled } from "@cerberus/icons";
3
- var defaultIcons = {
4
- invalid: WarningFilled,
5
- toggleChecked: Checkmark
6
- };
7
-
8
- export {
9
- defaultIcons
10
- };
11
- //# sourceMappingURL=chunk-5MNCW677.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/config/cerbIcons.ts"],"sourcesContent":["import { Checkmark, WarningFilled, type CarbonIconType } from '@cerberus/icons'\nimport type { ElementType } from 'react'\n\nexport interface DefinedIcons {\n invalid: CarbonIconType | ElementType\n toggleChecked: CarbonIconType | ElementType\n}\n\nexport const defaultIcons: DefinedIcons = {\n invalid: WarningFilled,\n toggleChecked: Checkmark,\n}\n"],"mappings":";AAAA,SAAS,WAAW,qBAA0C;AAQvD,IAAM,eAA6B;AAAA,EACxC,SAAS;AAAA,EACT,eAAe;AACjB;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/components/Tag.tsx"],"sourcesContent":["import type { HTMLAttributes, PropsWithChildren } from 'react'\nimport { Close } from '@cerberus/icons'\nimport { Show } from './Show'\nimport { css, cx } from '@cerberus/styled-system/css'\nimport { iconButton, tag } from '@cerberus/styled-system/recipes'\nimport type { RecipeVariantProps } from '@cerberus/styled-system/types'\n\n/**\n * This module contains the tag component.\n * @module\n */\n\nexport type TagRecipeProps = RecipeVariantProps<typeof tag>\n\nexport type StaticTagProps = HTMLAttributes<HTMLSpanElement> &\n TagRecipeProps & {\n onClick?: never\n }\n\nexport type ClickableTagProps = HTMLAttributes<HTMLSpanElement> & {\n gradient?: never\n palette?: never\n onClick: () => void\n shape: 'pill'\n usage: 'filled'\n}\n\nexport type TagProps = StaticTagProps | ClickableTagProps\n\n/**\n * The Tag component is used to display a meta descriptions.\n * @definition [Tag docs](https://cerberus.digitalu.design/react/tags)\n * @example\n * ```tsx\n * <Tag>Tag</Tag>\n * ```\n */\nexport function Tag(props: PropsWithChildren<TagProps>): JSX.Element {\n const { shape: initShape, gradient, onClick, usage, ...nativeProps } = props\n const palette = props?.palette ?? 'neutral'\n const isClosable = Boolean(onClick)\n const shape = isClosable ? 'pill' : initShape\n const closableStyles = isClosable ? closableCss : ''\n\n return (\n <span\n {...nativeProps}\n className={cx(\n nativeProps.className,\n tag({\n gradient,\n palette,\n shape,\n usage,\n }),\n closableStyles,\n )}\n >\n {props.children}\n\n <Show when={isClosable}>\n <button\n aria-label=\"Close\"\n className={iconButton({\n palette: 'action',\n usage: 'filled',\n size: 'sm',\n })}\n onClick={onClick}\n >\n <Close />\n </button>\n </Show>\n </span>\n )\n}\n\nconst closableCss = css({\n bgColor: 'action.bg.active',\n color: 'action.text.initial',\n paddingInlineEnd: '0',\n})\n"],"mappings":";;;;;AACA,SAAS,aAAa;AAEtB,SAAS,KAAK,UAAU;AACxB,SAAS,YAAY,WAAW;AAyC5B,SAyBM,KAzBN;AARG,SAAS,IAAI,OAAiD;AACnE,QAAM,EAAE,OAAO,WAAW,UAAU,SAAS,OAAO,GAAG,YAAY,IAAI;AACvE,QAAM,WAAU,+BAAO,YAAW;AAClC,QAAM,aAAa,QAAQ,OAAO;AAClC,QAAM,QAAQ,aAAa,SAAS;AACpC,QAAM,iBAAiB,aAAa,cAAc;AAElD,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ,WAAW;AAAA,QACT,YAAY;AAAA,QACZ,IAAI;AAAA,UACF;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF,CAAC;AAAA,QACD;AAAA,MACF;AAAA,MAEC;AAAA,cAAM;AAAA,QAEP,oBAAC,QAAK,MAAM,YACV;AAAA,UAAC;AAAA;AAAA,YACC,cAAW;AAAA,YACX,WAAW,WAAW;AAAA,cACpB,SAAS;AAAA,cACT,OAAO;AAAA,cACP,MAAM;AAAA,YACR,CAAC;AAAA,YACD;AAAA,YAEA,8BAAC,SAAM;AAAA;AAAA,QACT,GACF;AAAA;AAAA;AAAA,EACF;AAEJ;AAEA,IAAM,cAAc,IAAI;AAAA,EACtB,SAAS;AAAA,EACT,OAAO;AAAA,EACP,kBAAkB;AACpB,CAAC;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/components/NavMenuList.tsx"],"sourcesContent":["'use client'\n\nimport { useMemo, type HTMLAttributes } from 'react'\nimport { cx } from '@cerberus/styled-system/css'\nimport { vstack } from '@cerberus/styled-system/patterns'\nimport { useNavMenuContext } from '../context/navMenu'\nimport type { Positions } from '../types'\nimport { Show } from './Show'\n\ninterface GetPositionResult {\n left: string\n right: string\n top: string\n bottom: string\n}\n\nexport function getPosition(position: Positions): GetPositionResult {\n const defaultPositions = {\n left: 'auto',\n right: 'auto',\n top: 'auto',\n bottom: 'auto',\n }\n switch (position) {\n case 'right':\n return { ...defaultPositions, top: '0%', left: '105%' }\n case 'left':\n return { ...defaultPositions, top: '0%', right: '105%' }\n case 'bottom':\n return { ...defaultPositions, top: '110%' }\n case 'top':\n return { ...defaultPositions, bottom: '110%' }\n default:\n return defaultPositions\n }\n}\n\nconst navListStyles = vstack({\n alignItems: 'flex-start',\n bgColor: 'neutral.surface.100',\n boxShadow: 'lg',\n gap: '2',\n opacity: '0',\n p: '4',\n position: 'absolute',\n rounded: 'md',\n zIndex: 'dropdown',\n _motionSafe: {\n animationName: 'zoomIn',\n animationDelay: '100ms',\n animationDuration: '150ms',\n animationFillMode: 'both',\n animationTimingFunction: 'ease-in-out',\n },\n _positionBottom: {\n transformOrigin: 'top left',\n },\n _positionTop: {\n transformOrigin: 'bottom left',\n },\n _positionLeft: {\n transformOrigin: 'top right',\n },\n _positionRight: {\n transformOrigin: 'top left',\n },\n})\n\nexport interface NavMenuListProps extends HTMLAttributes<HTMLUListElement> {\n id: string\n position?: Positions\n}\n\n/**\n * A component that allows the user to display a menu of navigation links.\n * @definition [Disclosure Nav](https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/examples/disclosure-navigation/)\n * @definition [NavMenu Docs](https://cerberus.digitalu.design/react/nav-menu)\n *\n * @example\n * ```tsx\n * <NavMenuList id=\"nav-menu-list\" position=\"bottom\">\n * <NavMenuLink href=\"/home\">Home</NavMenuLink>\n * <NavMenuLink href=\"/about\">About</NavMenuLink>\n * </NavMenuList>\n * ```\n **/\nexport function NavMenuList(props: NavMenuListProps): JSX.Element {\n const { position, ...nativeProps } = props\n const { menuRef, expanded } = useNavMenuContext()\n const locationStyles = useMemo(\n () => getPosition(position ?? 'bottom'),\n [position],\n )\n\n return (\n <Show when={expanded}>\n <ul\n {...nativeProps}\n data-position={position ?? 'bottom'}\n className={cx(nativeProps.className, navListStyles)}\n ref={menuRef}\n style={locationStyles}\n />\n </Show>\n )\n}\n"],"mappings":";;;;;;;;AAEA,SAAS,eAAoC;AAC7C,SAAS,UAAU;AACnB,SAAS,cAAc;AA4FjB;AAhFC,SAAS,YAAY,UAAwC;AAClE,QAAM,mBAAmB;AAAA,IACvB,MAAM;AAAA,IACN,OAAO;AAAA,IACP,KAAK;AAAA,IACL,QAAQ;AAAA,EACV;AACA,UAAQ,UAAU;AAAA,IAChB,KAAK;AACH,aAAO,EAAE,GAAG,kBAAkB,KAAK,MAAM,MAAM,OAAO;AAAA,IACxD,KAAK;AACH,aAAO,EAAE,GAAG,kBAAkB,KAAK,MAAM,OAAO,OAAO;AAAA,IACzD,KAAK;AACH,aAAO,EAAE,GAAG,kBAAkB,KAAK,OAAO;AAAA,IAC5C,KAAK;AACH,aAAO,EAAE,GAAG,kBAAkB,QAAQ,OAAO;AAAA,IAC/C;AACE,aAAO;AAAA,EACX;AACF;AAEA,IAAM,gBAAgB,OAAO;AAAA,EAC3B,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,WAAW;AAAA,EACX,KAAK;AAAA,EACL,SAAS;AAAA,EACT,GAAG;AAAA,EACH,UAAU;AAAA,EACV,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,aAAa;AAAA,IACX,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,mBAAmB;AAAA,IACnB,mBAAmB;AAAA,IACnB,yBAAyB;AAAA,EAC3B;AAAA,EACA,iBAAiB;AAAA,IACf,iBAAiB;AAAA,EACnB;AAAA,EACA,cAAc;AAAA,IACZ,iBAAiB;AAAA,EACnB;AAAA,EACA,eAAe;AAAA,IACb,iBAAiB;AAAA,EACnB;AAAA,EACA,gBAAgB;AAAA,IACd,iBAAiB;AAAA,EACnB;AACF,CAAC;AAoBM,SAAS,YAAY,OAAsC;AAChE,QAAM,EAAE,UAAU,GAAG,YAAY,IAAI;AACrC,QAAM,EAAE,SAAS,SAAS,IAAI,kBAAkB;AAChD,QAAM,iBAAiB;AAAA,IACrB,MAAM,YAAY,YAAY,QAAQ;AAAA,IACtC,CAAC,QAAQ;AAAA,EACX;AAEA,SACE,oBAAC,QAAK,MAAM,UACV;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ,iBAAe,YAAY;AAAA,MAC3B,WAAW,GAAG,YAAY,WAAW,aAAa;AAAA,MAClD,KAAK;AAAA,MACL,OAAO;AAAA;AAAA,EACT,GACF;AAEJ;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/config/defineIcons.ts"],"sourcesContent":["import { defaultIcons, type DefinedIcons } from './cerbIcons'\n\nfunction _validateIconsProperties(icons: DefinedIcons) {\n if (!icons.invalid) {\n throw new Error(\n 'The an invalid property must be defined in your custom icons library.',\n )\n }\n}\n\nexport function defineIcons(icons: DefinedIcons): DefinedIcons {\n _validateIconsProperties(icons)\n $cerberusIcons = icons\n return $cerberusIcons\n}\n\n// Default icons\n\nexport let $cerberusIcons: DefinedIcons = defaultIcons\n"],"mappings":";;;;;AAEA,SAAS,yBAAyB,OAAqB;AACrD,MAAI,CAAC,MAAM,SAAS;AAClB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,YAAY,OAAmC;AAC7D,2BAAyB,KAAK;AAC9B,mBAAiB;AACjB,SAAO;AACT;AAIO,IAAI,iBAA+B;","names":[]}
@@ -1,11 +0,0 @@
1
- // src/config/cerbIcons.ts
2
- import { Checkmark, WarningFilled } from "@cerberus/icons";
3
- var defaultIcons = {
4
- invalid: WarningFilled,
5
- toggleChecked: Checkmark
6
- };
7
-
8
- export {
9
- defaultIcons
10
- };
11
- //# sourceMappingURL=chunk-5MNCW677.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/config/cerbIcons.ts"],"sourcesContent":["import { Checkmark, WarningFilled, type CarbonIconType } from '@cerberus/icons'\nimport type { ElementType } from 'react'\n\nexport interface DefinedIcons {\n invalid: CarbonIconType | ElementType\n toggleChecked: CarbonIconType | ElementType\n}\n\nexport const defaultIcons: DefinedIcons = {\n invalid: WarningFilled,\n toggleChecked: Checkmark,\n}\n"],"mappings":";AAAA,SAAS,WAAW,qBAA0C;AAQvD,IAAM,eAA6B;AAAA,EACxC,SAAS;AAAA,EACT,eAAe;AACjB;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/components/NavMenuList.tsx"],"sourcesContent":["'use client'\n\nimport { useMemo, type HTMLAttributes } from 'react'\nimport { cx } from '@cerberus/styled-system/css'\nimport { vstack } from '@cerberus/styled-system/patterns'\nimport { useNavMenuContext } from '../context/navMenu'\nimport type { Positions } from '../types'\nimport { Show } from './Show'\n\ninterface GetPositionResult {\n left: string\n right: string\n top: string\n bottom: string\n}\n\nexport function getPosition(position: Positions): GetPositionResult {\n const defaultPositions = {\n left: 'auto',\n right: 'auto',\n top: 'auto',\n bottom: 'auto',\n }\n switch (position) {\n case 'right':\n return { ...defaultPositions, top: '0%', left: '105%' }\n case 'left':\n return { ...defaultPositions, top: '0%', right: '105%' }\n case 'bottom':\n return { ...defaultPositions, top: '110%' }\n case 'top':\n return { ...defaultPositions, bottom: '110%' }\n default:\n return defaultPositions\n }\n}\n\nconst navListStyles = vstack({\n alignItems: 'flex-start',\n bgColor: 'neutral.surface.100',\n boxShadow: 'lg',\n gap: '2',\n opacity: '0',\n p: '4',\n position: 'absolute',\n rounded: 'md',\n zIndex: 'dropdown',\n _motionSafe: {\n animationName: 'zoomIn',\n animationDelay: '100ms',\n animationDuration: '150ms',\n animationFillMode: 'both',\n animationTimingFunction: 'ease-in-out',\n },\n _positionBottom: {\n transformOrigin: 'top left',\n },\n _positionTop: {\n transformOrigin: 'bottom left',\n },\n _positionLeft: {\n transformOrigin: 'top right',\n },\n _positionRight: {\n transformOrigin: 'top left',\n },\n})\n\nexport interface NavMenuListProps extends HTMLAttributes<HTMLUListElement> {\n id: string\n position?: Positions\n}\n\n/**\n * A component that allows the user to display a menu of navigation links.\n * @definition [Disclosure Nav](https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/examples/disclosure-navigation/)\n * @definition [NavMenu Docs](https://cerberus.digitalu.design/react/nav-menu)\n *\n * @example\n * ```tsx\n * <NavMenuList id=\"nav-menu-list\" position=\"bottom\">\n * <NavMenuLink href=\"/home\">Home</NavMenuLink>\n * <NavMenuLink href=\"/about\">About</NavMenuLink>\n * </NavMenuList>\n * ```\n **/\nexport function NavMenuList(props: NavMenuListProps): JSX.Element {\n const { position, ...nativeProps } = props\n const { menuRef, expanded } = useNavMenuContext()\n const locationStyles = useMemo(\n () => getPosition(position ?? 'bottom'),\n [position],\n )\n\n return (\n <Show when={expanded}>\n <ul\n {...nativeProps}\n data-position={position ?? 'bottom'}\n className={cx(nativeProps.className, navListStyles)}\n ref={menuRef}\n style={locationStyles}\n />\n </Show>\n )\n}\n"],"mappings":";;;;;;;;AAEA,SAAS,eAAoC;AAC7C,SAAS,UAAU;AACnB,SAAS,cAAc;AA4FjB;AAhFC,SAAS,YAAY,UAAwC;AAClE,QAAM,mBAAmB;AAAA,IACvB,MAAM;AAAA,IACN,OAAO;AAAA,IACP,KAAK;AAAA,IACL,QAAQ;AAAA,EACV;AACA,UAAQ,UAAU;AAAA,IAChB,KAAK;AACH,aAAO,EAAE,GAAG,kBAAkB,KAAK,MAAM,MAAM,OAAO;AAAA,IACxD,KAAK;AACH,aAAO,EAAE,GAAG,kBAAkB,KAAK,MAAM,OAAO,OAAO;AAAA,IACzD,KAAK;AACH,aAAO,EAAE,GAAG,kBAAkB,KAAK,OAAO;AAAA,IAC5C,KAAK;AACH,aAAO,EAAE,GAAG,kBAAkB,QAAQ,OAAO;AAAA,IAC/C;AACE,aAAO;AAAA,EACX;AACF;AAEA,IAAM,gBAAgB,OAAO;AAAA,EAC3B,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,WAAW;AAAA,EACX,KAAK;AAAA,EACL,SAAS;AAAA,EACT,GAAG;AAAA,EACH,UAAU;AAAA,EACV,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,aAAa;AAAA,IACX,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,mBAAmB;AAAA,IACnB,mBAAmB;AAAA,IACnB,yBAAyB;AAAA,EAC3B;AAAA,EACA,iBAAiB;AAAA,IACf,iBAAiB;AAAA,EACnB;AAAA,EACA,cAAc;AAAA,IACZ,iBAAiB;AAAA,EACnB;AAAA,EACA,eAAe;AAAA,IACb,iBAAiB;AAAA,EACnB;AAAA,EACA,gBAAgB;AAAA,IACd,iBAAiB;AAAA,EACnB;AACF,CAAC;AAoBM,SAAS,YAAY,OAAsC;AAChE,QAAM,EAAE,UAAU,GAAG,YAAY,IAAI;AACrC,QAAM,EAAE,SAAS,SAAS,IAAI,kBAAkB;AAChD,QAAM,iBAAiB;AAAA,IACrB,MAAM,YAAY,YAAY,QAAQ;AAAA,IACtC,CAAC,QAAQ;AAAA,EACX;AAEA,SACE,oBAAC,QAAK,MAAM,UACV;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ,iBAAe,YAAY;AAAA,MAC3B,WAAW,GAAG,YAAY,WAAW,aAAa;AAAA,MAClD,KAAK;AAAA,MACL,OAAO;AAAA;AAAA,EACT,GACF;AAEJ;","names":[]}