@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
package/package.json CHANGED
@@ -1,20 +1,29 @@
1
1
  {
2
2
  "name": "@saas-ui/react",
3
- "version": "2.11.2",
3
+ "version": "3.0.0-alpha.0",
4
4
  "description": "Saas UI - The React component library for startups.",
5
+ "source": "src/index.ts",
6
+ "type": "module",
5
7
  "exports": {
6
8
  ".": {
9
+ "sui": "./src/index.ts",
7
10
  "types": "./dist/index.d.ts",
8
- "require": "./dist/index.js",
9
- "import": "./dist/index.mjs"
11
+ "require": "./dist/index.cjs",
12
+ "import": "./dist/index.js"
10
13
  },
11
- "./src": {
12
- "default": "./src/index.ts"
14
+ "./*": {
15
+ "sui": "./src/components/*/index.ts",
16
+ "types": "./dist/components/*/index.d.ts",
17
+ "require": "./dist/components/*/index.cjs",
18
+ "import": "./dist/components/*/index.js"
13
19
  }
14
20
  },
15
- "source": "src/index.ts",
16
- "main": "./dist/index.js",
17
- "module": "./dist/index.mjs",
21
+ "imports": {
22
+ "#system": "./src/system",
23
+ "#components/*": "./src/components/*"
24
+ },
25
+ "main": "./dist/index.cjs",
26
+ "module": "./dist/index.js",
18
27
  "types": "./dist/index.d.ts",
19
28
  "scripts": {
20
29
  "clean": "rimraf --no-glob ./dist",
@@ -31,7 +40,7 @@
31
40
  "publishConfig": {
32
41
  "access": "public"
33
42
  },
34
- "author": "Eelco Wiersma <eelco@appulse.nl>",
43
+ "author": "Eelco Wiersma <eelco@saas-ui.dev>",
35
44
  "license": "MIT",
36
45
  "homepage": "https://saas-ui.dev/",
37
46
  "repository": {
@@ -56,22 +65,16 @@
56
65
  "url": "https://storybook.saas-ui.dev"
57
66
  },
58
67
  "dependencies": {
59
- "@chakra-ui/utils": "^2.2.3",
60
- "@saas-ui/core": "2.8.1",
61
- "@saas-ui/data-table": "13.0.2",
62
- "@saas-ui/forms": "2.9.1",
63
- "@saas-ui/hooks": "2.3.0",
64
- "@saas-ui/hotkeys": "2.5.1",
65
- "@saas-ui/modals": "2.4.2",
66
- "@saas-ui/nprogress": "2.2.1",
67
- "@saas-ui/theme": "2.6.1"
68
+ "@saas-ui/core": "3.0.0-alpha.0",
69
+ "@saas-ui/hooks": "3.0.0-alpha.0"
68
70
  },
69
71
  "peerDependencies": {
70
- "@chakra-ui/react": ">=2.9.0 <3",
72
+ "@chakra-ui/react": "^3.0.0",
71
73
  "@emotion/react": "^11",
72
- "@emotion/styled": "^11",
73
- "framer-motion": ">=5.5.0",
74
74
  "react": ">=18",
75
75
  "react-dom": ">=18"
76
+ },
77
+ "devDependencies": {
78
+ "react-icons": "^5.3.0"
76
79
  }
77
80
  }
@@ -0,0 +1,47 @@
1
+ import { Accordion, HStack } from "@chakra-ui/react"
2
+ import { forwardRef } from "react"
3
+ import { LuChevronDown } from "react-icons/lu"
4
+
5
+ interface AccordionItemTriggerProps extends Accordion.ItemTriggerProps {
6
+ indicatorPlacement?: "start" | "end"
7
+ }
8
+
9
+ export const AccordionItemTrigger = forwardRef<
10
+ HTMLButtonElement,
11
+ AccordionItemTriggerProps
12
+ >(function AccordionItemTrigger(props, ref) {
13
+ const { children, indicatorPlacement = "end", ...rest } = props
14
+ return (
15
+ <Accordion.ItemTrigger {...rest} ref={ref}>
16
+ {indicatorPlacement === "start" && (
17
+ <Accordion.ItemIndicator rotate={{ base: "-90deg", _open: "0deg" }}>
18
+ <LuChevronDown />
19
+ </Accordion.ItemIndicator>
20
+ )}
21
+ <HStack gap="4" flex="1" textAlign="start" width="full">
22
+ {children}
23
+ </HStack>
24
+ {indicatorPlacement === "end" && (
25
+ <Accordion.ItemIndicator>
26
+ <LuChevronDown />
27
+ </Accordion.ItemIndicator>
28
+ )}
29
+ </Accordion.ItemTrigger>
30
+ )
31
+ })
32
+
33
+ interface AccordionItemContentProps extends Accordion.ItemContentProps {}
34
+
35
+ export const AccordionItemContent = forwardRef<
36
+ HTMLDivElement,
37
+ AccordionItemContentProps
38
+ >(function AccordionItemContent(props, ref) {
39
+ return (
40
+ <Accordion.ItemContent>
41
+ <Accordion.ItemBody {...props} ref={ref} />
42
+ </Accordion.ItemContent>
43
+ )
44
+ })
45
+
46
+ export const AccordionRoot = Accordion.Root
47
+ export const AccordionItem = Accordion.Item
@@ -0,0 +1,40 @@
1
+ import { ActionBar, Portal } from "@chakra-ui/react"
2
+ import { CloseButton } from "compositions/ui/close-button"
3
+ import { forwardRef } from "react"
4
+
5
+ interface ActionBarContentProps extends ActionBar.ContentProps {
6
+ portalled?: boolean
7
+ portalRef?: React.RefObject<HTMLElement>
8
+ }
9
+
10
+ export const ActionBarContent = forwardRef<
11
+ HTMLDivElement,
12
+ ActionBarContentProps
13
+ >(function ActionBarContent(props, ref) {
14
+ const { children, portalled = true, portalRef, ...rest } = props
15
+
16
+ return (
17
+ <Portal disabled={!portalled} container={portalRef}>
18
+ <ActionBar.Positioner>
19
+ <ActionBar.Content ref={ref} {...rest} asChild={false}>
20
+ {children}
21
+ </ActionBar.Content>
22
+ </ActionBar.Positioner>
23
+ </Portal>
24
+ )
25
+ })
26
+
27
+ export const ActionBarCloseTrigger = forwardRef<
28
+ HTMLButtonElement,
29
+ ActionBar.CloseTriggerProps
30
+ >(function ActionBarCloseTrigger(props, ref) {
31
+ return (
32
+ <ActionBar.CloseTrigger {...props} asChild ref={ref}>
33
+ <CloseButton size="sm" />
34
+ </ActionBar.CloseTrigger>
35
+ )
36
+ })
37
+
38
+ export const ActionBarRoot = ActionBar.Root
39
+ export const ActionBarSelectionTrigger = ActionBar.SelectionTrigger
40
+ export const ActionBarSeparator = ActionBar.Separator
@@ -0,0 +1,51 @@
1
+ import { Alert as ChakraAlert } from "@chakra-ui/react"
2
+ import { CloseButton } from "compositions/ui/close-button"
3
+ import { forwardRef } from "react"
4
+
5
+ export interface AlertProps extends Omit<ChakraAlert.RootProps, "title"> {
6
+ startElement?: React.ReactNode
7
+ endElement?: React.ReactNode
8
+ title?: React.ReactNode
9
+ icon?: React.ReactElement
10
+ closable?: boolean
11
+ onClose?: () => void
12
+ }
13
+
14
+ export const Alert = forwardRef<HTMLDivElement, AlertProps>(
15
+ function Alert(props, ref) {
16
+ const {
17
+ title,
18
+ children,
19
+ icon,
20
+ closable,
21
+ onClose,
22
+ startElement,
23
+ endElement,
24
+ ...rest
25
+ } = props
26
+ return (
27
+ <ChakraAlert.Root ref={ref} {...rest}>
28
+ {startElement || <ChakraAlert.Indicator>{icon}</ChakraAlert.Indicator>}
29
+ {children ? (
30
+ <ChakraAlert.Content>
31
+ <ChakraAlert.Title>{title}</ChakraAlert.Title>
32
+ <ChakraAlert.Description>{children}</ChakraAlert.Description>
33
+ </ChakraAlert.Content>
34
+ ) : (
35
+ <ChakraAlert.Title flex="1">{title}</ChakraAlert.Title>
36
+ )}
37
+ {endElement}
38
+ {closable && (
39
+ <CloseButton
40
+ size="sm"
41
+ pos="relative"
42
+ top="-2"
43
+ insetEnd="-2"
44
+ alignSelf="flex-start"
45
+ onClick={onClose}
46
+ />
47
+ )}
48
+ </ChakraAlert.Root>
49
+ )
50
+ },
51
+ )
@@ -0,0 +1,52 @@
1
+ import { defineSlotRecipe } from '@chakra-ui/react'
2
+
3
+ export const appShellSlotRecipe = defineSlotRecipe({
4
+ className: 'sui-app-shell',
5
+ slots: ['root', 'content', 'main'],
6
+ base: {
7
+ root: {
8
+ display: 'flex',
9
+ flexDirection: 'column',
10
+ },
11
+ content: {
12
+ display: 'flex',
13
+ flex: 1,
14
+ minWidth: 0,
15
+ minHeight: 0,
16
+ },
17
+ main: {
18
+ display: 'flex',
19
+ flex: 1,
20
+ flexDirection: 'column',
21
+ minWidth: 0,
22
+ },
23
+ },
24
+ variants: {
25
+ position: {
26
+ static: {
27
+ root: {
28
+ height: '100vh',
29
+ },
30
+ },
31
+ fullscreen: {
32
+ root: {
33
+ position: 'fixed',
34
+ inset: 0,
35
+ },
36
+ },
37
+ },
38
+ variant: {
39
+ plain: {},
40
+ raised: {
41
+ main: {
42
+ boxShadow: 'xs',
43
+ zIndex: 'layer-1',
44
+ },
45
+ },
46
+ },
47
+ },
48
+ defaultVariants: {
49
+ position: 'static',
50
+ variant: 'raised',
51
+ },
52
+ })
@@ -0,0 +1,51 @@
1
+ import * as React from 'react'
2
+
3
+ import { Box } from '@chakra-ui/react'
4
+ import type { Meta } from '@storybook/react'
5
+
6
+ import { useAppShellStyles } from './app-shell.tsx'
7
+ import { AppShell } from './index.ts'
8
+
9
+ export default {
10
+ title: 'Components/AppShell',
11
+ parameters: {
12
+ layout: 'fullscreen',
13
+ },
14
+ } as Meta
15
+
16
+ export const FullscreenVariant = {
17
+ render: () => (
18
+ <AppShell
19
+ header={
20
+ <Box height="40px" borderBottomWidth="1px" p="2">
21
+ Header
22
+ </Box>
23
+ }
24
+ sidebar={
25
+ <Box width="200px" borderRightWidth="1px" p="2">
26
+ Sidebar
27
+ </Box>
28
+ }
29
+ aside={
30
+ <Box width="200px" borderLeftWidth="1px" p="2">
31
+ Aside
32
+ </Box>
33
+ }
34
+ footer={
35
+ <Box height="40px" borderTopWidth="1px" p="2">
36
+ Footer
37
+ </Box>
38
+ }
39
+ >
40
+ <Box p="2">Content</Box>
41
+ </AppShell>
42
+ ),
43
+ }
44
+
45
+ function Test() {
46
+ const styles = useAppShellStyles()
47
+
48
+ console.log(styles)
49
+
50
+ return null
51
+ }
@@ -0,0 +1,94 @@
1
+ 'use client'
2
+
3
+ import { forwardRef } from 'react'
4
+
5
+ import {
6
+ type HTMLChakraProps,
7
+ type SlotRecipeProps,
8
+ createSlotRecipeContext,
9
+ } from '@chakra-ui/react'
10
+
11
+ ////////////////////////////////////////////////////////////////////////////////////
12
+
13
+ const {
14
+ withProvider,
15
+ withContext,
16
+ useStyles: useAppShellStyles,
17
+ } = createSlotRecipeContext({
18
+ key: 'appShell',
19
+ })
20
+
21
+ export { useAppShellStyles }
22
+
23
+ export interface AppShellProps extends HTMLChakraProps<'div'> {
24
+ /**
25
+ * The top header navigation
26
+ */
27
+ header?: React.ReactNode
28
+ /**
29
+ * Main sidebar, positioned on the left
30
+ */
31
+ sidebar?: React.ReactElement
32
+ /**
33
+ * Secondary sidebar, positioned on the right
34
+ */
35
+ aside?: React.ReactNode
36
+ /**
37
+ * The footer
38
+ */
39
+ footer?: React.ReactNode
40
+ /**
41
+ * The main content
42
+ */
43
+ children: React.ReactNode
44
+ }
45
+
46
+ export interface AppShellRootProps
47
+ extends AppShellProps,
48
+ SlotRecipeProps<'appShell'> {}
49
+
50
+ /**
51
+ * The App Shell defines the main structure of your app.
52
+ *
53
+ * @see Docs https://saas-ui.dev/docs/components/layout/app-shell
54
+ */
55
+ export const AppShellRoot = withProvider<HTMLDivElement, AppShellRootProps>(
56
+ 'div',
57
+ 'root',
58
+ { forwardAsChild: true },
59
+ )
60
+
61
+ export interface AppShellContentProps extends HTMLChakraProps<'div'> {}
62
+
63
+ export const AppShellContent = withContext<
64
+ HTMLDivElement,
65
+ AppShellContentProps
66
+ >('div', 'content', { forwardAsChild: true })
67
+
68
+ export interface AppShellMainProps extends HTMLChakraProps<'div'> {}
69
+
70
+ export const AppShellMain = withContext<HTMLDivElement, AppShellMainProps>(
71
+ 'div',
72
+ 'main',
73
+ { forwardAsChild: true },
74
+ )
75
+
76
+ export const AppShell = forwardRef<HTMLDivElement, AppShellRootProps>(
77
+ (props, ref) => {
78
+ const { header, sidebar, aside, footer, children, ...rootProps } = props
79
+
80
+ return (
81
+ <AppShellRoot ref={ref} {...rootProps}>
82
+ {header}
83
+ <AppShellContent>
84
+ {sidebar}
85
+ <AppShellMain>{children}</AppShellMain>
86
+ {aside}
87
+ </AppShellContent>
88
+ {footer}
89
+ </AppShellRoot>
90
+ )
91
+ },
92
+ )
93
+
94
+ AppShell.displayName = 'AppShell'
@@ -0,0 +1,3 @@
1
+ export { AppShell } from './app-shell'
2
+
3
+ export type { AppShellProps } from './app-shell'
@@ -0,0 +1,74 @@
1
+ "use client"
2
+
3
+ import type { GroupProps, SlotRecipeProps } from "@chakra-ui/react"
4
+ import { Avatar as ChakraAvatar, Group } from "@chakra-ui/react"
5
+ import { forwardRef } from "react"
6
+
7
+ type ImageProps = React.ImgHTMLAttributes<HTMLImageElement>
8
+
9
+ export interface AvatarProps extends ChakraAvatar.RootProps {
10
+ name?: string
11
+ src?: string
12
+ srcSet?: string
13
+ loading?: ImageProps["loading"]
14
+ icon?: React.ReactElement
15
+ fallback?: React.ReactNode
16
+ }
17
+
18
+ export const Avatar = forwardRef<HTMLDivElement, AvatarProps>(
19
+ function Avatar(props, ref) {
20
+ const { name, src, srcSet, loading, icon, fallback, children, ...rest } =
21
+ props
22
+ return (
23
+ <ChakraAvatar.Root ref={ref} {...rest}>
24
+ <AvatarFallback name={name} icon={icon}>
25
+ {fallback}
26
+ </AvatarFallback>
27
+ <ChakraAvatar.Image src={src} srcSet={srcSet} loading={loading} />
28
+ {children}
29
+ </ChakraAvatar.Root>
30
+ )
31
+ },
32
+ )
33
+
34
+ interface AvatarFallbackProps extends ChakraAvatar.FallbackProps {
35
+ name?: string
36
+ icon?: React.ReactElement
37
+ }
38
+
39
+ const AvatarFallback = forwardRef<HTMLDivElement, AvatarFallbackProps>(
40
+ function AvatarFallback(props, ref) {
41
+ const { name, icon, children, ...rest } = props
42
+ return (
43
+ <ChakraAvatar.Fallback ref={ref} {...rest}>
44
+ {children}
45
+ {name != null && children == null && <>{getInitials(name)}</>}
46
+ {name == null && children == null && (
47
+ <ChakraAvatar.Icon asChild={!!icon}>{icon}</ChakraAvatar.Icon>
48
+ )}
49
+ </ChakraAvatar.Fallback>
50
+ )
51
+ },
52
+ )
53
+
54
+ function getInitials(name: string) {
55
+ const names = name.trim().split(" ")
56
+ const firstName = names[0] != null ? names[0] : ""
57
+ const lastName = names.length > 1 ? names[names.length - 1] : ""
58
+ return firstName && lastName
59
+ ? `${firstName.charAt(0)}${lastName.charAt(0)}`
60
+ : firstName.charAt(0)
61
+ }
62
+
63
+ interface AvatarGroupProps extends GroupProps, SlotRecipeProps<"avatar"> {}
64
+
65
+ export const AvatarGroup = forwardRef<HTMLDivElement, AvatarGroupProps>(
66
+ function AvatarGroup(props, ref) {
67
+ const { size, variant, borderless, ...rest } = props
68
+ return (
69
+ <ChakraAvatar.PropsProvider value={{ size, variant, borderless }}>
70
+ <Group gap="0" spaceX="-3" ref={ref} {...rest} />
71
+ </ChakraAvatar.PropsProvider>
72
+ )
73
+ },
74
+ )
@@ -0,0 +1,31 @@
1
+ import { Blockquote as ChakraBlockquote } from "@chakra-ui/react"
2
+ import { forwardRef } from "react"
3
+
4
+ export interface BlockquoteProps extends ChakraBlockquote.RootProps {
5
+ cite?: React.ReactNode
6
+ citeUrl?: string
7
+ icon?: React.ReactNode
8
+ showDash?: boolean
9
+ }
10
+
11
+ export const Blockquote = forwardRef<HTMLDivElement, BlockquoteProps>(
12
+ function Blockquote(props, ref) {
13
+ const { children, cite, citeUrl, showDash, icon, ...rest } = props
14
+
15
+ return (
16
+ <ChakraBlockquote.Root ref={ref} {...rest}>
17
+ {icon}
18
+ <ChakraBlockquote.Content cite={citeUrl}>
19
+ {children}
20
+ </ChakraBlockquote.Content>
21
+ {cite && (
22
+ <ChakraBlockquote.Caption>
23
+ {showDash ? <>&mdash;</> : null} <cite>{cite}</cite>
24
+ </ChakraBlockquote.Caption>
25
+ )}
26
+ </ChakraBlockquote.Root>
27
+ )
28
+ },
29
+ )
30
+
31
+ export const BlockquoteIcon = ChakraBlockquote.Icon
@@ -0,0 +1,17 @@
1
+ import React from 'react'
2
+
3
+ import { Breadcrumb } from './index.ts'
4
+
5
+ export default {
6
+ title: 'Components/Breadcrumbs',
7
+ component: Breadcrumb.Root,
8
+ }
9
+
10
+ export const Default = {
11
+ args: {
12
+ children: [
13
+ <Breadcrumb.Link href="/">Home</Breadcrumb.Link>,
14
+ <Breadcrumb.CurrentLink>Contact</Breadcrumb.CurrentLink>,
15
+ ],
16
+ },
17
+ }
@@ -0,0 +1,36 @@
1
+ import { Children, Fragment, forwardRef, isValidElement } from 'react'
2
+
3
+ import { Breadcrumb, type SystemStyleObject } from '@chakra-ui/react'
4
+
5
+ export interface BreadcrumbRootProps extends Breadcrumb.RootProps {
6
+ separator?: React.ReactNode
7
+ separatorGap?: SystemStyleObject['gap']
8
+ }
9
+
10
+ export const BreadcrumbRoot = forwardRef<HTMLDivElement, BreadcrumbRootProps>(
11
+ function BreadcrumbRoot(props, ref) {
12
+ const { separator = '/', separatorGap, children, ...rest } = props
13
+ const validChildren = Children.toArray(children).filter(isValidElement)
14
+ return (
15
+ <Breadcrumb.Root ref={ref} {...rest}>
16
+ <Breadcrumb.List gap={separatorGap}>
17
+ {validChildren.map((child, index) => {
18
+ const last = index === validChildren.length - 1
19
+ return (
20
+ <Fragment key={index}>
21
+ <Breadcrumb.Item>{child}</Breadcrumb.Item>
22
+ {!last && (
23
+ <Breadcrumb.Separator>{separator}</Breadcrumb.Separator>
24
+ )}
25
+ </Fragment>
26
+ )
27
+ })}
28
+ </Breadcrumb.List>
29
+ </Breadcrumb.Root>
30
+ )
31
+ },
32
+ )
33
+
34
+ export const BreadcrumbLink = Breadcrumb.Link
35
+ export const BreadcrumbCurrentLink = Breadcrumb.CurrentLink
36
+ export const BreadcrumbEllipsis = Breadcrumb.Ellipsis
@@ -0,0 +1 @@
1
+ export * as Breadcrumb from './namespace.ts'
@@ -0,0 +1,8 @@
1
+ export {
2
+ BreadcrumbRoot as Root,
3
+ BreadcrumbLink as Link,
4
+ BreadcrumbCurrentLink as CurrentLink,
5
+ BreadcrumbEllipsis as Ellipsis,
6
+ } from './breadcrumb.tsx'
7
+
8
+ export type { BreadcrumbRootProps } from './breadcrumb.tsx'