@jongh/ui 1.6.5

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 (267) hide show
  1. package/.storybook/index.css +1 -0
  2. package/.storybook/main.ts +40 -0
  3. package/.storybook/preview.ts +16 -0
  4. package/.storybook/vitest.setup.ts +9 -0
  5. package/.turbo/turbo-build.log +79 -0
  6. package/CHANGELOG.md +54 -0
  7. package/chromatic.config.json +6 -0
  8. package/eslint.config.mjs +14 -0
  9. package/index.html +13 -0
  10. package/package.json +58 -0
  11. package/panda.config.ts +13 -0
  12. package/postcss.config.cjs +3 -0
  13. package/preset.ts +134 -0
  14. package/src/component/accordion/ui/index.tsx +80 -0
  15. package/src/component/accordion/ui/recipe.ts +65 -0
  16. package/src/component/avatar/ui/index.tsx +47 -0
  17. package/src/component/avatar/ui/recipe.ts +30 -0
  18. package/src/component/button/ui/index.tsx +29 -0
  19. package/src/component/button/ui/recipe.ts +102 -0
  20. package/src/component/chip/ui/index.tsx +30 -0
  21. package/src/component/chip/ui/recipe.ts +112 -0
  22. package/src/component/dialog/ui/index.tsx +73 -0
  23. package/src/component/dialog/ui/recipe.ts +92 -0
  24. package/src/component/select/ui/index.tsx +128 -0
  25. package/src/component/select/ui/recipe.ts +142 -0
  26. package/src/component/slider/ui/index.tsx +61 -0
  27. package/src/component/slider/ui/recipe.ts +52 -0
  28. package/src/component/tabs/ui/index.tsx +61 -0
  29. package/src/component/tabs/ui/recipe.ts +59 -0
  30. package/src/hooks/createContext.tsx +34 -0
  31. package/src/hooks/useComposedRefs.ts +20 -0
  32. package/src/hooks/useControllableState.ts +87 -0
  33. package/src/hooks/useKeyboardEvent.ts +58 -0
  34. package/src/stories/accordion.stories.tsx +63 -0
  35. package/src/stories/avatar.stories.tsx +33 -0
  36. package/src/stories/button.stories.tsx +53 -0
  37. package/src/stories/chip.stories.tsx +69 -0
  38. package/src/stories/dialog.stories.tsx +134 -0
  39. package/src/stories/select.stories.tsx +35 -0
  40. package/src/stories/slider.stories.tsx +31 -0
  41. package/src/stories/tabs.stories.tsx +63 -0
  42. package/src/test/accordion.test.tsx +66 -0
  43. package/src/test/tabs.test.tsx +30 -0
  44. package/src/types/index.ts +1 -0
  45. package/src/utils/createStyleContext.tsx +108 -0
  46. package/src/utils/defineSafe.ts +46 -0
  47. package/src/utils/getObjectKeys.ts +20 -0
  48. package/src/vite-env.d.ts +1 -0
  49. package/storybook-static/assets/Color-F6OSRLHC-CrKta8Qx.js +1 -0
  50. package/storybook-static/assets/DocsRenderer-CFRXHY34-Crd9Mepd.js +586 -0
  51. package/storybook-static/assets/_commonjsHelpers-Cpj98o6Y.js +1 -0
  52. package/storybook-static/assets/accordion.stories-0Om0AnMm.js +50 -0
  53. package/storybook-static/assets/avatar.stories-DMDsrSks.js +16 -0
  54. package/storybook-static/assets/axe-Dzet_oDA.js +30 -0
  55. package/storybook-static/assets/button.stories-CuVC-3x-.js +40 -0
  56. package/storybook-static/assets/chip.stories-FBIp8XNi.js +48 -0
  57. package/storybook-static/assets/chunk-XP5HYGXS-D5tuasO7.js +1 -0
  58. package/storybook-static/assets/createLucideIcon-DmXe7Z8R.js +21 -0
  59. package/storybook-static/assets/dialog.stories-3WsEvXt4.js +106 -0
  60. package/storybook-static/assets/entry-preview-Bkgdgq1b.js +10 -0
  61. package/storybook-static/assets/entry-preview-docs-zLz1Es7d.js +46 -0
  62. package/storybook-static/assets/iframe-LPPPXabV.js +199 -0
  63. package/storybook-static/assets/index-Bklpsb39.js +1 -0
  64. package/storybook-static/assets/index-BrlJLjep.js +24 -0
  65. package/storybook-static/assets/index-C2tRLqin.js +41 -0
  66. package/storybook-static/assets/index-CBft-ReK.js +8 -0
  67. package/storybook-static/assets/index-CSbWd7UJ.js +1 -0
  68. package/storybook-static/assets/index-ClcD9ViR.js +9 -0
  69. package/storybook-static/assets/index-Cu4lwwaE.js +1 -0
  70. package/storybook-static/assets/index-Cvkemp2J.js +1 -0
  71. package/storybook-static/assets/index-D59aU5s_.js +240 -0
  72. package/storybook-static/assets/index-DNo8LKN3.js +1 -0
  73. package/storybook-static/assets/index-DUy19JZU.js +1 -0
  74. package/storybook-static/assets/index-D_35mznO.js +1 -0
  75. package/storybook-static/assets/index-DrFu-skq.js +6 -0
  76. package/storybook-static/assets/index-DvbTp2M2.js +1 -0
  77. package/storybook-static/assets/index-rtmQni2k.js +1 -0
  78. package/storybook-static/assets/jsx-runtime-BYYWji4R.js +9 -0
  79. package/storybook-static/assets/matchers-57EZJSQE-oeXCqs4p.js +14 -0
  80. package/storybook-static/assets/preview-1l6V4UsQ.js +1 -0
  81. package/storybook-static/assets/preview-B3PTUHS7.js +1 -0
  82. package/storybook-static/assets/preview-BBWR9nbA.js +1 -0
  83. package/storybook-static/assets/preview-BCV5r-Ja.js +1 -0
  84. package/storybook-static/assets/preview-BWzBA1C2.js +396 -0
  85. package/storybook-static/assets/preview-Bb56VplF.js +2 -0
  86. package/storybook-static/assets/preview-Bl8rsKRy.js +1 -0
  87. package/storybook-static/assets/preview-Bm-a94Ct.js +2 -0
  88. package/storybook-static/assets/preview-Br-h4d84.js +1 -0
  89. package/storybook-static/assets/preview-D77C14du.js +34 -0
  90. package/storybook-static/assets/preview-DC8N7cZb.css +1 -0
  91. package/storybook-static/assets/preview-DGUiP6tS.js +7 -0
  92. package/storybook-static/assets/react-18-BPs3tMGP.js +1 -0
  93. package/storybook-static/assets/select.stories-AN8Hb81Z.js +20 -0
  94. package/storybook-static/assets/slider.stories-CxOczq0y.js +12 -0
  95. package/storybook-static/assets/tabs.stories-BbTU4QU3.js +28 -0
  96. package/storybook-static/favicon.svg +1 -0
  97. package/storybook-static/iframe.html +666 -0
  98. package/storybook-static/index.html +193 -0
  99. package/storybook-static/index.json +1 -0
  100. package/storybook-static/nunito-sans-bold-italic.woff2 +0 -0
  101. package/storybook-static/nunito-sans-bold.woff2 +0 -0
  102. package/storybook-static/nunito-sans-italic.woff2 +0 -0
  103. package/storybook-static/nunito-sans-regular.woff2 +0 -0
  104. package/storybook-static/project.json +1 -0
  105. package/storybook-static/sb-addons/a11y-12/manager-bundle.js +3 -0
  106. package/storybook-static/sb-addons/a11y-12/manager-bundle.js.LEGAL.txt +0 -0
  107. package/storybook-static/sb-addons/chromatic-com-storybook-10/manager-bundle.js +331 -0
  108. package/storybook-static/sb-addons/chromatic-com-storybook-10/manager-bundle.js.LEGAL.txt +51 -0
  109. package/storybook-static/sb-addons/controls-11/manager-bundle.js +391 -0
  110. package/storybook-static/sb-addons/controls-11/manager-bundle.js.LEGAL.txt +0 -0
  111. package/storybook-static/sb-addons/essentials-actions-3/manager-bundle.js +3 -0
  112. package/storybook-static/sb-addons/essentials-actions-3/manager-bundle.js.LEGAL.txt +0 -0
  113. package/storybook-static/sb-addons/essentials-backgrounds-5/manager-bundle.js +12 -0
  114. package/storybook-static/sb-addons/essentials-backgrounds-5/manager-bundle.js.LEGAL.txt +0 -0
  115. package/storybook-static/sb-addons/essentials-controls-2/manager-bundle.js +391 -0
  116. package/storybook-static/sb-addons/essentials-controls-2/manager-bundle.js.LEGAL.txt +0 -0
  117. package/storybook-static/sb-addons/essentials-docs-4/manager-bundle.js +230 -0
  118. package/storybook-static/sb-addons/essentials-docs-4/manager-bundle.js.LEGAL.txt +0 -0
  119. package/storybook-static/sb-addons/essentials-measure-8/manager-bundle.js +3 -0
  120. package/storybook-static/sb-addons/essentials-measure-8/manager-bundle.js.LEGAL.txt +0 -0
  121. package/storybook-static/sb-addons/essentials-outline-9/manager-bundle.js +3 -0
  122. package/storybook-static/sb-addons/essentials-outline-9/manager-bundle.js.LEGAL.txt +0 -0
  123. package/storybook-static/sb-addons/essentials-toolbars-7/manager-bundle.js +3 -0
  124. package/storybook-static/sb-addons/essentials-toolbars-7/manager-bundle.js.LEGAL.txt +0 -0
  125. package/storybook-static/sb-addons/essentials-viewport-6/manager-bundle.js +3 -0
  126. package/storybook-static/sb-addons/essentials-viewport-6/manager-bundle.js.LEGAL.txt +0 -0
  127. package/storybook-static/sb-addons/links-1/manager-bundle.js +3 -0
  128. package/storybook-static/sb-addons/links-1/manager-bundle.js.LEGAL.txt +0 -0
  129. package/storybook-static/sb-addons/storybook-core-core-server-presets-0/common-manager-bundle.js +3 -0
  130. package/storybook-static/sb-addons/storybook-core-core-server-presets-0/common-manager-bundle.js.LEGAL.txt +0 -0
  131. package/storybook-static/sb-addons/storybook-experimental-addon-test-13/manager-bundle.js +211 -0
  132. package/storybook-static/sb-addons/storybook-experimental-addon-test-13/manager-bundle.js.LEGAL.txt +0 -0
  133. package/storybook-static/sb-common-assets/favicon.svg +1 -0
  134. package/storybook-static/sb-common-assets/nunito-sans-bold-italic.woff2 +0 -0
  135. package/storybook-static/sb-common-assets/nunito-sans-bold.woff2 +0 -0
  136. package/storybook-static/sb-common-assets/nunito-sans-italic.woff2 +0 -0
  137. package/storybook-static/sb-common-assets/nunito-sans-regular.woff2 +0 -0
  138. package/storybook-static/sb-manager/globals-module-info.js +1037 -0
  139. package/storybook-static/sb-manager/globals-runtime.js +40857 -0
  140. package/storybook-static/sb-manager/globals.js +48 -0
  141. package/storybook-static/sb-manager/runtime.js +11963 -0
  142. package/styled-system/css/conditions.mjs +36 -0
  143. package/styled-system/css/css.d.ts +22 -0
  144. package/styled-system/css/css.mjs +45 -0
  145. package/styled-system/css/cva.d.ts +6 -0
  146. package/styled-system/css/cva.mjs +87 -0
  147. package/styled-system/css/cx.d.ts +5 -0
  148. package/styled-system/css/cx.mjs +15 -0
  149. package/styled-system/css/index.d.ts +5 -0
  150. package/styled-system/css/index.mjs +4 -0
  151. package/styled-system/css/sva.d.ts +4 -0
  152. package/styled-system/css/sva.mjs +41 -0
  153. package/styled-system/helpers.mjs +336 -0
  154. package/styled-system/jsx/aspect-ratio.d.ts +10 -0
  155. package/styled-system/jsx/aspect-ratio.mjs +14 -0
  156. package/styled-system/jsx/bleed.d.ts +10 -0
  157. package/styled-system/jsx/bleed.mjs +14 -0
  158. package/styled-system/jsx/box.d.ts +10 -0
  159. package/styled-system/jsx/box.mjs +14 -0
  160. package/styled-system/jsx/center.d.ts +10 -0
  161. package/styled-system/jsx/center.mjs +14 -0
  162. package/styled-system/jsx/circle.d.ts +10 -0
  163. package/styled-system/jsx/circle.mjs +14 -0
  164. package/styled-system/jsx/container.d.ts +10 -0
  165. package/styled-system/jsx/container.mjs +14 -0
  166. package/styled-system/jsx/cq.d.ts +10 -0
  167. package/styled-system/jsx/cq.mjs +14 -0
  168. package/styled-system/jsx/divider.d.ts +10 -0
  169. package/styled-system/jsx/divider.mjs +14 -0
  170. package/styled-system/jsx/factory-helper.mjs +22 -0
  171. package/styled-system/jsx/factory.d.ts +3 -0
  172. package/styled-system/jsx/factory.mjs +80 -0
  173. package/styled-system/jsx/flex.d.ts +10 -0
  174. package/styled-system/jsx/flex.mjs +14 -0
  175. package/styled-system/jsx/float.d.ts +10 -0
  176. package/styled-system/jsx/float.mjs +14 -0
  177. package/styled-system/jsx/grid-item.d.ts +10 -0
  178. package/styled-system/jsx/grid-item.mjs +14 -0
  179. package/styled-system/jsx/grid.d.ts +10 -0
  180. package/styled-system/jsx/grid.mjs +14 -0
  181. package/styled-system/jsx/hstack.d.ts +10 -0
  182. package/styled-system/jsx/hstack.mjs +14 -0
  183. package/styled-system/jsx/index.d.ts +24 -0
  184. package/styled-system/jsx/index.mjs +22 -0
  185. package/styled-system/jsx/is-valid-prop.d.ts +11 -0
  186. package/styled-system/jsx/is-valid-prop.mjs +17 -0
  187. package/styled-system/jsx/link-overlay.d.ts +10 -0
  188. package/styled-system/jsx/link-overlay.mjs +14 -0
  189. package/styled-system/jsx/spacer.d.ts +10 -0
  190. package/styled-system/jsx/spacer.mjs +14 -0
  191. package/styled-system/jsx/square.d.ts +10 -0
  192. package/styled-system/jsx/square.mjs +14 -0
  193. package/styled-system/jsx/stack.d.ts +10 -0
  194. package/styled-system/jsx/stack.mjs +14 -0
  195. package/styled-system/jsx/visually-hidden.d.ts +10 -0
  196. package/styled-system/jsx/visually-hidden.mjs +14 -0
  197. package/styled-system/jsx/vstack.d.ts +10 -0
  198. package/styled-system/jsx/vstack.mjs +14 -0
  199. package/styled-system/jsx/wrap.d.ts +10 -0
  200. package/styled-system/jsx/wrap.mjs +14 -0
  201. package/styled-system/patterns/aspect-ratio.d.ts +21 -0
  202. package/styled-system/patterns/aspect-ratio.mjs +38 -0
  203. package/styled-system/patterns/bleed.d.ts +22 -0
  204. package/styled-system/patterns/bleed.mjs +24 -0
  205. package/styled-system/patterns/box.d.ts +21 -0
  206. package/styled-system/patterns/box.mjs +15 -0
  207. package/styled-system/patterns/center.d.ts +21 -0
  208. package/styled-system/patterns/center.mjs +21 -0
  209. package/styled-system/patterns/circle.d.ts +21 -0
  210. package/styled-system/patterns/circle.mjs +25 -0
  211. package/styled-system/patterns/container.d.ts +21 -0
  212. package/styled-system/patterns/container.mjs +21 -0
  213. package/styled-system/patterns/cq.d.ts +22 -0
  214. package/styled-system/patterns/cq.mjs +21 -0
  215. package/styled-system/patterns/divider.d.ts +23 -0
  216. package/styled-system/patterns/divider.mjs +25 -0
  217. package/styled-system/patterns/flex.d.ts +27 -0
  218. package/styled-system/patterns/flex.mjs +26 -0
  219. package/styled-system/patterns/float.d.ts +24 -0
  220. package/styled-system/patterns/float.mjs +52 -0
  221. package/styled-system/patterns/grid-item.d.ts +26 -0
  222. package/styled-system/patterns/grid-item.mjs +25 -0
  223. package/styled-system/patterns/grid.d.ts +25 -0
  224. package/styled-system/patterns/grid.mjs +27 -0
  225. package/styled-system/patterns/hstack.d.ts +22 -0
  226. package/styled-system/patterns/hstack.mjs +24 -0
  227. package/styled-system/patterns/index.d.ts +21 -0
  228. package/styled-system/patterns/index.mjs +20 -0
  229. package/styled-system/patterns/link-overlay.d.ts +21 -0
  230. package/styled-system/patterns/link-overlay.mjs +24 -0
  231. package/styled-system/patterns/spacer.d.ts +21 -0
  232. package/styled-system/patterns/spacer.mjs +21 -0
  233. package/styled-system/patterns/square.d.ts +21 -0
  234. package/styled-system/patterns/square.mjs +24 -0
  235. package/styled-system/patterns/stack.d.ts +24 -0
  236. package/styled-system/patterns/stack.mjs +24 -0
  237. package/styled-system/patterns/visually-hidden.d.ts +21 -0
  238. package/styled-system/patterns/visually-hidden.mjs +18 -0
  239. package/styled-system/patterns/vstack.d.ts +22 -0
  240. package/styled-system/patterns/vstack.mjs +24 -0
  241. package/styled-system/patterns/wrap.d.ts +25 -0
  242. package/styled-system/patterns/wrap.mjs +25 -0
  243. package/styled-system/tokens/index.d.ts +9 -0
  244. package/styled-system/tokens/index.mjs +1992 -0
  245. package/styled-system/tokens/tokens.d.ts +60 -0
  246. package/styled-system/types/composition.d.ts +164 -0
  247. package/styled-system/types/conditions.d.ts +274 -0
  248. package/styled-system/types/csstype.d.ts +21298 -0
  249. package/styled-system/types/global.d.ts +20 -0
  250. package/styled-system/types/index.d.ts +8 -0
  251. package/styled-system/types/jsx.d.ts +52 -0
  252. package/styled-system/types/parts.d.ts +8 -0
  253. package/styled-system/types/pattern.d.ts +78 -0
  254. package/styled-system/types/prop-type.d.ts +235 -0
  255. package/styled-system/types/recipe.d.ts +181 -0
  256. package/styled-system/types/selectors.d.ts +59 -0
  257. package/styled-system/types/static-css.d.ts +56 -0
  258. package/styled-system/types/style-props.d.ts +7468 -0
  259. package/styled-system/types/system-types.d.ts +109 -0
  260. package/tsconfig.json +13 -0
  261. package/turbo/generators/config.cjs +7 -0
  262. package/turbo/generators/stories.cjs +23 -0
  263. package/turbo/generators/templates/stories.tsx.hbs +16 -0
  264. package/turbo/generators/templates/ui.tsx.hbs +8 -0
  265. package/turbo/generators/ui.cjs +19 -0
  266. package/vite.config.ts +7 -0
  267. package/vitest.config.ts +45 -0
@@ -0,0 +1,142 @@
1
+ import { sva } from "@styled-system/css"
2
+
3
+ export const recipe = sva({
4
+ className: "select",
5
+ slots: [
6
+ "root",
7
+ "group",
8
+ "value",
9
+ "trigger",
10
+ "viewport",
11
+ "content",
12
+ "label",
13
+ "item",
14
+ "itemIndicator",
15
+ "separator",
16
+ ],
17
+ base: {
18
+ trigger: {
19
+ display: "flex",
20
+ h: "10",
21
+ w: "full",
22
+ alignItems: "center",
23
+ justifyContent: "space-between",
24
+ rounded: "md",
25
+ border: "input",
26
+ bg: "transparent",
27
+ px: "3",
28
+ py: "2",
29
+ textStyle: "sm",
30
+ cursor: "pointer",
31
+ ringColor: "background",
32
+
33
+ _placeholder: {
34
+ color: "muted.foreground",
35
+ },
36
+
37
+ _focus: {
38
+ ringWidth: "1",
39
+ ringColor: "ring",
40
+ outlineOffset: "1",
41
+ },
42
+
43
+ _disabled: {
44
+ cursor: "not-allowed",
45
+ opacity: "0.5",
46
+ },
47
+ },
48
+ viewport: {
49
+ "&:is([data-position=popper])": {
50
+ h: "var(--radix-select-trigger-height)",
51
+ w: "full",
52
+ minW: "var(--radix-select-trigger-width)",
53
+ },
54
+ },
55
+ content: {
56
+ position: "relative",
57
+ zIndex: 50,
58
+ minW: "full",
59
+ overflow: "hidden",
60
+ rounded: "md",
61
+ border: "base",
62
+ bg: "popover",
63
+ color: "popover.foreground",
64
+ shadow: "md",
65
+ maxH: "96",
66
+
67
+ "&:is([data-state=open])": {
68
+ animationName: "fadeIn",
69
+ animationState: "ease-in",
70
+ animationDuration: "slowest",
71
+ },
72
+
73
+ "&:is(&[data-state=closed])": {
74
+ animationName: "slideInDown",
75
+ animationState: "ease-in",
76
+ animationDuration: "slowest",
77
+ },
78
+
79
+ "&:is([data-position=popper])": {
80
+ "&:is([data-side=top])": {
81
+ translateY: "-1",
82
+ },
83
+
84
+ "&:is([data-side=bottom])": {
85
+ translateY: "1",
86
+ },
87
+
88
+ "&:is([data-side=left])": {
89
+ translateX: "-1",
90
+ },
91
+
92
+ "&:is([data-side=right])": {
93
+ translateX: "1",
94
+ },
95
+ },
96
+ },
97
+ label: {
98
+ py: "1.5",
99
+ pl: "8",
100
+ pr: "2",
101
+ textStyle: "sm",
102
+ fontWeight: "semibold",
103
+ },
104
+ item: {
105
+ position: "relative",
106
+ display: "flex",
107
+ cursor: "default",
108
+ userSelect: "none",
109
+ alignItems: "center",
110
+ rounded: "sm",
111
+ py: "1.5",
112
+ pl: "8",
113
+ pr: "2",
114
+ textStyle: "sm",
115
+
116
+ _focus: {
117
+ bg: "accent",
118
+ color: "accent.foreground",
119
+ },
120
+
121
+ ["&[data-disabled]"]: {
122
+ pointerEvents: "none",
123
+ opacity: "0.5",
124
+ },
125
+ },
126
+ itemIndicator: {
127
+ position: "absolute",
128
+ left: "2",
129
+ display: "flex",
130
+ h: "3.5",
131
+ w: "3.5",
132
+ alignItems: "center",
133
+ justifyContent: "center",
134
+ },
135
+ separator: {
136
+ mx: "-1",
137
+ my: "1",
138
+ h: "1",
139
+ bg: "muted",
140
+ },
141
+ },
142
+ })
@@ -0,0 +1,61 @@
1
+ import { css, cx } from "@styled-system/css"
2
+ import { Slider as SliderPrimitive } from "radix-ui"
3
+ import { ComponentPropsWithoutRef, ElementRef, forwardRef } from "react"
4
+
5
+ import { recipe } from "./recipe"
6
+
7
+ export const Root = forwardRef<
8
+ ElementRef<typeof SliderPrimitive.Root>,
9
+ ComponentPropsWithoutRef<typeof SliderPrimitive.Root>
10
+ >(({ className, ...props }, ref) => {
11
+ const styles = recipe.raw()
12
+ return (
13
+ <SliderPrimitive.Root
14
+ ref={ref}
15
+ className={cx(css(styles.root), className)}
16
+ {...props}
17
+ />
18
+ )
19
+ })
20
+
21
+ export const Track = forwardRef<
22
+ ElementRef<typeof SliderPrimitive.Track>,
23
+ ComponentPropsWithoutRef<typeof SliderPrimitive.Track>
24
+ >(({ className, ...props }, ref) => {
25
+ const styles = recipe.raw()
26
+ return (
27
+ <SliderPrimitive.Track
28
+ ref={ref}
29
+ className={cx(css(styles.track), className)}
30
+ {...props}
31
+ />
32
+ )
33
+ })
34
+
35
+ export const Range = forwardRef<
36
+ ElementRef<typeof SliderPrimitive.Range>,
37
+ ComponentPropsWithoutRef<typeof SliderPrimitive.Range>
38
+ >(({ className, ...props }, ref) => {
39
+ const styles = recipe.raw()
40
+ return (
41
+ <SliderPrimitive.Range
42
+ ref={ref}
43
+ className={cx(css(styles.range), className)}
44
+ {...props}
45
+ />
46
+ )
47
+ })
48
+
49
+ export const Thumb = forwardRef<
50
+ ElementRef<typeof SliderPrimitive.Thumb>,
51
+ ComponentPropsWithoutRef<typeof SliderPrimitive.Thumb>
52
+ >(({ className, ...props }, ref) => {
53
+ const styles = recipe.raw()
54
+ return (
55
+ <SliderPrimitive.Thumb
56
+ ref={ref}
57
+ className={cx(css(styles.thumb), className)}
58
+ {...props}
59
+ />
60
+ )
61
+ })
@@ -0,0 +1,52 @@
1
+ import { sva } from "@styled-system/css"
2
+
3
+ export const recipe = sva({
4
+ slots: ["root", "track", "range", "thumb"],
5
+ base: {
6
+ root: {
7
+ position: "relative",
8
+ display: "flex",
9
+ touchAction: "none",
10
+ userSelect: "none",
11
+ alignItems: "center",
12
+ },
13
+ track: {
14
+ position: "relative",
15
+ h: "2",
16
+ w: "full",
17
+ flexGrow: "1",
18
+ overflow: "hidden",
19
+ rounded: "full",
20
+ bg: "secondary",
21
+ },
22
+ range: {
23
+ position: "absolute",
24
+ h: "full",
25
+ bg: "primary",
26
+ },
27
+ thumb: {
28
+ display: "block",
29
+ h: "5",
30
+ w: "5",
31
+ cursor: "pointer",
32
+ rounded: "full",
33
+ borderWidth: "2px",
34
+ borderStyle: "solid",
35
+ borderColor: "primary",
36
+ bg: "background",
37
+ ringColor: "background",
38
+ transition: "colors",
39
+
40
+ _focusVisible: {
41
+ ringWidth: "1",
42
+ ringColor: "ring",
43
+ ringOffset: "1",
44
+ },
45
+
46
+ _disabled: {
47
+ pointerEvents: "none",
48
+ opacity: "0.5",
49
+ },
50
+ },
51
+ },
52
+ })
@@ -0,0 +1,61 @@
1
+ import { css, cx } from "@styled-system/css"
2
+ import { Tabs as TabsPrimitive } from "radix-ui"
3
+ import { ComponentPropsWithoutRef, ElementRef, forwardRef } from "react"
4
+
5
+ import { recipe } from "./recipe"
6
+
7
+ export const Root = forwardRef<
8
+ ElementRef<typeof TabsPrimitive.Root>,
9
+ ComponentPropsWithoutRef<typeof TabsPrimitive.Root>
10
+ >(({ className, ...props }, ref) => {
11
+ const styles = recipe.raw()
12
+ return (
13
+ <TabsPrimitive.Root
14
+ ref={ref}
15
+ className={cx(css(styles.root), className)}
16
+ {...props}
17
+ />
18
+ )
19
+ })
20
+
21
+ export const List = forwardRef<
22
+ ElementRef<typeof TabsPrimitive.List>,
23
+ ComponentPropsWithoutRef<typeof TabsPrimitive.List>
24
+ >(({ className, ...props }, ref) => {
25
+ const styles = recipe.raw()
26
+ return (
27
+ <TabsPrimitive.List
28
+ ref={ref}
29
+ className={cx(css(styles.list), className)}
30
+ {...props}
31
+ />
32
+ )
33
+ })
34
+
35
+ export const Trigger = forwardRef<
36
+ ElementRef<typeof TabsPrimitive.Trigger>,
37
+ ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
38
+ >(({ className, ...props }, ref) => {
39
+ const styles = recipe.raw()
40
+ return (
41
+ <TabsPrimitive.Trigger
42
+ ref={ref}
43
+ className={cx(css(styles.trigger), className)}
44
+ {...props}
45
+ />
46
+ )
47
+ })
48
+
49
+ export const Content = forwardRef<
50
+ ElementRef<typeof TabsPrimitive.Content>,
51
+ ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
52
+ >(({ className, ...props }, ref) => {
53
+ const styles = recipe.raw()
54
+ return (
55
+ <TabsPrimitive.Content
56
+ ref={ref}
57
+ className={cx(css(styles.content), className)}
58
+ {...props}
59
+ />
60
+ )
61
+ })
@@ -0,0 +1,59 @@
1
+ import { sva } from "@styled-system/css"
2
+
3
+ export const recipe = sva({
4
+ slots: ["root", "list", "trigger", "content"],
5
+ base: {
6
+ list: {
7
+ display: "inline-flex",
8
+ h: "10",
9
+ alignItems: "center",
10
+ justifyContent: "center",
11
+ rounded: "md",
12
+ bg: "muted",
13
+ p: "1",
14
+ color: "muted.foreground",
15
+ },
16
+ trigger: {
17
+ display: "inline-flex",
18
+ alignItems: "center",
19
+ justifyContent: "center",
20
+ whiteSpace: "nowrap",
21
+ rounded: "sm",
22
+ px: "3",
23
+ py: "1.5",
24
+ textStyle: "sm",
25
+ fontWeight: "medium",
26
+ transition: "all",
27
+ cursor: "pointer",
28
+ ringColor: "background",
29
+
30
+ _focusVisible: {
31
+ ringWidth: "1",
32
+ ringColor: "ring",
33
+ ringOffset: "1",
34
+ },
35
+
36
+ _disabled: {
37
+ pointerEvents: "none",
38
+ opacity: "50%",
39
+ },
40
+
41
+ "&:is([data-state=active])": {
42
+ bg: "background",
43
+ color: "foreground",
44
+ shadow: "sm",
45
+ },
46
+ },
47
+ content: {
48
+ mt: "2",
49
+ ringColor: "background",
50
+
51
+ _focusVisible: {
52
+ outlineWidth: "2",
53
+ outlineOffset: "2",
54
+ ringWidth: "2",
55
+ ringColor: "ring",
56
+ },
57
+ },
58
+ },
59
+ })
@@ -0,0 +1,34 @@
1
+ /* eslint-disable react-hooks/exhaustive-deps */
2
+ import * as React from "react"
3
+
4
+ export function createContext<ContextValueType extends object | null>(
5
+ rootComponentName: string,
6
+ defaultContext?: ContextValueType,
7
+ ) {
8
+ const C = React.createContext<ContextValueType | undefined>(defaultContext) //context 생성
9
+ const Provider = (
10
+ props: ContextValueType & { children: React.ReactNode },
11
+ ) => {
12
+ const { children, ...context } = props
13
+ // Only re-memoize when prop values change
14
+ const value = React.useMemo(
15
+ () => context,
16
+ Object.values(context),
17
+ ) as ContextValueType
18
+
19
+ return <C.Provider value={value}>{children}</C.Provider>
20
+ }
21
+
22
+ function useContext(consumerName?: string) {
23
+ const context = React.useContext(C)
24
+ if (context) return context
25
+ if (defaultContext !== undefined) return defaultContext
26
+ // if a defaultContext wasn't specified, it's a required context.
27
+ throw new Error(
28
+ `\`${consumerName}\` must be used within \`${rootComponentName}\``,
29
+ )
30
+ }
31
+
32
+ Provider.displayName = rootComponentName + "Provider"
33
+ return [Provider, useContext] as const
34
+ }
@@ -0,0 +1,20 @@
1
+ import { useCallback } from "react"
2
+
3
+ type PossibleRef<T> = React.Ref<T> | undefined
4
+
5
+ function setRef<T>(ref: PossibleRef<T>, value: T) {
6
+ if (typeof ref === "function") {
7
+ ref(value)
8
+ } else if (ref !== null && ref !== undefined) {
9
+ ;(ref as React.MutableRefObject<T>).current = value
10
+ }
11
+ }
12
+
13
+ export function composeRefs<T>(...refs: Array<PossibleRef<T>>) {
14
+ return (node: T) => refs.forEach((ref) => setRef(ref, node))
15
+ }
16
+
17
+ export function useComposedRefs<T>(...refs: Array<PossibleRef<T>>) {
18
+ // eslint-disable-next-line react-hooks/exhaustive-deps
19
+ return useCallback(composeRefs(...refs), refs)
20
+ }
@@ -0,0 +1,87 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import {
3
+ Dispatch,
4
+ SetStateAction,
5
+ useCallback,
6
+ useEffect,
7
+ useMemo,
8
+ useRef,
9
+ useState,
10
+ } from "react"
11
+
12
+ export const useCallbackRef = <T extends (...args: any[]) => any>(
13
+ callback?: T,
14
+ ) => {
15
+ const callbackRef = useRef(callback)
16
+
17
+ useEffect(() => {
18
+ callbackRef.current = callback
19
+ })
20
+
21
+ return useMemo(
22
+ () =>
23
+ (...args: any[]) =>
24
+ callbackRef.current?.(...args),
25
+ [],
26
+ )
27
+ }
28
+ //그냥 useState인데, onChange 이벤트를 할수있게 해준 hook
29
+ export const useUncontrolledState = <T>({
30
+ defaultValue,
31
+ onChange,
32
+ }: {
33
+ defaultValue?: T | undefined
34
+ onChange?: (params: T) => void
35
+ }) => {
36
+ const unControlledState = useState(defaultValue)
37
+ const [value] = unControlledState
38
+ const handleChange = useCallbackRef(onChange)
39
+ const ref = useRef(value)
40
+ useEffect(() => {
41
+ if (ref.current !== value) {
42
+ handleChange(value)
43
+ ref.current = value
44
+ }
45
+ }, [value, ref, handleChange])
46
+
47
+ return unControlledState
48
+ }
49
+
50
+ type SetStateFn<T> = (prev: T) => void
51
+
52
+ type UseControllableState<T> = {
53
+ prop?: T | undefined
54
+ defaultProp?: T | undefined
55
+ onChange?: (state: T) => void
56
+ }
57
+
58
+ export const useControlledState = <T>({
59
+ prop,
60
+ defaultProp,
61
+ onChange,
62
+ }: UseControllableState<T>) => {
63
+ const isControlled = prop !== undefined
64
+ const [unControlledProp, setUncontrolledProp] = useUncontrolledState({
65
+ defaultValue: defaultProp,
66
+ onChange,
67
+ })
68
+
69
+ const value = isControlled ? prop : unControlledProp
70
+ const handleChange = useCallbackRef(onChange)
71
+ const setValue: Dispatch<SetStateAction<T | undefined>> = useCallback(
72
+ (nextValue) => {
73
+ if (isControlled) {
74
+ const setter = nextValue as SetStateFn<T>
75
+ const value = typeof nextValue === "function" ? setter(prop) : nextValue
76
+ if (value !== prop) {
77
+ handleChange?.(value as T)
78
+ }
79
+ } else {
80
+ setUncontrolledProp(nextValue)
81
+ }
82
+ },
83
+ [isControlled, prop, setUncontrolledProp, handleChange],
84
+ )
85
+
86
+ return [value, setValue] as const
87
+ }
@@ -0,0 +1,58 @@
1
+ /* eslint-disable react-hooks/exhaustive-deps */
2
+ import { KeyboardEvent, useCallback, useRef } from "react"
3
+
4
+ type UseKeybaordEvent = {
5
+ keyList: string[]
6
+ changeIndex?: (index: number) => void
7
+ }
8
+
9
+ export const useKeyboardEvent = ({
10
+ keyList,
11
+ changeIndex,
12
+ }: UseKeybaordEvent) => {
13
+ const refs = useRef<HTMLElement[]>([])
14
+
15
+ const handleKeyDown = useCallback(
16
+ (event: KeyboardEvent<HTMLElement>, callback?: () => void) => {
17
+ if (!keyList.includes(event.key)) return
18
+ const length = refs.current.length
19
+ const target = event.target as HTMLElement
20
+ const currentIndex = refs.current.indexOf(target)
21
+ event.preventDefault()
22
+
23
+ let nextIndex = 0
24
+ switch (event.key) {
25
+ case "ArrowDown":
26
+ nextIndex = (currentIndex + 1) % length
27
+ break
28
+ case "ArrowUp":
29
+ nextIndex = (currentIndex - 1 + length) % length
30
+ break
31
+ case "ArrowRight":
32
+ nextIndex = (currentIndex + 1) % length
33
+ break
34
+ case "ArrowLeft":
35
+ nextIndex = (currentIndex - 1 + length) % length
36
+ break
37
+ case "Home":
38
+ nextIndex = 0
39
+ break
40
+ case "End":
41
+ nextIndex = length - 1
42
+ break
43
+ case "Tab":
44
+ nextIndex = (currentIndex + 1) % length
45
+ break
46
+ case "Enter":
47
+ callback?.()
48
+ }
49
+ changeIndex?.(nextIndex)
50
+ refs.current[nextIndex]?.focus()
51
+ },
52
+ [],
53
+ )
54
+
55
+ return { refs, handleKeyDown }
56
+ }
57
+
58
+ export default useKeyboardEvent
@@ -0,0 +1,63 @@
1
+ import type { Meta, StoryObj } from "@storybook/react"
2
+ import { expect, userEvent, waitFor } from "@storybook/test"
3
+ import { css } from "@styled-system/css"
4
+
5
+ import * as Accordion from "../component/accordion/ui"
6
+ export default {
7
+ title: "Accordion",
8
+ tags: ["autodocs"],
9
+ } satisfies Meta<typeof Accordion>
10
+
11
+ type Story = StoryObj<typeof Accordion>
12
+
13
+ export const Primary: Story = {
14
+ render: () => {
15
+ return (
16
+ <div style={{ width: "500px" }}>
17
+ <Accordion.Root type="single" collapsible>
18
+ <Accordion.Item value="1">
19
+ <Accordion.Header>
20
+ <Accordion.Trigger
21
+ className={css({
22
+ color: "red.100",
23
+ })}
24
+ >
25
+ 1번
26
+ </Accordion.Trigger>
27
+ </Accordion.Header>
28
+ <Accordion.Content>
29
+ <div>내용1</div>
30
+ </Accordion.Content>
31
+ </Accordion.Item>
32
+ <Accordion.Item value="2">
33
+ <Accordion.Header>
34
+ <Accordion.Trigger>2번</Accordion.Trigger>
35
+ </Accordion.Header>
36
+ <Accordion.Content>
37
+ <div>내용1</div>
38
+ </Accordion.Content>
39
+ </Accordion.Item>
40
+ <Accordion.Item value="3">
41
+ <Accordion.Header>
42
+ <Accordion.Trigger>3번</Accordion.Trigger>
43
+ </Accordion.Header>
44
+ <Accordion.Content>내용3</Accordion.Content>
45
+ </Accordion.Item>
46
+ </Accordion.Root>
47
+ </div>
48
+ )
49
+ },
50
+ play: async ({ canvas }) => {
51
+ const Item = canvas.getByText("1번")
52
+ expect(Item).toBeInTheDocument()
53
+ //토글로 내용이 열고 닫히는지 확인
54
+ await userEvent.click(Item)
55
+ await expect(canvas.getByText("내용1")).toBeInTheDocument()
56
+
57
+ await userEvent.click(Item)
58
+ await waitFor(async () => {
59
+ const Content = canvas.queryByText("내용1")
60
+ expect(Content).toBeNull()
61
+ })
62
+ },
63
+ }
@@ -0,0 +1,33 @@
1
+ import type { Meta, StoryObj } from "@storybook/react"
2
+
3
+ import * as Avatar from "../component/avatar/ui"
4
+
5
+ export default {
6
+ title: "Avatar",
7
+ tags: ["autodocs"],
8
+ } satisfies Meta<typeof Avatar>
9
+
10
+ type Story = StoryObj<typeof Avatar>
11
+
12
+ export const Primary: Story = {
13
+ args: {},
14
+ render: () => {
15
+ return (
16
+ <Avatar.Root>
17
+ <Avatar.Image src="https://encrypted-tbn3.gstatic.com/licensed-image?q=tbn:ANd9GcSDvLC5bOMlnrUBoojLDYnfS0S8G6kuUgQfcFq6d60TsnCmfNGimIc4pIgCmTHdnLaIgxGHBcdNeJ6FAoE" />
18
+ </Avatar.Root>
19
+ )
20
+ },
21
+ }
22
+
23
+ export const Fallback: Story = {
24
+ args: {},
25
+ render: () => {
26
+ return (
27
+ <Avatar.Root>
28
+ <Avatar.Image src="" />
29
+ <Avatar.Fallback>JD</Avatar.Fallback>
30
+ </Avatar.Root>
31
+ )
32
+ },
33
+ }