@shipfox/react-ui 0.3.0 → 0.5.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 (314) hide show
  1. package/.storybook/main.ts +20 -10
  2. package/.storybook/preview.tsx +1 -1
  3. package/.storybook/vitest.setup.ts +4 -0
  4. package/.turbo/turbo-build.log +2 -2
  5. package/.turbo/turbo-check.log +2 -2
  6. package/.turbo/turbo-type.log +1 -1
  7. package/CHANGELOG.md +18 -0
  8. package/README.md +40 -1
  9. package/argos.config.ts +33 -0
  10. package/dist/components/alert/alert.d.ts +2 -2
  11. package/dist/components/alert/alert.js +3 -3
  12. package/dist/components/alert/alert.js.map +1 -1
  13. package/dist/components/alert/alert.stories.js +2 -2
  14. package/dist/components/alert/alert.stories.js.map +1 -1
  15. package/dist/components/avatar/avatar-group.js +3 -3
  16. package/dist/components/avatar/avatar-group.js.map +1 -1
  17. package/dist/components/avatar/avatar.d.ts +4 -1
  18. package/dist/components/avatar/avatar.d.ts.map +1 -1
  19. package/dist/components/avatar/avatar.js +7 -8
  20. package/dist/components/avatar/avatar.js.map +1 -1
  21. package/dist/components/avatar/avatar.stories.js +15 -3
  22. package/dist/components/avatar/avatar.stories.js.map +1 -1
  23. package/dist/components/badge/badge.d.ts +48 -0
  24. package/dist/components/badge/badge.d.ts.map +1 -0
  25. package/dist/components/badge/badge.js +72 -0
  26. package/dist/components/badge/badge.js.map +1 -0
  27. package/dist/components/badge/badge.stories.js +802 -0
  28. package/dist/components/badge/badge.stories.js.map +1 -0
  29. package/dist/components/badge/icon-badge.d.ts +9 -0
  30. package/dist/components/badge/icon-badge.d.ts.map +1 -0
  31. package/dist/components/badge/icon-badge.js +32 -0
  32. package/dist/components/badge/icon-badge.js.map +1 -0
  33. package/dist/components/badge/index.d.ts +5 -0
  34. package/dist/components/badge/index.d.ts.map +1 -0
  35. package/dist/components/badge/index.js +6 -0
  36. package/dist/components/badge/index.js.map +1 -0
  37. package/dist/components/badge/status-badge.d.ts +9 -0
  38. package/dist/components/badge/status-badge.d.ts.map +1 -0
  39. package/dist/components/badge/status-badge.js +29 -0
  40. package/dist/components/badge/status-badge.js.map +1 -0
  41. package/dist/components/badge/user-badge.d.ts +8 -0
  42. package/dist/components/badge/user-badge.d.ts.map +1 -0
  43. package/dist/components/badge/user-badge.js +24 -0
  44. package/dist/components/badge/user-badge.js.map +1 -0
  45. package/dist/components/button/button-link.d.ts +14 -0
  46. package/dist/components/button/button-link.d.ts.map +1 -0
  47. package/dist/components/button/button-link.js +63 -0
  48. package/dist/components/button/button-link.js.map +1 -0
  49. package/dist/components/button/button-link.stories.js +127 -0
  50. package/dist/components/button/button-link.stories.js.map +1 -0
  51. package/dist/components/{button.d.ts → button/button.d.ts} +2 -2
  52. package/dist/components/button/button.d.ts.map +1 -0
  53. package/dist/components/{button.js → button/button.js} +9 -8
  54. package/dist/components/button/button.js.map +1 -0
  55. package/dist/components/{button.stories.js → button/button.stories.js} +2 -14
  56. package/dist/components/button/button.stories.js.map +1 -0
  57. package/dist/components/button/icon-button.d.ts +14 -0
  58. package/dist/components/button/icon-button.d.ts.map +1 -0
  59. package/dist/components/button/icon-button.js +53 -0
  60. package/dist/components/button/icon-button.js.map +1 -0
  61. package/dist/components/button/icon-button.stories.js +254 -0
  62. package/dist/components/button/icon-button.stories.js.map +1 -0
  63. package/dist/components/button/index.d.ts +4 -0
  64. package/dist/components/button/index.d.ts.map +1 -0
  65. package/dist/components/button/index.js +5 -0
  66. package/dist/components/button/index.js.map +1 -0
  67. package/dist/components/checkbox/checkbox-label.d.ts +14 -0
  68. package/dist/components/checkbox/checkbox-label.d.ts.map +1 -0
  69. package/dist/components/checkbox/checkbox-label.js +82 -0
  70. package/dist/components/checkbox/checkbox-label.js.map +1 -0
  71. package/dist/components/checkbox/checkbox-links.d.ts +18 -0
  72. package/dist/components/checkbox/checkbox-links.d.ts.map +1 -0
  73. package/dist/components/checkbox/checkbox-links.js +58 -0
  74. package/dist/components/checkbox/checkbox-links.js.map +1 -0
  75. package/dist/components/checkbox/checkbox.d.ts +9 -0
  76. package/dist/components/checkbox/checkbox.d.ts.map +1 -0
  77. package/dist/components/checkbox/checkbox.js +49 -0
  78. package/dist/components/checkbox/checkbox.js.map +1 -0
  79. package/dist/components/checkbox/checkbox.stories.js +566 -0
  80. package/dist/components/checkbox/checkbox.stories.js.map +1 -0
  81. package/dist/components/checkbox/index.d.ts +4 -0
  82. package/dist/components/checkbox/index.d.ts.map +1 -0
  83. package/dist/components/checkbox/index.js +5 -0
  84. package/dist/components/checkbox/index.js.map +1 -0
  85. package/dist/components/code-block/code-block-footer.d.ts +26 -0
  86. package/dist/components/code-block/code-block-footer.d.ts.map +1 -0
  87. package/dist/components/code-block/code-block-footer.js +86 -0
  88. package/dist/components/code-block/code-block-footer.js.map +1 -0
  89. package/dist/components/code-block/code-block.d.ts +50 -0
  90. package/dist/components/code-block/code-block.d.ts.map +1 -0
  91. package/dist/components/code-block/code-block.js +142 -0
  92. package/dist/components/code-block/code-block.js.map +1 -0
  93. package/dist/components/code-block/code-block.stories.js +341 -0
  94. package/dist/components/code-block/code-block.stories.js.map +1 -0
  95. package/dist/components/code-block/code-content.d.ts +11 -0
  96. package/dist/components/code-block/code-content.d.ts.map +1 -0
  97. package/dist/components/code-block/code-content.js +29 -0
  98. package/dist/components/code-block/code-content.js.map +1 -0
  99. package/dist/components/code-block/code-copy-button.d.ts +11 -0
  100. package/dist/components/code-block/code-copy-button.d.ts.map +1 -0
  101. package/dist/components/code-block/code-copy-button.js +49 -0
  102. package/dist/components/code-block/code-copy-button.js.map +1 -0
  103. package/dist/components/code-block/code-tabs.d.ts +16 -0
  104. package/dist/components/code-block/code-tabs.d.ts.map +1 -0
  105. package/dist/components/code-block/code-tabs.js +98 -0
  106. package/dist/components/code-block/code-tabs.js.map +1 -0
  107. package/dist/components/code-block/index.d.ts +4 -0
  108. package/dist/components/code-block/index.d.ts.map +1 -0
  109. package/dist/components/code-block/index.js +5 -0
  110. package/dist/components/code-block/index.js.map +1 -0
  111. package/dist/components/dynamic-item/dynamic-item.d.ts +13 -0
  112. package/dist/components/dynamic-item/dynamic-item.d.ts.map +1 -0
  113. package/dist/components/dynamic-item/dynamic-item.js +43 -0
  114. package/dist/components/dynamic-item/dynamic-item.js.map +1 -0
  115. package/dist/components/dynamic-item/dynamic-item.stories.js +375 -0
  116. package/dist/components/dynamic-item/dynamic-item.stories.js.map +1 -0
  117. package/dist/components/dynamic-item/index.d.ts +2 -0
  118. package/dist/components/dynamic-item/index.d.ts.map +1 -0
  119. package/dist/components/dynamic-item/index.js +3 -0
  120. package/dist/components/dynamic-item/index.js.map +1 -0
  121. package/dist/components/icon/custom/index.d.ts +2 -0
  122. package/dist/components/icon/custom/index.d.ts.map +1 -1
  123. package/dist/components/icon/custom/index.js +2 -0
  124. package/dist/components/icon/custom/index.js.map +1 -1
  125. package/dist/components/icon/custom/slack-logo.d.ts +6 -0
  126. package/dist/components/icon/custom/slack-logo.d.ts.map +1 -0
  127. package/dist/components/icon/custom/slack-logo.js +34 -0
  128. package/dist/components/icon/custom/slack-logo.js.map +1 -0
  129. package/dist/components/icon/custom/stripe-logo.d.ts +8 -0
  130. package/dist/components/icon/custom/stripe-logo.d.ts.map +1 -0
  131. package/dist/components/icon/custom/stripe-logo.js +24 -0
  132. package/dist/components/icon/custom/stripe-logo.js.map +1 -0
  133. package/dist/components/icon/icon.d.ts +13 -2
  134. package/dist/components/icon/icon.d.ts.map +1 -1
  135. package/dist/components/icon/icon.js +14 -3
  136. package/dist/components/icon/icon.js.map +1 -1
  137. package/dist/components/icon/icon.stories.js +6 -3
  138. package/dist/components/icon/icon.stories.js.map +1 -1
  139. package/dist/components/index.d.ts +9 -1
  140. package/dist/components/index.d.ts.map +1 -1
  141. package/dist/components/index.js +10 -2
  142. package/dist/components/index.js.map +1 -1
  143. package/dist/components/inline-tips/inline-tips.d.ts +1 -1
  144. package/dist/components/inline-tips/inline-tips.d.ts.map +1 -1
  145. package/dist/components/inline-tips/inline-tips.js +1 -1
  146. package/dist/components/inline-tips/inline-tips.js.map +1 -1
  147. package/dist/components/inline-tips/inline-tips.stories.js +5 -5
  148. package/dist/components/inline-tips/inline-tips.stories.js.map +1 -1
  149. package/dist/components/input/index.d.ts +2 -0
  150. package/dist/components/input/index.d.ts.map +1 -0
  151. package/dist/components/input/index.js +3 -0
  152. package/dist/components/input/index.js.map +1 -0
  153. package/dist/components/input/input.d.ts.map +1 -0
  154. package/dist/components/{input.js → input/input.js} +2 -2
  155. package/dist/components/input/input.js.map +1 -0
  156. package/dist/components/{input.stories.js → input/input.stories.js} +1 -1
  157. package/dist/components/input/input.stories.js.map +1 -0
  158. package/dist/components/item/index.d.ts +2 -0
  159. package/dist/components/item/index.d.ts.map +1 -0
  160. package/dist/components/item/index.js +3 -0
  161. package/dist/components/item/index.js.map +1 -0
  162. package/dist/components/item/item.d.ts +32 -0
  163. package/dist/components/item/item.d.ts.map +1 -0
  164. package/dist/components/item/item.js +120 -0
  165. package/dist/components/item/item.js.map +1 -0
  166. package/dist/components/item/item.stories.js +232 -0
  167. package/dist/components/item/item.stories.js.map +1 -0
  168. package/dist/components/label/index.d.ts +2 -0
  169. package/dist/components/label/index.d.ts.map +1 -0
  170. package/dist/components/label/index.js +3 -0
  171. package/dist/components/label/index.js.map +1 -0
  172. package/dist/components/label/label.d.ts +7 -0
  173. package/dist/components/label/label.d.ts.map +1 -0
  174. package/dist/components/label/label.js +13 -0
  175. package/dist/components/label/label.js.map +1 -0
  176. package/dist/components/label/label.stories.js +105 -0
  177. package/dist/components/label/label.stories.js.map +1 -0
  178. package/dist/components/moving-border/moving-border.d.ts +9 -0
  179. package/dist/components/moving-border/moving-border.d.ts.map +1 -0
  180. package/dist/components/moving-border/moving-border.js +54 -0
  181. package/dist/components/moving-border/moving-border.js.map +1 -0
  182. package/dist/components/textarea/textarea.js +1 -1
  183. package/dist/components/textarea/textarea.js.map +1 -1
  184. package/dist/components/theme/index.d.ts +2 -0
  185. package/dist/components/theme/index.d.ts.map +1 -0
  186. package/dist/components/theme/index.js +3 -0
  187. package/dist/components/theme/index.js.map +1 -0
  188. package/dist/components/{theme-provider.d.ts → theme/theme-provider.d.ts} +1 -1
  189. package/dist/components/theme/theme-provider.d.ts.map +1 -0
  190. package/dist/components/{theme-provider.js → theme/theme-provider.js} +1 -1
  191. package/dist/components/theme/theme-provider.js.map +1 -0
  192. package/dist/components/toast/index.d.ts +3 -0
  193. package/dist/components/toast/index.d.ts.map +1 -0
  194. package/dist/components/toast/index.js +4 -0
  195. package/dist/components/toast/index.js.map +1 -0
  196. package/dist/components/toast/toast-custom.d.ts +19 -0
  197. package/dist/components/toast/toast-custom.d.ts.map +1 -0
  198. package/dist/components/toast/toast-custom.js +134 -0
  199. package/dist/components/toast/toast-custom.js.map +1 -0
  200. package/dist/components/toast/toast.d.ts +5 -0
  201. package/dist/components/toast/toast.d.ts.map +1 -0
  202. package/dist/components/toast/toast.js +40 -0
  203. package/dist/components/toast/toast.js.map +1 -0
  204. package/dist/components/toast/toast.stories.js +326 -0
  205. package/dist/components/toast/toast.stories.js.map +1 -0
  206. package/dist/components/tooltip/index.d.ts +2 -0
  207. package/dist/components/tooltip/index.d.ts.map +1 -0
  208. package/dist/components/tooltip/index.js +3 -0
  209. package/dist/components/tooltip/index.js.map +1 -0
  210. package/dist/components/tooltip/tooltip.d.ts +18 -5
  211. package/dist/components/tooltip/tooltip.d.ts.map +1 -1
  212. package/dist/components/tooltip/tooltip.js +63 -3
  213. package/dist/components/tooltip/tooltip.js.map +1 -1
  214. package/dist/components/tooltip/tooltip.stories.js +560 -0
  215. package/dist/components/tooltip/tooltip.stories.js.map +1 -0
  216. package/dist/hooks/index.d.ts +3 -0
  217. package/dist/hooks/index.d.ts.map +1 -1
  218. package/dist/hooks/index.js +3 -0
  219. package/dist/hooks/index.js.map +1 -1
  220. package/dist/hooks/useResolvedTheme.d.ts +2 -0
  221. package/dist/hooks/useResolvedTheme.d.ts.map +1 -0
  222. package/dist/hooks/useResolvedTheme.js +24 -0
  223. package/dist/hooks/useResolvedTheme.js.map +1 -0
  224. package/dist/hooks/useShikiHighlight.d.ts +28 -0
  225. package/dist/hooks/useShikiHighlight.d.ts.map +1 -0
  226. package/dist/hooks/useShikiHighlight.js +106 -0
  227. package/dist/hooks/useShikiHighlight.js.map +1 -0
  228. package/dist/hooks/useShikiStyleInjection.d.ts +2 -0
  229. package/dist/hooks/useShikiStyleInjection.d.ts.map +1 -0
  230. package/dist/hooks/useShikiStyleInjection.js +34 -0
  231. package/dist/hooks/useShikiStyleInjection.js.map +1 -0
  232. package/dist/onboarding/sign-in.stories.js +93 -0
  233. package/dist/onboarding/sign-in.stories.js.map +1 -0
  234. package/index.css +130 -12
  235. package/package.json +14 -3
  236. package/src/assets/illustration-1.svg +92 -0
  237. package/src/assets/illustration-2.svg +14 -0
  238. package/src/assets/illustration-gradient.svg +7049 -0
  239. package/src/components/alert/alert.stories.tsx +2 -2
  240. package/src/components/alert/alert.tsx +3 -3
  241. package/src/components/avatar/avatar-group.tsx +3 -3
  242. package/src/components/avatar/avatar.stories.tsx +9 -2
  243. package/src/components/avatar/avatar.tsx +10 -6
  244. package/src/components/badge/badge.stories.tsx +468 -0
  245. package/src/components/badge/badge.tsx +147 -0
  246. package/src/components/badge/icon-badge.tsx +43 -0
  247. package/src/components/badge/index.ts +4 -0
  248. package/src/components/badge/status-badge.tsx +43 -0
  249. package/src/components/badge/user-badge.tsx +34 -0
  250. package/src/components/button/button-link.stories.tsx +86 -0
  251. package/src/components/button/button-link.tsx +76 -0
  252. package/src/components/{button.stories.tsx → button/button.stories.tsx} +1 -7
  253. package/src/components/{button.tsx → button/button.tsx} +9 -7
  254. package/src/components/button/icon-button.stories.tsx +182 -0
  255. package/src/components/button/icon-button.tsx +69 -0
  256. package/src/components/button/index.ts +3 -0
  257. package/src/components/checkbox/checkbox-label.tsx +125 -0
  258. package/src/components/checkbox/checkbox-links.tsx +90 -0
  259. package/src/components/checkbox/checkbox.stories.tsx +375 -0
  260. package/src/components/checkbox/checkbox.tsx +71 -0
  261. package/src/components/checkbox/index.ts +3 -0
  262. package/src/components/code-block/code-block-footer.tsx +173 -0
  263. package/src/components/code-block/code-block.stories.tsx +323 -0
  264. package/src/components/code-block/code-block.tsx +283 -0
  265. package/src/components/code-block/code-content.tsx +63 -0
  266. package/src/components/code-block/code-copy-button.tsx +73 -0
  267. package/src/components/code-block/code-tabs.tsx +170 -0
  268. package/src/components/code-block/index.ts +3 -0
  269. package/src/components/dynamic-item/dynamic-item.stories.tsx +261 -0
  270. package/src/components/dynamic-item/dynamic-item.tsx +68 -0
  271. package/src/components/dynamic-item/index.ts +1 -0
  272. package/src/components/icon/custom/index.ts +2 -0
  273. package/src/components/icon/custom/slack-logo.tsx +35 -0
  274. package/src/components/icon/custom/stripe-logo.tsx +27 -0
  275. package/src/components/icon/icon.stories.tsx +3 -1
  276. package/src/components/icon/icon.tsx +23 -1
  277. package/src/components/index.ts +9 -1
  278. package/src/components/inline-tips/inline-tips.stories.tsx +3 -3
  279. package/src/components/inline-tips/inline-tips.tsx +2 -2
  280. package/src/components/input/index.ts +1 -0
  281. package/src/components/{input.tsx → input/input.tsx} +1 -1
  282. package/src/components/item/index.ts +1 -0
  283. package/src/components/item/item.stories.tsx +150 -0
  284. package/src/components/item/item.tsx +182 -0
  285. package/src/components/label/index.ts +1 -0
  286. package/src/components/label/label.stories.tsx +67 -0
  287. package/src/components/label/label.tsx +15 -0
  288. package/src/components/moving-border/moving-border.tsx +67 -0
  289. package/src/components/textarea/textarea.tsx +1 -1
  290. package/src/components/theme/index.ts +1 -0
  291. package/src/components/toast/index.ts +2 -0
  292. package/src/components/toast/toast-custom.tsx +154 -0
  293. package/src/components/toast/toast.stories.tsx +369 -0
  294. package/src/components/toast/toast.tsx +41 -0
  295. package/src/components/tooltip/index.ts +1 -0
  296. package/src/components/tooltip/tooltip.stories.tsx +284 -0
  297. package/src/components/tooltip/tooltip.tsx +79 -10
  298. package/src/hooks/index.ts +3 -0
  299. package/src/hooks/useResolvedTheme.ts +34 -0
  300. package/src/hooks/useShikiHighlight.ts +140 -0
  301. package/src/hooks/useShikiStyleInjection.ts +34 -0
  302. package/src/onboarding/sign-in.stories.tsx +73 -0
  303. package/vitest.config.ts +30 -3
  304. package/dist/components/button.d.ts.map +0 -1
  305. package/dist/components/button.js.map +0 -1
  306. package/dist/components/button.stories.js.map +0 -1
  307. package/dist/components/input.d.ts.map +0 -1
  308. package/dist/components/input.js.map +0 -1
  309. package/dist/components/input.stories.js.map +0 -1
  310. package/dist/components/theme-provider.d.ts.map +0 -1
  311. package/dist/components/theme-provider.js.map +0 -1
  312. /package/dist/components/{input.d.ts → input/input.d.ts} +0 -0
  313. /package/src/components/{input.stories.tsx → input/input.stories.tsx} +0 -0
  314. /package/src/components/{theme-provider.tsx → theme/theme-provider.tsx} +0 -0
@@ -1,10 +1,35 @@
1
1
  import * as TooltipPrimitive from '@radix-ui/react-tooltip';
2
+ import {cva, type VariantProps} from 'class-variance-authority';
3
+ import {motion, type Transition} from 'framer-motion';
4
+ import type {ComponentProps} from 'react';
2
5
  import {cn} from 'utils/cn';
3
6
 
7
+ const tooltipContentVariants = cva(
8
+ 'rounded-8 px-8 py-4 text-xs font-medium leading-20 z-50 w-fit text-balance shadow-tooltip',
9
+ {
10
+ variants: {
11
+ variant: {
12
+ default: 'bg-background-components-base text-foreground-neutral-base',
13
+ inverted: 'bg-background-button-inverted-default text-foreground-contrast-primary',
14
+ muted: 'bg-background-neutral-subtle text-foreground-neutral-muted',
15
+ },
16
+ size: {
17
+ sm: 'px-6 py-2 text-xs',
18
+ md: 'px-8 py-4 text-xs',
19
+ lg: 'px-10 py-6 text-sm',
20
+ },
21
+ },
22
+ defaultVariants: {
23
+ variant: 'default',
24
+ size: 'md',
25
+ },
26
+ },
27
+ );
28
+
4
29
  function TooltipProvider({
5
30
  delayDuration = 0,
6
31
  ...props
7
- }: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
32
+ }: ComponentProps<typeof TooltipPrimitive.Provider>) {
8
33
  return (
9
34
  <TooltipPrimitive.Provider
10
35
  data-slot="tooltip-provider"
@@ -14,7 +39,7 @@ function TooltipProvider({
14
39
  );
15
40
  }
16
41
 
17
- function Tooltip({...props}: React.ComponentProps<typeof TooltipPrimitive.Root>) {
42
+ function Tooltip({...props}: ComponentProps<typeof TooltipPrimitive.Root>) {
18
43
  return (
19
44
  <TooltipProvider>
20
45
  <TooltipPrimitive.Root data-slot="tooltip" {...props} />
@@ -22,25 +47,61 @@ function Tooltip({...props}: React.ComponentProps<typeof TooltipPrimitive.Root>)
22
47
  );
23
48
  }
24
49
 
25
- function TooltipTrigger({...props}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
50
+ function TooltipTrigger({...props}: ComponentProps<typeof TooltipPrimitive.Trigger>) {
26
51
  return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />;
27
52
  }
28
53
 
54
+ const defaultTransition: Transition = {
55
+ type: 'spring',
56
+ stiffness: 300,
57
+ damping: 17,
58
+ };
59
+
60
+ type TooltipContentProps = ComponentProps<typeof TooltipPrimitive.Content> &
61
+ VariantProps<typeof tooltipContentVariants> & {
62
+ animated?: boolean;
63
+ transition?: Transition;
64
+ };
65
+
29
66
  function TooltipContent({
30
67
  className,
31
- sideOffset = 0,
68
+ sideOffset = 8,
32
69
  children,
70
+ variant,
71
+ size,
72
+ animated = true,
73
+ transition = defaultTransition,
33
74
  ...props
34
- }: React.ComponentProps<typeof TooltipPrimitive.Content>) {
75
+ }: TooltipContentProps) {
76
+ if (animated) {
77
+ return (
78
+ <TooltipPrimitive.Portal>
79
+ <TooltipPrimitive.Content
80
+ data-slot="tooltip-content"
81
+ sideOffset={sideOffset}
82
+ asChild
83
+ {...props}
84
+ >
85
+ <motion.div
86
+ className={cn(tooltipContentVariants({variant, size, className}))}
87
+ initial={{opacity: 0, scale: 0.95}}
88
+ animate={{opacity: 1, scale: 1}}
89
+ exit={{opacity: 0, scale: 0.95}}
90
+ transition={transition}
91
+ >
92
+ {children}
93
+ </motion.div>
94
+ </TooltipPrimitive.Content>
95
+ </TooltipPrimitive.Portal>
96
+ );
97
+ }
98
+
35
99
  return (
36
100
  <TooltipPrimitive.Portal>
37
101
  <TooltipPrimitive.Content
38
102
  data-slot="tooltip-content"
39
103
  sideOffset={sideOffset}
40
- className={cn(
41
- 'rounded-8 bg-background-components-base text-foreground-neutral-base px-8 py-4 text-xs font-medium leading-20 shadow-button-neutral animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md text-balance',
42
- className,
43
- )}
104
+ className={cn(tooltipContentVariants({variant, size, className}))}
44
105
  {...props}
45
106
  >
46
107
  {children}
@@ -49,4 +110,12 @@ function TooltipContent({
49
110
  );
50
111
  }
51
112
 
52
- export {Tooltip, TooltipTrigger, TooltipContent, TooltipProvider};
113
+ export {
114
+ Tooltip,
115
+ TooltipTrigger,
116
+ TooltipContent,
117
+ TooltipProvider,
118
+ tooltipContentVariants,
119
+ defaultTransition,
120
+ };
121
+ export type {TooltipContentProps};
@@ -1,2 +1,5 @@
1
1
  export * from './useCopyToClipboard';
2
+ export * from './useResolvedTheme';
3
+ export * from './useShikiHighlight';
4
+ export * from './useShikiStyleInjection';
2
5
  export * from './useTheme';
@@ -0,0 +1,34 @@
1
+ import {useSyncExternalStore} from 'react';
2
+ import {useTheme} from './useTheme';
3
+
4
+ export function useResolvedTheme(): 'light' | 'dark' {
5
+ const {theme} = useTheme();
6
+
7
+ const systemTheme = useSyncExternalStore<'light' | 'dark'>(
8
+ (callback) => {
9
+ if (typeof window === 'undefined' || theme !== 'system') {
10
+ return () => {
11
+ // No-op unsubscribe
12
+ };
13
+ }
14
+ const mql = window.matchMedia('(prefers-color-scheme: dark)');
15
+ mql.addEventListener('change', callback);
16
+ return () => {
17
+ mql.removeEventListener('change', callback);
18
+ };
19
+ },
20
+ (): 'light' | 'dark' =>
21
+ typeof window !== 'undefined' && theme === 'system'
22
+ ? window.matchMedia('(prefers-color-scheme: dark)').matches
23
+ ? 'dark'
24
+ : 'light'
25
+ : 'light',
26
+ (): 'light' | 'dark' => 'light', // Server snapshot
27
+ );
28
+
29
+ if (theme === 'system') {
30
+ return systemTheme;
31
+ }
32
+ // TypeScript should narrow theme to 'light' | 'dark' here
33
+ return theme as 'light' | 'dark';
34
+ }
@@ -0,0 +1,140 @@
1
+ import {useEffect, useState} from 'react';
2
+
3
+ type ShikiThemes = {
4
+ light: string;
5
+ dark: string;
6
+ };
7
+
8
+ type UseShikiHighlightOptions = {
9
+ code: string;
10
+ lang: string;
11
+ themes: ShikiThemes;
12
+ resolvedTheme: 'light' | 'dark';
13
+ syntaxHighlighting: boolean;
14
+ };
15
+
16
+ export function useShikiHighlight({
17
+ code,
18
+ lang,
19
+ themes,
20
+ resolvedTheme,
21
+ syntaxHighlighting,
22
+ }: UseShikiHighlightOptions): {highlightedCode: string; isLoading: boolean} {
23
+ const [highlightedCode, setHighlightedCode] = useState<string>('');
24
+ const [isLoading, setIsLoading] = useState(syntaxHighlighting);
25
+
26
+ useEffect(() => {
27
+ if (!syntaxHighlighting) {
28
+ setIsLoading(false);
29
+ return;
30
+ }
31
+
32
+ setIsLoading(true);
33
+ let cancelled = false;
34
+
35
+ const loadHighlightedCode = async () => {
36
+ try {
37
+ const {codeToHtml} = await import('shiki');
38
+
39
+ const html = await codeToHtml(code, {
40
+ lang,
41
+ themes: {
42
+ light: themes.light,
43
+ dark: themes.dark,
44
+ },
45
+ defaultColor: resolvedTheme === 'dark' ? 'dark' : 'light',
46
+ });
47
+
48
+ if (!cancelled) {
49
+ setHighlightedCode(html);
50
+ setIsLoading(false);
51
+ }
52
+ } catch {
53
+ if (!cancelled) {
54
+ setIsLoading(false);
55
+ }
56
+ }
57
+ };
58
+
59
+ loadHighlightedCode();
60
+
61
+ return () => {
62
+ cancelled = true;
63
+ };
64
+ }, [code, lang, themes.light, themes.dark, resolvedTheme, syntaxHighlighting]);
65
+
66
+ return {highlightedCode, isLoading};
67
+ }
68
+
69
+ type UseShikiHighlightMultipleOptions = {
70
+ codes: Record<string, string>;
71
+ lang: string;
72
+ themes: ShikiThemes;
73
+ resolvedTheme: 'light' | 'dark';
74
+ syntaxHighlighting: boolean;
75
+ };
76
+
77
+ export function useShikiHighlightMultiple({
78
+ codes,
79
+ lang,
80
+ themes,
81
+ resolvedTheme,
82
+ syntaxHighlighting,
83
+ }: UseShikiHighlightMultipleOptions): {
84
+ highlightedCodes: Record<string, string>;
85
+ isLoading: boolean;
86
+ } {
87
+ const [highlightedCodes, setHighlightedCodes] = useState<Record<string, string>>({});
88
+ const [isLoading, setIsLoading] = useState(syntaxHighlighting);
89
+
90
+ useEffect(() => {
91
+ if (!syntaxHighlighting) {
92
+ setIsLoading(false);
93
+ return;
94
+ }
95
+
96
+ setIsLoading(true);
97
+ let cancelled = false;
98
+
99
+ const loadHighlightedCode = async () => {
100
+ try {
101
+ const {codeToHtml} = await import('shiki');
102
+ const newHighlightedCodes: Record<string, string> = {};
103
+
104
+ for (const [command, val] of Object.entries(codes)) {
105
+ if (cancelled) {
106
+ return;
107
+ }
108
+
109
+ const highlighted = await codeToHtml(val, {
110
+ lang,
111
+ themes: {
112
+ light: themes.light,
113
+ dark: themes.dark,
114
+ },
115
+ defaultColor: resolvedTheme === 'dark' ? 'dark' : 'light',
116
+ });
117
+
118
+ newHighlightedCodes[command] = highlighted;
119
+ }
120
+
121
+ if (!cancelled) {
122
+ setHighlightedCodes(newHighlightedCodes);
123
+ setIsLoading(false);
124
+ }
125
+ } catch {
126
+ if (!cancelled) {
127
+ setIsLoading(false);
128
+ }
129
+ }
130
+ };
131
+
132
+ loadHighlightedCode();
133
+
134
+ return () => {
135
+ cancelled = true;
136
+ };
137
+ }, [resolvedTheme, lang, themes.light, themes.dark, codes, syntaxHighlighting]);
138
+
139
+ return {highlightedCodes, isLoading};
140
+ }
@@ -0,0 +1,34 @@
1
+ import {useEffect} from 'react';
2
+
3
+ export function useShikiStyleInjection(syntaxHighlighting: boolean): void {
4
+ useEffect(() => {
5
+ if (!syntaxHighlighting) {
6
+ return;
7
+ }
8
+
9
+ const styleId = 'shiki-override-styles';
10
+ if (document.getElementById(styleId)) {
11
+ return;
12
+ }
13
+
14
+ const style = document.createElement('style');
15
+ style.id = styleId;
16
+ style.textContent = `
17
+ .shiki-override pre,
18
+ .shiki-override code,
19
+ .shiki-override pre *,
20
+ .shiki-override code * {
21
+ background: transparent !important;
22
+ font-family: "Commit Mono", monospace !important;
23
+ }
24
+ `;
25
+ document.head.appendChild(style);
26
+
27
+ return () => {
28
+ const existingStyle = document.getElementById(styleId);
29
+ if (existingStyle) {
30
+ existingStyle.remove();
31
+ }
32
+ };
33
+ }, [syntaxHighlighting]);
34
+ }
@@ -0,0 +1,73 @@
1
+ import {argosScreenshot} from '@argos-ci/storybook/vitest';
2
+ import type {Meta, StoryObj} from '@storybook/react';
3
+ import {Avatar} from 'components/avatar';
4
+ import {Button} from 'components/button';
5
+ import {Header, Text} from 'components/typography';
6
+
7
+ const meta = {
8
+ title: 'Onboarding/Signin',
9
+ parameters: {
10
+ layout: 'fullscreen',
11
+ },
12
+ } satisfies Meta;
13
+
14
+ export default meta;
15
+ type Story = StoryObj<typeof meta>;
16
+
17
+ export const Default: Story = {
18
+ play: async (ctx) => {
19
+ await argosScreenshot(ctx, 'example-screenshot');
20
+ },
21
+ render: () => {
22
+ return (
23
+ <div className="flex min-h-screen items-center justify-center bg-background-subtle-base">
24
+ {/* Background illustration - simplified decorative element */}
25
+ <div className="pointer-events-none absolute left-1/2 top-0 -translate-x-1/2 -translate-y-[120px]">
26
+ <div
27
+ className="h-[332px] w-[800px] opacity-20"
28
+ style={{
29
+ backgroundImage: `radial-gradient(circle, rgba(255, 75, 0, 0.3) 1px, transparent 1px)`,
30
+ backgroundSize: '24px 24px',
31
+ backgroundPosition: '-80px 31px',
32
+ }}
33
+ />
34
+ </div>
35
+
36
+ {/* Main content */}
37
+ <div className="relative flex w-full max-w-[384px] flex-col items-center gap-32 px-24 pb-80 pt-24">
38
+ {/* Logo and title section */}
39
+ <div className="flex flex-col items-center gap-16">
40
+ <Avatar content="logo" size="xl" radius="rounded" logoName="shipfox" />
41
+ <div className="flex min-w-[128px] flex-col items-center gap-4 text-center">
42
+ <Header
43
+ variant="h1"
44
+ className="text-[28px] font-medium leading-[44px] text-foreground-neutral-base"
45
+ >
46
+ Connect to Shipfox
47
+ </Header>
48
+ <Text
49
+ size="sm"
50
+ className="text-sm font-normal leading-[24px] text-foreground-neutral-subtle"
51
+ >
52
+ Log in to access Shipfox.
53
+ </Text>
54
+ </div>
55
+ </div>
56
+
57
+ {/* Action buttons */}
58
+ <div className="flex w-full flex-col gap-20">
59
+ <Button variant="primary" size="md" iconLeft="google" className="w-full">
60
+ Continue with Google
61
+ </Button>
62
+ <Button variant="primary" size="md" iconLeft="microsoft" className="w-full">
63
+ Continue with Microsoft
64
+ </Button>
65
+ <Button variant="transparent" size="md" className="w-full">
66
+ Connect with Enterprise SSO
67
+ </Button>
68
+ </div>
69
+ </div>
70
+ </div>
71
+ );
72
+ },
73
+ };
package/vitest.config.ts CHANGED
@@ -1,6 +1,14 @@
1
+ import * as path from 'node:path';
2
+ import {fileURLToPath} from 'node:url';
3
+ import {argosVitestPlugin} from '@argos-ci/storybook/vitest-plugin';
1
4
  import {defineConfig} from '@shipfox/vitest';
5
+ import {storybookTest} from '@storybook/addon-vitest/vitest-plugin';
2
6
  import tailwindcss from '@tailwindcss/vite';
3
7
  import react from '@vitejs/plugin-react';
8
+ import {playwright} from '@vitest/browser-playwright';
9
+
10
+ const dirname =
11
+ typeof __dirname !== 'undefined' ? __dirname : path.dirname(fileURLToPath(import.meta.url));
4
12
 
5
13
  // https://vitejs.dev/config/
6
14
  export default defineConfig(
@@ -8,9 +16,28 @@ export default defineConfig(
8
16
  plugins: [react(), tailwindcss()],
9
17
  css: {},
10
18
  test: {
11
- environment: 'jsdom',
12
- setupFiles: ['./test/setup.ts'],
13
- globalSetup: './test/global.ts',
19
+ projects: [
20
+ {
21
+ extends: true,
22
+ plugins: [
23
+ storybookTest({configDir: path.join(dirname, '.storybook')}),
24
+ argosVitestPlugin({
25
+ uploadToArgos: !!process.env.CI,
26
+ token: process.env.ARGOS_TOKEN,
27
+ }),
28
+ ],
29
+ test: {
30
+ name: 'storybook',
31
+ browser: {
32
+ enabled: true,
33
+ headless: true,
34
+ provider: playwright(),
35
+ instances: [{browser: 'chromium'}],
36
+ },
37
+ setupFiles: ['.storybook/vitest.setup.ts'],
38
+ },
39
+ },
40
+ ],
14
41
  },
15
42
  },
16
43
  import.meta.url,
@@ -1 +0,0 @@
1
- {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../src/components/button.tsx"],"names":[],"mappings":"AACA,OAAO,EAAM,KAAK,YAAY,EAAC,MAAM,0BAA0B,CAAC;AAChE,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,OAAO,CAAC;AAE1C,OAAO,EAAO,KAAK,QAAQ,EAAC,MAAM,aAAa,CAAC;AAEhD,eAAO,MAAM,cAAc;;;8EA8B1B,CAAC;AAEF,wBAAgB,MAAM,CAAC,EACrB,SAAS,EACT,OAAO,EACP,IAAI,EACJ,OAAe,EACf,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,QAAQ,CAAC,GACzB,YAAY,CAAC,OAAO,cAAc,CAAC,GAAG;IACpC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,SAAS,CAAC,EAAE,QAAQ,CAAC;CACtB,2CAUF"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/components/button.tsx"],"sourcesContent":["import {Slot} from '@radix-ui/react-slot';\nimport {cva, type VariantProps} from 'class-variance-authority';\nimport type {ComponentProps} from 'react';\nimport {cn} from 'utils/cn';\nimport {Icon, type IconName} from './icon/icon';\n\nexport const buttonVariants = cva(\n 'rounded-6 inline-flex items-center justify-center whitespace-nowrap transition-colors disabled:pointer-events-none shrink-0 outline-none',\n {\n variants: {\n variant: {\n primary:\n 'bg-background-button-inverted-default text-foreground-contrast-primary shadow-button-inverted hover:bg-background-button-inverted-hover active:bg-background-button-inverted-pressed focus-visible:shadow-button-inverted-focus disabled:bg-background-neutral-disabled disabled:text-foreground-neutral-disabled disabled:shadow-none',\n secondary:\n 'bg-background-button-neutral-default text-foreground-neutral-base shadow-button-neutral hover:bg-background-button-neutral-hover active:bg-background-button-neutral-pressed disabled:bg-background-neutral-disabled focus-visible:shadow-button-neutral-focus disabled:text-foreground-neutral-disabled disabled:shadow-none',\n danger:\n 'bg-background-button-danger-default text-foreground-neutral-on-color shadow-button-danger hover:bg-background-button-danger-hover active:bg-background-button-danger-pressed focus-visible:shadow-button-danger-focus disabled:bg-background-neutral-disabled disabled:text-foreground-neutral-disabled disabled:shadow-none',\n transparent:\n 'bg-background-button-transparent-default text-foreground-neutral-base hover:bg-background-button-transparent-hover active:bg-background-button-transparent-pressed focus-visible:shadow-button-neutral-focus disabled:text-foreground-neutral-disabled',\n transparentMuted:\n 'bg-background-button-transparent-default text-foreground-neutral-muted hover:bg-background-button-transparent-hover active:bg-background-button-transparent-pressed focus-visible:shadow-button-neutral-focus disabled:text-foreground-neutral-disabled',\n },\n size: {\n '2xs': 'px-6 text-xs gap-4',\n xs: 'px-6 py-2 text-xs gap-4',\n sm: 'px-8 py-4 text-sm gap-6',\n md: 'px-10 py-6 text-md gap-8',\n lg: 'px-12 py-8 text-lg gap-8',\n xl: 'px-12 py-10 text-xl gap-10',\n },\n },\n defaultVariants: {\n variant: 'primary',\n size: 'md',\n },\n },\n);\n\nexport function Button({\n className,\n variant,\n size,\n asChild = false,\n children,\n iconLeft,\n iconRight,\n ...props\n}: ComponentProps<'button'> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean;\n iconLeft?: IconName;\n iconRight?: IconName;\n }) {\n const Comp = asChild ? Slot : 'button';\n\n return (\n <Comp data-slot=\"button\" className={cn(buttonVariants({variant, size, className}))} {...props}>\n {iconLeft && <Icon name={iconLeft} />}\n {children}\n {iconRight && <Icon name={iconRight} />}\n </Comp>\n );\n}\n"],"names":["Slot","cva","cn","Icon","buttonVariants","variants","variant","primary","secondary","danger","transparent","transparentMuted","size","xs","sm","md","lg","xl","defaultVariants","Button","className","asChild","children","iconLeft","iconRight","props","Comp","data-slot","name"],"mappings":";AAAA,SAAQA,IAAI,QAAO,uBAAuB;AAC1C,SAAQC,GAAG,QAA0B,2BAA2B;AAEhE,SAAQC,EAAE,QAAO,WAAW;AAC5B,SAAQC,IAAI,QAAsB,cAAc;AAEhD,OAAO,MAAMC,iBAAiBH,IAC5B,4IACA;IACEI,UAAU;QACRC,SAAS;YACPC,SACE;YACFC,WACE;YACFC,QACE;YACFC,aACE;YACFC,kBACE;QACJ;QACAC,MAAM;YACJ,OAAO;YACPC,IAAI;YACJC,IAAI;YACJC,IAAI;YACJC,IAAI;YACJC,IAAI;QACN;IACF;IACAC,iBAAiB;QACfZ,SAAS;QACTM,MAAM;IACR;AACF,GACA;AAEF,OAAO,SAASO,OAAO,EACrBC,SAAS,EACTd,OAAO,EACPM,IAAI,EACJS,UAAU,KAAK,EACfC,QAAQ,EACRC,QAAQ,EACRC,SAAS,EACT,GAAGC,OAMF;IACD,MAAMC,OAAOL,UAAUrB,OAAO;IAE9B,qBACE,MAAC0B;QAAKC,aAAU;QAASP,WAAWlB,GAAGE,eAAe;YAACE;YAASM;YAAMQ;QAAS;QAAM,GAAGK,KAAK;;YAC1FF,0BAAY,KAACpB;gBAAKyB,MAAML;;YACxBD;YACAE,2BAAa,KAACrB;gBAAKyB,MAAMJ;;;;AAGhC"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/components/button.stories.tsx"],"sourcesContent":["import type {Meta, StoryObj} from '@storybook/react';\nimport {Code} from 'components/typography';\nimport {Button} from './button';\n\nconst variantOptions = [\n 'primary',\n 'secondary',\n 'danger',\n 'transparent',\n 'transparentMuted',\n] as const;\nconst sizeOptions = ['2xs', 'xs', 'sm', 'md', 'lg', 'xl'] as const;\n\nconst meta = {\n title: 'Components/Button',\n component: Button,\n tags: ['autodocs'],\n argTypes: {\n variant: {\n control: 'select',\n options: variantOptions,\n },\n size: {\n control: 'select',\n options: sizeOptions,\n },\n asChild: {control: 'boolean'},\n },\n args: {\n children: 'Click me',\n variant: 'primary',\n size: 'md',\n },\n} satisfies Meta<typeof Button>;\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\nexport const Default: Story = {};\n\nexport const Variants: Story = {\n render: (args) => (\n <div className=\"flex flex-col gap-32\">\n {sizeOptions.map((size) => (\n <table key={size} className=\"w-fit border-separate border-spacing-x-32 border-spacing-y-16\">\n <thead>\n <tr>\n <th>{size}</th>\n <th>Default</th>\n <th>Hover</th>\n <th>Active</th>\n <th>Focus</th>\n <th>Disabled</th>\n </tr>\n </thead>\n <tbody>\n {variantOptions.map((variant) => (\n <tr key={variant}>\n <td>\n <Code variant=\"label\" className=\"text-foreground-neutral-subtle\">\n {variant}\n </Code>\n </td>\n <td>\n <Button {...args} variant={variant} size={size}>\n Click me\n </Button>\n </td>\n <td>\n <Button {...args} variant={variant} className=\"hover\" size={size}>\n Click me\n </Button>\n </td>\n <td>\n <Button {...args} variant={variant} className=\"active\" size={size}>\n Click me\n </Button>\n </td>\n <td>\n <Button {...args} variant={variant} className=\"focus\" size={size}>\n Click me\n </Button>\n </td>\n <td>\n <Button {...args} variant={variant} disabled size={size}>\n Click me\n </Button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n ))}\n </div>\n ),\n};\n\nVariants.parameters = {\n pseudo: {\n hover: '.hover',\n active: '.active',\n focusVisible: '.focus',\n },\n};\n\nexport const Icons: Story = {\n render: (args) => (\n <div className=\"flex flex-col gap-16\">\n <div>\n <Button {...args} iconLeft=\"google\">\n Click me\n </Button>\n </div>\n <div>\n <Button {...args} iconRight=\"microsoft\">\n Click me\n </Button>\n </div>\n <div>\n <Button {...args} iconLeft=\"google\" iconRight=\"microsoft\">\n Click me\n </Button>\n </div>\n </div>\n ),\n};\n"],"names":["Code","Button","variantOptions","sizeOptions","meta","title","component","tags","argTypes","variant","control","options","size","asChild","args","children","Default","Variants","render","div","className","map","table","thead","tr","th","tbody","td","disabled","parameters","pseudo","hover","active","focusVisible","Icons","iconLeft","iconRight"],"mappings":";AACA,SAAQA,IAAI,QAAO,wBAAwB;AAC3C,SAAQC,MAAM,QAAO,WAAW;AAEhC,MAAMC,iBAAiB;IACrB;IACA;IACA;IACA;IACA;CACD;AACD,MAAMC,cAAc;IAAC;IAAO;IAAM;IAAM;IAAM;IAAM;CAAK;AAEzD,MAAMC,OAAO;IACXC,OAAO;IACPC,WAAWL;IACXM,MAAM;QAAC;KAAW;IAClBC,UAAU;QACRC,SAAS;YACPC,SAAS;YACTC,SAAST;QACX;QACAU,MAAM;YACJF,SAAS;YACTC,SAASR;QACX;QACAU,SAAS;YAACH,SAAS;QAAS;IAC9B;IACAI,MAAM;QACJC,UAAU;QACVN,SAAS;QACTG,MAAM;IACR;AACF;AAEA,eAAeR,KAAK;AAGpB,OAAO,MAAMY,UAAiB,CAAC,EAAE;AAEjC,OAAO,MAAMC,WAAkB;IAC7BC,QAAQ,CAACJ,qBACP,KAACK;YAAIC,WAAU;sBACZjB,YAAYkB,GAAG,CAAC,CAACT,qBAChB,MAACU;oBAAiBF,WAAU;;sCAC1B,KAACG;sCACC,cAAA,MAACC;;kDACC,KAACC;kDAAIb;;kDACL,KAACa;kDAAG;;kDACJ,KAACA;kDAAG;;kDACJ,KAACA;kDAAG;;kDACJ,KAACA;kDAAG;;kDACJ,KAACA;kDAAG;;;;;sCAGR,KAACC;sCACExB,eAAemB,GAAG,CAAC,CAACZ,wBACnB,MAACe;;sDACC,KAACG;sDACC,cAAA,KAAC3B;gDAAKS,SAAQ;gDAAQW,WAAU;0DAC7BX;;;sDAGL,KAACkB;sDACC,cAAA,KAAC1B;gDAAQ,GAAGa,IAAI;gDAAEL,SAASA;gDAASG,MAAMA;0DAAM;;;sDAIlD,KAACe;sDACC,cAAA,KAAC1B;gDAAQ,GAAGa,IAAI;gDAAEL,SAASA;gDAASW,WAAU;gDAAQR,MAAMA;0DAAM;;;sDAIpE,KAACe;sDACC,cAAA,KAAC1B;gDAAQ,GAAGa,IAAI;gDAAEL,SAASA;gDAASW,WAAU;gDAASR,MAAMA;0DAAM;;;sDAIrE,KAACe;sDACC,cAAA,KAAC1B;gDAAQ,GAAGa,IAAI;gDAAEL,SAASA;gDAASW,WAAU;gDAAQR,MAAMA;0DAAM;;;sDAIpE,KAACe;sDACC,cAAA,KAAC1B;gDAAQ,GAAGa,IAAI;gDAAEL,SAASA;gDAASmB,QAAQ;gDAAChB,MAAMA;0DAAM;;;;mCA3BpDH;;;mBAbHG;;AAmDpB,EAAE;AAEFK,SAASY,UAAU,GAAG;IACpBC,QAAQ;QACNC,OAAO;QACPC,QAAQ;QACRC,cAAc;IAChB;AACF;AAEA,OAAO,MAAMC,QAAe;IAC1BhB,QAAQ,CAACJ,qBACP,MAACK;YAAIC,WAAU;;8BACb,KAACD;8BACC,cAAA,KAAClB;wBAAQ,GAAGa,IAAI;wBAAEqB,UAAS;kCAAS;;;8BAItC,KAAChB;8BACC,cAAA,KAAClB;wBAAQ,GAAGa,IAAI;wBAAEsB,WAAU;kCAAY;;;8BAI1C,KAACjB;8BACC,cAAA,KAAClB;wBAAQ,GAAGa,IAAI;wBAAEqB,UAAS;wBAASC,WAAU;kCAAY;;;;;AAMlE,EAAE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../src/components/input.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAM,KAAK,YAAY,EAAC,MAAM,0BAA0B,CAAC;AAChE,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,OAAO,CAAC;AAG1C,eAAO,MAAM,aAAa;;;8EAexB,CAAC;AAEH,KAAK,UAAU,GAAG,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,GAAG,YAAY,CAAC,OAAO,aAAa,CAAC,CAAC;AAE7F,wBAAgB,KAAK,CAAC,EAAC,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,KAAK,EAAC,EAAE,UAAU,2CAmB3E"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/components/input.tsx"],"sourcesContent":["import {cva, type VariantProps} from 'class-variance-authority';\nimport type {ComponentProps} from 'react';\nimport {cn} from 'utils/cn';\n\nexport const inputVariants = cva('', {\n variants: {\n variant: {\n base: 'bg-background-field-base',\n component: 'bg-background-field-component',\n },\n size: {\n base: 'py-6',\n small: 'py-4',\n },\n },\n defaultVariants: {\n variant: 'base',\n size: 'base',\n },\n});\n\ntype InputProps = Omit<ComponentProps<'input'>, 'size'> & VariantProps<typeof inputVariants>;\n\nexport function Input({className, type, variant, size, ...props}: InputProps) {\n return (\n <input\n type={type}\n data-slot=\"input\"\n className={cn(\n 'placeholder:text-foreground-neutral-muted w-full min-w-0 rounded-6 px-8 text-sm leading-20 text-foreground-neutral-base shadow-border-base transition-[color,box-shadow] outline-none',\n 'hover:bg-background-field-hover',\n 'selection:bg-background-accent-neutral-soft selection:text-foreground-neutral-on-inverted',\n 'file:text-foreground-neutral-base file:inline-flex file:font-medium',\n 'disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-background-neutral-disabled disabled:shadow-none disabled:text-foreground-neutral-disabled',\n 'focus-visible:shadow-border-interactive-with-active',\n 'aria-invalid:shadow-border-error',\n inputVariants({variant, size}),\n className,\n )}\n {...props}\n />\n );\n}\n"],"names":["cva","cn","inputVariants","variants","variant","base","component","size","small","defaultVariants","Input","className","type","props","input","data-slot"],"mappings":";AAAA,SAAQA,GAAG,QAA0B,2BAA2B;AAEhE,SAAQC,EAAE,QAAO,WAAW;AAE5B,OAAO,MAAMC,gBAAgBF,IAAI,IAAI;IACnCG,UAAU;QACRC,SAAS;YACPC,MAAM;YACNC,WAAW;QACb;QACAC,MAAM;YACJF,MAAM;YACNG,OAAO;QACT;IACF;IACAC,iBAAiB;QACfL,SAAS;QACTG,MAAM;IACR;AACF,GAAG;AAIH,OAAO,SAASG,MAAM,EAACC,SAAS,EAAEC,IAAI,EAAER,OAAO,EAAEG,IAAI,EAAE,GAAGM,OAAkB;IAC1E,qBACE,KAACC;QACCF,MAAMA;QACNG,aAAU;QACVJ,WAAWV,GACT,yLACA,mCACA,6FACA,uEACA,mKACA,uDACA,oCACAC,cAAc;YAACE;YAASG;QAAI,IAC5BI;QAED,GAAGE,KAAK;;AAGf"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/components/input.stories.tsx"],"sourcesContent":["import type {Meta, StoryObj} from '@storybook/react';\nimport {Code, Header} from 'components/typography';\nimport {Input} from './input';\n\nconst typeOptions = [\n 'text',\n 'email',\n 'password',\n 'number',\n 'search',\n 'url',\n 'tel',\n 'date',\n 'time',\n 'datetime-local',\n 'month',\n 'week',\n 'color',\n 'file',\n] as const;\n\nconst meta = {\n title: 'Components/Input',\n component: Input,\n tags: ['autodocs'],\n argTypes: {\n type: {\n control: 'select',\n options: typeOptions,\n },\n placeholder: {control: 'text'},\n disabled: {control: 'boolean'},\n 'aria-invalid': {control: 'boolean'},\n },\n args: {\n type: 'text',\n placeholder: 'Type something…',\n disabled: false,\n 'aria-invalid': false,\n },\n} satisfies Meta<typeof Input>;\n\nexport default meta;\n\ntype Story = StoryObj<typeof meta>;\n\nexport const Default: Story = {};\n\nconst variants = ['base', 'component'] as const;\nconst sizes = ['base', 'small'] as const;\n\nexport const States: Story = {\n render: (args) => (\n <div className=\"flex flex-col gap-32\">\n {variants.map((variant) =>\n sizes.map((size) => (\n <div key={variant + size} className=\"flex flex-col gap-16\">\n <Header variant=\"h3\">\n {variant} {size}\n </Header>\n <div className=\"flex flex-col gap-8\">\n <Code variant=\"label\" className=\"text-foreground-neutral-subtle\">\n Default\n </Code>\n\n <Input {...args} variant={variant} size={size} />\n </div>\n\n <div className=\"flex flex-col gap-8\">\n <Code variant=\"label\" className=\"text-foreground-neutral-subtle\">\n Hover\n </Code>\n\n <Input {...args} className=\"hover\" variant={variant} size={size} />\n </div>\n <div className=\"flex flex-col gap-8\">\n <Code variant=\"label\" className=\"text-foreground-neutral-subtle\">\n Active\n </Code>\n\n <Input\n {...args}\n className=\"active\"\n defaultValue=\"The quick brown fox jumps over the lazy dog\"\n variant={variant}\n size={size}\n />\n </div>\n <div className=\"flex flex-col gap-8\">\n <Code variant=\"label\" className=\"text-foreground-neutral-subtle\">\n Focus\n </Code>\n\n <Input {...args} className=\"focus\" variant={variant} size={size} />\n </div>\n <div className=\"flex flex-col gap-8\">\n <Code variant=\"label\" className=\"text-foreground-neutral-subtle\">\n Disabled\n </Code>\n\n <Input {...args} disabled variant={variant} size={size} />\n </div>\n <div className=\"flex flex-col gap-8\">\n <Code variant=\"label\" className=\"text-foreground-neutral-subtle\">\n Invalid\n </Code>\n\n <Input {...args} aria-invalid variant={variant} size={size} />\n </div>\n </div>\n )),\n )}\n </div>\n ),\n};\n\nStates.parameters = {\n pseudo: {\n hover: '.hover',\n active: '.active',\n focusVisible: '.focus',\n },\n};\n\nexport const Types: Story = {\n render: (args) => (\n <div className=\"flex flex-col gap-32\">\n {typeOptions.map((t) => (\n <div key={t} className=\"flex flex-col gap-8\">\n <Code variant=\"label\" className=\"text-foreground-neutral-subtle\">\n {t}\n </Code>\n <Input {...args} type={t} />\n </div>\n ))}\n </div>\n ),\n};\n"],"names":["Code","Header","Input","typeOptions","meta","title","component","tags","argTypes","type","control","options","placeholder","disabled","args","Default","variants","sizes","States","render","div","className","map","variant","size","defaultValue","aria-invalid","parameters","pseudo","hover","active","focusVisible","Types","t"],"mappings":";AACA,SAAQA,IAAI,EAAEC,MAAM,QAAO,wBAAwB;AACnD,SAAQC,KAAK,QAAO,UAAU;AAE9B,MAAMC,cAAc;IAClB;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD;AAED,MAAMC,OAAO;IACXC,OAAO;IACPC,WAAWJ;IACXK,MAAM;QAAC;KAAW;IAClBC,UAAU;QACRC,MAAM;YACJC,SAAS;YACTC,SAASR;QACX;QACAS,aAAa;YAACF,SAAS;QAAM;QAC7BG,UAAU;YAACH,SAAS;QAAS;QAC7B,gBAAgB;YAACA,SAAS;QAAS;IACrC;IACAI,MAAM;QACJL,MAAM;QACNG,aAAa;QACbC,UAAU;QACV,gBAAgB;IAClB;AACF;AAEA,eAAeT,KAAK;AAIpB,OAAO,MAAMW,UAAiB,CAAC,EAAE;AAEjC,MAAMC,WAAW;IAAC;IAAQ;CAAY;AACtC,MAAMC,QAAQ;IAAC;IAAQ;CAAQ;AAE/B,OAAO,MAAMC,SAAgB;IAC3BC,QAAQ,CAACL,qBACP,KAACM;YAAIC,WAAU;sBACZL,SAASM,GAAG,CAAC,CAACC,UACbN,MAAMK,GAAG,CAAC,CAACE,qBACT,MAACJ;wBAAyBC,WAAU;;0CAClC,MAACpB;gCAAOsB,SAAQ;;oCACbA;oCAAQ;oCAAEC;;;0CAEb,MAACJ;gCAAIC,WAAU;;kDACb,KAACrB;wCAAKuB,SAAQ;wCAAQF,WAAU;kDAAiC;;kDAIjE,KAACnB;wCAAO,GAAGY,IAAI;wCAAES,SAASA;wCAASC,MAAMA;;;;0CAG3C,MAACJ;gCAAIC,WAAU;;kDACb,KAACrB;wCAAKuB,SAAQ;wCAAQF,WAAU;kDAAiC;;kDAIjE,KAACnB;wCAAO,GAAGY,IAAI;wCAAEO,WAAU;wCAAQE,SAASA;wCAASC,MAAMA;;;;0CAE7D,MAACJ;gCAAIC,WAAU;;kDACb,KAACrB;wCAAKuB,SAAQ;wCAAQF,WAAU;kDAAiC;;kDAIjE,KAACnB;wCACE,GAAGY,IAAI;wCACRO,WAAU;wCACVI,cAAa;wCACbF,SAASA;wCACTC,MAAMA;;;;0CAGV,MAACJ;gCAAIC,WAAU;;kDACb,KAACrB;wCAAKuB,SAAQ;wCAAQF,WAAU;kDAAiC;;kDAIjE,KAACnB;wCAAO,GAAGY,IAAI;wCAAEO,WAAU;wCAAQE,SAASA;wCAASC,MAAMA;;;;0CAE7D,MAACJ;gCAAIC,WAAU;;kDACb,KAACrB;wCAAKuB,SAAQ;wCAAQF,WAAU;kDAAiC;;kDAIjE,KAACnB;wCAAO,GAAGY,IAAI;wCAAED,QAAQ;wCAACU,SAASA;wCAASC,MAAMA;;;;0CAEpD,MAACJ;gCAAIC,WAAU;;kDACb,KAACrB;wCAAKuB,SAAQ;wCAAQF,WAAU;kDAAiC;;kDAIjE,KAACnB;wCAAO,GAAGY,IAAI;wCAAEY,cAAY;wCAACH,SAASA;wCAASC,MAAMA;;;;;uBAnDhDD,UAAUC;;AA0D9B,EAAE;AAEFN,OAAOS,UAAU,GAAG;IAClBC,QAAQ;QACNC,OAAO;QACPC,QAAQ;QACRC,cAAc;IAChB;AACF;AAEA,OAAO,MAAMC,QAAe;IAC1Bb,QAAQ,CAACL,qBACP,KAACM;YAAIC,WAAU;sBACZlB,YAAYmB,GAAG,CAAC,CAACW,kBAChB,MAACb;oBAAYC,WAAU;;sCACrB,KAACrB;4BAAKuB,SAAQ;4BAAQF,WAAU;sCAC7BY;;sCAEH,KAAC/B;4BAAO,GAAGY,IAAI;4BAAEL,MAAMwB;;;mBAJfA;;AASlB,EAAE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"theme-provider.d.ts","sourceRoot":"","sources":["../../src/components/theme-provider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,SAAS,EAAsB,MAAM,OAAO,CAAC;AAC1D,OAAO,EAAC,KAAK,KAAK,EAAuB,MAAM,aAAa,CAAC;AAE7D,KAAK,kBAAkB,GAAG;IACxB,QAAQ,EAAE,SAAS,CAAC;IACpB,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,YAAuB,EACvB,UAA4B,EAC5B,GAAG,KAAK,EACT,EAAE,kBAAkB,2CAmCpB"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/components/theme-provider.tsx"],"sourcesContent":["import {type ReactNode, useEffect, useState} from 'react';\nimport {type Theme, ThemeProviderContext} from 'state/theme';\n\ntype ThemeProviderProps = {\n children: ReactNode;\n defaultTheme?: Theme;\n storageKey?: string;\n};\n\nexport function ThemeProvider({\n children,\n defaultTheme = 'system',\n storageKey = 'shipfox-theme',\n ...props\n}: ThemeProviderProps) {\n const [theme, setTheme] = useState<Theme>(\n () => (localStorage.getItem(storageKey) as Theme) || defaultTheme,\n );\n\n useEffect(() => {\n const root = window.document.documentElement;\n\n root.classList.remove('light', 'dark');\n\n if (theme === 'system') {\n const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches\n ? 'dark'\n : 'light';\n\n root.classList.add(systemTheme);\n return;\n }\n\n root.classList.add(theme);\n }, [theme]);\n\n const value = {\n theme,\n setTheme: (theme: Theme) => {\n localStorage.setItem(storageKey, theme);\n setTheme(theme);\n },\n };\n\n return (\n <ThemeProviderContext.Provider {...props} value={value}>\n {children}\n </ThemeProviderContext.Provider>\n );\n}\n"],"names":["useEffect","useState","ThemeProviderContext","ThemeProvider","children","defaultTheme","storageKey","props","theme","setTheme","localStorage","getItem","root","window","document","documentElement","classList","remove","systemTheme","matchMedia","matches","add","value","setItem","Provider"],"mappings":";AAAA,SAAwBA,SAAS,EAAEC,QAAQ,QAAO,QAAQ;AAC1D,SAAoBC,oBAAoB,QAAO,cAAc;AAQ7D,OAAO,SAASC,cAAc,EAC5BC,QAAQ,EACRC,eAAe,QAAQ,EACvBC,aAAa,eAAe,EAC5B,GAAGC,OACgB;IACnB,MAAM,CAACC,OAAOC,SAAS,GAAGR,SACxB,IAAM,AAACS,aAAaC,OAAO,CAACL,eAAyBD;IAGvDL,UAAU;QACR,MAAMY,OAAOC,OAAOC,QAAQ,CAACC,eAAe;QAE5CH,KAAKI,SAAS,CAACC,MAAM,CAAC,SAAS;QAE/B,IAAIT,UAAU,UAAU;YACtB,MAAMU,cAAcL,OAAOM,UAAU,CAAC,gCAAgCC,OAAO,GACzE,SACA;YAEJR,KAAKI,SAAS,CAACK,GAAG,CAACH;YACnB;QACF;QAEAN,KAAKI,SAAS,CAACK,GAAG,CAACb;IACrB,GAAG;QAACA;KAAM;IAEV,MAAMc,QAAQ;QACZd;QACAC,UAAU,CAACD;YACTE,aAAaa,OAAO,CAACjB,YAAYE;YACjCC,SAASD;QACX;IACF;IAEA,qBACE,KAACN,qBAAqBsB,QAAQ;QAAE,GAAGjB,KAAK;QAAEe,OAAOA;kBAC9ClB;;AAGP"}