@infonomic/uikit 2.0.0 → 2.1.1

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 (314) hide show
  1. package/dist/components/button/index.js +1 -17
  2. package/dist/components/card/card.d.ts.map +1 -1
  3. package/dist/tsconfig.build.tsbuildinfo +1 -1
  4. package/package.json +35 -31
  5. package/src/astro.d.ts +43 -0
  6. package/src/astro.js +2 -2
  7. package/src/components/@types/shared.ts +24 -0
  8. package/src/components/accordion/accordion.module.css +60 -0
  9. package/src/components/accordion/accordion.stories.tsx +117 -0
  10. package/src/components/accordion/accordion.tsx +105 -0
  11. package/src/components/animation/fade-in-lift.stories.tsx +81 -0
  12. package/src/components/animation/fade-in-lift.tsx +42 -0
  13. package/src/components/avatar/avatar.module.css +54 -0
  14. package/src/components/avatar/avatar.stories.tsx +28 -0
  15. package/src/components/avatar/avatar.tsx +19 -0
  16. package/src/components/button/@types/button.ts +17 -0
  17. package/src/components/button/button-group.module.css +17 -0
  18. package/src/components/button/button-group.stories.tsx +45 -0
  19. package/src/components/button/button-group.tsx +132 -0
  20. package/src/components/button/button-icon.stories.tsx +145 -0
  21. package/src/components/button/button-intents.stories.tsx +50 -0
  22. package/src/components/button/button-variants.stories.tsx +60 -0
  23. package/src/components/button/button.astro +86 -0
  24. package/src/components/button/button.module.css +533 -0
  25. package/src/components/button/button.tsx +81 -0
  26. package/src/components/button/control-buttons.module.css +144 -0
  27. package/src/components/button/control-buttons.stories.tsx +60 -0
  28. package/src/components/button/control-buttons.tsx +137 -0
  29. package/src/components/button/copy-button.module.css +31 -0
  30. package/src/components/button/copy-button.stories.tsx +50 -0
  31. package/src/components/button/copy-button.tsx +92 -0
  32. package/src/components/button/icon-button.astro +47 -0
  33. package/src/components/button/icon-button.tsx +44 -0
  34. package/src/components/button/index.ts +5 -0
  35. package/src/components/calendar/calendar.module.css +315 -0
  36. package/src/components/calendar/calendar.stories.tsx +139 -0
  37. package/src/components/calendar/calendar.tsx +173 -0
  38. package/src/components/card/card-content.astro +14 -0
  39. package/src/components/card/card-description.astro +14 -0
  40. package/src/components/card/card-footer.astro +14 -0
  41. package/src/components/card/card-header.astro +14 -0
  42. package/src/components/card/card-title.astro +14 -0
  43. package/src/components/card/card.astro +41 -0
  44. package/src/components/card/card.module.css +67 -0
  45. package/src/components/card/card.stories.tsx +61 -0
  46. package/src/components/card/card.tsx +86 -0
  47. package/src/components/container/container.astro +13 -0
  48. package/src/components/container/container.module.css +28 -0
  49. package/src/components/container/container.stories.tsx +42 -0
  50. package/src/components/container/container.tsx +23 -0
  51. package/src/components/dropdown/dropdown.module.css +131 -0
  52. package/src/components/dropdown/dropdown.stories.tsx +103 -0
  53. package/src/components/dropdown/dropdown.tsx +193 -0
  54. package/src/components/hamburger/hamburger.astro +30 -0
  55. package/src/components/hamburger/hamburger.tsx +66 -0
  56. package/src/components/input/@types/checkbox.ts +20 -0
  57. package/src/components/input/@types/input.ts +20 -0
  58. package/src/components/input/checkbox-group.tsx +78 -0
  59. package/src/components/input/checkbox.module.css +267 -0
  60. package/src/components/input/checkbox.stories.tsx +240 -0
  61. package/src/components/input/checkbox.tsx +95 -0
  62. package/src/components/input/error-text.astro +14 -0
  63. package/src/components/input/error-text.module.css +19 -0
  64. package/src/components/input/error-text.tsx +18 -0
  65. package/src/components/input/errors.tsx +37 -0
  66. package/src/components/input/help-text.astro +13 -0
  67. package/src/components/input/help-text.module.css +19 -0
  68. package/src/components/input/help-text.tsx +13 -0
  69. package/src/components/input/index.tsx +8 -0
  70. package/src/components/input/input-adornment.astro +26 -0
  71. package/src/components/input/input-adornment.module.css +18 -0
  72. package/src/components/input/input-adornment.tsx +36 -0
  73. package/src/components/input/input.astro +99 -0
  74. package/src/components/input/input.module.css +310 -0
  75. package/src/components/input/input.stories.tsx +174 -0
  76. package/src/components/input/input.tsx +103 -0
  77. package/src/components/input/label.astro +24 -0
  78. package/src/components/input/label.module.css +28 -0
  79. package/src/components/input/label.tsx +25 -0
  80. package/src/components/input/radio-group.module.css +219 -0
  81. package/src/components/input/radio-group.stories.tsx +73 -0
  82. package/src/components/input/radio-group.tsx +67 -0
  83. package/src/components/input/select.module.css +75 -0
  84. package/src/components/input/select.stories.tsx +34 -0
  85. package/src/components/input/select.tsx +115 -0
  86. package/src/components/input/text-area.module.css +9 -0
  87. package/src/components/input/text-area.stories.tsx +51 -0
  88. package/src/components/input/text-area.tsx +81 -0
  89. package/src/components/input/utils.ts +21 -0
  90. package/src/components/notifications/@types/alert.ts +12 -0
  91. package/src/components/notifications/@types/toast.ts +12 -0
  92. package/src/components/notifications/alert.module.css +114 -0
  93. package/src/components/notifications/alert.stories.tsx +39 -0
  94. package/src/components/notifications/alert.tsx +117 -0
  95. package/src/components/notifications/index.ts +2 -0
  96. package/src/components/notifications/toast.module.css +237 -0
  97. package/src/components/notifications/toast.stories.tsx +42 -0
  98. package/src/components/notifications/toast.tsx +124 -0
  99. package/src/components/overlay/index.stories.tsx +29 -0
  100. package/src/components/overlay/index.ts +2 -0
  101. package/src/components/overlay/overlay.module.css +41 -0
  102. package/src/components/overlay/overlay.tsx +61 -0
  103. package/src/components/pager/@types/index.ts +2 -0
  104. package/src/components/pager/ellipses.tsx +18 -0
  105. package/src/components/pager/event-pager.tsx +18 -0
  106. package/src/components/pager/first-button.tsx +53 -0
  107. package/src/components/pager/hooks/types/usePagination.ts +80 -0
  108. package/src/components/pager/hooks/usePagination.ts +140 -0
  109. package/src/components/pager/icons/first.tsx +33 -0
  110. package/src/components/pager/icons/index.tsx +4 -0
  111. package/src/components/pager/icons/last.tsx +33 -0
  112. package/src/components/pager/icons/next.tsx +20 -0
  113. package/src/components/pager/icons/previous.tsx +20 -0
  114. package/src/components/pager/index.ts +4 -0
  115. package/src/components/pager/last-button.tsx +57 -0
  116. package/src/components/pager/next-button.tsx +55 -0
  117. package/src/components/pager/number-button.tsx +83 -0
  118. package/src/components/pager/pagination.module.css +165 -0
  119. package/src/components/pager/pagination.stories.tsx +190 -0
  120. package/src/components/pager/pagination.tsx +266 -0
  121. package/src/components/pager/previous-button.tsx +51 -0
  122. package/src/components/scroll-area/scroll-area.module.css +80 -0
  123. package/src/components/scroll-area/scroll-area.stories.tsx +33 -0
  124. package/src/components/scroll-area/scroll-area.tsx +22 -0
  125. package/src/components/scroll-to-top/scroll-to-top.tsx +59 -0
  126. package/src/components/section/section.astro +13 -0
  127. package/src/components/section/section.module.css +7 -0
  128. package/src/components/section/section.tsx +23 -0
  129. package/src/components/shimmer/shimmer.module.css +53 -0
  130. package/src/components/shimmer/shimmer.stories.tsx +24 -0
  131. package/src/components/shimmer/shimmer.tsx +70 -0
  132. package/src/components/table/table.module.css +100 -0
  133. package/src/components/table/table.stories.tsx +95 -0
  134. package/src/components/table/table.tsx +165 -0
  135. package/src/components/tabs/tabs.module.css +64 -0
  136. package/src/components/tabs/tabs.stories.tsx +47 -0
  137. package/src/components/tabs/tabs.tsx +75 -0
  138. package/src/components/timeline/timeline.module.css +87 -0
  139. package/src/components/timeline/timeline.stories.tsx +50 -0
  140. package/src/components/timeline/timeline.tsx +177 -0
  141. package/src/components/tooltip/tooltip.module.css +55 -0
  142. package/src/components/tooltip/tooltip.stories.tsx +59 -0
  143. package/src/components/tooltip/tooltip.tsx +51 -0
  144. package/src/declarations.d.ts +4 -0
  145. package/src/hooks/use-media-query.ts +20 -0
  146. package/src/icons/activity-icon.tsx +40 -0
  147. package/src/icons/calendar-icon.tsx +39 -0
  148. package/src/icons/check-icon.tsx +33 -0
  149. package/src/icons/chevron-down-icon.tsx +39 -0
  150. package/src/icons/chevron-left-double-icon.tsx +58 -0
  151. package/src/icons/chevron-left-icon.tsx +58 -0
  152. package/src/icons/chevron-right-double-icon.tsx +58 -0
  153. package/src/icons/chevron-right-icon.tsx +58 -0
  154. package/src/icons/chevrons-up-down.tsx +37 -0
  155. package/src/icons/close-icon.astro +38 -0
  156. package/src/icons/close-icon.tsx +30 -0
  157. package/src/icons/copy-icon.tsx +35 -0
  158. package/src/icons/danger-icon.tsx +18 -0
  159. package/src/icons/dashboard-icon.tsx +41 -0
  160. package/src/icons/delete-icon.tsx +34 -0
  161. package/src/icons/document-icon.tsx +38 -0
  162. package/src/icons/download-icon.tsx +39 -0
  163. package/src/icons/edit-icon.tsx +35 -0
  164. package/src/icons/ellipsis-icon.tsx +38 -0
  165. package/src/icons/email-icon.tsx +33 -0
  166. package/src/icons/external-link-icon.tsx +39 -0
  167. package/src/icons/github-icon.tsx +27 -0
  168. package/src/icons/globe-icon.tsx +50 -0
  169. package/src/icons/google-icon.tsx +44 -0
  170. package/src/icons/gripper-vertical-icon.tsx +43 -0
  171. package/src/icons/history-icon.tsx +32 -0
  172. package/src/icons/home-icon.tsx +34 -0
  173. package/src/icons/icon-element.astro +27 -0
  174. package/src/icons/icon-element.tsx +32 -0
  175. package/src/icons/icon-sprite.tsx +18 -0
  176. package/src/icons/icons.module.css +147 -0
  177. package/src/icons/index.stories.tsx +25 -0
  178. package/src/icons/index.ts +39 -0
  179. package/src/icons/info-icon.tsx +18 -0
  180. package/src/icons/infonomic-icon.tsx +173 -0
  181. package/src/icons/light-icon.astro +36 -0
  182. package/src/icons/light-icon.tsx +29 -0
  183. package/src/icons/location-pin-icon.tsx +36 -0
  184. package/src/icons/moon-icon.astro +38 -0
  185. package/src/icons/moon-icon.tsx +42 -0
  186. package/src/icons/plus-icon.tsx +34 -0
  187. package/src/icons/primary-icon.tsx +22 -0
  188. package/src/icons/refresh-icon.tsx +33 -0
  189. package/src/icons/return-icon.tsx +36 -0
  190. package/src/icons/roles-icon.tsx +34 -0
  191. package/src/icons/search-icon.astro +40 -0
  192. package/src/icons/search-icon.tsx +29 -0
  193. package/src/icons/search-menu-icon.tsx +42 -0
  194. package/src/icons/settings-gear-icon.tsx +36 -0
  195. package/src/icons/settings-sliders-icon.tsx +43 -0
  196. package/src/icons/sign-out-icon.tsx +35 -0
  197. package/src/icons/source/icon-calendar.svg +1 -0
  198. package/src/icons/source/icon-check.svg +4 -0
  199. package/src/icons/source/icon-close.svg +3 -0
  200. package/src/icons/source/icon-coinbase.svg +9 -0
  201. package/src/icons/source/icon-copy.svg +4 -0
  202. package/src/icons/source/icon-document.svg +5 -0
  203. package/src/icons/source/icon-download.svg +4 -0
  204. package/src/icons/source/icon-edit.svg +6 -0
  205. package/src/icons/source/icon-eth-purple.svg +15 -0
  206. package/src/icons/source/icon-etherscan.svg +5 -0
  207. package/src/icons/source/icon-external-link.svg +4 -0
  208. package/src/icons/source/icon-globe.svg +7 -0
  209. package/src/icons/source/icon-gripper-vertical.svg +9 -0
  210. package/src/icons/source/icon-info.svg +4 -0
  211. package/src/icons/source/icon-infonomic.svg +43 -0
  212. package/src/icons/source/icon-ledger.svg +4 -0
  213. package/src/icons/source/icon-light.svg +3 -0
  214. package/src/icons/source/icon-location-pin.svg +8 -0
  215. package/src/icons/source/icon-logout.svg +6 -0
  216. package/src/icons/source/icon-metamask.svg +32 -0
  217. package/src/icons/source/icon-moon.svg +3 -0
  218. package/src/icons/source/icon-plus.svg +4 -0
  219. package/src/icons/source/icon-refresh.svg +4 -0
  220. package/src/icons/source/icon-return.svg +4 -0
  221. package/src/icons/source/icon-search-menu.svg +13 -0
  222. package/src/icons/source/icon-search.svg +3 -0
  223. package/src/icons/source/icon-settings-gear.svg +5 -0
  224. package/src/icons/source/icon-settings.svg +12 -0
  225. package/src/icons/source/icon-wallet.svg +3 -0
  226. package/src/icons/source/icon-walletconnect.svg +4 -0
  227. package/src/icons/source/icon-x.svg +4 -0
  228. package/src/icons/stopwatch-icon.tsx +39 -0
  229. package/src/icons/success-icon.tsx +18 -0
  230. package/src/icons/types/icon.ts +8 -0
  231. package/src/icons/user-icon.tsx +33 -0
  232. package/src/icons/users-icon.tsx +35 -0
  233. package/src/icons/wallet-icon.tsx +29 -0
  234. package/src/icons/warning-icon.tsx +18 -0
  235. package/src/icons/x-icon.tsx +33 -0
  236. package/src/loaders/ellipses.tsx +36 -0
  237. package/src/loaders/loaders.stories.tsx +46 -0
  238. package/src/loaders/ring.tsx +33 -0
  239. package/src/loaders/spinner.tsx +28 -0
  240. package/src/loaders/types/index.ts +6 -0
  241. package/src/react.ts +99 -0
  242. package/src/styles/base/animations.css +143 -0
  243. package/src/styles/base/base.css +5 -0
  244. package/src/styles/base/colors.css +163 -0
  245. package/src/styles/base/colors.stories.tsx +671 -0
  246. package/src/styles/base/reset.css +464 -0
  247. package/src/styles/base/typography.css +25 -0
  248. package/src/styles/base/vars.css +188 -0
  249. package/src/styles/components/card.css +20 -0
  250. package/src/styles/components/checkbox.css +55 -0
  251. package/src/styles/components/components.css +11 -0
  252. package/src/styles/components/directional-button.css +92 -0
  253. package/src/styles/components/dropdown.css +19 -0
  254. package/src/styles/components/fade-in-lift.css +13 -0
  255. package/src/styles/components/hamburger.css +107 -0
  256. package/src/styles/components/icon-element.css +4 -0
  257. package/src/styles/components/list-checkbox.css +60 -0
  258. package/src/styles/components/loaders.css +196 -0
  259. package/src/styles/components/popover.css +15 -0
  260. package/src/styles/components/scroll-to-top.css +89 -0
  261. package/src/styles/components/toast.css +18 -0
  262. package/src/styles/styles.css +6 -0
  263. package/src/styles/theme/autofill.css +58 -0
  264. package/src/styles/theme/scrollers.css +52 -0
  265. package/src/styles/theme/theme.css +130 -0
  266. package/src/styles/theme/theme.stories.tsx +33 -0
  267. package/src/styles/typography/code.stories.tsx +76 -0
  268. package/src/styles/typography/default.stories.tsx +51 -0
  269. package/src/styles/typography/fonts.css +30 -0
  270. package/src/styles/typography/lists.stories.tsx +50 -0
  271. package/src/styles/typography/prose.css +404 -0
  272. package/src/styles/typography/quote.stories.tsx +37 -0
  273. package/src/styles/typography.css +24 -0
  274. package/src/styles/utils/scroll-layout-shift.css +9 -0
  275. package/src/styles/utils/utility-classes.css +1278 -0
  276. package/src/styles/utils/utils.css +2 -0
  277. package/src/theme/theme-provider/index.ts +1 -0
  278. package/src/theme/theme-provider/provider.tsx +44 -0
  279. package/src/utils/capitalize.ts +6 -0
  280. package/src/utils/externalLinkProps.ts +6 -0
  281. package/src/utils/findMatch.ts +7 -0
  282. package/src/utils/getPortalRoot.ts +3 -0
  283. package/src/utils/isTouchDevice.ts +11 -0
  284. package/src/utils/objectsToArray.ts +15 -0
  285. package/src/utils/objectsToString.ts +5 -0
  286. package/src/utils/polymorphic.ts +16 -0
  287. package/src/utils/to-kebab-case.ts +5 -0
  288. package/src/widgets/datepicker/datepicker.module.css +189 -0
  289. package/src/widgets/datepicker/datepicker.stories.tsx +25 -0
  290. package/src/widgets/datepicker/datepicker.tsx +310 -0
  291. package/src/widgets/drawer/drawer-container.tsx +26 -0
  292. package/src/widgets/drawer/drawer-content.tsx +26 -0
  293. package/src/widgets/drawer/drawer-context.tsx +49 -0
  294. package/src/widgets/drawer/drawer-header.tsx +27 -0
  295. package/src/widgets/drawer/drawer-top-actions.tsx +27 -0
  296. package/src/widgets/drawer/drawer-wrapper.tsx +54 -0
  297. package/src/widgets/drawer/drawer.module.css +116 -0
  298. package/src/widgets/drawer/drawer.stories.tsx +224 -0
  299. package/src/widgets/drawer/drawer.tsx +115 -0
  300. package/src/widgets/drawer/motionDomAnimation.ts +4 -0
  301. package/src/widgets/drawer/motionDomMax.ts +4 -0
  302. package/src/widgets/modal/modal-actions.tsx +26 -0
  303. package/src/widgets/modal/modal-container.tsx +26 -0
  304. package/src/widgets/modal/modal-content.tsx +26 -0
  305. package/src/widgets/modal/modal-header.tsx +27 -0
  306. package/src/widgets/modal/modal-wrapper.tsx +50 -0
  307. package/src/widgets/modal/modal.module.css +85 -0
  308. package/src/widgets/modal/modal.stories.tsx +71 -0
  309. package/src/widgets/modal/modal.tsx +110 -0
  310. package/src/widgets/modal/motionDomAnimation.ts +4 -0
  311. package/src/widgets/modal/motionDomMax.ts +4 -0
  312. package/src/widgets/search/index.ts +1 -0
  313. package/src/widgets/search/search.stories.tsx +18 -0
  314. package/src/widgets/search/search.tsx +186 -0
@@ -0,0 +1,26 @@
1
+ 'use client'
2
+ import type * as React from 'react'
3
+
4
+ import cx from 'classnames'
5
+
6
+ import styles from './drawer.module.css'
7
+
8
+ type DrawerContentIntrinsicProps = React.JSX.IntrinsicElements['div']
9
+ export interface DrawerContentProps extends DrawerContentIntrinsicProps {
10
+ className?: string
11
+ }
12
+
13
+ export function DrawerContent({
14
+ ref,
15
+ children,
16
+ className,
17
+ ...rest
18
+ }: DrawerContentProps & {
19
+ ref?: React.RefObject<HTMLDivElement>
20
+ }) {
21
+ return (
22
+ <div ref={ref} {...rest} className={cx(styles['drawer-content'], className)}>
23
+ {children}
24
+ </div>
25
+ )
26
+ }
@@ -0,0 +1,49 @@
1
+ 'use client'
2
+
3
+ import type React from 'react'
4
+
5
+ import { createContext, useCallback, useContext, useState } from 'react'
6
+
7
+ import type { ReactNode } from 'react'
8
+
9
+ interface DrawerContextType {
10
+ drawers: string[]
11
+ addDrawer: (id: string) => void
12
+ removeDrawer: (id: string) => void
13
+ }
14
+
15
+ const DrawerContext = createContext<DrawerContextType>({
16
+ drawers: [],
17
+ addDrawer: () => {},
18
+ removeDrawer: () => {},
19
+ })
20
+
21
+ interface DrawerProviderProps {
22
+ children: ReactNode
23
+ }
24
+
25
+ export const DrawerProvider: React.FC<DrawerProviderProps> = ({ children }) => {
26
+ const [drawers, setDrawers] = useState<string[]>([])
27
+
28
+ const addDrawer = useCallback((id: string) => {
29
+ setDrawers((prev) => [...prev, id])
30
+ }, [])
31
+
32
+ const removeDrawer = useCallback((id: string) => {
33
+ setDrawers((prev) => prev.filter((drawerId) => drawerId !== id))
34
+ }, [])
35
+
36
+ return (
37
+ <DrawerContext.Provider value={{ drawers, addDrawer, removeDrawer }}>
38
+ {children}
39
+ </DrawerContext.Provider>
40
+ )
41
+ }
42
+
43
+ export function useDrawer(): DrawerContextType {
44
+ const context = useContext(DrawerContext)
45
+ if (context === undefined) {
46
+ throw new Error('useDrawer must be used within a DrawerProvider')
47
+ }
48
+ return context
49
+ }
@@ -0,0 +1,27 @@
1
+ 'use client'
2
+ import type * as React from 'react'
3
+
4
+ import cx from 'classnames'
5
+
6
+ import styles from './drawer.module.css'
7
+
8
+ type DrawerHeaderIntrinsicProps = React.JSX.IntrinsicElements['div']
9
+ export interface DrawerHeaderProps extends DrawerHeaderIntrinsicProps {
10
+ className?: string
11
+ }
12
+
13
+ export const DrawerHeader = function DrawerHeader({
14
+ ref,
15
+ children,
16
+ className,
17
+ ...rest
18
+ }: DrawerHeaderProps & {
19
+ ref?: React.RefObject<HTMLDivElement>
20
+ }) {
21
+ const classes = cx(styles['drawer-header'], className)
22
+ return (
23
+ <div style={{ overflowWrap: 'anywhere' }} ref={ref} {...rest} className={classes}>
24
+ {children}
25
+ </div>
26
+ )
27
+ }
@@ -0,0 +1,27 @@
1
+ 'use client'
2
+ import type * as React from 'react'
3
+
4
+ import cx from 'classnames'
5
+
6
+ import styles from './drawer.module.css'
7
+
8
+ type DrawerTopActionIntrinsicProps = React.JSX.IntrinsicElements['div']
9
+ export interface DrawerTopActionProps extends DrawerTopActionIntrinsicProps {
10
+ className?: string
11
+ }
12
+
13
+ export const DrawerTopActions = function DrawerHeader({
14
+ ref,
15
+ children,
16
+ className,
17
+ ...rest
18
+ }: DrawerTopActionProps & {
19
+ ref?: React.RefObject<HTMLDivElement>
20
+ }) {
21
+ const classes = cx(styles['drawer-top-actions'], className)
22
+ return (
23
+ <div style={{ whiteSpace: 'nowrap' }} ref={ref} {...rest} className={classes}>
24
+ {children}
25
+ </div>
26
+ )
27
+ }
@@ -0,0 +1,54 @@
1
+ 'use client'
2
+ /* eslint-disable @typescript-eslint/consistent-type-imports */
3
+ import type React from 'react'
4
+ import { useEffect } from 'react'
5
+
6
+ import cx from 'classnames'
7
+
8
+ import { useFocusTrap } from '@mantine/hooks'
9
+ import { m } from 'motion/react'
10
+
11
+ import type { HTMLMotionProps } from 'motion/react'
12
+
13
+ import styles from './drawer.module.css'
14
+
15
+ export interface DrawerWrapperProps extends HTMLMotionProps<'div'> {
16
+ className?: string
17
+ children: React.ReactNode
18
+ onEscapeKey?: (e: any) => void
19
+ }
20
+
21
+ export function DrawerWrapper({
22
+ className,
23
+ children,
24
+ onEscapeKey,
25
+ ...rest
26
+ }: DrawerWrapperProps): React.JSX.Element {
27
+ const focusTrapRef = useFocusTrap()
28
+
29
+ useEffect(() => {
30
+ const handleKeyDown = (event: KeyboardEvent) => {
31
+ if (event.key === 'Escape' && onEscapeKey) {
32
+ onEscapeKey(event)
33
+ }
34
+ }
35
+
36
+ document.addEventListener('keydown', handleKeyDown)
37
+ return () => {
38
+ document.removeEventListener('keydown', handleKeyDown)
39
+ }
40
+ }, [onEscapeKey])
41
+
42
+ return (
43
+ <m.div
44
+ ref={focusTrapRef}
45
+ {...rest}
46
+ className={cx(styles['drawer-wrapper'], className)}
47
+ initial={{ opacity: 0 }}
48
+ animate={{ opacity: 1 }}
49
+ exit={{ opacity: 0 }}
50
+ >
51
+ {children}
52
+ </m.div>
53
+ )
54
+ }
@@ -0,0 +1,116 @@
1
+ @layer infonomic-base, infonomic-utilities, infonomic-theme, infonomic-components;
2
+
3
+ @layer infonomic-components {
4
+ .drawer-wrapper {
5
+ position: fixed;
6
+ display: flex;
7
+ flex-direction: column;
8
+ justify-content: end;
9
+ top: 0;
10
+ left: 0;
11
+ right: 0;
12
+ bottom: 0;
13
+ z-index: 30;
14
+ opacity: 1;
15
+ }
16
+
17
+
18
+ .drawer-container {
19
+ position: absolute;
20
+ right: 0;
21
+ height: 100%;
22
+ background-color: var(--canvas-25);
23
+ box-shadow: var(--shadow-md);
24
+ z-index: inherit;
25
+ }
26
+
27
+ .drawer-container[aria-hidden="false"] {
28
+ animation: slideIn 150ms cubic-bezier(0.16, 1, 0.3, 1);
29
+ }
30
+
31
+ .drawer-container:is(:global(.dark) *) {
32
+ background: var(--canvas-800);
33
+ }
34
+
35
+ .drawer-depth-0.drawer-medium .drawer-container,
36
+ .drawer-depth-0.drawer-wide .drawer-container {
37
+ width: 90%;
38
+ }
39
+
40
+ .drawer-depth-1.drawer-medium .drawer-container,
41
+ .drawer-depth-1.drawer-wide .drawer-container {
42
+ width: 88%;
43
+ }
44
+
45
+ .drawer-depth-2.drawer- .drawer-container,
46
+ .drawer-depth-2.drawer-wide .drawer-container {
47
+ width: 86%;
48
+ }
49
+
50
+ @media (min-width: 768px) {
51
+ .drawer-depth-0.drawer-medium .drawer-container {
52
+ width: 600px;
53
+ }
54
+
55
+ .drawer-depth-1.drawer-medium .drawer-container {
56
+ width: 580px;
57
+ }
58
+
59
+ .drawer-depth-2.drawer- .drawer-container {
60
+ width: 560px;
61
+ }
62
+ }
63
+
64
+ .drawer-narrow .drawer-container {
65
+ width: calc(100% - 32px);
66
+ max-width: 400px
67
+ }
68
+
69
+ .drawer-container[aria-hidden="true"] {
70
+ transform: translateX(100%);
71
+ opacity: 0;
72
+ }
73
+
74
+ .drawer-top-actions {
75
+ display: flex;
76
+ align-items: center;
77
+ justify-content: flex-end;
78
+ padding-top: var(--spacing-3);
79
+ padding-left: var(--spacing-6);
80
+ padding-right: var(--spacing-6);
81
+ padding-bottom: 0;
82
+ max-width: 100%;
83
+ }
84
+
85
+ .drawer-header {
86
+ display: flex;
87
+ align-items: center;
88
+ justify-content: space-between;
89
+ gap: var(--gap-3);
90
+ padding-top: 0;
91
+ padding-left: var(--spacing-6);
92
+ padding-right: var(--spacing-6);
93
+ max-width: 100%;
94
+ }
95
+
96
+ .drawer-header h2,
97
+ .drawer-header h3 {
98
+ margin: 0;
99
+ }
100
+
101
+ .drawer-content {
102
+ padding: var(--spacing-6);
103
+ }
104
+
105
+ @keyframes slideIn {
106
+ from {
107
+ transform: translateX(100%);
108
+ opacity: 0;
109
+ }
110
+
111
+ to {
112
+ transform: translateX(0);
113
+ opacity: 1;
114
+ }
115
+ }
116
+ }
@@ -0,0 +1,224 @@
1
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
2
+ import React from 'react'
3
+
4
+ import { Button } from '../../components/button/button.js'
5
+ import { IconButton } from '../../components/button/icon-button.js'
6
+ import { CloseIcon } from '../../icons/close-icon.js'
7
+
8
+ import { Drawer } from './drawer.js'
9
+
10
+ export default {
11
+ title: 'Widgets/Drawer',
12
+ component: Drawer,
13
+ argTypes: {},
14
+ }
15
+
16
+ export const Default = (): React.JSX.Element => {
17
+ const [isOpen, setIsOpen] = React.useState(false)
18
+
19
+ const whiteIcon = `
20
+ .white-icon {
21
+ fill: white;
22
+ }
23
+
24
+ .dark .white-icon {
25
+ fill: black;
26
+ }
27
+ `
28
+
29
+ return (
30
+ <>
31
+ <style>{whiteIcon}</style>
32
+ <Button
33
+ onClick={() => {
34
+ setIsOpen(true)
35
+ }}
36
+ >
37
+ Open Drawer
38
+ </Button>
39
+ <Drawer
40
+ id="first-drawer"
41
+ closeOnOverlayClick={true}
42
+ isOpen={isOpen}
43
+ onDismiss={() => setIsOpen(false)}
44
+ >
45
+ <Drawer.Container aria-hidden={!isOpen}>
46
+ <Drawer.TopActions>
47
+ <button type="button" tabIndex={0} className="sr-only">
48
+ no action
49
+ </button>
50
+ <IconButton
51
+ arial-label="Close"
52
+ size="xs"
53
+ onClick={() => {
54
+ setIsOpen(false)
55
+ }}
56
+ >
57
+ <CloseIcon width="14px" height="14px" svgClassName="white-icon" />
58
+ </IconButton>
59
+ </Drawer.TopActions>
60
+ <Drawer.Header className="flex items-center justify-between mb-4">
61
+ <h2>Drawer Actions Here</h2>
62
+ </Drawer.Header>
63
+ <Drawer.Content>
64
+ <p>Drawer content here...</p>
65
+ </Drawer.Content>
66
+ </Drawer.Container>
67
+ </Drawer>
68
+ </>
69
+ )
70
+ }
71
+
72
+ const whiteIcon = `
73
+ .white-icon {
74
+ fill: white;
75
+ }
76
+
77
+ .dark .white-icon {
78
+ fill: black;
79
+ }
80
+ `
81
+
82
+ export const Wide = (): React.JSX.Element => {
83
+ const [isOpen, setIsOpen] = React.useState(false)
84
+
85
+ return (
86
+ <>
87
+ <style>{whiteIcon}</style>
88
+ <Button
89
+ onClick={() => {
90
+ setIsOpen(true)
91
+ }}
92
+ >
93
+ Open Drawer
94
+ </Button>
95
+ <Drawer
96
+ id="first-drawer"
97
+ closeOnOverlayClick={true}
98
+ isOpen={isOpen}
99
+ width="wide"
100
+ onDismiss={() => setIsOpen(false)}
101
+ >
102
+ <Drawer.Container aria-hidden={!isOpen}>
103
+ <Drawer.TopActions>
104
+ <button type="button" tabIndex={0} className="sr-only">
105
+ no action
106
+ </button>
107
+ <IconButton
108
+ arial-label="Close"
109
+ size="xs"
110
+ onClick={() => {
111
+ setIsOpen(false)
112
+ }}
113
+ >
114
+ <CloseIcon width="14px" height="14px" svgClassName="white-icon" />
115
+ </IconButton>
116
+ </Drawer.TopActions>
117
+ <Drawer.Header className="flex items-center justify-between mb-4">
118
+ <h2>Drawer Actions Here</h2>
119
+ </Drawer.Header>
120
+ <Drawer.Content>
121
+ <p>Drawer content here...</p>
122
+ </Drawer.Content>
123
+ </Drawer.Container>
124
+ </Drawer>
125
+ </>
126
+ )
127
+ }
128
+
129
+ export const Nested = (): React.JSX.Element => {
130
+ const [isOpen1, setIsOpen1] = React.useState(false)
131
+ const [isOpen2, setIsOpen2] = React.useState(false)
132
+
133
+ const whiteIcon = `
134
+ .white-icon {
135
+ fill: white;
136
+ }
137
+
138
+ .dark .white-icon {
139
+ fill: black;
140
+ }
141
+ `
142
+
143
+ return (
144
+ <>
145
+ <style>{whiteIcon}</style>
146
+ <Button
147
+ onClick={() => {
148
+ setIsOpen1(true)
149
+ }}
150
+ >
151
+ Open Drawer 1
152
+ </Button>
153
+ <Drawer
154
+ id="first-drawer"
155
+ width="medium"
156
+ closeOnOverlayClick={true}
157
+ isOpen={isOpen1}
158
+ onDismiss={() => setIsOpen1(false)}
159
+ >
160
+ <Drawer.Container aria-hidden={!isOpen1}>
161
+ <Drawer.TopActions>
162
+ <button type="button" tabIndex={0} className="sr-only">
163
+ no action
164
+ </button>
165
+ <IconButton
166
+ arial-label="Close"
167
+ size="xs"
168
+ onClick={() => {
169
+ setIsOpen1(false)
170
+ }}
171
+ >
172
+ <CloseIcon width="14px" height="14px" svgClassName="white-icon" />
173
+ </IconButton>
174
+ </Drawer.TopActions>
175
+ <Drawer.Header className="flex items-center justify-between mb-4">
176
+ <h2>Drawer 1</h2>
177
+ </Drawer.Header>
178
+ <Drawer.Content>
179
+ <>
180
+ <p>Drawer 1 actions here...</p>
181
+ <Button
182
+ onClick={() => {
183
+ setIsOpen2(true)
184
+ }}
185
+ >
186
+ Open Drawer 2
187
+ </Button>
188
+ <Drawer
189
+ id="second-drawer"
190
+ width="medium"
191
+ closeOnOverlayClick={true}
192
+ isOpen={isOpen2}
193
+ onDismiss={() => setIsOpen2(false)}
194
+ >
195
+ <Drawer.Container aria-hidden={!isOpen2}>
196
+ <Drawer.TopActions>
197
+ <button type="button" tabIndex={0} className="sr-only">
198
+ no action
199
+ </button>
200
+ <IconButton
201
+ arial-label="Close"
202
+ size="xs"
203
+ onClick={() => {
204
+ setIsOpen2(false)
205
+ }}
206
+ >
207
+ <CloseIcon width="14px" height="14px" svgClassName="white-icon" />
208
+ </IconButton>
209
+ </Drawer.TopActions>
210
+ <Drawer.Header className="flex items-center justify-between mb-4">
211
+ <h2>Drawer 2</h2>
212
+ </Drawer.Header>
213
+ <Drawer.Content>
214
+ <p>Drawer content here...</p>
215
+ </Drawer.Content>
216
+ </Drawer.Container>
217
+ </Drawer>
218
+ </>
219
+ </Drawer.Content>
220
+ </Drawer.Container>
221
+ </Drawer>
222
+ </>
223
+ )
224
+ }
@@ -0,0 +1,115 @@
1
+ 'use client'
2
+ import type React from 'react'
3
+
4
+ import cx from 'classnames'
5
+
6
+ import { AnimatePresence, type FeatureBundle, LazyMotion } from 'motion/react'
7
+ import { useEffect } from 'react'
8
+ import { createPortal } from 'react-dom'
9
+ import { Overlay } from '../../components/overlay'
10
+ import { useMediaQuery } from '../../hooks/use-media-query'
11
+ import { getPortalRoot } from '../../utils/getPortalRoot'
12
+ import { useDrawer } from './drawer-context'
13
+
14
+ import { DrawerContainer } from './drawer-container'
15
+ import { DrawerContent } from './drawer-content'
16
+ import { DrawerHeader } from './drawer-header'
17
+ import { DrawerTopActions } from './drawer-top-actions'
18
+ import { DrawerWrapper } from './drawer-wrapper'
19
+
20
+ import type { ReactNode } from 'react'
21
+
22
+ import styles from './drawer.module.css'
23
+
24
+ type Styles = {
25
+ [key: string]: string
26
+ }
27
+
28
+ const typedStyles: Styles = styles
29
+
30
+ const DomMax: () => Promise<FeatureBundle> = async () =>
31
+ await import('./motionDomMax').then((mod) => mod.default)
32
+ const DomAnimation: () => Promise<FeatureBundle> = async () =>
33
+ await import('./motionDomAnimation').then((mod) => mod.default)
34
+
35
+ export interface DrawerProps {
36
+ id: string
37
+ isOpen: boolean
38
+ closeOnOverlayClick?: boolean
39
+ onDismiss: () => void
40
+ children: ReactNode
41
+ width?: 'narrow' | 'medium' | 'wide'
42
+ topOffset?: string
43
+ }
44
+
45
+ const Drawer = ({
46
+ id,
47
+ isOpen,
48
+ onDismiss,
49
+ closeOnOverlayClick,
50
+ children,
51
+ width = 'narrow',
52
+ topOffset = '0',
53
+ ...rest
54
+ }: DrawerProps) => {
55
+ const isMobile = useMediaQuery('(max-width: 768px)') ?? false
56
+ const { addDrawer, removeDrawer, drawers } = useDrawer()
57
+ const depth = drawers.indexOf(id)
58
+
59
+ const handleOverlayDismiss = (e: any): void => {
60
+ e.stopPropagation()
61
+ e.preventDefault()
62
+ if (closeOnOverlayClick === true) {
63
+ onDismiss?.()
64
+ }
65
+ }
66
+
67
+ useEffect(() => {
68
+ if (isOpen) {
69
+ addDrawer(id)
70
+ } else {
71
+ removeDrawer(id)
72
+ }
73
+ return () => removeDrawer(id)
74
+ }, [isOpen, id, addDrawer, removeDrawer])
75
+
76
+ const portal = getPortalRoot()
77
+
78
+ if (portal === false) return null
79
+
80
+ return createPortal(
81
+ <LazyMotion features={isMobile ? DomMax : DomAnimation}>
82
+ <AnimatePresence>
83
+ {isOpen === true && (
84
+ <DrawerWrapper
85
+ style={{ zIndex: 20 + depth, top: topOffset }}
86
+ transition={{ duration: 0.2 }}
87
+ onEscapeKey={handleOverlayDismiss}
88
+ className={cx(
89
+ typedStyles[`drawer-${width}`],
90
+ typedStyles[`drawer-depth-${depth.toString()}`]
91
+ )}
92
+ {...rest}
93
+ >
94
+ <Overlay
95
+ onClick={handleOverlayDismiss}
96
+ style={{ top: topOffset }}
97
+ isUnmounting={!(isOpen ?? false)}
98
+ />
99
+ {children}
100
+ </DrawerWrapper>
101
+ )}
102
+ </AnimatePresence>
103
+ </LazyMotion>,
104
+ portal
105
+ )
106
+ }
107
+
108
+ Drawer.displayName = 'Drawer'
109
+
110
+ Drawer.Container = DrawerContainer
111
+ Drawer.Content = DrawerContent
112
+ Drawer.Header = DrawerHeader
113
+ Drawer.TopActions = DrawerTopActions
114
+
115
+ export { Drawer }
@@ -0,0 +1,4 @@
1
+ 'use client'
2
+ import { domAnimation } from 'motion/react'
3
+
4
+ export default domAnimation
@@ -0,0 +1,4 @@
1
+ 'use client'
2
+ import { domMax } from 'motion/react'
3
+
4
+ export default domMax
@@ -0,0 +1,26 @@
1
+ 'use client'
2
+ import type * as React from 'react'
3
+
4
+ import cx from 'classnames'
5
+
6
+ import styles from './modal.module.css'
7
+
8
+ type ModalActionsIntrinsicProps = React.JSX.IntrinsicElements['div']
9
+ export interface ModalActionsProps extends ModalActionsIntrinsicProps {
10
+ className?: string
11
+ }
12
+
13
+ export const ModalActions = function ModalActions({
14
+ ref,
15
+ children,
16
+ className,
17
+ ...rest
18
+ }: ModalActionsProps & {
19
+ ref?: React.RefObject<HTMLDivElement>
20
+ }) {
21
+ return (
22
+ <div ref={ref} {...rest} className={cx(styles['modal-actions'], className)}>
23
+ {children}
24
+ </div>
25
+ )
26
+ }
@@ -0,0 +1,26 @@
1
+ 'use client'
2
+ import type * as React from 'react'
3
+
4
+ import cx from 'classnames'
5
+
6
+ import styles from './modal.module.css'
7
+
8
+ type ModalContainerIntrinsicProps = React.JSX.IntrinsicElements['div']
9
+ export interface ModalContainerProps extends ModalContainerIntrinsicProps {
10
+ className?: string
11
+ }
12
+
13
+ export const ModalContainer = function ModalContainer({
14
+ ref,
15
+ children,
16
+ className,
17
+ ...rest
18
+ }: ModalContainerProps & {
19
+ ref?: React.RefObject<HTMLDivElement>
20
+ }) {
21
+ return (
22
+ <div ref={ref} className={cx(styles['modal-container'], className)} {...rest}>
23
+ {children}
24
+ </div>
25
+ )
26
+ }