@sntlr/registry-shell 1.0.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.
- package/LICENSE +21 -0
- package/README.md +200 -0
- package/dist/adapter/custom.d.ts +47 -0
- package/dist/adapter/custom.js +53 -0
- package/dist/adapter/custom.js.map +1 -0
- package/dist/adapter/default.d.ts +40 -0
- package/dist/adapter/default.js +202 -0
- package/dist/adapter/default.js.map +1 -0
- package/dist/cli/build.d.ts +1 -0
- package/dist/cli/build.js +31 -0
- package/dist/cli/build.js.map +1 -0
- package/dist/cli/dev.d.ts +1 -0
- package/dist/cli/dev.js +26 -0
- package/dist/cli/dev.js.map +1 -0
- package/dist/cli/index.d.ts +12 -0
- package/dist/cli/index.js +49 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init.d.ts +1 -0
- package/dist/cli/init.js +70 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/shared.d.ts +33 -0
- package/dist/cli/shared.js +278 -0
- package/dist/cli/shared.js.map +1 -0
- package/dist/cli/start.d.ts +1 -0
- package/dist/cli/start.js +24 -0
- package/dist/cli/start.js.map +1 -0
- package/dist/config-loader.d.ts +49 -0
- package/dist/config-loader.js +140 -0
- package/dist/define-config.d.ts +188 -0
- package/dist/define-config.js +21 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +9 -0
- package/package.json +124 -0
- package/src/adapter/custom.ts +90 -0
- package/src/adapter/default.ts +241 -0
- package/src/cli/build.ts +38 -0
- package/src/cli/dev.ts +38 -0
- package/src/cli/index.ts +52 -0
- package/src/cli/init.ts +76 -0
- package/src/cli/shared.ts +306 -0
- package/src/cli/start.ts +28 -0
- package/src/config-loader.ts +190 -0
- package/src/define-config.ts +206 -0
- package/src/index.ts +17 -0
- package/src/next-app/app/[...asset]/route.ts +81 -0
- package/src/next-app/app/_user-global.css +6 -0
- package/src/next-app/app/_user-sources.css +9 -0
- package/src/next-app/app/a11y/[name]/route.ts +19 -0
- package/src/next-app/app/api/search-index/route.ts +19 -0
- package/src/next-app/app/components/[name]/page.tsx +61 -0
- package/src/next-app/app/components/layout.tsx +18 -0
- package/src/next-app/app/docs/[slug]/page.tsx +53 -0
- package/src/next-app/app/docs/layout.tsx +18 -0
- package/src/next-app/app/globals.css +329 -0
- package/src/next-app/app/layout.tsx +102 -0
- package/src/next-app/app/page.tsx +9 -0
- package/src/next-app/app/preview-snapshot/[name]/page.tsx +20 -0
- package/src/next-app/app/preview-snapshot/layout.tsx +17 -0
- package/src/next-app/app/props/[name]/route.ts +19 -0
- package/src/next-app/app/r/[name]/route.ts +14 -0
- package/src/next-app/app/tests/[name]/route.ts +19 -0
- package/src/next-app/components/a11y-info.tsx +287 -0
- package/src/next-app/components/a11y-provider.tsx +39 -0
- package/src/next-app/components/component-breadcrumb.tsx +55 -0
- package/src/next-app/components/component-icon.tsx +140 -0
- package/src/next-app/components/component-preview.tsx +13 -0
- package/src/next-app/components/component-tabs.tsx +209 -0
- package/src/next-app/components/docs-toc.tsx +86 -0
- package/src/next-app/components/global-mobile-sidebar.tsx +35 -0
- package/src/next-app/components/header.tsx +188 -0
- package/src/next-app/components/heading-anchor.tsx +52 -0
- package/src/next-app/components/homepage-demo.tsx +180 -0
- package/src/next-app/components/locale-toggle.tsx +35 -0
- package/src/next-app/components/localized-mdx-client.tsx +14 -0
- package/src/next-app/components/localized-mdx.tsx +27 -0
- package/src/next-app/components/mobile-sidebar.tsx +22 -0
- package/src/next-app/components/nav-data-provider.tsx +37 -0
- package/src/next-app/components/navigation-progress.tsx +62 -0
- package/src/next-app/components/preview-canvas.tsx +368 -0
- package/src/next-app/components/preview-controls.tsx +94 -0
- package/src/next-app/components/preview-layout.tsx +218 -0
- package/src/next-app/components/props-table.tsx +134 -0
- package/src/next-app/components/resizable-preview.tsx +101 -0
- package/src/next-app/components/search.tsx +177 -0
- package/src/next-app/components/settings-modal.tsx +98 -0
- package/src/next-app/components/shell-ui/accordion.tsx +70 -0
- package/src/next-app/components/shell-ui/backdrop.tsx +29 -0
- package/src/next-app/components/shell-ui/badge.tsx +55 -0
- package/src/next-app/components/shell-ui/breadcrumb.tsx +120 -0
- package/src/next-app/components/shell-ui/button.tsx +64 -0
- package/src/next-app/components/shell-ui/card.tsx +127 -0
- package/src/next-app/components/shell-ui/checkbox.tsx +33 -0
- package/src/next-app/components/shell-ui/dialog.tsx +171 -0
- package/src/next-app/components/shell-ui/empty-state.tsx +66 -0
- package/src/next-app/components/shell-ui/input.tsx +27 -0
- package/src/next-app/components/shell-ui/kbd.tsx +30 -0
- package/src/next-app/components/shell-ui/label.tsx +25 -0
- package/src/next-app/components/shell-ui/select.tsx +204 -0
- package/src/next-app/components/shell-ui/separator.tsx +32 -0
- package/src/next-app/components/shell-ui/skeleton.tsx +18 -0
- package/src/next-app/components/shell-ui/table.tsx +124 -0
- package/src/next-app/components/shell-ui/tabs.tsx +102 -0
- package/src/next-app/components/shell-ui/toggle.tsx +56 -0
- package/src/next-app/components/sidebar-layout.tsx +37 -0
- package/src/next-app/components/sidebar-provider.tsx +75 -0
- package/src/next-app/components/sidebar.tsx +222 -0
- package/src/next-app/components/snapshot-preview.tsx +28 -0
- package/src/next-app/components/test-info.tsx +155 -0
- package/src/next-app/components/theme-provider.tsx +16 -0
- package/src/next-app/components/theme-toggle.tsx +21 -0
- package/src/next-app/components/translated-text.tsx +8 -0
- package/src/next-app/fallback/homepage.tsx +112 -0
- package/src/next-app/fallback/previews.ts +17 -0
- package/src/next-app/hooks/use-active-section.ts +23 -0
- package/src/next-app/hooks/use-controls.ts +72 -0
- package/src/next-app/hooks/use-mobile.ts +19 -0
- package/src/next-app/lib/branding.ts +52 -0
- package/src/next-app/lib/components-nav.ts +8 -0
- package/src/next-app/lib/docs.ts +16 -0
- package/src/next-app/lib/github.ts +38 -0
- package/src/next-app/lib/i18n.tsx +630 -0
- package/src/next-app/lib/locales.ts +17 -0
- package/src/next-app/lib/preview-loader.ts +7 -0
- package/src/next-app/lib/registry-adapter.ts +199 -0
- package/src/next-app/lib/utils.ts +6 -0
- package/src/next-app/next-env.d.ts +6 -0
- package/src/next-app/next.config.ts +101 -0
- package/src/next-app/postcss.config.mjs +7 -0
- package/src/next-app/public/favicon.ico +0 -0
- package/src/next-app/public/favicon_dark.svg +3 -0
- package/src/next-app/public/favicon_light.svg +3 -0
- package/src/next-app/registry.config.ts +50 -0
- package/src/next-app/tsconfig.json +29 -0
- package/src/next-app/user-aliases.d.ts +17 -0
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
@import "tailwindcss";
|
|
2
|
+
@import "tw-animate-css";
|
|
3
|
+
@plugin "@tailwindcss/typography";
|
|
4
|
+
|
|
5
|
+
/* Tailwind content scan for the user's registry files. Generated by the CLI
|
|
6
|
+
* from the `paths` declared in sntlr.ui-shell.config.ts — regenerated every
|
|
7
|
+
* `ui-shell dev` / `build` boot. Do not edit _user-sources.css by hand. */
|
|
8
|
+
@import "./_user-sources.css";
|
|
9
|
+
|
|
10
|
+
@custom-variant dark (&:is(.dark *));
|
|
11
|
+
|
|
12
|
+
@theme inline {
|
|
13
|
+
--color-background: var(--background);
|
|
14
|
+
--color-foreground: var(--foreground);
|
|
15
|
+
--default-font-family: var(--font-sans);
|
|
16
|
+
--default-mono-font-family: var(--font-mono);
|
|
17
|
+
--color-sidebar-ring: var(--sidebar-ring);
|
|
18
|
+
--color-sidebar-border: var(--sidebar-border);
|
|
19
|
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
20
|
+
--color-sidebar-accent: var(--sidebar-accent);
|
|
21
|
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
22
|
+
--color-sidebar-primary: var(--sidebar-primary);
|
|
23
|
+
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
24
|
+
--color-sidebar: var(--sidebar);
|
|
25
|
+
--color-chart-5: var(--chart-5);
|
|
26
|
+
--color-chart-4: var(--chart-4);
|
|
27
|
+
--color-chart-3: var(--chart-3);
|
|
28
|
+
--color-chart-2: var(--chart-2);
|
|
29
|
+
--color-chart-1: var(--chart-1);
|
|
30
|
+
--color-ring: var(--ring);
|
|
31
|
+
--color-input: var(--input);
|
|
32
|
+
--color-border: var(--border);
|
|
33
|
+
--color-destructive: var(--destructive);
|
|
34
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
35
|
+
--color-accent: var(--accent);
|
|
36
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
37
|
+
--color-muted: var(--muted);
|
|
38
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
39
|
+
--color-secondary: var(--secondary);
|
|
40
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
41
|
+
--color-primary: var(--primary);
|
|
42
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
43
|
+
--color-popover: var(--popover);
|
|
44
|
+
--color-card-foreground: var(--card-foreground);
|
|
45
|
+
--color-card: var(--card);
|
|
46
|
+
--radius-sm: calc(var(--radius) - 4px);
|
|
47
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
48
|
+
--radius-lg: var(--radius);
|
|
49
|
+
--radius-xl: calc(var(--radius) + 4px);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
:root {
|
|
53
|
+
--radius: 0.625rem;
|
|
54
|
+
--background: oklch(1 0 0);
|
|
55
|
+
--foreground: oklch(0.145 0 0);
|
|
56
|
+
--card: oklch(1 0 0);
|
|
57
|
+
--card-foreground: oklch(0.145 0 0);
|
|
58
|
+
--popover: oklch(1 0 0);
|
|
59
|
+
--popover-foreground: oklch(0.145 0 0);
|
|
60
|
+
--primary: oklch(0.426 0.094 161.619);
|
|
61
|
+
--primary-foreground: oklch(0.985 0 0);
|
|
62
|
+
--secondary: oklch(0.97 0 0);
|
|
63
|
+
--secondary-foreground: oklch(0.205 0 0);
|
|
64
|
+
--muted: oklch(0.97 0 0);
|
|
65
|
+
--muted-foreground: oklch(0.525 0 0);
|
|
66
|
+
--accent: oklch(0.97 0 0);
|
|
67
|
+
--accent-foreground: oklch(0.205 0 0);
|
|
68
|
+
--destructive: oklch(0.577 0.245 27.325);
|
|
69
|
+
--border: oklch(0.922 0 0);
|
|
70
|
+
--input: oklch(0.922 0 0);
|
|
71
|
+
--ring: oklch(0.708 0 0);
|
|
72
|
+
--chart-1: oklch(0.646 0.222 41.116);
|
|
73
|
+
--chart-2: oklch(0.6 0.118 184.714);
|
|
74
|
+
--chart-3: oklch(0.398 0.07 227.392);
|
|
75
|
+
--chart-4: oklch(0.828 0.189 84.429);
|
|
76
|
+
--chart-5: oklch(0.769 0.188 70.08);
|
|
77
|
+
--sidebar: oklch(0.985 0 0);
|
|
78
|
+
--sidebar-foreground: oklch(0.145 0 0);
|
|
79
|
+
--sidebar-primary: oklch(0.426 0.094 161.619);
|
|
80
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
81
|
+
--sidebar-accent: oklch(0.97 0 0);
|
|
82
|
+
--sidebar-accent-foreground: oklch(0.205 0 0);
|
|
83
|
+
--sidebar-border: oklch(0.922 0 0);
|
|
84
|
+
--sidebar-ring: oklch(0.708 0 0);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.dark {
|
|
88
|
+
--background: oklch(0.145 0 0);
|
|
89
|
+
--foreground: oklch(0.985 0 0);
|
|
90
|
+
--card: oklch(0.145 0 0);
|
|
91
|
+
--card-foreground: oklch(0.985 0 0);
|
|
92
|
+
--popover: oklch(0.145 0 0);
|
|
93
|
+
--popover-foreground: oklch(0.985 0 0);
|
|
94
|
+
--primary: oklch(0.796 0.125 168.082);
|
|
95
|
+
--primary-foreground: oklch(0.145 0 0);
|
|
96
|
+
--secondary: oklch(0.269 0 0);
|
|
97
|
+
--secondary-foreground: oklch(0.985 0 0);
|
|
98
|
+
--muted: oklch(0.269 0 0);
|
|
99
|
+
--muted-foreground: oklch(0.708 0 0);
|
|
100
|
+
--accent: oklch(0.269 0 0);
|
|
101
|
+
--accent-foreground: oklch(0.985 0 0);
|
|
102
|
+
--destructive: oklch(0.577 0.245 27.325);
|
|
103
|
+
--border: oklch(0.269 0 0);
|
|
104
|
+
--input: oklch(0.269 0 0);
|
|
105
|
+
--ring: oklch(0.439 0 0);
|
|
106
|
+
--chart-1: oklch(0.488 0.243 264.376);
|
|
107
|
+
--chart-2: oklch(0.696 0.17 162.48);
|
|
108
|
+
--chart-3: oklch(0.769 0.188 70.08);
|
|
109
|
+
--chart-4: oklch(0.627 0.265 303.9);
|
|
110
|
+
--chart-5: oklch(0.645 0.246 16.439);
|
|
111
|
+
--sidebar: oklch(0.205 0 0);
|
|
112
|
+
--sidebar-foreground: oklch(0.985 0 0);
|
|
113
|
+
--sidebar-primary: oklch(0.796 0.125 168.082);
|
|
114
|
+
--sidebar-primary-foreground: oklch(0.145 0 0);
|
|
115
|
+
--sidebar-accent: oklch(0.269 0 0);
|
|
116
|
+
--sidebar-accent-foreground: oklch(0.985 0 0);
|
|
117
|
+
--sidebar-border: oklch(0.269 0 0);
|
|
118
|
+
--sidebar-ring: oklch(0.439 0 0);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
@layer base {
|
|
122
|
+
* {
|
|
123
|
+
@apply border-border;
|
|
124
|
+
}
|
|
125
|
+
html, body {
|
|
126
|
+
scrollbar-gutter: stable;
|
|
127
|
+
}
|
|
128
|
+
body {
|
|
129
|
+
@apply bg-background text-foreground font-sans;
|
|
130
|
+
}
|
|
131
|
+
/* Prevent Radix scroll-lock from causing layout shift */
|
|
132
|
+
body[data-scroll-locked] {
|
|
133
|
+
margin-right: 0 !important;
|
|
134
|
+
scrollbar-gutter: stable;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/* Minimal scrollbars */
|
|
139
|
+
* {
|
|
140
|
+
scrollbar-width: thin;
|
|
141
|
+
scrollbar-color: var(--border) transparent;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
*::-webkit-scrollbar {
|
|
145
|
+
width: 6px;
|
|
146
|
+
height: 6px;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
*::-webkit-scrollbar-track {
|
|
150
|
+
background: transparent;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
*::-webkit-scrollbar-thumb {
|
|
154
|
+
background: var(--border);
|
|
155
|
+
border-radius: 3px;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
*::-webkit-scrollbar-thumb:hover {
|
|
159
|
+
background: var(--muted-foreground);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.prose pre {
|
|
163
|
+
@apply bg-muted text-foreground rounded-lg;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.prose code::before,
|
|
167
|
+
.prose code::after {
|
|
168
|
+
content: none;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.prose :not(pre) > code {
|
|
172
|
+
@apply bg-muted px-1.5 py-0.5 rounded text-xs font-medium;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.prose a {
|
|
176
|
+
@apply underline underline-offset-2 decoration-border hover:decoration-foreground transition-colors;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.prose table {
|
|
180
|
+
@apply w-full text-sm;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.prose th {
|
|
184
|
+
@apply text-left font-medium px-3 py-2 border-b border-border;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.prose td {
|
|
188
|
+
@apply px-3 py-2 border-b border-border;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
@media (prefers-reduced-motion: reduce) {
|
|
192
|
+
*, *::before, *::after {
|
|
193
|
+
animation-duration: 0.01ms !important;
|
|
194
|
+
animation-iteration-count: 1 !important;
|
|
195
|
+
transition-duration: 0.01ms !important;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/* Chart line draw-in animation */
|
|
200
|
+
@keyframes chart-draw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
|
|
201
|
+
/* Pair with `pathLength="1"` on the path so the animation is length-agnostic. */
|
|
202
|
+
.chart-line { stroke-dasharray: 1; animation: chart-draw 1.5s ease-out forwards; }
|
|
203
|
+
|
|
204
|
+
/* Bento chart entry animations — line draws, area fades in, dots pop sequentially */
|
|
205
|
+
@keyframes chart-area-fade { from { opacity: 0; } to { opacity: 1; } }
|
|
206
|
+
@keyframes chart-dot-pop {
|
|
207
|
+
0% { opacity: 0; transform: scale(0); }
|
|
208
|
+
60% { opacity: 1; transform: scale(1.4); }
|
|
209
|
+
100% { opacity: 1; transform: scale(1); }
|
|
210
|
+
}
|
|
211
|
+
.chart-area-fade { animation: chart-area-fade 1.4s ease-out 0.4s both; }
|
|
212
|
+
.chart-dot-pop { transform-box: fill-box; transform-origin: center; animation: chart-dot-pop 0.5s ease-out both; }
|
|
213
|
+
|
|
214
|
+
/* Typing cursor blink */
|
|
215
|
+
@keyframes cursor-blink { 0%, 100% { opacity: 1; } 50% { opacity: 0; } }
|
|
216
|
+
.typing-cursor { animation: cursor-blink 0.8s step-end infinite; }
|
|
217
|
+
|
|
218
|
+
/* Marquee */
|
|
219
|
+
@keyframes marquee-left { from { transform: translateX(0); } to { transform: translateX(-50%); } }
|
|
220
|
+
@keyframes marquee-right { from { transform: translateX(-50%); } to { transform: translateX(0); } }
|
|
221
|
+
.marquee-track { animation: marquee-left 30s linear infinite; }
|
|
222
|
+
.marquee-track-reverse { animation: marquee-right 30s linear infinite; }
|
|
223
|
+
.marquee-container:hover .marquee-track,
|
|
224
|
+
.marquee-container:hover .marquee-track-reverse { animation-play-state: paused; }
|
|
225
|
+
|
|
226
|
+
/* Bounce chevron */
|
|
227
|
+
@keyframes bounce-gentle { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(6px); } }
|
|
228
|
+
.bounce-gentle { animation: bounce-gentle 2s ease-in-out infinite; }
|
|
229
|
+
|
|
230
|
+
/* Hero bento card entrance — pre-animation hidden state.
|
|
231
|
+
* The actual animation is driven by the Web Animations API in HeroSection
|
|
232
|
+
* (with a module-level guard) so it's guaranteed to fire exactly once per
|
|
233
|
+
* page load — even under React strict-mode double-mounts or hydration
|
|
234
|
+
* recovery. Cells are kept invisible via this class until the JS effect
|
|
235
|
+
* runs and replaces it with the WAAPI-driven keyframes. */
|
|
236
|
+
.bento-cell-pending { opacity: 0; }
|
|
237
|
+
|
|
238
|
+
/* Prototyping section — file flying along the conveyor */
|
|
239
|
+
@keyframes proto-fly {
|
|
240
|
+
0% { left: 0%; opacity: 0; transform: translate(-50%, -50%) scale(0.85); }
|
|
241
|
+
10% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
|
|
242
|
+
85% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
|
|
243
|
+
100% { left: 100%; opacity: 0; transform: translate(-50%, -50%) scale(0.85); }
|
|
244
|
+
}
|
|
245
|
+
.proto-fly { animation: proto-fly 2.2s ease-in-out forwards; }
|
|
246
|
+
|
|
247
|
+
/* Prototyping section — checkmark pop-in for the test list */
|
|
248
|
+
@keyframes proto-check-pop {
|
|
249
|
+
0% { opacity: 0; transform: scale(0.4); }
|
|
250
|
+
60% { opacity: 1; transform: scale(1.25); }
|
|
251
|
+
100% { opacity: 1; transform: scale(1); }
|
|
252
|
+
}
|
|
253
|
+
.proto-check-pop { animation: proto-check-pop 0.45s ease-out both; }
|
|
254
|
+
|
|
255
|
+
/* Prototyping section — neural network node pulse */
|
|
256
|
+
@keyframes proto-node-pulse {
|
|
257
|
+
0%, 100% { opacity: 0.55; r: 3.5; }
|
|
258
|
+
50% { opacity: 1; r: 5; }
|
|
259
|
+
}
|
|
260
|
+
.proto-node-pulse { animation: proto-node-pulse 1.6s ease-in-out infinite; }
|
|
261
|
+
|
|
262
|
+
/* Prototyping section — synapse trail (used by stroke-dasharray fired links) */
|
|
263
|
+
@keyframes proto-synapse {
|
|
264
|
+
0% { stroke-dashoffset: 1; opacity: 0; }
|
|
265
|
+
20% { opacity: 0.9; }
|
|
266
|
+
100% { stroke-dashoffset: 0; opacity: 0; }
|
|
267
|
+
}
|
|
268
|
+
.proto-synapse { stroke-dasharray: 1; animation: proto-synapse 1.4s ease-out forwards; }
|
|
269
|
+
|
|
270
|
+
/* Data-table row flash highlights — appear (primary), update (orange), delete (red→fade out) */
|
|
271
|
+
@keyframes row-flash-appear {
|
|
272
|
+
0% { background-color: color-mix(in oklch, var(--color-primary) 28%, transparent); }
|
|
273
|
+
100% { background-color: transparent; }
|
|
274
|
+
}
|
|
275
|
+
@keyframes row-flash-update {
|
|
276
|
+
0% { background-color: oklch(0.75 0.18 65 / 0.32); }
|
|
277
|
+
100% { background-color: transparent; }
|
|
278
|
+
}
|
|
279
|
+
@keyframes row-flash-delete {
|
|
280
|
+
0% { background-color: oklch(0.6 0.22 25 / 0.45); opacity: 1; }
|
|
281
|
+
70% { background-color: oklch(0.6 0.22 25 / 0.45); opacity: 1; }
|
|
282
|
+
100% { background-color: oklch(0.6 0.22 25 / 0.45); opacity: 0; }
|
|
283
|
+
}
|
|
284
|
+
.row-flash-appear { animation: row-flash-appear 3s ease-out forwards; }
|
|
285
|
+
.row-flash-update { animation: row-flash-update 3s ease-out forwards; }
|
|
286
|
+
.row-flash-delete { animation: row-flash-delete 1.4s ease-out forwards; pointer-events: none; }
|
|
287
|
+
|
|
288
|
+
/* Row presence avatar — fades+scales in (and stays visible until removed by JS) */
|
|
289
|
+
@keyframes row-presence-pop {
|
|
290
|
+
0% { opacity: 0; transform: translateY(-50%) scale(0.6); }
|
|
291
|
+
60% { opacity: 1; transform: translateY(-50%) scale(1.1); }
|
|
292
|
+
100% { opacity: 1; transform: translateY(-50%) scale(1); }
|
|
293
|
+
}
|
|
294
|
+
.row-presence-pop { animation: row-presence-pop 0.35s ease-out forwards; }
|
|
295
|
+
|
|
296
|
+
/* Gradient text */
|
|
297
|
+
.text-gradient-primary {
|
|
298
|
+
color: transparent;
|
|
299
|
+
background-image: linear-gradient(135deg, var(--color-primary), oklch(0.6 0.15 180));
|
|
300
|
+
-webkit-background-clip: text;
|
|
301
|
+
background-clip: text;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/* Skip navigation link */
|
|
305
|
+
.skip-nav {
|
|
306
|
+
@apply sr-only focus:not-sr-only focus:fixed focus:top-2 focus:left-2 focus:z-[100] focus:px-4 focus:py-2 focus:rounded-md focus:bg-background focus:text-foreground focus:border focus:border-border focus:shadow-lg;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/* High contrast mode */
|
|
310
|
+
@media (forced-colors: active) {
|
|
311
|
+
* { border-color: CanvasText !important; }
|
|
312
|
+
button, [role="button"] { border: 1px solid ButtonText !important; }
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/* Text scaling safety */
|
|
316
|
+
html { font-size: clamp(14px, 1rem, 20px); }
|
|
317
|
+
|
|
318
|
+
@media print {
|
|
319
|
+
header, aside, .no-print { display: none !important; }
|
|
320
|
+
main { width: 100% !important; margin: 0 !important; }
|
|
321
|
+
pre { white-space: pre-wrap !important; word-break: break-word !important; }
|
|
322
|
+
* { box-shadow: none !important; }
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/* User's optional global CSS — `paths.globalCss` in their config.
|
|
326
|
+
* Generated by the CLI. Imported LAST so user `:root`/`.dark` token
|
|
327
|
+
* overrides cascade-win over the shell's defaults above. Always exists
|
|
328
|
+
* (no-op when unconfigured) so this import never 404s. */
|
|
329
|
+
@import "./_user-global.css";
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import type { Metadata } from "next"
|
|
2
|
+
import { Space_Grotesk, JetBrains_Mono } from "next/font/google"
|
|
3
|
+
import { ThemeProvider } from "@shell/components/theme-provider"
|
|
4
|
+
import { I18nProvider } from "@shell/lib/i18n"
|
|
5
|
+
import { SidebarProvider } from "@shell/components/sidebar-provider"
|
|
6
|
+
import { Header } from "@shell/components/header"
|
|
7
|
+
import { A11yProvider } from "@shell/components/a11y-provider"
|
|
8
|
+
import { NavigationProgress } from "@shell/components/navigation-progress"
|
|
9
|
+
import { NavDataProvider } from "@shell/components/nav-data-provider"
|
|
10
|
+
import { GlobalMobileSidebar } from "@shell/components/global-mobile-sidebar"
|
|
11
|
+
import { getAllDocs } from "@shell/lib/docs"
|
|
12
|
+
import { getAllComponents } from "@shell/lib/components-nav"
|
|
13
|
+
import { getGithubStars } from "@shell/lib/github"
|
|
14
|
+
import { branding } from "@shell/lib/branding"
|
|
15
|
+
import { registry } from "@shell/registry.config"
|
|
16
|
+
import { getShellDefaultLocale, getShellLocales } from "@shell/lib/locales"
|
|
17
|
+
import "./globals.css"
|
|
18
|
+
|
|
19
|
+
const shellLocales = getShellLocales()
|
|
20
|
+
const shellDefaultLocale = getShellDefaultLocale() || "en"
|
|
21
|
+
|
|
22
|
+
const spaceGrotesk = Space_Grotesk({
|
|
23
|
+
variable: "--font-sans",
|
|
24
|
+
subsets: ["latin"],
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
const spaceMono = JetBrains_Mono({
|
|
28
|
+
variable: "--font-mono",
|
|
29
|
+
weight: ["400", "700"],
|
|
30
|
+
subsets: ["latin"],
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
const description = branding.description || `${branding.siteName} component registry.`
|
|
34
|
+
|
|
35
|
+
export const metadata: Metadata = {
|
|
36
|
+
title: branding.siteName,
|
|
37
|
+
description,
|
|
38
|
+
metadataBase: branding.siteUrl ? new URL(branding.siteUrl) : undefined,
|
|
39
|
+
openGraph: {
|
|
40
|
+
title: branding.siteName,
|
|
41
|
+
description,
|
|
42
|
+
siteName: branding.siteName,
|
|
43
|
+
url: branding.siteUrl || undefined,
|
|
44
|
+
images: branding.ogImage ? [{ url: branding.ogImage }] : undefined,
|
|
45
|
+
type: "website",
|
|
46
|
+
},
|
|
47
|
+
twitter: {
|
|
48
|
+
card: branding.ogImage ? "summary_large_image" : "summary",
|
|
49
|
+
title: branding.siteName,
|
|
50
|
+
description,
|
|
51
|
+
site: branding.twitterHandle ? `@${branding.twitterHandle}` : undefined,
|
|
52
|
+
images: branding.ogImage ? [branding.ogImage] : undefined,
|
|
53
|
+
},
|
|
54
|
+
icons: {
|
|
55
|
+
icon: [
|
|
56
|
+
{ url: branding.faviconDark, type: "image/svg+xml", media: "(prefers-color-scheme: light)" },
|
|
57
|
+
{ url: branding.faviconLight, type: "image/svg+xml", media: "(prefers-color-scheme: dark)" },
|
|
58
|
+
{ url: branding.faviconIco, sizes: "48x48" },
|
|
59
|
+
],
|
|
60
|
+
},
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export default async function RootLayout({
|
|
64
|
+
children,
|
|
65
|
+
}: Readonly<{
|
|
66
|
+
children: React.ReactNode
|
|
67
|
+
}>) {
|
|
68
|
+
const docs = getAllDocs()
|
|
69
|
+
const components = getAllComponents()
|
|
70
|
+
// Server-side, revalidates hourly. Returns null on failure → header shows
|
|
71
|
+
// the GitHub icon without a count.
|
|
72
|
+
const githubStars = await getGithubStars()
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<html lang="en" suppressHydrationWarning>
|
|
76
|
+
<body
|
|
77
|
+
className={`${spaceGrotesk.variable} ${spaceMono.variable} antialiased`}
|
|
78
|
+
>
|
|
79
|
+
<ThemeProvider>
|
|
80
|
+
<I18nProvider
|
|
81
|
+
extraTranslations={registry?.extraTranslations}
|
|
82
|
+
defaultLocale={shellDefaultLocale}
|
|
83
|
+
availableLocales={shellLocales}
|
|
84
|
+
>
|
|
85
|
+
<NavDataProvider docs={docs} components={components}>
|
|
86
|
+
<SidebarProvider>
|
|
87
|
+
<NavigationProgress />
|
|
88
|
+
<A11yProvider />
|
|
89
|
+
<Header githubStars={githubStars} />
|
|
90
|
+
{/* Mobile-only sidebar mounted here so the hamburger menu works
|
|
91
|
+
on every page (including the homepage). Per-section layouts
|
|
92
|
+
still mount their own desktop-only Sidebar via SidebarLayout. */}
|
|
93
|
+
<GlobalMobileSidebar docs={docs} components={components} />
|
|
94
|
+
{children}
|
|
95
|
+
</SidebarProvider>
|
|
96
|
+
</NavDataProvider>
|
|
97
|
+
</I18nProvider>
|
|
98
|
+
</ThemeProvider>
|
|
99
|
+
</body>
|
|
100
|
+
</html>
|
|
101
|
+
)
|
|
102
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { notFound } from "next/navigation"
|
|
2
|
+
import { getAllComponents } from "@shell/lib/components-nav"
|
|
3
|
+
import { SnapshotPreview } from "@shell/components/snapshot-preview"
|
|
4
|
+
|
|
5
|
+
export function generateStaticParams() {
|
|
6
|
+
return getAllComponents().map((comp) => ({ name: comp.name }))
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export default async function SnapshotPage({
|
|
10
|
+
params,
|
|
11
|
+
}: {
|
|
12
|
+
params: Promise<{ name: string }>
|
|
13
|
+
}) {
|
|
14
|
+
const { name } = await params
|
|
15
|
+
const comp = getAllComponents().find((c) => c.name === name)
|
|
16
|
+
|
|
17
|
+
if (!comp) notFound()
|
|
18
|
+
|
|
19
|
+
return <SnapshotPreview name={name} />
|
|
20
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import "@shell/app/globals.css"
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Minimal layout for Playwright visual snapshots.
|
|
5
|
+
* No header, sidebar, or chrome — just the component.
|
|
6
|
+
*/
|
|
7
|
+
export default function SnapshotLayout({
|
|
8
|
+
children,
|
|
9
|
+
}: {
|
|
10
|
+
children: React.ReactNode
|
|
11
|
+
}) {
|
|
12
|
+
return (
|
|
13
|
+
<div className="p-4 bg-background text-foreground font-sans">
|
|
14
|
+
{children}
|
|
15
|
+
</div>
|
|
16
|
+
)
|
|
17
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { NextRequest, NextResponse } from "next/server"
|
|
2
|
+
import { registry } from "@shell/registry.config"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Serves the user registry's `public/props/{name}.json` files via the
|
|
6
|
+
* adapter, so the props table inside the Docs tab can fetch them through a
|
|
7
|
+
* stable URL even though the files live in the user's project.
|
|
8
|
+
*/
|
|
9
|
+
export async function GET(
|
|
10
|
+
_request: NextRequest,
|
|
11
|
+
{ params }: { params: Promise<{ name: string }> },
|
|
12
|
+
) {
|
|
13
|
+
const { name } = await params
|
|
14
|
+
const data = registry?.getPropsData ? await registry.getPropsData(name) : null
|
|
15
|
+
if (!data) {
|
|
16
|
+
return NextResponse.json({ error: "Props data not found" }, { status: 404 })
|
|
17
|
+
}
|
|
18
|
+
return NextResponse.json(data)
|
|
19
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { NextRequest, NextResponse } from "next/server"
|
|
2
|
+
import { registry } from "@shell/registry.config"
|
|
3
|
+
|
|
4
|
+
export async function GET(
|
|
5
|
+
_request: NextRequest,
|
|
6
|
+
{ params }: { params: Promise<{ name: string }> },
|
|
7
|
+
) {
|
|
8
|
+
const { name } = await params
|
|
9
|
+
const data = registry ? await registry.getRegistryItem(name) : null
|
|
10
|
+
if (!data) {
|
|
11
|
+
return NextResponse.json({ error: "Registry item not found" }, { status: 404 })
|
|
12
|
+
}
|
|
13
|
+
return NextResponse.json(data)
|
|
14
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { NextRequest, NextResponse } from "next/server"
|
|
2
|
+
import { registry } from "@shell/registry.config"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Serves the user registry's `public/tests/{name}.json` files via the
|
|
6
|
+
* adapter, so the Tests tab can fetch them through standard URLs even though
|
|
7
|
+
* the files live in the user's project rather than the shell's `public/`.
|
|
8
|
+
*/
|
|
9
|
+
export async function GET(
|
|
10
|
+
_request: NextRequest,
|
|
11
|
+
{ params }: { params: Promise<{ name: string }> },
|
|
12
|
+
) {
|
|
13
|
+
const { name } = await params
|
|
14
|
+
const data = registry?.getTestData ? await registry.getTestData(name) : null
|
|
15
|
+
if (!data) {
|
|
16
|
+
return NextResponse.json({ error: "Test data not found" }, { status: 404 })
|
|
17
|
+
}
|
|
18
|
+
return NextResponse.json(data)
|
|
19
|
+
}
|