arcway 0.1.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 (274) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +711 -0
  3. package/client/env.js +55 -0
  4. package/client/fetcher.js +50 -0
  5. package/client/graphql.js +35 -0
  6. package/client/head.js +140 -0
  7. package/client/hooks/use-api.js +80 -0
  8. package/client/hooks/use-debounce.js +12 -0
  9. package/client/hooks/use-form.js +86 -0
  10. package/client/hooks/use-graphql.js +30 -0
  11. package/client/hooks/use-interval.js +12 -0
  12. package/client/hooks/use-mutation.js +27 -0
  13. package/client/hooks/use-query.js +45 -0
  14. package/client/hooks/web/use-click-outside.js +22 -0
  15. package/client/hooks/web/use-local-storage.js +42 -0
  16. package/client/index.js +62 -0
  17. package/client/page-loader.js +155 -0
  18. package/client/provider.js +53 -0
  19. package/client/query.js +13 -0
  20. package/client/router.jsx +303 -0
  21. package/client/ui/accordion.jsx +65 -0
  22. package/client/ui/accordion.stories.jsx +48 -0
  23. package/client/ui/alert-dialog.jsx +122 -0
  24. package/client/ui/alert-dialog.stories.jsx +44 -0
  25. package/client/ui/alert.jsx +52 -0
  26. package/client/ui/alert.stories.jsx +31 -0
  27. package/client/ui/app-shell.jsx +39 -0
  28. package/client/ui/app-shell.stories.jsx +51 -0
  29. package/client/ui/aspect-ratio.jsx +6 -0
  30. package/client/ui/aspect-ratio.stories.jsx +69 -0
  31. package/client/ui/avatar.jsx +78 -0
  32. package/client/ui/avatar.stories.jsx +62 -0
  33. package/client/ui/badge.jsx +34 -0
  34. package/client/ui/badge.stories.js +32 -0
  35. package/client/ui/breadcrumb.jsx +86 -0
  36. package/client/ui/breadcrumb.stories.jsx +43 -0
  37. package/client/ui/button-group.jsx +58 -0
  38. package/client/ui/button-group.stories.jsx +67 -0
  39. package/client/ui/button.jsx +46 -0
  40. package/client/ui/button.stories.js +72 -0
  41. package/client/ui/calendar.jsx +172 -0
  42. package/client/ui/card.jsx +57 -0
  43. package/client/ui/card.stories.jsx +33 -0
  44. package/client/ui/carousel.jsx +167 -0
  45. package/client/ui/chart.jsx +244 -0
  46. package/client/ui/checkbox.jsx +24 -0
  47. package/client/ui/checkbox.stories.js +33 -0
  48. package/client/ui/collapsible.jsx +12 -0
  49. package/client/ui/collapsible.stories.jsx +42 -0
  50. package/client/ui/combobox.jsx +223 -0
  51. package/client/ui/command.jsx +128 -0
  52. package/client/ui/context-menu.jsx +170 -0
  53. package/client/ui/context-menu.stories.jsx +35 -0
  54. package/client/ui/dialog.jsx +109 -0
  55. package/client/ui/dialog.stories.jsx +37 -0
  56. package/client/ui/direction.jsx +9 -0
  57. package/client/ui/drawer.jsx +87 -0
  58. package/client/ui/dropdown-menu.jsx +172 -0
  59. package/client/ui/dropdown-menu.stories.jsx +34 -0
  60. package/client/ui/empty.jsx +76 -0
  61. package/client/ui/empty.stories.jsx +64 -0
  62. package/client/ui/field.jsx +174 -0
  63. package/client/ui/field.stories.jsx +118 -0
  64. package/client/ui/form.jsx +17 -0
  65. package/client/ui/hooks/use-mobile.js +16 -0
  66. package/client/ui/hover-card.jsx +26 -0
  67. package/client/ui/hover-card.stories.jsx +28 -0
  68. package/client/ui/index.js +649 -0
  69. package/client/ui/input-group.jsx +116 -0
  70. package/client/ui/input-group.stories.jsx +65 -0
  71. package/client/ui/input-otp.jsx +62 -0
  72. package/client/ui/input.jsx +16 -0
  73. package/client/ui/input.stories.js +27 -0
  74. package/client/ui/item.jsx +155 -0
  75. package/client/ui/item.stories.jsx +118 -0
  76. package/client/ui/kbd.jsx +24 -0
  77. package/client/ui/kbd.stories.jsx +32 -0
  78. package/client/ui/label.jsx +16 -0
  79. package/client/ui/label.stories.js +25 -0
  80. package/client/ui/lib/utils.js +6 -0
  81. package/client/ui/main-content.jsx +30 -0
  82. package/client/ui/menubar.jsx +189 -0
  83. package/client/ui/menubar.stories.jsx +43 -0
  84. package/client/ui/native-select.jsx +34 -0
  85. package/client/ui/native-select.stories.jsx +67 -0
  86. package/client/ui/navigation-menu.jsx +120 -0
  87. package/client/ui/navigation-menu.stories.jsx +45 -0
  88. package/client/ui/pagination.jsx +92 -0
  89. package/client/ui/pagination.stories.jsx +52 -0
  90. package/client/ui/panel.jsx +66 -0
  91. package/client/ui/popover.jsx +54 -0
  92. package/client/ui/popover.stories.jsx +27 -0
  93. package/client/ui/progress.jsx +19 -0
  94. package/client/ui/progress.stories.js +34 -0
  95. package/client/ui/radio-group.jsx +33 -0
  96. package/client/ui/radio-group.stories.jsx +49 -0
  97. package/client/ui/resizable.jsx +33 -0
  98. package/client/ui/scroll-area.jsx +41 -0
  99. package/client/ui/scroll-area.stories.jsx +43 -0
  100. package/client/ui/select.jsx +145 -0
  101. package/client/ui/select.stories.jsx +80 -0
  102. package/client/ui/separator.jsx +18 -0
  103. package/client/ui/separator.stories.jsx +37 -0
  104. package/client/ui/sheet.jsx +95 -0
  105. package/client/ui/sheet.stories.jsx +56 -0
  106. package/client/ui/sidebar.jsx +544 -0
  107. package/client/ui/skeleton.jsx +8 -0
  108. package/client/ui/skeleton.stories.js +23 -0
  109. package/client/ui/slider.jsx +41 -0
  110. package/client/ui/slider.stories.js +31 -0
  111. package/client/ui/sonner.jsx +37 -0
  112. package/client/ui/spinner.jsx +14 -0
  113. package/client/ui/spinner.stories.js +16 -0
  114. package/client/ui/style-mira.css +1316 -0
  115. package/client/ui/switch.jsx +22 -0
  116. package/client/ui/switch.stories.js +44 -0
  117. package/client/ui/table.jsx +33 -0
  118. package/client/ui/table.stories.jsx +42 -0
  119. package/client/ui/tabs.jsx +63 -0
  120. package/client/ui/tabs.stories.jsx +45 -0
  121. package/client/ui/textarea.jsx +15 -0
  122. package/client/ui/textarea.stories.js +33 -0
  123. package/client/ui/theme.css +459 -0
  124. package/client/ui/toggle-group.jsx +62 -0
  125. package/client/ui/toggle-group.stories.jsx +68 -0
  126. package/client/ui/toggle.jsx +34 -0
  127. package/client/ui/toggle.stories.js +46 -0
  128. package/client/ui/tooltip.jsx +37 -0
  129. package/client/ui/tooltip.stories.jsx +32 -0
  130. package/client/ui/use-transition.js +35 -0
  131. package/client/ws.js +132 -0
  132. package/package.json +134 -0
  133. package/server/bin/cli.js +42 -0
  134. package/server/bin/commands/build.js +23 -0
  135. package/server/bin/commands/dev.js +57 -0
  136. package/server/bin/commands/docs.js +30 -0
  137. package/server/bin/commands/graphql-schema.js +32 -0
  138. package/server/bin/commands/lint.js +35 -0
  139. package/server/bin/commands/mcp.js +26 -0
  140. package/server/bin/commands/migrate.js +82 -0
  141. package/server/bin/commands/schema.js +41 -0
  142. package/server/bin/commands/seed.js +36 -0
  143. package/server/bin/commands/start.js +31 -0
  144. package/server/bin/commands/test.js +20 -0
  145. package/server/bin/solo.js +4 -0
  146. package/server/boot/index.js +150 -0
  147. package/server/boot.js +2 -0
  148. package/server/build.js +23 -0
  149. package/server/cache/drivers/memory.js +23 -0
  150. package/server/cache/drivers/redis.js +28 -0
  151. package/server/cache/index.js +69 -0
  152. package/server/config/loader.js +89 -0
  153. package/server/config/modules/api.js +17 -0
  154. package/server/config/modules/build.js +9 -0
  155. package/server/config/modules/cache.js +10 -0
  156. package/server/config/modules/database.js +29 -0
  157. package/server/config/modules/events.js +15 -0
  158. package/server/config/modules/files.js +15 -0
  159. package/server/config/modules/jobs.js +20 -0
  160. package/server/config/modules/logger.js +9 -0
  161. package/server/config/modules/mail.js +11 -0
  162. package/server/config/modules/mcp.js +9 -0
  163. package/server/config/modules/pages.js +20 -0
  164. package/server/config/modules/queue.js +10 -0
  165. package/server/config/modules/redis.js +9 -0
  166. package/server/config/modules/server.js +30 -0
  167. package/server/config/modules/session.js +9 -0
  168. package/server/config/modules/websocket.js +11 -0
  169. package/server/constants.js +67 -0
  170. package/server/context.js +15 -0
  171. package/server/db/index.js +87 -0
  172. package/server/db/schema/drivers/mysql.js +28 -0
  173. package/server/db/schema/drivers/pg.js +34 -0
  174. package/server/db/schema/drivers/sqlite.js +22 -0
  175. package/server/db/schema/index.js +78 -0
  176. package/server/db/seeds.js +22 -0
  177. package/server/discovery.js +67 -0
  178. package/server/docs/openapi.js +153 -0
  179. package/server/env.js +17 -0
  180. package/server/events/drivers/memory.js +45 -0
  181. package/server/events/drivers/redis.js +64 -0
  182. package/server/events/handler.js +67 -0
  183. package/server/events/index.js +35 -0
  184. package/server/events/pattern.js +5 -0
  185. package/server/files/drivers/local.js +83 -0
  186. package/server/files/drivers/s3.js +113 -0
  187. package/server/files/index.js +57 -0
  188. package/server/filewatcher/index.js +156 -0
  189. package/server/glob.js +6 -0
  190. package/server/graphql/discovery.js +70 -0
  191. package/server/graphql/handler.js +41 -0
  192. package/server/graphql/index.js +13 -0
  193. package/server/graphql/loaders.js +19 -0
  194. package/server/graphql/merge.js +48 -0
  195. package/server/graphql/subscriptions.js +43 -0
  196. package/server/health.js +34 -0
  197. package/server/helpers.js +9 -0
  198. package/server/index.js +55 -0
  199. package/server/internals.js +139 -0
  200. package/server/jobs/cron.js +10 -0
  201. package/server/jobs/drivers/knex-queue.js +207 -0
  202. package/server/jobs/drivers/lease.js +148 -0
  203. package/server/jobs/drivers/memory-queue.js +134 -0
  204. package/server/jobs/queue.js +27 -0
  205. package/server/jobs/runner.js +197 -0
  206. package/server/jobs/throughput.js +63 -0
  207. package/server/lib/vault/encrypt.js +40 -0
  208. package/server/lib/vault/ids.js +9 -0
  209. package/server/lib/vault/index.js +14 -0
  210. package/server/lib/vault/jwt.js +55 -0
  211. package/server/lib/vault/password.js +10 -0
  212. package/server/lint/boundaries.js +77 -0
  213. package/server/logger/index.js +130 -0
  214. package/server/mail/drivers/console.js +31 -0
  215. package/server/mail/drivers/smtp.js +34 -0
  216. package/server/mail/imap.js +105 -0
  217. package/server/mail/inbound-store.js +58 -0
  218. package/server/mail/inbound.js +79 -0
  219. package/server/mail/index.js +112 -0
  220. package/server/mcp/debug-api.js +137 -0
  221. package/server/mcp/helpers.js +30 -0
  222. package/server/mcp/index.js +77 -0
  223. package/server/mcp/runtime.js +7 -0
  224. package/server/mcp/server.js +19 -0
  225. package/server/mcp/tools/debugging.js +133 -0
  226. package/server/mcp/tools/introspection.js +87 -0
  227. package/server/middlewares/cors.js +30 -0
  228. package/server/middlewares/index.js +3 -0
  229. package/server/middlewares/require-session.js +15 -0
  230. package/server/module-loader.js +9 -0
  231. package/server/pages/build-client.js +187 -0
  232. package/server/pages/build-css.js +47 -0
  233. package/server/pages/build-manifest.js +55 -0
  234. package/server/pages/build-plugins.js +75 -0
  235. package/server/pages/build-server.js +115 -0
  236. package/server/pages/build.js +116 -0
  237. package/server/pages/discovery.js +120 -0
  238. package/server/pages/fonts.js +128 -0
  239. package/server/pages/handler.js +276 -0
  240. package/server/pages/hmr.js +176 -0
  241. package/server/pages/pages-router.js +78 -0
  242. package/server/pages/ssr.js +276 -0
  243. package/server/pages/static.js +92 -0
  244. package/server/pages/watcher.js +90 -0
  245. package/server/queue/drivers/knex.js +67 -0
  246. package/server/queue/drivers/redis.js +91 -0
  247. package/server/queue/index.js +61 -0
  248. package/server/rate-limit/consume.js +21 -0
  249. package/server/rate-limit/drivers/memory.js +24 -0
  250. package/server/rate-limit/drivers/redis.js +32 -0
  251. package/server/rate-limit/index.js +33 -0
  252. package/server/redis/index.js +67 -0
  253. package/server/ring-buffer.js +44 -0
  254. package/server/route.js +4 -0
  255. package/server/router/api-router.js +317 -0
  256. package/server/router/cors.js +31 -0
  257. package/server/router/middleware.js +91 -0
  258. package/server/router/routes.js +132 -0
  259. package/server/server.js +35 -0
  260. package/server/session/helpers.js +21 -0
  261. package/server/session/index.js +89 -0
  262. package/server/static/index.js +36 -0
  263. package/server/system-jobs/index.js +50 -0
  264. package/server/system-routes/index.js +84 -0
  265. package/server/testing/index.js +263 -0
  266. package/server/validation.js +41 -0
  267. package/server/watcher.js +34 -0
  268. package/server/web-server.js +231 -0
  269. package/server/ws/discovery.js +54 -0
  270. package/server/ws/index.js +14 -0
  271. package/server/ws/realtime.js +318 -0
  272. package/server/ws/registry.js +17 -0
  273. package/server/ws/server.js +152 -0
  274. package/server/ws/ws-router.js +335 -0
@@ -0,0 +1,459 @@
1
+ /* ── Color scheme variables ──
2
+ * Uses the shadcn/ui Zinc palette: black & white with neutral grays.
3
+ * Dark mode activates via the `.dark` class on <html> or any ancestor.
4
+ */
5
+
6
+ :root {
7
+ --background: #ffffff;
8
+ --foreground: #09090b;
9
+ --card: #ffffff;
10
+ --card-foreground: #09090b;
11
+ --popover: #ffffff;
12
+ --popover-foreground: #09090b;
13
+ --primary: #18181b;
14
+ --primary-foreground: #fafafa;
15
+ --secondary: #f4f4f5;
16
+ --secondary-foreground: #18181b;
17
+ --muted: #f4f4f5;
18
+ --muted-foreground: #71717a;
19
+ --accent: #f4f4f5;
20
+ --accent-foreground: #18181b;
21
+ --destructive: #ef4444;
22
+ --destructive-foreground: #fafafa;
23
+ --border: #e4e4e7;
24
+ --input: #e4e4e7;
25
+ --ring: #a1a1aa;
26
+ --radius: 0.45rem;
27
+
28
+ /* Sidebar */
29
+ --sidebar: #fafafa;
30
+ --sidebar-foreground: #09090b;
31
+ --sidebar-muted: #71717a;
32
+ --sidebar-accent: #f4f4f5;
33
+ --sidebar-accent-foreground: #18181b;
34
+ --sidebar-border: #e4e4e7;
35
+ --sidebar-ring: #a1a1aa;
36
+
37
+ /* Panel */
38
+ --panel: #ffffff;
39
+ --panel-foreground: #09090b;
40
+ --panel-border: #e4e4e7;
41
+ }
42
+
43
+ .dark {
44
+ --background: #09090b;
45
+ --foreground: #fafafa;
46
+ --card: #09090b;
47
+ --card-foreground: #fafafa;
48
+ --popover: #18181b;
49
+ --popover-foreground: #fafafa;
50
+ --primary: #fafafa;
51
+ --primary-foreground: #18181b;
52
+ --secondary: #27272a;
53
+ --secondary-foreground: #fafafa;
54
+ --muted: #27272a;
55
+ --muted-foreground: #a1a1aa;
56
+ --accent: #27272a;
57
+ --accent-foreground: #fafafa;
58
+ --destructive: #dc2626;
59
+ --destructive-foreground: #fafafa;
60
+ --border: #27272a;
61
+ --input: #27272a;
62
+ --ring: #d4d4d8;
63
+
64
+ /* Sidebar */
65
+ --sidebar: #18181b;
66
+ --sidebar-foreground: #fafafa;
67
+ --sidebar-muted: #a1a1aa;
68
+ --sidebar-accent: #27272a;
69
+ --sidebar-accent-foreground: #fafafa;
70
+ --sidebar-border: #27272a;
71
+ --sidebar-ring: #d4d4d8;
72
+
73
+ /* Panel */
74
+ --panel: #09090b;
75
+ --panel-foreground: #fafafa;
76
+ --panel-border: #27272a;
77
+ }
78
+
79
+ /* ── Tailwind v4 theme tokens ── */
80
+
81
+ @theme {
82
+ /* Core semantic colors — reference CSS variables for dark mode support */
83
+ --color-background: var(--background);
84
+ --color-foreground: var(--foreground);
85
+ --color-card: var(--card);
86
+ --color-card-foreground: var(--card-foreground);
87
+ --color-popover: var(--popover);
88
+ --color-popover-foreground: var(--popover-foreground);
89
+ --color-primary: var(--primary);
90
+ --color-primary-foreground: var(--primary-foreground);
91
+ --color-secondary: var(--secondary);
92
+ --color-secondary-foreground: var(--secondary-foreground);
93
+ --color-muted: var(--muted);
94
+ --color-muted-foreground: var(--muted-foreground);
95
+ --color-accent: var(--accent);
96
+ --color-accent-foreground: var(--accent-foreground);
97
+ --color-destructive: var(--destructive);
98
+ --color-destructive-foreground: var(--destructive-foreground);
99
+ --color-border: var(--border);
100
+ --color-input: var(--input);
101
+ --color-ring: var(--ring);
102
+
103
+ /* Sidebar */
104
+ --color-sidebar: var(--sidebar);
105
+ --color-sidebar-foreground: var(--sidebar-foreground);
106
+ --color-sidebar-muted: var(--sidebar-muted);
107
+ --color-sidebar-accent: var(--sidebar-accent);
108
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
109
+ --color-sidebar-border: var(--sidebar-border);
110
+ --color-sidebar-ring: var(--sidebar-ring);
111
+
112
+ /* Panel */
113
+ --color-panel: var(--panel);
114
+ --color-panel-foreground: var(--panel-foreground);
115
+ --color-panel-border: var(--panel-border);
116
+
117
+ /* Transition timing */
118
+ --transition-duration: 150ms;
119
+
120
+ /* Animations */
121
+ --animate-fade-in: fade-in 150ms ease-out;
122
+ --animate-fade-out: fade-out 150ms ease-in;
123
+ --animate-scale-in: scale-in 150ms ease-out;
124
+ --animate-scale-out: scale-out 150ms ease-in;
125
+ --animate-slide-down-in: slide-down-in 200ms ease-out;
126
+ --animate-slide-down-out: slide-down-out 200ms ease-in;
127
+ --animate-slide-up-in: slide-up-in 200ms ease-out;
128
+ --animate-slide-up-out: slide-up-out 200ms ease-in;
129
+ --animate-toast-in: toast-in 200ms ease-out;
130
+ --animate-toast-out: toast-out 150ms ease-in;
131
+
132
+ /* Sheet slide animations */
133
+ --animate-sheet-right-in: sheet-right-in 200ms ease-out;
134
+ --animate-sheet-right-out: sheet-right-out 200ms ease-in;
135
+ --animate-sheet-left-in: sheet-left-in 200ms ease-out;
136
+ --animate-sheet-left-out: sheet-left-out 200ms ease-in;
137
+ --animate-sheet-top-in: sheet-top-in 200ms ease-out;
138
+ --animate-sheet-top-out: sheet-top-out 200ms ease-in;
139
+ --animate-sheet-bottom-in: sheet-bottom-in 200ms ease-out;
140
+ --animate-sheet-bottom-out: sheet-bottom-out 200ms ease-in;
141
+
142
+ /* Accordion */
143
+ --animate-accordion-down: accordion-down 200ms ease-out;
144
+ --animate-accordion-up: accordion-up 200ms ease-in;
145
+
146
+ /* Generic enter/exit (tailwindcss-animate compatible) */
147
+ --animate-in: enter 200ms ease-out;
148
+ --animate-out: exit 150ms ease-in;
149
+
150
+ /* Caret blink (input OTP) */
151
+ --animate-caret-blink: caret-blink 1.25s ease-out infinite;
152
+ }
153
+
154
+ /* ── Keyframes ── */
155
+
156
+ @keyframes fade-in {
157
+ from {
158
+ opacity: 0;
159
+ }
160
+ to {
161
+ opacity: 1;
162
+ }
163
+ }
164
+
165
+ @keyframes fade-out {
166
+ from {
167
+ opacity: 1;
168
+ }
169
+ to {
170
+ opacity: 0;
171
+ }
172
+ }
173
+
174
+ @keyframes scale-in {
175
+ from {
176
+ opacity: 0;
177
+ transform: scale(0.95);
178
+ }
179
+ to {
180
+ opacity: 1;
181
+ transform: scale(1);
182
+ }
183
+ }
184
+
185
+ @keyframes scale-out {
186
+ from {
187
+ opacity: 1;
188
+ transform: scale(1);
189
+ }
190
+ to {
191
+ opacity: 0;
192
+ transform: scale(0.95);
193
+ }
194
+ }
195
+
196
+ @keyframes slide-down-in {
197
+ from {
198
+ opacity: 0;
199
+ transform: translateY(-4px);
200
+ }
201
+ to {
202
+ opacity: 1;
203
+ transform: translateY(0);
204
+ }
205
+ }
206
+
207
+ @keyframes slide-down-out {
208
+ from {
209
+ opacity: 1;
210
+ transform: translateY(0);
211
+ }
212
+ to {
213
+ opacity: 0;
214
+ transform: translateY(-4px);
215
+ }
216
+ }
217
+
218
+ @keyframes slide-up-in {
219
+ from {
220
+ opacity: 0;
221
+ transform: translateY(4px);
222
+ }
223
+ to {
224
+ opacity: 1;
225
+ transform: translateY(0);
226
+ }
227
+ }
228
+
229
+ @keyframes slide-up-out {
230
+ from {
231
+ opacity: 1;
232
+ transform: translateY(0);
233
+ }
234
+ to {
235
+ opacity: 0;
236
+ transform: translateY(4px);
237
+ }
238
+ }
239
+
240
+ @keyframes toast-in {
241
+ from {
242
+ opacity: 0;
243
+ transform: translateX(100%);
244
+ }
245
+ to {
246
+ opacity: 1;
247
+ transform: translateX(0);
248
+ }
249
+ }
250
+
251
+ @keyframes toast-out {
252
+ from {
253
+ opacity: 1;
254
+ transform: translateX(0);
255
+ }
256
+ to {
257
+ opacity: 0;
258
+ transform: translateX(100%);
259
+ }
260
+ }
261
+
262
+ /* Sheet slide keyframes */
263
+
264
+ @keyframes sheet-right-in {
265
+ from {
266
+ transform: translateX(100%);
267
+ }
268
+ to {
269
+ transform: translateX(0);
270
+ }
271
+ }
272
+
273
+ @keyframes sheet-right-out {
274
+ from {
275
+ transform: translateX(0);
276
+ }
277
+ to {
278
+ transform: translateX(100%);
279
+ }
280
+ }
281
+
282
+ @keyframes sheet-left-in {
283
+ from {
284
+ transform: translateX(-100%);
285
+ }
286
+ to {
287
+ transform: translateX(0);
288
+ }
289
+ }
290
+
291
+ @keyframes sheet-left-out {
292
+ from {
293
+ transform: translateX(0);
294
+ }
295
+ to {
296
+ transform: translateX(-100%);
297
+ }
298
+ }
299
+
300
+ @keyframes sheet-top-in {
301
+ from {
302
+ transform: translateY(-100%);
303
+ }
304
+ to {
305
+ transform: translateY(0);
306
+ }
307
+ }
308
+
309
+ @keyframes sheet-top-out {
310
+ from {
311
+ transform: translateY(0);
312
+ }
313
+ to {
314
+ transform: translateY(-100%);
315
+ }
316
+ }
317
+
318
+ @keyframes sheet-bottom-in {
319
+ from {
320
+ transform: translateY(100%);
321
+ }
322
+ to {
323
+ transform: translateY(0);
324
+ }
325
+ }
326
+
327
+ @keyframes sheet-bottom-out {
328
+ from {
329
+ transform: translateY(0);
330
+ }
331
+ to {
332
+ transform: translateY(100%);
333
+ }
334
+ }
335
+
336
+ /* Accordion collapse/expand */
337
+
338
+ @keyframes accordion-down {
339
+ from {
340
+ height: 0;
341
+ }
342
+ to {
343
+ height: var(--radix-accordion-content-height);
344
+ }
345
+ }
346
+
347
+ @keyframes accordion-up {
348
+ from {
349
+ height: var(--radix-accordion-content-height);
350
+ }
351
+ to {
352
+ height: 0;
353
+ }
354
+ }
355
+
356
+ /* Generic enter/exit animations (used by dialog, sheet, popover, etc.) */
357
+
358
+ @keyframes enter {
359
+ from {
360
+ opacity: var(--tw-enter-opacity, 1);
361
+ transform: translate3d(var(--tw-enter-translate-x, 0), var(--tw-enter-translate-y, 0), 0)
362
+ scale3d(var(--tw-enter-scale, 1), var(--tw-enter-scale, 1), var(--tw-enter-scale, 1))
363
+ rotate(var(--tw-enter-rotate, 0));
364
+ }
365
+ }
366
+
367
+ @keyframes exit {
368
+ to {
369
+ opacity: var(--tw-exit-opacity, 1);
370
+ transform: translate3d(var(--tw-exit-translate-x, 0), var(--tw-exit-translate-y, 0), 0)
371
+ scale3d(var(--tw-exit-scale, 1), var(--tw-exit-scale, 1), var(--tw-exit-scale, 1))
372
+ rotate(var(--tw-exit-rotate, 0));
373
+ }
374
+ }
375
+
376
+ /* Caret blink for OTP input */
377
+
378
+ @keyframes caret-blink {
379
+ 0%,
380
+ 70%,
381
+ 100% {
382
+ opacity: 1;
383
+ }
384
+ 20%,
385
+ 50% {
386
+ opacity: 0;
387
+ }
388
+ }
389
+
390
+ /* ── Custom utilities ── */
391
+
392
+ @utility no-scrollbar {
393
+ -ms-overflow-style: none;
394
+ scrollbar-width: none;
395
+ &::-webkit-scrollbar {
396
+ display: none;
397
+ }
398
+ }
399
+
400
+ /* ── tailwindcss-animate compatible utilities ──
401
+ * These provide fade-in/out, zoom-in/out, slide-in/out utilities
402
+ * used by shadcn/ui component styles via @apply.
403
+ */
404
+
405
+ @utility fade-in {
406
+ --tw-enter-opacity: 0;
407
+ }
408
+
409
+ @utility fade-in-* {
410
+ --tw-enter-opacity: calc(var(--value) * 1%);
411
+ }
412
+
413
+ @utility fade-out {
414
+ --tw-exit-opacity: 0;
415
+ }
416
+
417
+ @utility fade-out-* {
418
+ --tw-exit-opacity: calc(var(--value) * 1%);
419
+ }
420
+
421
+ @utility zoom-in-* {
422
+ --tw-enter-scale: calc(var(--value) * 1%);
423
+ }
424
+
425
+ @utility zoom-out-* {
426
+ --tw-exit-scale: calc(var(--value) * 1%);
427
+ }
428
+
429
+ @utility slide-in-from-top-* {
430
+ --tw-enter-translate-y: calc(var(--value) * -1);
431
+ }
432
+
433
+ @utility slide-in-from-bottom-* {
434
+ --tw-enter-translate-y: var(--value);
435
+ }
436
+
437
+ @utility slide-in-from-left-* {
438
+ --tw-enter-translate-x: calc(var(--value) * -1);
439
+ }
440
+
441
+ @utility slide-in-from-right-* {
442
+ --tw-enter-translate-x: var(--value);
443
+ }
444
+
445
+ @utility slide-out-to-top-* {
446
+ --tw-exit-translate-y: calc(var(--value) * -1);
447
+ }
448
+
449
+ @utility slide-out-to-bottom-* {
450
+ --tw-exit-translate-y: var(--value);
451
+ }
452
+
453
+ @utility slide-out-to-left-* {
454
+ --tw-exit-translate-x: calc(var(--value) * -1);
455
+ }
456
+
457
+ @utility slide-out-to-right-* {
458
+ --tw-exit-translate-x: var(--value);
459
+ }
@@ -0,0 +1,62 @@
1
+ import * as React from 'react';
2
+ import { ToggleGroup as ToggleGroupPrimitive } from 'radix-ui';
3
+ import { cn } from './lib/utils.js';
4
+ import { toggleVariants } from './toggle.jsx';
5
+ const ToggleGroupContext = React.createContext({
6
+ size: 'default',
7
+ variant: 'default',
8
+ spacing: 0,
9
+ orientation: 'horizontal',
10
+ });
11
+ function ToggleGroup({
12
+ className,
13
+ variant,
14
+ size,
15
+ spacing = 0,
16
+ orientation = 'horizontal',
17
+ children,
18
+ ...props
19
+ }) {
20
+ return (
21
+ <ToggleGroupPrimitive.Root
22
+ data-slot="toggle-group"
23
+ data-variant={variant}
24
+ data-size={size}
25
+ data-spacing={spacing}
26
+ data-orientation={orientation}
27
+ style={{ '--gap': spacing }}
28
+ className={cn(
29
+ 'cn-toggle-group group/toggle-group flex w-fit flex-row items-center gap-[--spacing(var(--gap))] data-vertical:flex-col data-vertical:items-stretch',
30
+ className,
31
+ )}
32
+ {...props}
33
+ >
34
+ <ToggleGroupContext.Provider value={{ variant, size, spacing, orientation }}>
35
+ {children}
36
+ </ToggleGroupContext.Provider>
37
+ </ToggleGroupPrimitive.Root>
38
+ );
39
+ }
40
+ function ToggleGroupItem({ className, children, variant = 'default', size = 'default', ...props }) {
41
+ const context = React.useContext(ToggleGroupContext);
42
+ return (
43
+ <ToggleGroupPrimitive.Item
44
+ data-slot="toggle-group-item"
45
+ data-variant={context.variant || variant}
46
+ data-size={context.size || size}
47
+ data-spacing={context.spacing}
48
+ className={cn(
49
+ 'cn-toggle-group-item shrink-0 focus:z-10 focus-visible:z-10 group-data-horizontal/toggle-group:data-[spacing=0]:data-[variant=outline]:border-l-0 group-data-vertical/toggle-group:data-[spacing=0]:data-[variant=outline]:border-t-0 group-data-horizontal/toggle-group:data-[spacing=0]:data-[variant=outline]:first:border-l group-data-vertical/toggle-group:data-[spacing=0]:data-[variant=outline]:first:border-t',
50
+ toggleVariants({
51
+ variant: context.variant || variant,
52
+ size: context.size || size,
53
+ }),
54
+ className,
55
+ )}
56
+ {...props}
57
+ >
58
+ {children}
59
+ </ToggleGroupPrimitive.Item>
60
+ );
61
+ }
62
+ export { ToggleGroup, ToggleGroupItem };
@@ -0,0 +1,68 @@
1
+ import React from 'react';
2
+ import { expect, within } from 'storybook/test';
3
+ import { BoldIcon, ItalicIcon, UnderlineIcon } from 'lucide-react';
4
+ import { ToggleGroup, ToggleGroupItem } from './toggle-group.jsx';
5
+ const meta = {
6
+ title: 'UI/ToggleGroup',
7
+ component: ToggleGroup,
8
+ };
9
+ var stdin_default = meta;
10
+ const Default = {
11
+ render: () => (
12
+ <ToggleGroup type="multiple">
13
+ <ToggleGroupItem value="bold" aria-label="Bold">
14
+ <BoldIcon className="size-4" />
15
+ </ToggleGroupItem>
16
+ <ToggleGroupItem value="italic" aria-label="Italic">
17
+ <ItalicIcon className="size-4" />
18
+ </ToggleGroupItem>
19
+ <ToggleGroupItem value="underline" aria-label="Underline">
20
+ <UnderlineIcon className="size-4" />
21
+ </ToggleGroupItem>
22
+ </ToggleGroup>
23
+ ),
24
+ play: async ({ canvasElement }) => {
25
+ const canvas = within(canvasElement);
26
+ const group = canvas.getByRole('group');
27
+ await expect(group).toBeInTheDocument();
28
+ await expect(group.dataset.slot).toBe('toggle-group');
29
+ const items = canvasElement.querySelectorAll('[data-slot="toggle-group-item"]');
30
+ await expect(items).toHaveLength(3);
31
+ },
32
+ };
33
+ const Single = {
34
+ render: () => (
35
+ <ToggleGroup type="single" defaultValue="bold">
36
+ <ToggleGroupItem value="bold" aria-label="Bold">
37
+ <BoldIcon className="size-4" />
38
+ </ToggleGroupItem>
39
+ <ToggleGroupItem value="italic" aria-label="Italic">
40
+ <ItalicIcon className="size-4" />
41
+ </ToggleGroupItem>
42
+ </ToggleGroup>
43
+ ),
44
+ play: async ({ canvasElement }) => {
45
+ const canvas = within(canvasElement);
46
+ const boldBtn = canvas.getByLabelText('Bold');
47
+ await expect(boldBtn.dataset.state).toBe('on');
48
+ const italicBtn = canvas.getByLabelText('Italic');
49
+ await expect(italicBtn.dataset.state).toBe('off');
50
+ },
51
+ };
52
+ const Outline = {
53
+ render: () => (
54
+ <ToggleGroup type="multiple" variant="outline">
55
+ <ToggleGroupItem value="bold" aria-label="Bold">
56
+ <BoldIcon className="size-4" />
57
+ </ToggleGroupItem>
58
+ <ToggleGroupItem value="italic" aria-label="Italic">
59
+ <ItalicIcon className="size-4" />
60
+ </ToggleGroupItem>
61
+ </ToggleGroup>
62
+ ),
63
+ play: async ({ canvasElement }) => {
64
+ const group = canvasElement.querySelector('[data-slot="toggle-group"]');
65
+ await expect(group?.getAttribute('data-variant')).toBe('outline');
66
+ },
67
+ };
68
+ export { Default, Outline, Single, stdin_default as default };
@@ -0,0 +1,34 @@
1
+ import React from 'react';
2
+ import { cva } from 'class-variance-authority';
3
+ import { Toggle as TogglePrimitive } from 'radix-ui';
4
+ import { cn } from './lib/utils.js';
5
+ const toggleVariants = cva(
6
+ 'cn-toggle group/toggle hover:bg-muted inline-flex items-center justify-center whitespace-nowrap outline-none focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0',
7
+ {
8
+ variants: {
9
+ variant: {
10
+ default: 'cn-toggle-variant-default',
11
+ outline: 'cn-toggle-variant-outline',
12
+ },
13
+ size: {
14
+ default: 'cn-toggle-size-default',
15
+ sm: 'cn-toggle-size-sm',
16
+ lg: 'cn-toggle-size-lg',
17
+ },
18
+ },
19
+ defaultVariants: {
20
+ variant: 'default',
21
+ size: 'default',
22
+ },
23
+ },
24
+ );
25
+ function Toggle({ className, variant = 'default', size = 'default', ...props }) {
26
+ return (
27
+ <TogglePrimitive.Root
28
+ data-slot="toggle"
29
+ className={cn(toggleVariants({ variant, size, className }))}
30
+ {...props}
31
+ />
32
+ );
33
+ }
34
+ export { Toggle, toggleVariants };
@@ -0,0 +1,46 @@
1
+ import { expect, within } from 'storybook/test';
2
+ import { Toggle } from './toggle.jsx';
3
+ const meta = {
4
+ title: 'UI/Toggle',
5
+ component: Toggle,
6
+ argTypes: {
7
+ variant: { control: 'select', options: ['default', 'outline'] },
8
+ size: { control: 'select', options: ['default', 'sm', 'lg'] },
9
+ },
10
+ };
11
+ var stdin_default = meta;
12
+ const Default = {
13
+ args: { children: 'B', 'aria-label': 'Toggle bold' },
14
+ play: async ({ canvasElement }) => {
15
+ const canvas = within(canvasElement);
16
+ const toggle = canvas.getByRole('button', { name: 'Toggle bold' });
17
+ await expect(toggle).toBeInTheDocument();
18
+ await expect(toggle.dataset.slot).toBe('toggle');
19
+ await expect(toggle.dataset.state).toBe('off');
20
+ },
21
+ };
22
+ const Pressed = {
23
+ args: { children: 'B', 'aria-label': 'Toggle bold', defaultPressed: true },
24
+ play: async ({ canvasElement }) => {
25
+ const canvas = within(canvasElement);
26
+ const toggle = canvas.getByRole('button', { name: 'Toggle bold' });
27
+ await expect(toggle.dataset.state).toBe('on');
28
+ },
29
+ };
30
+ const Outline = {
31
+ args: { children: 'I', variant: 'outline', 'aria-label': 'Toggle italic' },
32
+ play: async ({ canvasElement }) => {
33
+ const canvas = within(canvasElement);
34
+ const toggle = canvas.getByRole('button', { name: 'Toggle italic' });
35
+ await expect(toggle).toBeInTheDocument();
36
+ },
37
+ };
38
+ const Disabled = {
39
+ args: { children: 'B', disabled: true, 'aria-label': 'Toggle bold' },
40
+ play: async ({ canvasElement }) => {
41
+ const canvas = within(canvasElement);
42
+ const toggle = canvas.getByRole('button', { name: 'Toggle bold' });
43
+ await expect(toggle).toBeDisabled();
44
+ },
45
+ };
46
+ export { Default, Disabled, Outline, Pressed, stdin_default as default };
@@ -0,0 +1,37 @@
1
+ import React from 'react';
2
+ import { Tooltip as TooltipPrimitive } from 'radix-ui';
3
+ import { cn } from './lib/utils.js';
4
+ function TooltipProvider({ delayDuration = 0, ...props }) {
5
+ return (
6
+ <TooltipPrimitive.Provider
7
+ data-slot="tooltip-provider"
8
+ delayDuration={delayDuration}
9
+ {...props}
10
+ />
11
+ );
12
+ }
13
+ function Tooltip({ ...props }) {
14
+ return <TooltipPrimitive.Root data-slot="tooltip" {...props} />;
15
+ }
16
+ function TooltipTrigger({ ...props }) {
17
+ return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />;
18
+ }
19
+ function TooltipContent({ className, sideOffset = 0, children, ...props }) {
20
+ return (
21
+ <TooltipPrimitive.Portal>
22
+ <TooltipPrimitive.Content
23
+ data-slot="tooltip-content"
24
+ sideOffset={sideOffset}
25
+ className={cn(
26
+ 'cn-tooltip-content bg-foreground text-background z-50 w-fit max-w-xs origin-(--radix-tooltip-content-transform-origin)',
27
+ className,
28
+ )}
29
+ {...props}
30
+ >
31
+ {children}
32
+ <TooltipPrimitive.Arrow className="cn-tooltip-arrow bg-foreground fill-foreground z-50 translate-y-[calc(-50%_-_2px)]" />
33
+ </TooltipPrimitive.Content>
34
+ </TooltipPrimitive.Portal>
35
+ );
36
+ }
37
+ export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };