@happyvertical/smrt-playground 0.38.26 → 0.39.1
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/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/templates.ts"],"sourcesContent":["import {\n displayNameForScopedPackage,\n displayNameForSmrtPackage,\n} from './utils.js';\n\nexport function createPackagePlaygroundTemplate(packageName: string): string {\n const displayName = displayNameForSmrtPackage(packageName);\n\n return `/**\n * ${displayName} playground definitions\n *\n * Export preview entries for the shared SMRT playground host here.\n */\n\nexport default {\n packageName: '${packageName}',\n displayName: '${displayName}',\n entries: [],\n};\n`;\n}\n\nexport function createAppPlaygroundTemplate(packageName: string): string {\n const displayName = displayNameForScopedPackage(packageName);\n\n return `/**\n * Local app playground overrides\n *\n * Add app-specific previews here, or override installed package entries by\n * exporting an additional module with the same packageName + entry id.\n */\n\nexport default [\n {\n packageName: '${packageName}',\n displayName: '${displayName}',\n entries: [],\n },\n];\n`;\n}\n\nexport function createAppPlaygroundRouteTemplate(): string {\n return `<script lang=\"ts\">\nimport { PlaygroundHost } from '@happyvertical/smrt-playground/svelte';\nimport { playgroundModules } from 'virtual:smrt-playground/modules';\n</script>\n\n<PlaygroundHost\n title=\"
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/templates.ts"],"sourcesContent":["import {\n displayNameForScopedPackage,\n displayNameForSmrtPackage,\n} from './utils.js';\n\nexport function createPackagePlaygroundTemplate(packageName: string): string {\n const displayName = displayNameForSmrtPackage(packageName);\n\n return `/**\n * ${displayName} playground definitions\n *\n * Export preview entries for the shared SMRT playground host here.\n */\n\nexport default {\n packageName: '${packageName}',\n displayName: '${displayName}',\n entries: [],\n};\n`;\n}\n\nexport function createAppPlaygroundTemplate(packageName: string): string {\n const displayName = displayNameForScopedPackage(packageName);\n\n return `/**\n * Local app playground overrides\n *\n * Add app-specific previews here, or override installed package entries by\n * exporting an additional module with the same packageName + entry id.\n */\n\nexport default [\n {\n packageName: '${packageName}',\n displayName: '${displayName}',\n entries: [],\n },\n];\n`;\n}\n\nexport function createAppPlaygroundRouteTemplate(): string {\n return `<script lang=\"ts\">\nimport { PlaygroundHost } from '@happyvertical/smrt-playground/svelte';\nimport { playgroundModules } from 'virtual:smrt-playground/modules';\n</script>\n\n<PlaygroundHost\n title=\"s-m-r-t playground\"\n subtitle=\"Package previews and local app overrides\"\n modules={playgroundModules}\n/>\n`;\n}\n"],"mappings":";;;AAKO,SAAS,gCAAgC,aAA6B;CAC3E,MAAM,cAAc,0BAA0B,WAAW;CAEzD,OAAO;KACJ,YAAW;;;;;;kBAME,YAAW;kBACX,YAAW;;;;AAI7B;AAEO,SAAS,4BAA4B,aAA6B;CAGvE,OAAO;;;;;;;;;oBASW,YAAW;oBAXT,4BAA4B,WAY9B,EAAW;;;;;AAK/B;AAEO,SAAS,mCAA2C;CACzD,OAAO;;;;;;;;;;;AAWT"}
|
|
@@ -22,41 +22,110 @@ export interface Props {
|
|
|
22
22
|
|
|
23
23
|
let {
|
|
24
24
|
modules = [],
|
|
25
|
-
title = '
|
|
25
|
+
title = 's-m-r-t playground',
|
|
26
26
|
subtitle = 'Shared package previews with app-local overrides',
|
|
27
27
|
}: Props = $props();
|
|
28
28
|
|
|
29
|
-
const
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const query = searchTerm.toLowerCase();
|
|
37
|
-
return (
|
|
38
|
-
module.displayName.toLowerCase().includes(query) ||
|
|
39
|
-
module.entries.some(
|
|
40
|
-
(entry) =>
|
|
41
|
-
entry.title.toLowerCase().includes(query) ||
|
|
42
|
-
entry.id.toLowerCase().includes(query),
|
|
43
|
-
)
|
|
44
|
-
);
|
|
45
|
-
}),
|
|
46
|
-
);
|
|
29
|
+
const foundationPackageName = '@happyvertical/smrt-ui';
|
|
30
|
+
const foundationGroupOrder = [
|
|
31
|
+
'Inputs & controls',
|
|
32
|
+
'Feedback & overlays',
|
|
33
|
+
'Collections & data',
|
|
34
|
+
] as const;
|
|
47
35
|
|
|
36
|
+
let searchTerm = $state('');
|
|
48
37
|
let selectedModuleName = $state<string | null>(null);
|
|
49
38
|
let selectedEntryId = $state<string | null>(null);
|
|
50
39
|
let selectedMode = $state<SmrtPlaygroundMode>('mock');
|
|
51
|
-
let searchTerm = $state('');
|
|
52
40
|
let isHydrated = $state(false);
|
|
53
41
|
|
|
54
42
|
onMount(() => {
|
|
55
43
|
isHydrated = true;
|
|
56
44
|
});
|
|
57
45
|
|
|
46
|
+
const normalizedModules = $derived(mergePlaygroundModules(modules));
|
|
47
|
+
const orderedModules = $derived([
|
|
48
|
+
...normalizedModules.filter(
|
|
49
|
+
(module) => module.packageName === foundationPackageName,
|
|
50
|
+
),
|
|
51
|
+
...normalizedModules.filter(
|
|
52
|
+
(module) => module.packageName !== foundationPackageName,
|
|
53
|
+
),
|
|
54
|
+
]);
|
|
55
|
+
|
|
56
|
+
const filteredModules = $derived.by(() => {
|
|
57
|
+
const query = searchTerm.trim().toLowerCase();
|
|
58
|
+
if (!query) {
|
|
59
|
+
return orderedModules;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return orderedModules
|
|
63
|
+
.map((module) => {
|
|
64
|
+
const moduleMatches = [
|
|
65
|
+
module.displayName,
|
|
66
|
+
module.packageName,
|
|
67
|
+
module.description,
|
|
68
|
+
].some((value) => value?.toLowerCase().includes(query));
|
|
69
|
+
|
|
70
|
+
if (moduleMatches) {
|
|
71
|
+
return module;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
...module,
|
|
76
|
+
entries: module.entries.filter((entry) =>
|
|
77
|
+
[
|
|
78
|
+
entry.title,
|
|
79
|
+
entry.id,
|
|
80
|
+
entry.description,
|
|
81
|
+
...(entry.tags ?? []),
|
|
82
|
+
].some((value) => value?.toLowerCase().includes(query)),
|
|
83
|
+
),
|
|
84
|
+
};
|
|
85
|
+
})
|
|
86
|
+
.filter((module) => module.entries.length > 0);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const filteredFoundation = $derived(
|
|
90
|
+
filteredModules.find(
|
|
91
|
+
(module) => module.packageName === foundationPackageName,
|
|
92
|
+
) ?? null,
|
|
93
|
+
);
|
|
94
|
+
const filteredPackageModules = $derived(
|
|
95
|
+
filteredModules.filter(
|
|
96
|
+
(module) => module.packageName !== foundationPackageName,
|
|
97
|
+
),
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
function foundationGroup(entry: ResolvedSmrtPlaygroundEntry) {
|
|
101
|
+
const tags = entry.tags ?? [];
|
|
102
|
+
if (tags.includes('feedback') || tags.includes('overlays')) {
|
|
103
|
+
return 'Feedback & overlays';
|
|
104
|
+
}
|
|
105
|
+
if (
|
|
106
|
+
tags.some((tag) =>
|
|
107
|
+
['content', 'data', 'grid', 'list', 'table'].includes(tag),
|
|
108
|
+
)
|
|
109
|
+
) {
|
|
110
|
+
return 'Collections & data';
|
|
111
|
+
}
|
|
112
|
+
return 'Inputs & controls';
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const foundationGroups = $derived.by(() => {
|
|
116
|
+
const grouped = new Map<string, ResolvedSmrtPlaygroundEntry[]>();
|
|
117
|
+
for (const entry of filteredFoundation?.entries ?? []) {
|
|
118
|
+
const group = foundationGroup(entry);
|
|
119
|
+
grouped.set(group, [...(grouped.get(group) ?? []), entry]);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return foundationGroupOrder
|
|
123
|
+
.map((group) => [group, grouped.get(group) ?? []] as const)
|
|
124
|
+
.filter(([, entries]) => entries.length > 0);
|
|
125
|
+
});
|
|
126
|
+
|
|
58
127
|
$effect(() => {
|
|
59
|
-
const firstModule =
|
|
128
|
+
const firstModule = orderedModules[0] ?? null;
|
|
60
129
|
if (!firstModule) {
|
|
61
130
|
selectedModuleName = null;
|
|
62
131
|
selectedEntryId = null;
|
|
@@ -64,67 +133,66 @@ $effect(() => {
|
|
|
64
133
|
}
|
|
65
134
|
|
|
66
135
|
const activeModule =
|
|
67
|
-
|
|
136
|
+
orderedModules.find(
|
|
68
137
|
(module) => module.packageName === selectedModuleName,
|
|
69
|
-
)
|
|
70
|
-
normalizedModules.find(
|
|
71
|
-
(module) => module.packageName === selectedModuleName,
|
|
72
|
-
) ||
|
|
73
|
-
firstModule;
|
|
138
|
+
) ?? firstModule;
|
|
74
139
|
|
|
75
140
|
if (activeModule.packageName !== selectedModuleName) {
|
|
76
141
|
selectedModuleName = activeModule.packageName;
|
|
142
|
+
selectedEntryId =
|
|
143
|
+
activeModule.packageName === foundationPackageName
|
|
144
|
+
? (activeModule.entries[0]?.qualifiedId ?? null)
|
|
145
|
+
: null;
|
|
146
|
+
selectedMode = activeModule.entries[0]?.availableModes[0] ?? 'mock';
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (selectedEntryId === null) {
|
|
151
|
+
return;
|
|
77
152
|
}
|
|
78
153
|
|
|
79
154
|
const activeEntry =
|
|
80
155
|
activeModule.entries.find(
|
|
81
156
|
(entry) => entry.qualifiedId === selectedEntryId,
|
|
82
|
-
)
|
|
83
|
-
activeModule.entries[0] ||
|
|
84
|
-
null;
|
|
157
|
+
) ?? null;
|
|
85
158
|
|
|
86
|
-
if (activeEntry
|
|
87
|
-
selectedEntryId =
|
|
159
|
+
if (!activeEntry) {
|
|
160
|
+
selectedEntryId = null;
|
|
161
|
+
return;
|
|
88
162
|
}
|
|
89
163
|
|
|
90
|
-
|
|
164
|
+
selectedEntryId = activeEntry.qualifiedId;
|
|
165
|
+
if (!activeEntry.availableModes.includes(selectedMode)) {
|
|
91
166
|
selectedMode = activeEntry.availableModes[0] ?? 'mock';
|
|
92
167
|
}
|
|
93
168
|
});
|
|
94
169
|
|
|
95
170
|
const selectedModule = $derived(
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
) ||
|
|
99
|
-
normalizedModules[0] ||
|
|
171
|
+
orderedModules.find((module) => module.packageName === selectedModuleName) ??
|
|
172
|
+
orderedModules[0] ??
|
|
100
173
|
null,
|
|
101
174
|
);
|
|
102
|
-
|
|
103
175
|
const selectedEntry = $derived(
|
|
104
176
|
selectedModule?.entries.find(
|
|
105
177
|
(entry) => entry.qualifiedId === selectedEntryId,
|
|
106
|
-
)
|
|
107
|
-
|
|
108
|
-
|
|
178
|
+
) ?? null,
|
|
179
|
+
);
|
|
180
|
+
const selectedModeConfig = $derived(
|
|
181
|
+
selectedEntry ? (selectedEntry.modes[selectedMode] ?? null) : null,
|
|
109
182
|
);
|
|
110
|
-
|
|
111
|
-
let PreviewComponent = $state<Component<Record<string, unknown>> | null>(null);
|
|
112
|
-
let previewComponentEntryId = $state<string | null>(null);
|
|
113
|
-
let previewLoadError = $state<string | null>(null);
|
|
114
|
-
let previewIsLoading = $state(false);
|
|
115
|
-
|
|
116
183
|
const selectedProps = $derived(
|
|
117
184
|
selectedEntry
|
|
118
185
|
? {
|
|
119
|
-
...(selectedEntry.props
|
|
120
|
-
...(
|
|
186
|
+
...(selectedEntry.props ?? {}),
|
|
187
|
+
...(selectedModeConfig?.props ?? {}),
|
|
121
188
|
}
|
|
122
189
|
: {},
|
|
123
190
|
);
|
|
124
191
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
);
|
|
192
|
+
let PreviewComponent = $state<Component<Record<string, unknown>> | null>(null);
|
|
193
|
+
let previewComponentEntryId = $state<string | null>(null);
|
|
194
|
+
let previewLoadError = $state<string | null>(null);
|
|
195
|
+
let previewIsLoading = $state(false);
|
|
128
196
|
|
|
129
197
|
function resolvePreviewComponent(
|
|
130
198
|
loaded: PlaygroundComponentModule,
|
|
@@ -146,7 +214,6 @@ $effect(() => {
|
|
|
146
214
|
let cancelled = false;
|
|
147
215
|
|
|
148
216
|
previewLoadError = null;
|
|
149
|
-
|
|
150
217
|
if (!entry) {
|
|
151
218
|
PreviewComponent = null;
|
|
152
219
|
previewComponentEntryId = null;
|
|
@@ -179,7 +246,6 @@ $effect(() => {
|
|
|
179
246
|
if (cancelled) {
|
|
180
247
|
return;
|
|
181
248
|
}
|
|
182
|
-
|
|
183
249
|
PreviewComponent = resolvePreviewComponent(loaded);
|
|
184
250
|
previewComponentEntryId = entry.qualifiedId;
|
|
185
251
|
previewIsLoading = false;
|
|
@@ -188,7 +254,6 @@ $effect(() => {
|
|
|
188
254
|
if (cancelled) {
|
|
189
255
|
return;
|
|
190
256
|
}
|
|
191
|
-
|
|
192
257
|
PreviewComponent = null;
|
|
193
258
|
previewComponentEntryId = null;
|
|
194
259
|
previewLoadError =
|
|
@@ -202,8 +267,15 @@ $effect(() => {
|
|
|
202
267
|
});
|
|
203
268
|
|
|
204
269
|
function selectModule(packageName: string) {
|
|
270
|
+
const module = orderedModules.find(
|
|
271
|
+
(candidate) => candidate.packageName === packageName,
|
|
272
|
+
);
|
|
205
273
|
selectedModuleName = packageName;
|
|
206
|
-
selectedEntryId =
|
|
274
|
+
selectedEntryId =
|
|
275
|
+
packageName === foundationPackageName
|
|
276
|
+
? (module?.entries[0]?.qualifiedId ?? null)
|
|
277
|
+
: null;
|
|
278
|
+
selectedMode = module?.entries[0]?.availableModes[0] ?? 'mock';
|
|
207
279
|
}
|
|
208
280
|
|
|
209
281
|
function selectEntry(entry: ResolvedSmrtPlaygroundEntry) {
|
|
@@ -213,137 +285,188 @@ function selectEntry(entry: ResolvedSmrtPlaygroundEntry) {
|
|
|
213
285
|
}
|
|
214
286
|
</script>
|
|
215
287
|
|
|
288
|
+
{#snippet entryButton(entry: ResolvedSmrtPlaygroundEntry)}
|
|
289
|
+
<button
|
|
290
|
+
type="button"
|
|
291
|
+
class:active={entry.qualifiedId === selectedEntry?.qualifiedId}
|
|
292
|
+
aria-pressed={entry.qualifiedId === selectedEntry?.qualifiedId}
|
|
293
|
+
data-playground-entry={entry.qualifiedId}
|
|
294
|
+
onclick={() => selectEntry(entry)}
|
|
295
|
+
>
|
|
296
|
+
{entry.title}
|
|
297
|
+
</button>
|
|
298
|
+
{/snippet}
|
|
299
|
+
|
|
216
300
|
<ThemeProvider colorScheme="system" persist={true}>
|
|
217
301
|
<div class="playground-shell" data-hydrated={isHydrated ? 'true' : 'false'}>
|
|
218
|
-
<aside class="
|
|
219
|
-
<
|
|
220
|
-
<
|
|
221
|
-
<
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
<ThemeSwitcher variant="select" label="Theme" />
|
|
227
|
-
<ColorSchemeToggle />
|
|
228
|
-
</div>
|
|
302
|
+
<aside class="catalog-nav">
|
|
303
|
+
<header class="brand">
|
|
304
|
+
<span class="brand__mark" aria-hidden="true">S</span>
|
|
305
|
+
<div>
|
|
306
|
+
<h1>{title}</h1>
|
|
307
|
+
<p>{subtitle}</p>
|
|
308
|
+
</div>
|
|
309
|
+
</header>
|
|
229
310
|
|
|
230
|
-
<label class="search">
|
|
231
|
-
<span>
|
|
232
|
-
<input bind:value={searchTerm} placeholder="Search
|
|
311
|
+
<label class="search-field">
|
|
312
|
+
<span>Find a component</span>
|
|
313
|
+
<input bind:value={searchTerm} placeholder="Search" />
|
|
233
314
|
</label>
|
|
234
315
|
|
|
235
|
-
<div class="
|
|
316
|
+
<div class="catalog-scroll" data-testid="playground-modules">
|
|
236
317
|
{#if filteredModules.length === 0}
|
|
237
|
-
<div class="empty-
|
|
238
|
-
<strong>No
|
|
239
|
-
<p>
|
|
318
|
+
<div class="empty-state">
|
|
319
|
+
<strong>No components found</strong>
|
|
320
|
+
<p>Try another component, package, or tag.</p>
|
|
240
321
|
</div>
|
|
241
322
|
{:else}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
323
|
+
<nav aria-label="Component catalog" data-testid="playground-entries">
|
|
324
|
+
{#if filteredFoundation}
|
|
325
|
+
<section class="foundation-catalog">
|
|
326
|
+
<button
|
|
327
|
+
type="button"
|
|
328
|
+
class="foundation-heading"
|
|
329
|
+
data-playground-module={filteredFoundation.packageName}
|
|
330
|
+
onclick={() => selectModule(filteredFoundation.packageName)}
|
|
331
|
+
>
|
|
332
|
+
<span>Foundation</span>
|
|
333
|
+
<small>{filteredFoundation.entries.length}</small>
|
|
334
|
+
</button>
|
|
335
|
+
|
|
336
|
+
{#each foundationGroups as [group, entries]}
|
|
337
|
+
<section class="nav-group">
|
|
338
|
+
<h2>{group}</h2>
|
|
339
|
+
{#each entries as entry (entry.qualifiedId)}
|
|
340
|
+
{@render entryButton(entry)}
|
|
341
|
+
{/each}
|
|
342
|
+
</section>
|
|
343
|
+
{/each}
|
|
344
|
+
</section>
|
|
345
|
+
{/if}
|
|
346
|
+
|
|
347
|
+
{#if filteredPackageModules.length > 0}
|
|
348
|
+
<section class="package-groups">
|
|
349
|
+
<h2>Package components</h2>
|
|
350
|
+
{#each filteredPackageModules as module (module.packageName)}
|
|
351
|
+
<details open={module.packageName === selectedModule?.packageName}>
|
|
352
|
+
<summary
|
|
353
|
+
data-playground-module={module.packageName}
|
|
354
|
+
onclick={(event) => {
|
|
355
|
+
event.preventDefault();
|
|
356
|
+
selectModule(module.packageName);
|
|
357
|
+
}}
|
|
358
|
+
>
|
|
359
|
+
<span>{module.displayName}</span>
|
|
360
|
+
<small>{module.entries.length}</small>
|
|
361
|
+
</summary>
|
|
362
|
+
<div>
|
|
363
|
+
{#each module.entries as entry (entry.qualifiedId)}
|
|
364
|
+
{@render entryButton(entry)}
|
|
365
|
+
{/each}
|
|
366
|
+
</div>
|
|
367
|
+
</details>
|
|
368
|
+
{/each}
|
|
369
|
+
</section>
|
|
370
|
+
{/if}
|
|
371
|
+
</nav>
|
|
253
372
|
{/if}
|
|
254
373
|
</div>
|
|
374
|
+
|
|
375
|
+
<footer class="theme-controls" data-testid="playground-theme-controls">
|
|
376
|
+
<ThemeSwitcher variant="select" label="Theme" />
|
|
377
|
+
<ColorSchemeToggle />
|
|
378
|
+
</footer>
|
|
255
379
|
</aside>
|
|
256
380
|
|
|
257
|
-
<main class="
|
|
381
|
+
<main class="workspace">
|
|
258
382
|
{#if selectedModule}
|
|
259
|
-
<header class="
|
|
260
|
-
<div>
|
|
261
|
-
<
|
|
262
|
-
<
|
|
263
|
-
{
|
|
264
|
-
<p>{selectedModule.description}</p>
|
|
265
|
-
{/if}
|
|
383
|
+
<header class="workspace-header">
|
|
384
|
+
<div class="breadcrumbs">
|
|
385
|
+
<span data-testid="playground-selected-module">{selectedModule.displayName}</span>
|
|
386
|
+
<i aria-hidden="true">/</i>
|
|
387
|
+
<strong>{selectedEntry?.title ?? 'Overview'}</strong>
|
|
266
388
|
</div>
|
|
389
|
+
|
|
390
|
+
{#if selectedEntry && selectedEntry.availableModes.length > 1}
|
|
391
|
+
<div class="mode-control" role="group" aria-label="Preview mode">
|
|
392
|
+
{#each selectedEntry.availableModes as mode}
|
|
393
|
+
<button
|
|
394
|
+
type="button"
|
|
395
|
+
class:active={mode === selectedMode}
|
|
396
|
+
aria-pressed={mode === selectedMode}
|
|
397
|
+
data-playground-mode={mode}
|
|
398
|
+
onclick={() => (selectedMode = mode)}
|
|
399
|
+
>
|
|
400
|
+
{mode}
|
|
401
|
+
</button>
|
|
402
|
+
{/each}
|
|
403
|
+
</div>
|
|
404
|
+
{/if}
|
|
267
405
|
</header>
|
|
268
406
|
|
|
269
|
-
|
|
270
|
-
<
|
|
271
|
-
{
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
<strong>{entry.title}</strong>
|
|
281
|
-
<span>{entry.id}</span>
|
|
282
|
-
</div>
|
|
283
|
-
<div class="mode-pills">
|
|
284
|
-
{#each entry.availableModes as mode}
|
|
285
|
-
<span>{mode}</span>
|
|
286
|
-
{/each}
|
|
287
|
-
</div>
|
|
288
|
-
</button>
|
|
289
|
-
{/each}
|
|
290
|
-
</section>
|
|
407
|
+
{#if selectedEntry}
|
|
408
|
+
<div class="preview-heading">
|
|
409
|
+
<p data-testid="playground-selected-package">{selectedModule.packageName}</p>
|
|
410
|
+
<h2 data-testid="playground-preview-title">{selectedEntry.title}</h2>
|
|
411
|
+
{#if selectedEntry.description}
|
|
412
|
+
<span>{selectedEntry.description}</span>
|
|
413
|
+
{/if}
|
|
414
|
+
{#if selectedModeConfig?.description}
|
|
415
|
+
<span class="mode-description">{selectedModeConfig.description}</span>
|
|
416
|
+
{/if}
|
|
417
|
+
</div>
|
|
291
418
|
|
|
292
419
|
<section class="preview-panel" data-testid="playground-preview-panel">
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
<div>
|
|
296
|
-
<h3 data-testid="playground-preview-title">{selectedEntry.title}</h3>
|
|
297
|
-
{#if selectedEntry.description}
|
|
298
|
-
<p>{selectedEntry.description}</p>
|
|
299
|
-
{/if}
|
|
300
|
-
{#if selectedModeConfig?.description}
|
|
301
|
-
<p class="mode-description">{selectedModeConfig.description}</p>
|
|
302
|
-
{/if}
|
|
303
|
-
</div>
|
|
304
|
-
|
|
305
|
-
{#if selectedEntry.availableModes.length > 1}
|
|
306
|
-
<div class="mode-toggle" role="group" aria-label="Preview mode">
|
|
307
|
-
{#each selectedEntry.availableModes as mode}
|
|
308
|
-
<button
|
|
309
|
-
type="button"
|
|
310
|
-
class:active={mode === selectedMode}
|
|
311
|
-
aria-pressed={mode === selectedMode}
|
|
312
|
-
data-playground-mode={mode}
|
|
313
|
-
onclick={() => (selectedMode = mode)}
|
|
314
|
-
>
|
|
315
|
-
{mode}
|
|
316
|
-
</button>
|
|
317
|
-
{/each}
|
|
318
|
-
</div>
|
|
319
|
-
{/if}
|
|
320
|
-
</div>
|
|
321
|
-
|
|
322
|
-
<div class="preview-stage" data-testid="playground-preview-stage">
|
|
420
|
+
<div class="preview-stage" data-testid="playground-preview-stage">
|
|
421
|
+
{#if PreviewComponent && previewComponentEntryId === selectedEntry.qualifiedId}
|
|
323
422
|
<PreviewComponent {...selectedProps} />
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
<div class="empty-card">
|
|
337
|
-
<strong>No preview selected</strong>
|
|
338
|
-
<p>Select a preview entry from the left to render it.</p>
|
|
339
|
-
</div>
|
|
340
|
-
{/if}
|
|
423
|
+
{:else if previewIsLoading}
|
|
424
|
+
<div class="preview-state">
|
|
425
|
+
<span class="loader" aria-hidden="true"></span>
|
|
426
|
+
<p>Loading {selectedEntry.title}…</p>
|
|
427
|
+
</div>
|
|
428
|
+
{:else}
|
|
429
|
+
<div class="preview-state">
|
|
430
|
+
<strong>Preview unavailable</strong>
|
|
431
|
+
<p>{previewLoadError ?? 'Select a component to begin.'}</p>
|
|
432
|
+
</div>
|
|
433
|
+
{/if}
|
|
434
|
+
</div>
|
|
341
435
|
</section>
|
|
342
|
-
|
|
436
|
+
{:else}
|
|
437
|
+
<section class="package-landing" data-testid="playground-package-landing">
|
|
438
|
+
<header>
|
|
439
|
+
<p data-testid="playground-selected-package">{selectedModule.packageName}</p>
|
|
440
|
+
<h2>{selectedModule.displayName}</h2>
|
|
441
|
+
{#if selectedModule.description}
|
|
442
|
+
<span>{selectedModule.description}</span>
|
|
443
|
+
{/if}
|
|
444
|
+
<small>{selectedModule.entries.length} component{selectedModule.entries.length === 1 ? '' : 's'}</small>
|
|
445
|
+
</header>
|
|
446
|
+
|
|
447
|
+
<div class="package-index">
|
|
448
|
+
<h3>Components</h3>
|
|
449
|
+
{#each selectedModule.entries as entry (entry.qualifiedId)}
|
|
450
|
+
<button
|
|
451
|
+
type="button"
|
|
452
|
+
data-playground-landing-entry={entry.qualifiedId}
|
|
453
|
+
onclick={() => selectEntry(entry)}
|
|
454
|
+
>
|
|
455
|
+
<span class="package-index__copy">
|
|
456
|
+
<strong>{entry.title}</strong>
|
|
457
|
+
<small>{entry.description ?? entry.id}</small>
|
|
458
|
+
</span>
|
|
459
|
+
<span class="package-index__modes">{entry.availableModes.join(' · ')}</span>
|
|
460
|
+
<span class="package-index__arrow" aria-hidden="true">→</span>
|
|
461
|
+
</button>
|
|
462
|
+
{/each}
|
|
463
|
+
</div>
|
|
464
|
+
</section>
|
|
465
|
+
{/if}
|
|
343
466
|
{:else}
|
|
344
|
-
<div class="
|
|
467
|
+
<div class="preview-state full-height">
|
|
345
468
|
<strong>No playground modules discovered</strong>
|
|
346
|
-
<p>The shared host is ready, but nothing
|
|
469
|
+
<p>The shared host is ready, but nothing exports playground entries yet.</p>
|
|
347
470
|
</div>
|
|
348
471
|
{/if}
|
|
349
472
|
</main>
|
|
@@ -356,234 +479,536 @@ function selectEntry(entry: ResolvedSmrtPlaygroundEntry) {
|
|
|
356
479
|
min-height: 100vh;
|
|
357
480
|
}
|
|
358
481
|
|
|
482
|
+
:global(*) {
|
|
483
|
+
box-sizing: border-box;
|
|
484
|
+
}
|
|
485
|
+
|
|
359
486
|
.playground-shell {
|
|
360
487
|
display: grid;
|
|
361
|
-
grid-template-columns:
|
|
488
|
+
grid-template-columns: 17rem minmax(0, 1fr);
|
|
362
489
|
min-height: 100vh;
|
|
363
490
|
background: var(--smrt-color-background);
|
|
364
491
|
color: var(--smrt-color-on-background);
|
|
365
492
|
font-family: var(--smrt-font-family);
|
|
366
493
|
}
|
|
367
494
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
495
|
+
button,
|
|
496
|
+
input {
|
|
497
|
+
font: inherit;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
button {
|
|
501
|
+
color: inherit;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
.catalog-nav {
|
|
505
|
+
position: sticky;
|
|
506
|
+
top: 0;
|
|
507
|
+
display: flex;
|
|
508
|
+
height: 100vh;
|
|
509
|
+
flex-direction: column;
|
|
510
|
+
gap: 1.4rem;
|
|
511
|
+
padding: 1.25rem;
|
|
512
|
+
overflow: hidden;
|
|
373
513
|
border-right: 1px solid var(--smrt-color-outline-variant);
|
|
374
|
-
background: var(--smrt-color-surface-container);
|
|
514
|
+
background: var(--smrt-color-surface-container-low);
|
|
375
515
|
color: var(--smrt-color-on-surface);
|
|
376
|
-
backdrop-filter: blur(18px);
|
|
377
516
|
}
|
|
378
517
|
|
|
379
|
-
.
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
518
|
+
.brand {
|
|
519
|
+
display: flex;
|
|
520
|
+
min-width: 0;
|
|
521
|
+
align-items: center;
|
|
522
|
+
gap: 0.75rem;
|
|
383
523
|
}
|
|
384
524
|
|
|
385
|
-
.
|
|
386
|
-
.search,
|
|
387
|
-
.module-list,
|
|
388
|
-
.content,
|
|
389
|
-
.content__body,
|
|
390
|
-
.entry-list,
|
|
391
|
-
.preview-panel {
|
|
525
|
+
.brand__mark {
|
|
392
526
|
display: grid;
|
|
393
|
-
|
|
527
|
+
width: 2rem;
|
|
528
|
+
height: 2rem;
|
|
529
|
+
flex: 0 0 auto;
|
|
530
|
+
place-items: center;
|
|
531
|
+
border-radius: 0.55rem;
|
|
532
|
+
background: var(--smrt-color-primary);
|
|
533
|
+
color: var(--smrt-color-on-primary);
|
|
534
|
+
font-weight: 700;
|
|
394
535
|
}
|
|
395
536
|
|
|
396
|
-
.
|
|
397
|
-
|
|
398
|
-
font-size: 0.75rem;
|
|
399
|
-
letter-spacing: 0.12em;
|
|
400
|
-
text-transform: uppercase;
|
|
401
|
-
color: var(--smrt-color-primary);
|
|
537
|
+
.brand > div {
|
|
538
|
+
min-width: 0;
|
|
402
539
|
}
|
|
403
540
|
|
|
404
|
-
.
|
|
405
|
-
.content__header p,
|
|
406
|
-
.preview-panel__meta p,
|
|
407
|
-
.empty-card p {
|
|
541
|
+
.brand h1 {
|
|
408
542
|
margin: 0;
|
|
409
|
-
|
|
543
|
+
overflow: hidden;
|
|
544
|
+
font-size: 0.9rem;
|
|
545
|
+
letter-spacing: 0.035em;
|
|
546
|
+
text-overflow: ellipsis;
|
|
547
|
+
white-space: nowrap;
|
|
410
548
|
}
|
|
411
549
|
|
|
412
|
-
.
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
.theme-controls :global(.smrt-theme-switcher) {
|
|
420
|
-
flex: 1;
|
|
550
|
+
.brand p {
|
|
551
|
+
margin: 0.12rem 0 0;
|
|
552
|
+
overflow: hidden;
|
|
553
|
+
color: var(--smrt-color-on-surface-variant);
|
|
554
|
+
font-size: 0.72rem;
|
|
555
|
+
text-overflow: ellipsis;
|
|
556
|
+
white-space: nowrap;
|
|
421
557
|
}
|
|
422
558
|
|
|
423
|
-
.
|
|
424
|
-
|
|
559
|
+
.search-field {
|
|
560
|
+
display: grid;
|
|
561
|
+
gap: 0.4rem;
|
|
425
562
|
}
|
|
426
563
|
|
|
427
|
-
.search span {
|
|
428
|
-
font-size: 0.82rem;
|
|
564
|
+
.search-field span {
|
|
429
565
|
color: var(--smrt-color-on-surface-variant);
|
|
566
|
+
font-size: 0.72rem;
|
|
430
567
|
}
|
|
431
568
|
|
|
432
|
-
.search input {
|
|
569
|
+
.search-field input {
|
|
433
570
|
width: 100%;
|
|
434
|
-
|
|
571
|
+
padding: 0.65rem 0.75rem;
|
|
435
572
|
border: 1px solid var(--smrt-color-outline-variant);
|
|
436
|
-
border-radius: 0.
|
|
437
|
-
background: var(--smrt-color-surface
|
|
573
|
+
border-radius: 0.55rem;
|
|
574
|
+
background: var(--smrt-color-surface);
|
|
438
575
|
color: var(--smrt-color-on-surface);
|
|
439
|
-
padding: 0.8rem 0.95rem;
|
|
440
576
|
}
|
|
441
577
|
|
|
442
|
-
.
|
|
443
|
-
|
|
444
|
-
|
|
578
|
+
.catalog-scroll {
|
|
579
|
+
flex: 1;
|
|
580
|
+
min-height: 0;
|
|
581
|
+
overflow-y: auto;
|
|
582
|
+
scrollbar-width: thin;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
.catalog-scroll nav,
|
|
586
|
+
.foundation-catalog,
|
|
587
|
+
.nav-group,
|
|
588
|
+
.package-groups {
|
|
589
|
+
display: grid;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
.catalog-scroll nav {
|
|
593
|
+
gap: 1.15rem;
|
|
445
594
|
}
|
|
446
595
|
|
|
447
|
-
.
|
|
448
|
-
|
|
449
|
-
|
|
596
|
+
.foundation-catalog {
|
|
597
|
+
gap: 0.95rem;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
.foundation-heading,
|
|
601
|
+
.nav-group button,
|
|
602
|
+
details button {
|
|
603
|
+
width: 100%;
|
|
450
604
|
border: 0;
|
|
605
|
+
background: transparent;
|
|
606
|
+
text-align: left;
|
|
451
607
|
cursor: pointer;
|
|
452
|
-
transition:
|
|
453
|
-
transform 140ms ease,
|
|
454
|
-
background 140ms ease,
|
|
455
|
-
border-color 140ms ease;
|
|
456
608
|
}
|
|
457
609
|
|
|
458
|
-
.
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
610
|
+
.foundation-heading {
|
|
611
|
+
display: flex;
|
|
612
|
+
align-items: center;
|
|
613
|
+
justify-content: space-between;
|
|
614
|
+
padding: 0 0 0.7rem;
|
|
615
|
+
border-bottom: 1px solid var(--smrt-color-outline-variant);
|
|
616
|
+
font-size: 0.82rem;
|
|
617
|
+
font-weight: 650;
|
|
465
618
|
}
|
|
466
619
|
|
|
467
|
-
.
|
|
468
|
-
|
|
469
|
-
color: var(--smrt-color-on-surface);
|
|
470
|
-
|
|
620
|
+
.foundation-heading small,
|
|
621
|
+
details summary small {
|
|
622
|
+
color: var(--smrt-color-on-surface-variant);
|
|
623
|
+
font-size: 0.7rem;
|
|
624
|
+
font-weight: 500;
|
|
471
625
|
}
|
|
472
626
|
|
|
473
|
-
.
|
|
474
|
-
|
|
475
|
-
border-color: var(--smrt-color-primary);
|
|
476
|
-
background: var(--smrt-color-primary-container);
|
|
477
|
-
color: var(--smrt-color-on-primary-container);
|
|
627
|
+
.nav-group {
|
|
628
|
+
gap: 0.12rem;
|
|
478
629
|
}
|
|
479
630
|
|
|
480
|
-
.
|
|
481
|
-
.
|
|
631
|
+
.nav-group h2,
|
|
632
|
+
.package-groups > h2 {
|
|
633
|
+
margin: 0 0 0.35rem;
|
|
634
|
+
color: var(--smrt-color-on-surface-variant);
|
|
635
|
+
font-size: 0.66rem;
|
|
636
|
+
font-weight: 600;
|
|
637
|
+
letter-spacing: 0.08em;
|
|
638
|
+
text-transform: uppercase;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
.nav-group button,
|
|
642
|
+
details button {
|
|
643
|
+
padding: 0.52rem 0.6rem;
|
|
644
|
+
border-radius: 0.45rem;
|
|
482
645
|
font-size: 0.82rem;
|
|
483
|
-
opacity: 0.78;
|
|
484
646
|
}
|
|
485
647
|
|
|
486
|
-
.
|
|
487
|
-
|
|
488
|
-
|
|
648
|
+
.nav-group button:hover,
|
|
649
|
+
.nav-group button.active,
|
|
650
|
+
details button:hover,
|
|
651
|
+
details button.active {
|
|
652
|
+
background: var(--smrt-color-secondary-container);
|
|
653
|
+
color: var(--smrt-color-on-secondary-container);
|
|
489
654
|
}
|
|
490
655
|
|
|
491
|
-
.
|
|
492
|
-
|
|
493
|
-
|
|
656
|
+
.package-groups {
|
|
657
|
+
gap: 0.15rem;
|
|
658
|
+
padding-top: 0.4rem;
|
|
494
659
|
}
|
|
495
660
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
661
|
+
details summary {
|
|
662
|
+
display: flex;
|
|
663
|
+
align-items: center;
|
|
664
|
+
justify-content: space-between;
|
|
665
|
+
padding: 0.58rem 0.3rem;
|
|
666
|
+
cursor: pointer;
|
|
667
|
+
font-size: 0.82rem;
|
|
668
|
+
list-style: none;
|
|
501
669
|
}
|
|
502
670
|
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
transform: translateY(-1px);
|
|
506
|
-
border-color: var(--smrt-color-primary);
|
|
507
|
-
background: var(--smrt-color-primary-container);
|
|
508
|
-
color: var(--smrt-color-on-primary-container);
|
|
509
|
-
box-shadow: 0 18px 45px color-mix(in srgb, var(--smrt-color-primary) 14%, transparent);
|
|
671
|
+
details summary::-webkit-details-marker {
|
|
672
|
+
display: none;
|
|
510
673
|
}
|
|
511
674
|
|
|
512
|
-
|
|
675
|
+
details > div {
|
|
676
|
+
padding-left: 0.45rem;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
.theme-controls {
|
|
513
680
|
display: flex;
|
|
514
|
-
|
|
515
|
-
gap: 0.
|
|
681
|
+
align-items: end;
|
|
682
|
+
gap: 0.5rem;
|
|
683
|
+
padding-top: 0.8rem;
|
|
684
|
+
border-top: 1px solid var(--smrt-color-outline-variant);
|
|
516
685
|
}
|
|
517
686
|
|
|
518
|
-
.
|
|
519
|
-
|
|
520
|
-
border-radius: 999px;
|
|
521
|
-
padding: 0.25rem 0.6rem;
|
|
522
|
-
font-size: 0.75rem;
|
|
523
|
-
text-transform: uppercase;
|
|
524
|
-
letter-spacing: 0.08em;
|
|
687
|
+
.theme-controls :global(.smrt-theme-switcher__label) {
|
|
688
|
+
display: none;
|
|
525
689
|
}
|
|
526
690
|
|
|
527
|
-
.
|
|
528
|
-
|
|
529
|
-
|
|
691
|
+
.theme-controls :global(.smrt-theme-switcher__select) {
|
|
692
|
+
min-width: 7rem;
|
|
693
|
+
padding-block: 0.48rem;
|
|
530
694
|
}
|
|
531
695
|
|
|
532
|
-
.
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
color: var(--smrt-color-on-surface);
|
|
539
|
-
box-shadow: 0 24px 60px color-mix(in srgb, var(--smrt-color-shadow) 8%, transparent);
|
|
540
|
-
backdrop-filter: blur(18px);
|
|
696
|
+
.workspace {
|
|
697
|
+
display: grid;
|
|
698
|
+
min-width: 0;
|
|
699
|
+
align-content: start;
|
|
700
|
+
gap: 1.25rem;
|
|
701
|
+
padding: 1.25rem clamp(1.25rem, 3vw, 3rem) 3rem;
|
|
541
702
|
}
|
|
542
703
|
|
|
543
|
-
.
|
|
704
|
+
.workspace-header {
|
|
544
705
|
display: flex;
|
|
545
|
-
|
|
706
|
+
min-height: 2.75rem;
|
|
707
|
+
align-items: center;
|
|
546
708
|
justify-content: space-between;
|
|
547
709
|
gap: 1rem;
|
|
548
|
-
|
|
710
|
+
border-bottom: 1px solid var(--smrt-color-outline-variant);
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
.breadcrumbs {
|
|
714
|
+
display: flex;
|
|
715
|
+
min-width: 0;
|
|
716
|
+
gap: 0.55rem;
|
|
717
|
+
color: var(--smrt-color-on-surface-variant);
|
|
718
|
+
font-size: 0.76rem;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
.breadcrumbs span,
|
|
722
|
+
.breadcrumbs strong {
|
|
723
|
+
overflow: hidden;
|
|
724
|
+
text-overflow: ellipsis;
|
|
725
|
+
white-space: nowrap;
|
|
549
726
|
}
|
|
550
727
|
|
|
551
|
-
.
|
|
552
|
-
|
|
553
|
-
|
|
728
|
+
.breadcrumbs i {
|
|
729
|
+
opacity: 0.5;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
.breadcrumbs strong {
|
|
733
|
+
color: var(--smrt-color-on-surface);
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
.mode-control {
|
|
737
|
+
display: flex;
|
|
738
|
+
flex: 0 0 auto;
|
|
739
|
+
gap: 0.25rem;
|
|
554
740
|
padding: 0.2rem;
|
|
555
741
|
border-radius: 999px;
|
|
556
|
-
background: var(--smrt-color-surface-container
|
|
742
|
+
background: var(--smrt-color-surface-container);
|
|
557
743
|
}
|
|
558
744
|
|
|
559
|
-
.mode-
|
|
745
|
+
.mode-control button {
|
|
746
|
+
padding: 0.4rem 0.7rem;
|
|
747
|
+
border: 0;
|
|
748
|
+
border-radius: 999px;
|
|
560
749
|
background: transparent;
|
|
561
750
|
color: var(--smrt-color-on-surface-variant);
|
|
751
|
+
cursor: pointer;
|
|
752
|
+
font-size: 0.72rem;
|
|
753
|
+
text-transform: capitalize;
|
|
562
754
|
}
|
|
563
755
|
|
|
564
|
-
.mode-
|
|
565
|
-
background: var(--smrt-color-
|
|
566
|
-
color: var(--smrt-color-on-
|
|
756
|
+
.mode-control button.active {
|
|
757
|
+
background: var(--smrt-color-surface);
|
|
758
|
+
color: var(--smrt-color-on-surface);
|
|
759
|
+
box-shadow: var(--smrt-elevation-1);
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
.package-landing {
|
|
763
|
+
width: min(68rem, 100%);
|
|
764
|
+
padding: clamp(1.5rem, 4vw, 3.5rem) 0 2rem;
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
.package-landing > header {
|
|
768
|
+
position: relative;
|
|
769
|
+
display: grid;
|
|
770
|
+
gap: 0.55rem;
|
|
771
|
+
padding-bottom: clamp(1.75rem, 4vw, 3rem);
|
|
772
|
+
border-bottom: 1px solid var(--smrt-color-outline-variant);
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
.package-landing > header p {
|
|
776
|
+
margin: 0;
|
|
777
|
+
color: var(--smrt-color-primary);
|
|
778
|
+
font-size: 0.68rem;
|
|
779
|
+
letter-spacing: 0.08em;
|
|
780
|
+
text-transform: none;
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
.package-landing > header h2 {
|
|
784
|
+
max-width: 48rem;
|
|
785
|
+
margin: 0;
|
|
786
|
+
font-size: clamp(2rem, 5vw, 4rem);
|
|
787
|
+
font-weight: 520;
|
|
788
|
+
letter-spacing: -0.045em;
|
|
789
|
+
line-height: 1;
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
.package-landing > header span {
|
|
793
|
+
max-width: 42rem;
|
|
794
|
+
color: var(--smrt-color-on-surface-variant);
|
|
795
|
+
line-height: 1.55;
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
.package-landing > header > small {
|
|
799
|
+
position: absolute;
|
|
800
|
+
right: 0;
|
|
801
|
+
bottom: 1rem;
|
|
802
|
+
color: var(--smrt-color-on-surface-variant);
|
|
803
|
+
font-size: 0.75rem;
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
.package-index {
|
|
807
|
+
padding-top: 2rem;
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
.package-index > h3 {
|
|
811
|
+
margin: 0 0 0.65rem;
|
|
812
|
+
color: var(--smrt-color-on-surface-variant);
|
|
813
|
+
font-size: 0.68rem;
|
|
814
|
+
font-weight: 600;
|
|
815
|
+
letter-spacing: 0.08em;
|
|
816
|
+
text-transform: uppercase;
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
.package-index > button {
|
|
820
|
+
display: grid;
|
|
821
|
+
width: 100%;
|
|
822
|
+
grid-template-columns: minmax(0, 1fr) auto 1.5rem;
|
|
823
|
+
align-items: center;
|
|
824
|
+
gap: 1.25rem;
|
|
825
|
+
padding: 1.15rem 0;
|
|
826
|
+
border: 0;
|
|
827
|
+
border-bottom: 1px solid var(--smrt-color-outline-variant);
|
|
828
|
+
background: transparent;
|
|
829
|
+
text-align: left;
|
|
830
|
+
cursor: pointer;
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
.package-index__copy {
|
|
834
|
+
display: grid;
|
|
835
|
+
min-width: 0;
|
|
836
|
+
gap: 0.25rem;
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
.package-index__copy strong {
|
|
840
|
+
font-size: 0.95rem;
|
|
841
|
+
font-weight: 600;
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
.package-index__copy small,
|
|
845
|
+
.package-index__modes {
|
|
846
|
+
color: var(--smrt-color-on-surface-variant);
|
|
847
|
+
font-size: 0.76rem;
|
|
848
|
+
line-height: 1.4;
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
.package-index__modes {
|
|
852
|
+
text-transform: capitalize;
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
.package-index__arrow {
|
|
856
|
+
color: var(--smrt-color-primary);
|
|
857
|
+
transition: transform 140ms ease;
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
.package-index > button:hover .package-index__copy strong,
|
|
861
|
+
.package-index > button:focus-visible .package-index__copy strong {
|
|
862
|
+
color: var(--smrt-color-primary);
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
.package-index > button:hover .package-index__arrow,
|
|
866
|
+
.package-index > button:focus-visible .package-index__arrow {
|
|
867
|
+
transform: translateX(0.2rem);
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
.preview-heading {
|
|
871
|
+
padding: 1rem 0 0.25rem;
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
.preview-heading p {
|
|
875
|
+
margin: 0 0 0.35rem;
|
|
876
|
+
color: var(--smrt-color-primary);
|
|
877
|
+
font-size: 0.68rem;
|
|
878
|
+
letter-spacing: 0.08em;
|
|
879
|
+
text-transform: none;
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
.preview-heading h2 {
|
|
883
|
+
margin: 0;
|
|
884
|
+
font-size: clamp(1.45rem, 2.6vw, 2.15rem);
|
|
885
|
+
font-weight: 550;
|
|
886
|
+
letter-spacing: -0.025em;
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
.preview-heading span {
|
|
890
|
+
display: block;
|
|
891
|
+
max-width: 48rem;
|
|
892
|
+
margin-top: 0.45rem;
|
|
893
|
+
color: var(--smrt-color-on-surface-variant);
|
|
894
|
+
line-height: 1.5;
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
.preview-heading .mode-description {
|
|
898
|
+
font-size: 0.85rem;
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
.preview-panel {
|
|
902
|
+
min-width: 0;
|
|
567
903
|
}
|
|
568
904
|
|
|
569
905
|
.preview-stage {
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
background: var(--smrt-color-surface-container-lowest);
|
|
906
|
+
min-width: 0;
|
|
907
|
+
min-height: 30rem;
|
|
908
|
+
padding: clamp(1rem, 2.2vw, 2rem);
|
|
574
909
|
overflow: auto;
|
|
575
|
-
|
|
910
|
+
border: 1px solid var(--smrt-color-outline-variant);
|
|
911
|
+
border-radius: 1rem;
|
|
912
|
+
background: var(--smrt-color-surface);
|
|
913
|
+
color: var(--smrt-color-on-surface);
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
.preview-state {
|
|
917
|
+
display: grid;
|
|
918
|
+
min-height: 25rem;
|
|
919
|
+
place-content: center;
|
|
920
|
+
justify-items: center;
|
|
921
|
+
padding: 1rem;
|
|
922
|
+
color: var(--smrt-color-on-surface-variant);
|
|
923
|
+
text-align: center;
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
.preview-state p,
|
|
927
|
+
.empty-state p {
|
|
928
|
+
margin: 0.4rem 0 0;
|
|
929
|
+
line-height: 1.5;
|
|
576
930
|
}
|
|
577
931
|
|
|
578
932
|
.full-height {
|
|
579
933
|
min-height: 60vh;
|
|
580
|
-
align-content: center;
|
|
581
934
|
}
|
|
582
935
|
|
|
583
|
-
|
|
584
|
-
.
|
|
585
|
-
|
|
936
|
+
.empty-state {
|
|
937
|
+
padding: 1rem 0.25rem;
|
|
938
|
+
color: var(--smrt-color-on-surface-variant);
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
.loader {
|
|
942
|
+
width: 1.25rem;
|
|
943
|
+
height: 1.25rem;
|
|
944
|
+
border: 2px solid var(--smrt-color-outline-variant);
|
|
945
|
+
border-top-color: var(--smrt-color-primary);
|
|
946
|
+
border-radius: 50%;
|
|
947
|
+
animation: spin 0.8s linear infinite;
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
@keyframes spin {
|
|
951
|
+
to {
|
|
952
|
+
transform: rotate(360deg);
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
@media (max-width: 900px) {
|
|
957
|
+
.playground-shell {
|
|
586
958
|
grid-template-columns: 1fr;
|
|
587
959
|
}
|
|
960
|
+
|
|
961
|
+
.catalog-nav {
|
|
962
|
+
position: static;
|
|
963
|
+
height: auto;
|
|
964
|
+
border-right: 0;
|
|
965
|
+
border-bottom: 1px solid var(--smrt-color-outline-variant);
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
.catalog-scroll {
|
|
969
|
+
max-height: 18rem;
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
.catalog-scroll nav {
|
|
973
|
+
grid-template-columns: 1fr;
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
@media (max-width: 600px) {
|
|
978
|
+
.theme-controls :global(.smrt-theme-switcher) {
|
|
979
|
+
display: none;
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
.workspace-header {
|
|
983
|
+
align-items: flex-start;
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
.breadcrumbs {
|
|
987
|
+
display: grid;
|
|
988
|
+
gap: 0.15rem;
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
.breadcrumbs i {
|
|
992
|
+
display: none;
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
.package-landing > header > small {
|
|
996
|
+
position: static;
|
|
997
|
+
margin-top: 0.35rem;
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
.package-index > button {
|
|
1001
|
+
grid-template-columns: minmax(0, 1fr) 1.5rem;
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
.package-index__modes {
|
|
1005
|
+
display: none;
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1010
|
+
.loader {
|
|
1011
|
+
animation: none;
|
|
1012
|
+
}
|
|
588
1013
|
}
|
|
589
1014
|
</style>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlaygroundHost.svelte.d.ts","sourceRoot":"","sources":["../../src/svelte/PlaygroundHost.svelte.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAGxC,OAAO,KAAK,EAIV,oBAAoB,EACrB,MAAM,YAAY,CAAC;AAGpB,MAAM,WAAW,KAAK;IACpB,OAAO,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;
|
|
1
|
+
{"version":3,"file":"PlaygroundHost.svelte.d.ts","sourceRoot":"","sources":["../../src/svelte/PlaygroundHost.svelte.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAGxC,OAAO,KAAK,EAIV,oBAAoB,EACrB,MAAM,YAAY,CAAC;AAGpB,MAAM,WAAW,KAAK;IACpB,OAAO,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AA0bD,QAAA,MAAM,cAAc,0BAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@happyvertical/smrt-playground",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.39.1",
|
|
4
4
|
"description": "Shared playground discovery, runtime, and host components for SMRT UI packages",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"fast-glob": "3.3.3",
|
|
31
31
|
"tsx": "^4.23.0",
|
|
32
|
-
"@happyvertical/smrt-ui": "0.
|
|
32
|
+
"@happyvertical/smrt-ui": "0.39.1"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
35
|
"svelte": "^5.56.4",
|