@saas-ui/react 2.11.2 → 3.0.0-alpha.0

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 (232) hide show
  1. package/CHANGELOG.md +7 -154
  2. package/dist/index.cjs +8461 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.d.cts +26 -0
  5. package/dist/index.d.ts +25 -7
  6. package/dist/index.js +8415 -35
  7. package/dist/index.js.map +1 -1
  8. package/package.json +24 -21
  9. package/src/components/accordion.tsx +47 -0
  10. package/src/components/action-bar.tsx +40 -0
  11. package/src/components/alert.tsx +51 -0
  12. package/src/components/app-shell/app-shell.recipe.ts +52 -0
  13. package/src/components/app-shell/app-shell.stories.tsx +51 -0
  14. package/src/components/app-shell/app-shell.tsx +94 -0
  15. package/src/components/app-shell/index.ts +3 -0
  16. package/src/components/avatar.tsx +74 -0
  17. package/src/components/blockquote.tsx +31 -0
  18. package/src/components/breadcrumbs/breadcrumb.stories.tsx +17 -0
  19. package/src/components/breadcrumbs/breadcrumb.tsx +36 -0
  20. package/src/components/breadcrumbs/index.ts +1 -0
  21. package/src/components/breadcrumbs/namespace.ts +8 -0
  22. package/src/components/button/button.recipe.ts +182 -0
  23. package/src/components/button/button.stories.tsx +99 -0
  24. package/src/components/button/button.tsx +55 -0
  25. package/src/components/button/index.ts +2 -0
  26. package/src/components/checkbox/checkbox.tsx +26 -0
  27. package/src/components/checkbox/index.ts +2 -0
  28. package/src/components/checkbox-card.tsx +57 -0
  29. package/src/components/checkbox.tsx +25 -0
  30. package/src/components/clipboard.tsx +107 -0
  31. package/src/components/close-button/close-button.stories.tsx +12 -0
  32. package/src/components/close-button/close-button.tsx +18 -0
  33. package/src/components/close-button/index.ts +2 -0
  34. package/src/components/color-mode.tsx +65 -0
  35. package/src/components/command/command.recipe.ts +17 -0
  36. package/src/components/command/command.stories.tsx +47 -0
  37. package/src/components/command/command.tsx +50 -0
  38. package/src/components/command/index.ts +1 -0
  39. package/src/components/data-list.tsx +37 -0
  40. package/src/components/dialog/dialog.tsx +66 -0
  41. package/src/components/dialog/index.ts +1 -0
  42. package/src/components/dialog/namespace.ts +18 -0
  43. package/src/components/drawer/drawer.tsx +56 -0
  44. package/src/components/drawer/index.ts +3 -0
  45. package/src/components/drawer/namespace.ts +19 -0
  46. package/src/components/empty-state.tsx +34 -0
  47. package/src/components/field.tsx +33 -0
  48. package/src/components/file-button.tsx +166 -0
  49. package/src/components/grid-list/grid-list.recipe.ts +113 -0
  50. package/src/components/hover-card.tsx +35 -0
  51. package/src/components/icon-badge/icon-badge.recipe.ts +57 -0
  52. package/src/components/icon-badge/icon-badge.stories.tsx +38 -0
  53. package/src/components/icon-badge/icon-badge.tsx +59 -0
  54. package/src/components/icon-badge/index.ts +2 -0
  55. package/src/components/icons/create-icon.tsx +41 -0
  56. package/src/components/icons/icons.tsx +121 -0
  57. package/src/components/icons/index.ts +1 -0
  58. package/src/components/input-group/index.ts +1 -0
  59. package/src/components/input-group/input-group.tsx +46 -0
  60. package/src/components/link/index.ts +2 -0
  61. package/src/components/link/link.stories.tsx +17 -0
  62. package/src/components/link/link.test.tsx +33 -0
  63. package/src/components/link/link.tsx +27 -0
  64. package/src/components/link-button.tsx +12 -0
  65. package/src/components/loading-overlay/index.ts +1 -0
  66. package/src/components/loading-overlay/loading-overlay.recipe.ts +61 -0
  67. package/src/components/loading-overlay/loading-overlay.stories.tsx +68 -0
  68. package/src/components/loading-overlay/loading-overlay.tsx +54 -0
  69. package/src/components/loading-overlay/namespace.ts +7 -0
  70. package/src/components/menu.tsx +108 -0
  71. package/src/components/native-select.tsx +57 -0
  72. package/src/components/navbar/index.ts +1 -0
  73. package/src/components/navbar/namespace.ts +9 -0
  74. package/src/components/navbar/navbar.recipe.ts +109 -0
  75. package/src/components/navbar/navbar.stories.tsx +435 -0
  76. package/src/components/navbar/navbar.test.tsx +49 -0
  77. package/src/components/navbar/navbar.tsx +39 -0
  78. package/src/components/number-input/index.ts +2 -0
  79. package/src/components/number-input/number-input.tsx +41 -0
  80. package/src/components/pagination.tsx +207 -0
  81. package/src/components/password-input/index.ts +2 -0
  82. package/src/components/password-input/password-input.tsx +98 -0
  83. package/src/components/persona/index.ts +2 -0
  84. package/src/components/persona/namespace.ts +18 -0
  85. package/src/components/persona/persona-primitive.tsx +220 -0
  86. package/src/components/persona/persona.recipe.ts +94 -0
  87. package/src/components/persona/persona.stories.tsx +101 -0
  88. package/src/components/persona/persona.tsx +143 -0
  89. package/src/components/pin-input/index.ts +2 -0
  90. package/src/components/pin-input/pin-input.tsx +36 -0
  91. package/src/components/popover.tsx +58 -0
  92. package/src/components/progress-circle.tsx +37 -0
  93. package/src/components/progress.tsx +40 -0
  94. package/src/components/prose.tsx +264 -0
  95. package/src/components/provider.tsx +12 -0
  96. package/src/components/radio/index.ts +2 -0
  97. package/src/components/radio/radio.tsx +27 -0
  98. package/src/components/radio-card.tsx +57 -0
  99. package/src/components/radio.tsx +24 -0
  100. package/src/components/rating.tsx +27 -0
  101. package/src/components/search-input/index.ts +2 -0
  102. package/src/components/search-input/search-input.stories.tsx +63 -0
  103. package/src/components/search-input/search-input.tsx +134 -0
  104. package/src/components/segmented-control.tsx +47 -0
  105. package/src/components/select/index.ts +1 -0
  106. package/src/components/select/namespace.ts +18 -0
  107. package/src/components/select/select.tsx +135 -0
  108. package/src/components/sidebar/index.ts +7 -0
  109. package/src/components/sidebar/namespace.ts +27 -0
  110. package/src/components/sidebar/sidebar-item.recipe.ts +65 -0
  111. package/src/components/sidebar/sidebar.recipe.ts +237 -0
  112. package/src/components/sidebar/sidebar.stories.tsx +903 -0
  113. package/src/components/sidebar/sidebar.tsx +204 -0
  114. package/src/components/skeleton.tsx +44 -0
  115. package/src/components/slider.tsx +53 -0
  116. package/src/components/spinner/index.ts +2 -0
  117. package/src/components/spinner/spinner.stories.tsx +19 -0
  118. package/src/components/spinner/spinner.tsx +21 -0
  119. package/src/components/stat.tsx +75 -0
  120. package/src/components/status.tsx +29 -0
  121. package/src/components/stepper-input.tsx +49 -0
  122. package/src/components/steps/index.ts +1 -0
  123. package/src/components/steps/namespace.ts +16 -0
  124. package/src/components/steps/steps.tsx +82 -0
  125. package/src/components/switch/index.ts +3 -0
  126. package/src/components/switch/switch.tsx +39 -0
  127. package/src/components/tag.tsx +39 -0
  128. package/src/components/timeline.tsx +17 -0
  129. package/src/components/toaster.tsx +43 -0
  130. package/src/components/toggle-tip.tsx +62 -0
  131. package/src/components/tooltip.tsx +46 -0
  132. package/src/index.ts +6 -7
  133. package/src/preset.ts +9 -0
  134. package/src/provider/index.ts +4 -0
  135. package/src/provider/sui-provider.tsx +34 -0
  136. package/src/provider/use-link.test.tsx +60 -0
  137. package/src/provider/use-link.tsx +13 -0
  138. package/src/theme/animation-styles.ts +53 -0
  139. package/src/theme/breakpoints.ts +11 -0
  140. package/src/theme/conditions.ts +26 -0
  141. package/src/theme/fluid-font-sizes.ts +65 -0
  142. package/src/theme/global-css.ts +94 -0
  143. package/src/theme/index.ts +72 -0
  144. package/src/theme/layer-styles.ts +116 -0
  145. package/src/theme/recipes/chakra/accordion.ts +145 -0
  146. package/src/theme/recipes/chakra/action-bar.ts +62 -0
  147. package/src/theme/recipes/chakra/alert.ts +157 -0
  148. package/src/theme/recipes/chakra/avatar.ts +141 -0
  149. package/src/theme/recipes/chakra/badge.ts +67 -0
  150. package/src/theme/recipes/chakra/blockquote.ts +83 -0
  151. package/src/theme/recipes/chakra/breadcrumb.ts +94 -0
  152. package/src/theme/recipes/chakra/card.ts +99 -0
  153. package/src/theme/recipes/chakra/checkbox-card.ts +212 -0
  154. package/src/theme/recipes/chakra/checkbox.ts +70 -0
  155. package/src/theme/recipes/chakra/checkmark.ts +83 -0
  156. package/src/theme/recipes/chakra/code.ts +17 -0
  157. package/src/theme/recipes/chakra/collapsible.ts +20 -0
  158. package/src/theme/recipes/chakra/container.ts +26 -0
  159. package/src/theme/recipes/chakra/data-list.ts +80 -0
  160. package/src/theme/recipes/chakra/dialog.ts +225 -0
  161. package/src/theme/recipes/chakra/drawer.ts +201 -0
  162. package/src/theme/recipes/chakra/editable.ts +88 -0
  163. package/src/theme/recipes/chakra/empty-state.ts +88 -0
  164. package/src/theme/recipes/chakra/field.ts +68 -0
  165. package/src/theme/recipes/chakra/fieldset.ts +62 -0
  166. package/src/theme/recipes/chakra/file-upload.ts +96 -0
  167. package/src/theme/recipes/chakra/heading.ts +27 -0
  168. package/src/theme/recipes/chakra/hover-card.ts +68 -0
  169. package/src/theme/recipes/chakra/icon.ts +30 -0
  170. package/src/theme/recipes/chakra/input-addon.ts +40 -0
  171. package/src/theme/recipes/chakra/input.ts +96 -0
  172. package/src/theme/recipes/chakra/kbd.ts +60 -0
  173. package/src/theme/recipes/chakra/link.ts +37 -0
  174. package/src/theme/recipes/chakra/list.ts +67 -0
  175. package/src/theme/recipes/chakra/mark.ts +27 -0
  176. package/src/theme/recipes/chakra/menu.ts +124 -0
  177. package/src/theme/recipes/chakra/native-select.ts +140 -0
  178. package/src/theme/recipes/chakra/number-input.ts +115 -0
  179. package/src/theme/recipes/chakra/pin-input.ts +27 -0
  180. package/src/theme/recipes/chakra/popover.ts +86 -0
  181. package/src/theme/recipes/chakra/progress-circle.ts +94 -0
  182. package/src/theme/recipes/chakra/progress.ts +127 -0
  183. package/src/theme/recipes/chakra/radio-card.ts +220 -0
  184. package/src/theme/recipes/chakra/radio-group.ts +72 -0
  185. package/src/theme/recipes/chakra/radiomark.ts +107 -0
  186. package/src/theme/recipes/chakra/rating-group.ts +94 -0
  187. package/src/theme/recipes/chakra/segment-group.ts +117 -0
  188. package/src/theme/recipes/chakra/select.ts +282 -0
  189. package/src/theme/recipes/chakra/separator.ts +51 -0
  190. package/src/theme/recipes/chakra/skeleton.ts +53 -0
  191. package/src/theme/recipes/chakra/skip-nav-link.ts +34 -0
  192. package/src/theme/recipes/chakra/slider.ts +178 -0
  193. package/src/theme/recipes/chakra/spinner.ts +32 -0
  194. package/src/theme/recipes/chakra/stat.ts +79 -0
  195. package/src/theme/recipes/chakra/status.ts +48 -0
  196. package/src/theme/recipes/chakra/steps.ts +218 -0
  197. package/src/theme/recipes/chakra/switch.ts +167 -0
  198. package/src/theme/recipes/chakra/table.ts +172 -0
  199. package/src/theme/recipes/chakra/tabs.ts +280 -0
  200. package/src/theme/recipes/chakra/tag.ts +131 -0
  201. package/src/theme/recipes/chakra/textarea.ts +88 -0
  202. package/src/theme/recipes/chakra/timeline.ts +138 -0
  203. package/src/theme/recipes/chakra/toast.ts +96 -0
  204. package/src/theme/recipes/chakra/tooltip.ts +40 -0
  205. package/src/theme/recipes.ts +46 -0
  206. package/src/theme/semantic-tokens/colors.ts +403 -0
  207. package/src/theme/semantic-tokens/radii.ts +7 -0
  208. package/src/theme/semantic-tokens/shadows.ts +52 -0
  209. package/src/theme/slot-recipes.ts +104 -0
  210. package/src/theme/text-styles.ts +39 -0
  211. package/src/theme/tokens/animations.ts +8 -0
  212. package/src/theme/tokens/aspect-ratios.ts +10 -0
  213. package/src/theme/tokens/blurs.ts +12 -0
  214. package/src/theme/tokens/borders.ts +9 -0
  215. package/src/theme/tokens/colors.ts +177 -0
  216. package/src/theme/tokens/cursor.ts +12 -0
  217. package/src/theme/tokens/durations.ts +11 -0
  218. package/src/theme/tokens/easings.ts +10 -0
  219. package/src/theme/tokens/font-sizes.ts +20 -0
  220. package/src/theme/tokens/font-weights.ts +13 -0
  221. package/src/theme/tokens/fonts.ts +15 -0
  222. package/src/theme/tokens/keyframes.ts +173 -0
  223. package/src/theme/tokens/letter-spacing.ts +9 -0
  224. package/src/theme/tokens/line-heights.ts +19 -0
  225. package/src/theme/tokens/radius.ts +18 -0
  226. package/src/theme/tokens/sizes.ts +71 -0
  227. package/src/theme/tokens/spacing.ts +38 -0
  228. package/src/theme/tokens/z-indices.ts +34 -0
  229. package/src/theme/utils.ts +46 -0
  230. package/dist/index.d.mts +0 -8
  231. package/dist/index.mjs +0 -11
  232. package/dist/index.mjs.map +0 -1
@@ -0,0 +1,47 @@
1
+ import React from 'react'
2
+
3
+ import { Button, Center, Tooltip, VStack } from '@chakra-ui/react'
4
+
5
+ import { Command } from './command'
6
+
7
+ export default {
8
+ title: 'Components/Command',
9
+ decorators: [
10
+ (Story: any) => (
11
+ <Center height="100%">
12
+ <Story />
13
+ </Center>
14
+ ),
15
+ ],
16
+ }
17
+
18
+ export const Basic = {
19
+ render: () => (
20
+ <VStack>
21
+ <Command>shift+X</Command>
22
+ <Command>A then B</Command>
23
+ <Command>alt or option</Command>
24
+ </VStack>
25
+ ),
26
+ }
27
+
28
+ export const TooltipCommand = {
29
+ render: () => (
30
+ <Tooltip.Root>
31
+ <Tooltip.Trigger>
32
+ <Button>Inbox</Button>
33
+ </Tooltip.Trigger>
34
+ <Tooltip.Positioner>
35
+ <Tooltip.Content>
36
+ <Tooltip.Arrow>
37
+ <Tooltip.ArrowTip />
38
+ </Tooltip.Arrow>
39
+
40
+ <>
41
+ Inbox <Command>G then I</Command>
42
+ </>
43
+ </Tooltip.Content>
44
+ </Tooltip.Positioner>
45
+ </Tooltip.Root>
46
+ ),
47
+ }
@@ -0,0 +1,50 @@
1
+ import * as React from 'react'
2
+
3
+ import { Kbd } from '@chakra-ui/react'
4
+ import {
5
+ type HTMLChakraProps,
6
+ type RecipeProps,
7
+ UnstyledProp,
8
+ createRecipeContext,
9
+ } from '@chakra-ui/react'
10
+
11
+ const { withContext } = createRecipeContext({
12
+ key: 'command',
13
+ })
14
+
15
+ export interface CommandBaseProps extends RecipeProps<'span'>, UnstyledProp {}
16
+
17
+ export interface CommandProps
18
+ extends HTMLChakraProps<'span', CommandBaseProps> {}
19
+
20
+ const Key: React.FC<HTMLChakraProps<'span'>> = ({ children }) => {
21
+ if (typeof children !== 'string') {
22
+ return <>{children}</>
23
+ }
24
+
25
+ if (['then', 'or', '+'].includes(children)) {
26
+ return <span>{children}</span>
27
+ }
28
+
29
+ return <Kbd>{children}</Kbd>
30
+ }
31
+
32
+ export const Command: React.FC<HTMLChakraProps<'span'>> = (props) => {
33
+ const { children, ...rest } = props
34
+
35
+ if (typeof children !== 'string') {
36
+ return <>{children}</>
37
+ }
38
+
39
+ const keys = children.split(/\s|\+/)
40
+
41
+ return (
42
+ <CommandRoot {...rest}>
43
+ {keys.map((key) => (
44
+ <Key key={key}>{key}</Key>
45
+ ))}
46
+ </CommandRoot>
47
+ )
48
+ }
49
+
50
+ const CommandRoot = withContext('span')
@@ -0,0 +1 @@
1
+ export { Command } from './command'
@@ -0,0 +1,37 @@
1
+ import { DataList as ChakraDataList, IconButton } from "@chakra-ui/react"
2
+ import { ToggleTip } from "compositions/ui/toggle-tip"
3
+ import { forwardRef } from "react"
4
+ import { HiOutlineInformationCircle } from "react-icons/hi2"
5
+
6
+ export const DataListRoot = ChakraDataList.Root
7
+
8
+ interface ItemProps extends ChakraDataList.ItemProps {
9
+ label: React.ReactNode
10
+ value: React.ReactNode
11
+ info?: React.ReactNode
12
+ grow?: boolean
13
+ }
14
+
15
+ export const DataListItem = forwardRef<HTMLDivElement, ItemProps>(
16
+ function DataListItem(props, ref) {
17
+ const { label, info, value, children, grow, ...rest } = props
18
+ return (
19
+ <ChakraDataList.Item ref={ref} {...rest}>
20
+ <ChakraDataList.ItemLabel flex={grow ? "1" : undefined}>
21
+ {label}
22
+ {info && (
23
+ <ToggleTip content={info}>
24
+ <IconButton variant="ghost" aria-label="info" size="2xs">
25
+ <HiOutlineInformationCircle />
26
+ </IconButton>
27
+ </ToggleTip>
28
+ )}
29
+ </ChakraDataList.ItemLabel>
30
+ <ChakraDataList.ItemValue flex={grow ? "1" : undefined}>
31
+ {value}
32
+ </ChakraDataList.ItemValue>
33
+ {children}
34
+ </ChakraDataList.Item>
35
+ )
36
+ },
37
+ )
@@ -0,0 +1,66 @@
1
+ import { forwardRef } from 'react'
2
+
3
+ import { Dialog as ChakraDialog, Portal } from '@chakra-ui/react'
4
+
5
+ import { CloseButton } from '#components/close-button'
6
+
7
+ export interface DialogContentProps extends ChakraDialog.ContentProps {
8
+ portalled?: boolean
9
+ portalRef?: React.RefObject<HTMLElement>
10
+ backdrop?: boolean
11
+ }
12
+
13
+ export const DialogContent = forwardRef<HTMLDivElement, DialogContentProps>(
14
+ function DialogContent(props, ref) {
15
+ const {
16
+ children,
17
+ portalled = true,
18
+ portalRef,
19
+ backdrop = true,
20
+ ...rest
21
+ } = props
22
+
23
+ return (
24
+ <Portal disabled={!portalled} container={portalRef}>
25
+ {backdrop && <ChakraDialog.Backdrop />}
26
+ <ChakraDialog.Positioner>
27
+ <ChakraDialog.Content ref={ref} {...rest} asChild={false}>
28
+ {children}
29
+ </ChakraDialog.Content>
30
+ </ChakraDialog.Positioner>
31
+ </Portal>
32
+ )
33
+ },
34
+ )
35
+
36
+ export const DialogCloseTrigger = forwardRef<
37
+ HTMLButtonElement,
38
+ ChakraDialog.CloseTriggerProps
39
+ >(function DialogCloseTrigger(props, ref) {
40
+ return (
41
+ <ChakraDialog.CloseTrigger
42
+ position="absolute"
43
+ top="2"
44
+ insetEnd="2"
45
+ {...props}
46
+ asChild
47
+ >
48
+ <CloseButton size="sm" ref={ref}>
49
+ {props.children}
50
+ </CloseButton>
51
+ </ChakraDialog.CloseTrigger>
52
+ )
53
+ })
54
+
55
+ export type DialogRootProps = ChakraDialog.RootProps
56
+
57
+ export const DialogRoot = ChakraDialog.Root
58
+ export const DialogFooter = ChakraDialog.Footer
59
+ export const DialogHeader = ChakraDialog.Header
60
+ export const DialogBody = ChakraDialog.Body
61
+ export const DialogBackdrop = ChakraDialog.Backdrop
62
+ export const DialogTitle = ChakraDialog.Title
63
+ export const DialogDescription = ChakraDialog.Description
64
+ export const DialogTrigger = ChakraDialog.Trigger
65
+ export const DialogActionTrigger = ChakraDialog.ActionTrigger
66
+ export const DialogContext = ChakraDialog.Context
@@ -0,0 +1 @@
1
+ export * as Dialog from './namespace.ts'
@@ -0,0 +1,18 @@
1
+ export {
2
+ DialogRoot as Root,
3
+ DialogContent as Content,
4
+ DialogCloseTrigger as CloseTrigger,
5
+ DialogHeader as Header,
6
+ DialogBody as Body,
7
+ DialogFooter as Footer,
8
+ DialogActionTrigger as ActionTrigger,
9
+ DialogBackdrop as Backdrop,
10
+ DialogDescription as Description,
11
+ DialogTitle as Title,
12
+ DialogTrigger as Trigger,
13
+ DialogContext as Context,
14
+ } from './dialog.tsx'
15
+ export type {
16
+ DialogContentProps as ContentProps,
17
+ DialogRootProps as RootProps,
18
+ } from './dialog.tsx'
@@ -0,0 +1,56 @@
1
+ import { forwardRef } from 'react'
2
+
3
+ import { Drawer as ChakraDrawer, Portal } from '@chakra-ui/react'
4
+
5
+ import { CloseButton } from '#components/close-button'
6
+
7
+ export interface DrawerContentProps extends ChakraDrawer.ContentProps {
8
+ portalled?: boolean
9
+ portalRef?: React.RefObject<HTMLElement>
10
+ offset?: ChakraDrawer.ContentProps['padding']
11
+ }
12
+
13
+ export const DrawerContent = forwardRef<HTMLDivElement, DrawerContentProps>(
14
+ function DrawerContent(props, ref) {
15
+ const { children, portalled = true, portalRef, offset, ...rest } = props
16
+ return (
17
+ <Portal disabled={!portalled} container={portalRef}>
18
+ <ChakraDrawer.Positioner padding={offset}>
19
+ <ChakraDrawer.Content ref={ref} {...rest} asChild={false}>
20
+ {children}
21
+ </ChakraDrawer.Content>
22
+ </ChakraDrawer.Positioner>
23
+ </Portal>
24
+ )
25
+ },
26
+ )
27
+
28
+ export const DrawerCloseTrigger = forwardRef<
29
+ HTMLButtonElement,
30
+ ChakraDrawer.CloseTriggerProps
31
+ >(function DrawerCloseTrigger(props, ref) {
32
+ return (
33
+ <ChakraDrawer.CloseTrigger
34
+ position="absolute"
35
+ top="2"
36
+ insetEnd="2"
37
+ {...props}
38
+ asChild
39
+ >
40
+ <CloseButton size="sm" ref={ref} />
41
+ </ChakraDrawer.CloseTrigger>
42
+ )
43
+ })
44
+
45
+ export const DrawerTrigger = ChakraDrawer.Trigger
46
+ export const DrawerRoot = ChakraDrawer.Root
47
+ export const DrawerFooter = ChakraDrawer.Footer
48
+ export const DrawerHeader = ChakraDrawer.Header
49
+ export const DrawerBody = ChakraDrawer.Body
50
+ export const DrawerBackdrop = ChakraDrawer.Backdrop
51
+ export const DrawerDescription = ChakraDrawer.Description
52
+ export const DrawerTitle = ChakraDrawer.Title
53
+ export const DrawerActionTrigger = ChakraDrawer.ActionTrigger
54
+ export const DrawerContext = ChakraDrawer.Context
55
+
56
+ export type DrawerRootProps = ChakraDrawer.RootProps
@@ -0,0 +1,3 @@
1
+ import * as Drawer from './namespace.ts'
2
+
3
+ export { Drawer }
@@ -0,0 +1,19 @@
1
+ export {
2
+ DrawerRoot as Root,
3
+ DrawerContent as Content,
4
+ DrawerCloseTrigger as CloseTrigger,
5
+ DrawerHeader as Header,
6
+ DrawerBody as Body,
7
+ DrawerFooter as Footer,
8
+ DrawerActionTrigger as ActionTrigger,
9
+ DrawerBackdrop as Backdrop,
10
+ DrawerDescription as Description,
11
+ DrawerTitle as Title,
12
+ DrawerTrigger as Trigger,
13
+ DrawerContext as Context,
14
+ } from './drawer.tsx'
15
+
16
+ export type {
17
+ DrawerContentProps as ContentProps,
18
+ DrawerRootProps as RootProps,
19
+ } from './drawer.tsx'
@@ -0,0 +1,34 @@
1
+ import { EmptyState as ChakraEmptyState, VStack } from "@chakra-ui/react"
2
+ import { forwardRef } from "react"
3
+
4
+ export interface EmptyStateProps extends ChakraEmptyState.RootProps {
5
+ title: string
6
+ description?: string
7
+ icon?: React.ReactNode
8
+ }
9
+
10
+ export const EmptyState = forwardRef<HTMLDivElement, EmptyStateProps>(
11
+ function EmptyState(props, ref) {
12
+ const { title, description, icon, children, ...rest } = props
13
+ return (
14
+ <ChakraEmptyState.Root ref={ref} {...rest}>
15
+ <ChakraEmptyState.Content>
16
+ {icon && (
17
+ <ChakraEmptyState.Indicator>{icon}</ChakraEmptyState.Indicator>
18
+ )}
19
+ {description ? (
20
+ <VStack textAlign="center">
21
+ <ChakraEmptyState.Title>{title}</ChakraEmptyState.Title>
22
+ <ChakraEmptyState.Description>
23
+ {description}
24
+ </ChakraEmptyState.Description>
25
+ </VStack>
26
+ ) : (
27
+ <ChakraEmptyState.Title>{title}</ChakraEmptyState.Title>
28
+ )}
29
+ {children}
30
+ </ChakraEmptyState.Content>
31
+ </ChakraEmptyState.Root>
32
+ )
33
+ },
34
+ )
@@ -0,0 +1,33 @@
1
+ import { Field as ChakraField } from "@chakra-ui/react"
2
+ import { forwardRef } from "react"
3
+
4
+ export interface FieldProps extends Omit<ChakraField.RootProps, "label"> {
5
+ label?: React.ReactNode
6
+ helperText?: React.ReactNode
7
+ errorText?: React.ReactNode
8
+ optionalText?: React.ReactNode
9
+ }
10
+
11
+ export const Field = forwardRef<HTMLDivElement, FieldProps>(
12
+ function Field(props, ref) {
13
+ const { label, children, helperText, errorText, optionalText, ...rest } =
14
+ props
15
+ return (
16
+ <ChakraField.Root ref={ref} {...rest}>
17
+ {label && (
18
+ <ChakraField.Label>
19
+ {label}
20
+ <ChakraField.RequiredIndicator fallback={optionalText} />
21
+ </ChakraField.Label>
22
+ )}
23
+ {children}
24
+ {helperText && (
25
+ <ChakraField.HelperText>{helperText}</ChakraField.HelperText>
26
+ )}
27
+ {errorText && (
28
+ <ChakraField.ErrorText>{errorText}</ChakraField.ErrorText>
29
+ )}
30
+ </ChakraField.Root>
31
+ )
32
+ },
33
+ )
@@ -0,0 +1,166 @@
1
+ "use client"
2
+
3
+ import type { ButtonProps, RecipeProps } from "@chakra-ui/react"
4
+ import {
5
+ Button,
6
+ FileUpload as ChakraFileUpload,
7
+ Icon,
8
+ IconButton,
9
+ Span,
10
+ Text,
11
+ useFileUploadContext,
12
+ useRecipe,
13
+ } from "@chakra-ui/react"
14
+ import { forwardRef } from "react"
15
+ import { LuFile, LuUpload, LuX } from "react-icons/lu"
16
+
17
+ export interface FileUploadRootProps extends ChakraFileUpload.RootProps {
18
+ inputProps?: React.InputHTMLAttributes<HTMLInputElement>
19
+ }
20
+
21
+ export const FileUploadRoot = forwardRef<HTMLInputElement, FileUploadRootProps>(
22
+ function FileUploadRoot(props, ref) {
23
+ const { children, inputProps, ...rest } = props
24
+ return (
25
+ <ChakraFileUpload.Root {...rest}>
26
+ <ChakraFileUpload.HiddenInput ref={ref} {...inputProps} />
27
+ {children}
28
+ </ChakraFileUpload.Root>
29
+ )
30
+ },
31
+ )
32
+
33
+ export interface FileUploadDropzoneProps
34
+ extends ChakraFileUpload.DropzoneProps {
35
+ label: React.ReactNode
36
+ description?: React.ReactNode
37
+ }
38
+
39
+ export const FileUploadDropzone = forwardRef<
40
+ HTMLInputElement,
41
+ FileUploadDropzoneProps
42
+ >(function FileUploadDropzone(props, ref) {
43
+ const { children, label, description, ...rest } = props
44
+ return (
45
+ <ChakraFileUpload.Dropzone ref={ref} {...rest}>
46
+ <Icon fontSize="xl" color="fg.muted">
47
+ <LuUpload />
48
+ </Icon>
49
+ <ChakraFileUpload.DropzoneContent>
50
+ <div>{label}</div>
51
+ {description && <Text color="fg.muted">{description}</Text>}
52
+ </ChakraFileUpload.DropzoneContent>
53
+ {children}
54
+ </ChakraFileUpload.Dropzone>
55
+ )
56
+ })
57
+
58
+ interface VisibilityProps {
59
+ showSize?: boolean
60
+ clearable?: boolean
61
+ }
62
+
63
+ interface FileUploadItemProps extends VisibilityProps {
64
+ file: File
65
+ }
66
+
67
+ const FileUploadItem = (props: FileUploadItemProps) => {
68
+ const { file, showSize, clearable } = props
69
+ return (
70
+ <ChakraFileUpload.Item file={file}>
71
+ <ChakraFileUpload.ItemPreview asChild>
72
+ <Icon fontSize="lg" color="fg.muted">
73
+ <LuFile />
74
+ </Icon>
75
+ </ChakraFileUpload.ItemPreview>
76
+
77
+ {showSize ? (
78
+ <ChakraFileUpload.ItemContent>
79
+ <ChakraFileUpload.ItemName />
80
+ <ChakraFileUpload.ItemSizeText />
81
+ </ChakraFileUpload.ItemContent>
82
+ ) : (
83
+ <ChakraFileUpload.ItemName flex="1" />
84
+ )}
85
+
86
+ {clearable && (
87
+ <ChakraFileUpload.ItemDeleteTrigger asChild>
88
+ <IconButton variant="ghost" color="fg.muted" size="xs">
89
+ <LuX />
90
+ </IconButton>
91
+ </ChakraFileUpload.ItemDeleteTrigger>
92
+ )}
93
+ </ChakraFileUpload.Item>
94
+ )
95
+ }
96
+
97
+ interface FileUploadListProps
98
+ extends VisibilityProps,
99
+ ChakraFileUpload.ItemGroupProps {
100
+ files?: File[]
101
+ }
102
+
103
+ export const FileUploadList = forwardRef<HTMLUListElement, FileUploadListProps>(
104
+ function FileUploadList(props, ref) {
105
+ const { showSize, clearable, files, ...rest } = props
106
+
107
+ const fileUpload = useFileUploadContext()
108
+ const acceptedFiles = files ?? fileUpload.acceptedFiles
109
+
110
+ if (acceptedFiles.length === 0) return null
111
+
112
+ return (
113
+ <ChakraFileUpload.ItemGroup ref={ref} {...rest}>
114
+ {acceptedFiles.map((file) => (
115
+ <FileUploadItem
116
+ key={file.name}
117
+ file={file}
118
+ showSize={showSize}
119
+ clearable={clearable}
120
+ />
121
+ ))}
122
+ </ChakraFileUpload.ItemGroup>
123
+ )
124
+ },
125
+ )
126
+
127
+ type Assign<T, U> = Omit<T, keyof U> & U
128
+
129
+ interface FileInputProps extends Assign<ButtonProps, RecipeProps<"input">> {
130
+ placeholder?: React.ReactNode
131
+ }
132
+
133
+ export const FileInput = forwardRef<HTMLButtonElement, FileInputProps>(
134
+ function FileInput(props, ref) {
135
+ const inputRecipe = useRecipe({ key: "input" })
136
+ const [recipeProps, restProps] = inputRecipe.splitVariantProps(props)
137
+ const { placeholder = "Select file(s)", ...rest } = restProps
138
+ return (
139
+ <ChakraFileUpload.Trigger asChild>
140
+ <Button
141
+ unstyled
142
+ py="0"
143
+ ref={ref}
144
+ {...rest}
145
+ css={[inputRecipe(recipeProps), props.css]}
146
+ >
147
+ <ChakraFileUpload.Context>
148
+ {({ acceptedFiles }) => {
149
+ if (acceptedFiles.length === 1) {
150
+ return <span>{acceptedFiles[0].name}</span>
151
+ }
152
+ if (acceptedFiles.length > 1) {
153
+ return <span>{acceptedFiles.length} files</span>
154
+ }
155
+ return <Span color="fg.subtle">{placeholder}</Span>
156
+ }}
157
+ </ChakraFileUpload.Context>
158
+ </Button>
159
+ </ChakraFileUpload.Trigger>
160
+ )
161
+ },
162
+ )
163
+
164
+ export const FileUploadLabel = ChakraFileUpload.Label
165
+ export const FileUploadClearTrigger = ChakraFileUpload.ClearTrigger
166
+ export const FileUploadTrigger = ChakraFileUpload.Trigger
@@ -0,0 +1,113 @@
1
+ import { defineSlotRecipe } from '@chakra-ui/react'
2
+
3
+ export const gridListSlotRecipe = defineSlotRecipe({
4
+ className: 'sui-grid-list',
5
+ slots: ['root', 'item', 'header', 'icon'],
6
+ base: {
7
+ root: {
8
+ py: 2,
9
+ position: 'relative',
10
+ },
11
+ item: {
12
+ display: 'flex',
13
+ flexDirection: 'row',
14
+ alignItems: 'center',
15
+ justifyContent: 'space-between',
16
+ flex: 1,
17
+ cursor: 'pointer',
18
+ userSelect: 'none',
19
+ transitionProperty: 'common',
20
+ transitionDuration: 'normal',
21
+ borderRadius: 'inherit',
22
+ outline: 'none',
23
+ _hover: {
24
+ bg: 'blackAlpha.50',
25
+ _dark: {
26
+ bg: 'whiteAlpha.50',
27
+ },
28
+ },
29
+ _focusVisible: {
30
+ boxShadow: 'outline',
31
+ },
32
+ _focus: {
33
+ bg: 'blackAlpha.50',
34
+ _dark: {
35
+ bg: 'whiteAlpha.50',
36
+ },
37
+ },
38
+ _active: {
39
+ bg: 'blackAlpha.100',
40
+ _dark: {
41
+ bg: 'whiteAlpha.100',
42
+ },
43
+ },
44
+ _disabled: {
45
+ cursor: 'inherit',
46
+ opacity: 0.5,
47
+ _hover: {
48
+ bg: 'transparent',
49
+ _dark: {
50
+ bg: 'transparent',
51
+ },
52
+ },
53
+ _active: {
54
+ bg: 'transparent',
55
+ _dark: {
56
+ bg: 'transparent',
57
+ },
58
+ },
59
+ },
60
+ },
61
+ header: {
62
+ display: 'flex',
63
+ flexDirection: 'row',
64
+ position: 'sticky',
65
+ fontSize: 'md',
66
+ fontWeight: 'semibold',
67
+ color: 'muted',
68
+ },
69
+ icon: {
70
+ display: 'flex',
71
+ flexShrink: 0,
72
+ },
73
+ },
74
+ variants: {
75
+ size: {
76
+ sm: {
77
+ root: {
78
+ fontSize: 'sm',
79
+ },
80
+ item: {
81
+ py: 1,
82
+ px: 1,
83
+ },
84
+ header: {
85
+ py: 1,
86
+ px: 1,
87
+ },
88
+ cell: {
89
+ px: 1,
90
+ },
91
+ },
92
+ md: {
93
+ root: {
94
+ fontSize: 'md',
95
+ },
96
+ item: {
97
+ py: 2,
98
+ px: 2,
99
+ },
100
+ header: {
101
+ py: 2,
102
+ px: 2,
103
+ },
104
+ cell: {
105
+ px: 2,
106
+ },
107
+ },
108
+ },
109
+ },
110
+ defaultVariants: {
111
+ size: 'md',
112
+ },
113
+ })
@@ -0,0 +1,35 @@
1
+ import { HoverCard, Portal } from "@chakra-ui/react"
2
+ import { forwardRef } from "react"
3
+
4
+ interface HoverCardContentProps extends HoverCard.ContentProps {
5
+ portalled?: boolean
6
+ portalRef?: React.RefObject<HTMLElement>
7
+ }
8
+
9
+ export const HoverCardContent = forwardRef<
10
+ HTMLDivElement,
11
+ HoverCardContentProps
12
+ >(function HoverCardContent(props, ref) {
13
+ const { portalled = true, portalRef, ...rest } = props
14
+
15
+ return (
16
+ <Portal disabled={!portalled} container={portalRef}>
17
+ <HoverCard.Positioner>
18
+ <HoverCard.Content ref={ref} {...rest} />
19
+ </HoverCard.Positioner>
20
+ </Portal>
21
+ )
22
+ })
23
+
24
+ export const HoverCardArrow = forwardRef<HTMLDivElement, HoverCard.ArrowProps>(
25
+ function HoverCardArrow(props, ref) {
26
+ return (
27
+ <HoverCard.Arrow ref={ref} {...props}>
28
+ <HoverCard.ArrowTip />
29
+ </HoverCard.Arrow>
30
+ )
31
+ },
32
+ )
33
+
34
+ export const HoverCardRoot = HoverCard.Root
35
+ export const HoverCardTrigger = HoverCard.Trigger