@happyvertical/smrt-playground 0.30.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/AGENTS.md +46 -0
- package/CLAUDE.md +1 -0
- package/LICENSE +7 -0
- package/README.md +46 -0
- package/dist/chunks/discovery-C0r-nDQB.js +177 -0
- package/dist/chunks/discovery-C0r-nDQB.js.map +1 -0
- package/dist/chunks/runtime-BtfwY7PF.js +104 -0
- package/dist/chunks/runtime-BtfwY7PF.js.map +1 -0
- package/dist/discovery.d.ts +10 -0
- package/dist/discovery.d.ts.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +67 -0
- package/dist/index.js.map +1 -0
- package/dist/runtime.d.ts +6 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +8 -0
- package/dist/runtime.js.map +1 -0
- package/dist/svelte/PlaygroundHost.svelte +563 -0
- package/dist/svelte/PlaygroundHost.svelte.d.ts +11 -0
- package/dist/svelte/PlaygroundHost.svelte.d.ts.map +1 -0
- package/dist/svelte/index.d.ts +2 -0
- package/dist/svelte/index.d.ts.map +1 -0
- package/dist/svelte/index.js +1 -0
- package/dist/svelte/runtime.d.ts +2 -0
- package/dist/svelte/runtime.d.ts.map +1 -0
- package/dist/svelte/runtime.js +1 -0
- package/dist/svelte/types.d.ts +2 -0
- package/dist/svelte/types.d.ts.map +1 -0
- package/dist/svelte/types.js +1 -0
- package/dist/templates.d.ts +4 -0
- package/dist/templates.d.ts.map +1 -0
- package/dist/types.d.ts +76 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +4 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/vite.d.ts +6 -0
- package/dist/vite.d.ts.map +1 -0
- package/dist/vite.js +115 -0
- package/dist/vite.js.map +1 -0
- package/package.json +76 -0
|
@@ -0,0 +1,563 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { ThemeProvider } from '@happyvertical/smrt-ui/themes';
|
|
3
|
+
import type { Component } from 'svelte';
|
|
4
|
+
import { onMount } from 'svelte';
|
|
5
|
+
import { mergePlaygroundModules } from './runtime.js';
|
|
6
|
+
import type {
|
|
7
|
+
PlaygroundComponentModule,
|
|
8
|
+
ResolvedSmrtPlaygroundEntry,
|
|
9
|
+
SmrtPlaygroundMode,
|
|
10
|
+
SmrtPlaygroundModule,
|
|
11
|
+
} from './types.js';
|
|
12
|
+
|
|
13
|
+
export interface Props {
|
|
14
|
+
modules?: SmrtPlaygroundModule[];
|
|
15
|
+
title?: string;
|
|
16
|
+
subtitle?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
let {
|
|
20
|
+
modules = [],
|
|
21
|
+
title = 'SMRT Playground',
|
|
22
|
+
subtitle = 'Shared package previews with app-local overrides',
|
|
23
|
+
}: Props = $props();
|
|
24
|
+
|
|
25
|
+
const normalizedModules = $derived(mergePlaygroundModules(modules));
|
|
26
|
+
const filteredModules = $derived(
|
|
27
|
+
normalizedModules.filter((module) => {
|
|
28
|
+
if (!searchTerm) {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const query = searchTerm.toLowerCase();
|
|
33
|
+
return (
|
|
34
|
+
module.displayName.toLowerCase().includes(query) ||
|
|
35
|
+
module.entries.some(
|
|
36
|
+
(entry) =>
|
|
37
|
+
entry.title.toLowerCase().includes(query) ||
|
|
38
|
+
entry.id.toLowerCase().includes(query),
|
|
39
|
+
)
|
|
40
|
+
);
|
|
41
|
+
}),
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
let selectedModuleName = $state<string | null>(null);
|
|
45
|
+
let selectedEntryId = $state<string | null>(null);
|
|
46
|
+
let selectedMode = $state<SmrtPlaygroundMode>('mock');
|
|
47
|
+
let searchTerm = $state('');
|
|
48
|
+
let isHydrated = $state(false);
|
|
49
|
+
|
|
50
|
+
onMount(() => {
|
|
51
|
+
isHydrated = true;
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
$effect(() => {
|
|
55
|
+
const firstModule = filteredModules[0] ?? normalizedModules[0] ?? null;
|
|
56
|
+
if (!firstModule) {
|
|
57
|
+
selectedModuleName = null;
|
|
58
|
+
selectedEntryId = null;
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const activeModule =
|
|
63
|
+
filteredModules.find(
|
|
64
|
+
(module) => module.packageName === selectedModuleName,
|
|
65
|
+
) ||
|
|
66
|
+
normalizedModules.find(
|
|
67
|
+
(module) => module.packageName === selectedModuleName,
|
|
68
|
+
) ||
|
|
69
|
+
firstModule;
|
|
70
|
+
|
|
71
|
+
if (activeModule.packageName !== selectedModuleName) {
|
|
72
|
+
selectedModuleName = activeModule.packageName;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const activeEntry =
|
|
76
|
+
activeModule.entries.find(
|
|
77
|
+
(entry) => entry.qualifiedId === selectedEntryId,
|
|
78
|
+
) ||
|
|
79
|
+
activeModule.entries[0] ||
|
|
80
|
+
null;
|
|
81
|
+
|
|
82
|
+
if (activeEntry && activeEntry.qualifiedId !== selectedEntryId) {
|
|
83
|
+
selectedEntryId = activeEntry.qualifiedId;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (activeEntry && !activeEntry.availableModes.includes(selectedMode)) {
|
|
87
|
+
selectedMode = activeEntry.availableModes[0] ?? 'mock';
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
const selectedModule = $derived(
|
|
92
|
+
normalizedModules.find(
|
|
93
|
+
(module) => module.packageName === selectedModuleName,
|
|
94
|
+
) ||
|
|
95
|
+
normalizedModules[0] ||
|
|
96
|
+
null,
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
const selectedEntry = $derived(
|
|
100
|
+
selectedModule?.entries.find(
|
|
101
|
+
(entry) => entry.qualifiedId === selectedEntryId,
|
|
102
|
+
) ||
|
|
103
|
+
selectedModule?.entries[0] ||
|
|
104
|
+
null,
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
let PreviewComponent = $state<Component<Record<string, unknown>> | null>(null);
|
|
108
|
+
let previewComponentEntryId = $state<string | null>(null);
|
|
109
|
+
let previewLoadError = $state<string | null>(null);
|
|
110
|
+
let previewIsLoading = $state(false);
|
|
111
|
+
|
|
112
|
+
const selectedProps = $derived(
|
|
113
|
+
selectedEntry
|
|
114
|
+
? {
|
|
115
|
+
...(selectedEntry.props || {}),
|
|
116
|
+
...(selectedEntry.modes[selectedMode]?.props || {}),
|
|
117
|
+
}
|
|
118
|
+
: {},
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
const selectedModeConfig = $derived(
|
|
122
|
+
selectedEntry ? (selectedEntry.modes[selectedMode] ?? null) : null,
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
function resolvePreviewComponent(
|
|
126
|
+
loaded: PlaygroundComponentModule,
|
|
127
|
+
): Component<Record<string, unknown>> {
|
|
128
|
+
if (
|
|
129
|
+
loaded &&
|
|
130
|
+
typeof loaded === 'object' &&
|
|
131
|
+
'default' in loaded &&
|
|
132
|
+
loaded.default
|
|
133
|
+
) {
|
|
134
|
+
return loaded.default as Component<Record<string, unknown>>;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return loaded as Component<Record<string, unknown>>;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
$effect(() => {
|
|
141
|
+
const entry = selectedEntry;
|
|
142
|
+
let cancelled = false;
|
|
143
|
+
|
|
144
|
+
previewLoadError = null;
|
|
145
|
+
|
|
146
|
+
if (!entry) {
|
|
147
|
+
PreviewComponent = null;
|
|
148
|
+
previewComponentEntryId = null;
|
|
149
|
+
previewIsLoading = false;
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (entry.component) {
|
|
154
|
+
PreviewComponent = entry.component as Component<Record<string, unknown>>;
|
|
155
|
+
previewComponentEntryId = entry.qualifiedId;
|
|
156
|
+
previewIsLoading = false;
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (!entry.loadComponent) {
|
|
161
|
+
PreviewComponent = null;
|
|
162
|
+
previewComponentEntryId = null;
|
|
163
|
+
previewIsLoading = false;
|
|
164
|
+
previewLoadError = 'This preview does not declare a renderable component.';
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
PreviewComponent = null;
|
|
169
|
+
previewComponentEntryId = null;
|
|
170
|
+
previewIsLoading = true;
|
|
171
|
+
|
|
172
|
+
void entry
|
|
173
|
+
.loadComponent()
|
|
174
|
+
.then((loaded) => {
|
|
175
|
+
if (cancelled) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
PreviewComponent = resolvePreviewComponent(loaded);
|
|
180
|
+
previewComponentEntryId = entry.qualifiedId;
|
|
181
|
+
previewIsLoading = false;
|
|
182
|
+
})
|
|
183
|
+
.catch((error) => {
|
|
184
|
+
if (cancelled) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
PreviewComponent = null;
|
|
189
|
+
previewComponentEntryId = null;
|
|
190
|
+
previewLoadError =
|
|
191
|
+
error instanceof Error ? error.message : 'Failed to load preview.';
|
|
192
|
+
previewIsLoading = false;
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
return () => {
|
|
196
|
+
cancelled = true;
|
|
197
|
+
};
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
function selectModule(packageName: string) {
|
|
201
|
+
selectedModuleName = packageName;
|
|
202
|
+
selectedEntryId = null;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function selectEntry(entry: ResolvedSmrtPlaygroundEntry) {
|
|
206
|
+
selectedModuleName = entry.packageName;
|
|
207
|
+
selectedEntryId = entry.qualifiedId;
|
|
208
|
+
selectedMode = entry.availableModes[0] ?? 'mock';
|
|
209
|
+
}
|
|
210
|
+
</script>
|
|
211
|
+
|
|
212
|
+
<ThemeProvider colorScheme="system" persist={true}>
|
|
213
|
+
<div class="playground-shell" data-hydrated={isHydrated ? 'true' : 'false'}>
|
|
214
|
+
<aside class="sidebar">
|
|
215
|
+
<div class="sidebar__header">
|
|
216
|
+
<p class="eyebrow">Shared Host</p>
|
|
217
|
+
<h1>{title}</h1>
|
|
218
|
+
<p>{subtitle}</p>
|
|
219
|
+
</div>
|
|
220
|
+
|
|
221
|
+
<label class="search">
|
|
222
|
+
<span>Filter previews</span>
|
|
223
|
+
<input bind:value={searchTerm} placeholder="Search packages or entries" />
|
|
224
|
+
</label>
|
|
225
|
+
|
|
226
|
+
<div class="module-list" data-testid="playground-modules">
|
|
227
|
+
{#if filteredModules.length === 0}
|
|
228
|
+
<div class="empty-card">
|
|
229
|
+
<strong>No previews found</strong>
|
|
230
|
+
<p>Add a `src/svelte/playground.ts` file to a package, or scaffold `src/playground.ts` in your app.</p>
|
|
231
|
+
</div>
|
|
232
|
+
{:else}
|
|
233
|
+
{#each filteredModules as module (module.packageName)}
|
|
234
|
+
<button
|
|
235
|
+
type="button"
|
|
236
|
+
class:selected={module.packageName === selectedModule?.packageName}
|
|
237
|
+
data-playground-module={module.packageName}
|
|
238
|
+
onclick={() => selectModule(module.packageName)}
|
|
239
|
+
>
|
|
240
|
+
<strong>{module.displayName}</strong>
|
|
241
|
+
<span>{module.entries.length} preview{module.entries.length === 1 ? '' : 's'}</span>
|
|
242
|
+
</button>
|
|
243
|
+
{/each}
|
|
244
|
+
{/if}
|
|
245
|
+
</div>
|
|
246
|
+
</aside>
|
|
247
|
+
|
|
248
|
+
<main class="content">
|
|
249
|
+
{#if selectedModule}
|
|
250
|
+
<header class="content__header">
|
|
251
|
+
<div>
|
|
252
|
+
<p class="eyebrow" data-testid="playground-selected-package">{selectedModule.packageName}</p>
|
|
253
|
+
<h2 data-testid="playground-selected-module">{selectedModule.displayName}</h2>
|
|
254
|
+
{#if selectedModule.description}
|
|
255
|
+
<p>{selectedModule.description}</p>
|
|
256
|
+
{/if}
|
|
257
|
+
</div>
|
|
258
|
+
</header>
|
|
259
|
+
|
|
260
|
+
<div class="content__body">
|
|
261
|
+
<section class="entry-list" data-testid="playground-entries">
|
|
262
|
+
{#each selectedModule.entries as entry (entry.qualifiedId)}
|
|
263
|
+
<button
|
|
264
|
+
type="button"
|
|
265
|
+
class:selected={entry.qualifiedId === selectedEntry?.qualifiedId}
|
|
266
|
+
aria-pressed={entry.qualifiedId === selectedEntry?.qualifiedId}
|
|
267
|
+
data-playground-entry={entry.qualifiedId}
|
|
268
|
+
onclick={() => selectEntry(entry)}
|
|
269
|
+
>
|
|
270
|
+
<div>
|
|
271
|
+
<strong>{entry.title}</strong>
|
|
272
|
+
<span>{entry.id}</span>
|
|
273
|
+
</div>
|
|
274
|
+
<div class="mode-pills">
|
|
275
|
+
{#each entry.availableModes as mode}
|
|
276
|
+
<span>{mode}</span>
|
|
277
|
+
{/each}
|
|
278
|
+
</div>
|
|
279
|
+
</button>
|
|
280
|
+
{/each}
|
|
281
|
+
</section>
|
|
282
|
+
|
|
283
|
+
<section class="preview-panel" data-testid="playground-preview-panel">
|
|
284
|
+
{#if selectedEntry && PreviewComponent && previewComponentEntryId === selectedEntry.qualifiedId}
|
|
285
|
+
<div class="preview-panel__meta">
|
|
286
|
+
<div>
|
|
287
|
+
<h3 data-testid="playground-preview-title">{selectedEntry.title}</h3>
|
|
288
|
+
{#if selectedEntry.description}
|
|
289
|
+
<p>{selectedEntry.description}</p>
|
|
290
|
+
{/if}
|
|
291
|
+
{#if selectedModeConfig?.description}
|
|
292
|
+
<p class="mode-description">{selectedModeConfig.description}</p>
|
|
293
|
+
{/if}
|
|
294
|
+
</div>
|
|
295
|
+
|
|
296
|
+
{#if selectedEntry.availableModes.length > 1}
|
|
297
|
+
<div class="mode-toggle" role="group" aria-label="Preview mode">
|
|
298
|
+
{#each selectedEntry.availableModes as mode}
|
|
299
|
+
<button
|
|
300
|
+
type="button"
|
|
301
|
+
class:active={mode === selectedMode}
|
|
302
|
+
aria-pressed={mode === selectedMode}
|
|
303
|
+
data-playground-mode={mode}
|
|
304
|
+
onclick={() => (selectedMode = mode)}
|
|
305
|
+
>
|
|
306
|
+
{mode}
|
|
307
|
+
</button>
|
|
308
|
+
{/each}
|
|
309
|
+
</div>
|
|
310
|
+
{/if}
|
|
311
|
+
</div>
|
|
312
|
+
|
|
313
|
+
<div class="preview-stage" data-testid="playground-preview-stage">
|
|
314
|
+
<PreviewComponent {...selectedProps} />
|
|
315
|
+
</div>
|
|
316
|
+
{:else if selectedEntry && previewIsLoading}
|
|
317
|
+
<div class="empty-card">
|
|
318
|
+
<strong>Loading preview...</strong>
|
|
319
|
+
<p>{selectedEntry.title} is being loaded for the selected mode.</p>
|
|
320
|
+
</div>
|
|
321
|
+
{:else if selectedEntry && previewLoadError}
|
|
322
|
+
<div class="empty-card">
|
|
323
|
+
<strong>Preview failed to load</strong>
|
|
324
|
+
<p>{previewLoadError}</p>
|
|
325
|
+
</div>
|
|
326
|
+
{:else}
|
|
327
|
+
<div class="empty-card">
|
|
328
|
+
<strong>No preview selected</strong>
|
|
329
|
+
<p>Select a preview entry from the left to render it.</p>
|
|
330
|
+
</div>
|
|
331
|
+
{/if}
|
|
332
|
+
</section>
|
|
333
|
+
</div>
|
|
334
|
+
{:else}
|
|
335
|
+
<div class="empty-card full-height">
|
|
336
|
+
<strong>No playground modules discovered</strong>
|
|
337
|
+
<p>The shared host is ready, but nothing is exporting playground entries yet.</p>
|
|
338
|
+
</div>
|
|
339
|
+
{/if}
|
|
340
|
+
</main>
|
|
341
|
+
</div>
|
|
342
|
+
</ThemeProvider>
|
|
343
|
+
|
|
344
|
+
<style>
|
|
345
|
+
:global(body) {
|
|
346
|
+
margin: 0;
|
|
347
|
+
font-family:
|
|
348
|
+
"IBM Plex Sans",
|
|
349
|
+
"Inter",
|
|
350
|
+
system-ui,
|
|
351
|
+
sans-serif;
|
|
352
|
+
background:
|
|
353
|
+
radial-gradient(circle at top left, rgba(30, 96, 145, 0.16), transparent 28rem),
|
|
354
|
+
linear-gradient(180deg, #f4f7fb 0%, #eef2f8 100%);
|
|
355
|
+
color: #0f1722;
|
|
356
|
+
min-height: 100vh;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
.playground-shell {
|
|
360
|
+
display: grid;
|
|
361
|
+
grid-template-columns: 20rem minmax(0, 1fr);
|
|
362
|
+
min-height: 100vh;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
.sidebar {
|
|
366
|
+
display: grid;
|
|
367
|
+
align-content: start;
|
|
368
|
+
gap: 1.25rem;
|
|
369
|
+
padding: 1.5rem;
|
|
370
|
+
background: rgba(7, 15, 26, 0.92);
|
|
371
|
+
color: #ecf2ff;
|
|
372
|
+
border-right: 1px solid rgba(255, 255, 255, 0.08);
|
|
373
|
+
backdrop-filter: blur(18px);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
.sidebar__header h1,
|
|
377
|
+
.content__header h2,
|
|
378
|
+
.preview-panel__meta h3 {
|
|
379
|
+
margin: 0;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
.sidebar__header,
|
|
383
|
+
.search,
|
|
384
|
+
.module-list,
|
|
385
|
+
.content,
|
|
386
|
+
.content__body,
|
|
387
|
+
.entry-list,
|
|
388
|
+
.preview-panel {
|
|
389
|
+
display: grid;
|
|
390
|
+
gap: 0.9rem;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
.eyebrow {
|
|
394
|
+
margin: 0 0 0.35rem;
|
|
395
|
+
font-size: 0.75rem;
|
|
396
|
+
letter-spacing: 0.12em;
|
|
397
|
+
text-transform: uppercase;
|
|
398
|
+
color: #6aa4ff;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
.sidebar__header p:last-child,
|
|
402
|
+
.content__header p,
|
|
403
|
+
.preview-panel__meta p,
|
|
404
|
+
.empty-card p {
|
|
405
|
+
margin: 0;
|
|
406
|
+
line-height: 1.55;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
.search span {
|
|
410
|
+
font-size: 0.82rem;
|
|
411
|
+
color: rgba(236, 242, 255, 0.72);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
.search input {
|
|
415
|
+
width: 100%;
|
|
416
|
+
box-sizing: border-box;
|
|
417
|
+
border: 1px solid rgba(255, 255, 255, 0.16);
|
|
418
|
+
border-radius: 0.9rem;
|
|
419
|
+
background: rgba(255, 255, 255, 0.08);
|
|
420
|
+
color: inherit;
|
|
421
|
+
padding: 0.8rem 0.95rem;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
.module-list button,
|
|
425
|
+
.entry-list button,
|
|
426
|
+
.mode-toggle button {
|
|
427
|
+
border: 0;
|
|
428
|
+
cursor: pointer;
|
|
429
|
+
transition:
|
|
430
|
+
transform 140ms ease,
|
|
431
|
+
background 140ms ease,
|
|
432
|
+
border-color 140ms ease;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
.module-list button,
|
|
436
|
+
.entry-list button {
|
|
437
|
+
display: grid;
|
|
438
|
+
gap: 0.25rem;
|
|
439
|
+
text-align: left;
|
|
440
|
+
padding: 0.9rem 1rem;
|
|
441
|
+
border-radius: 1rem;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
.module-list button {
|
|
445
|
+
background: rgba(255, 255, 255, 0.06);
|
|
446
|
+
color: inherit;
|
|
447
|
+
border: 1px solid transparent;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
.module-list button.selected,
|
|
451
|
+
.module-list button:hover {
|
|
452
|
+
background: rgba(106, 164, 255, 0.14);
|
|
453
|
+
border-color: rgba(106, 164, 255, 0.34);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
.module-list button span,
|
|
457
|
+
.entry-list button span {
|
|
458
|
+
font-size: 0.82rem;
|
|
459
|
+
opacity: 0.78;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
.content {
|
|
463
|
+
padding: 1.75rem;
|
|
464
|
+
align-content: start;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
.content__body {
|
|
468
|
+
grid-template-columns: 18rem minmax(0, 1fr);
|
|
469
|
+
align-items: start;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
.entry-list button {
|
|
473
|
+
background: rgba(255, 255, 255, 0.72);
|
|
474
|
+
border: 1px solid rgba(15, 23, 34, 0.08);
|
|
475
|
+
box-shadow: 0 18px 45px rgba(15, 23, 34, 0.05);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
.entry-list button.selected,
|
|
479
|
+
.entry-list button:hover {
|
|
480
|
+
transform: translateY(-1px);
|
|
481
|
+
border-color: rgba(14, 93, 224, 0.25);
|
|
482
|
+
box-shadow: 0 18px 45px rgba(14, 93, 224, 0.12);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
.mode-pills {
|
|
486
|
+
display: flex;
|
|
487
|
+
flex-wrap: wrap;
|
|
488
|
+
gap: 0.35rem;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
.mode-pills span,
|
|
492
|
+
.mode-toggle button {
|
|
493
|
+
border-radius: 999px;
|
|
494
|
+
padding: 0.25rem 0.6rem;
|
|
495
|
+
font-size: 0.75rem;
|
|
496
|
+
text-transform: uppercase;
|
|
497
|
+
letter-spacing: 0.08em;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
.mode-pills span {
|
|
501
|
+
background: rgba(14, 93, 224, 0.08);
|
|
502
|
+
color: #0e5de0;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
.preview-panel,
|
|
506
|
+
.empty-card {
|
|
507
|
+
padding: 1.1rem;
|
|
508
|
+
border-radius: 1.25rem;
|
|
509
|
+
background: rgba(255, 255, 255, 0.82);
|
|
510
|
+
border: 1px solid rgba(15, 23, 34, 0.08);
|
|
511
|
+
box-shadow: 0 24px 60px rgba(15, 23, 34, 0.08);
|
|
512
|
+
backdrop-filter: blur(18px);
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
.preview-panel__meta {
|
|
516
|
+
display: flex;
|
|
517
|
+
flex-wrap: wrap;
|
|
518
|
+
justify-content: space-between;
|
|
519
|
+
gap: 1rem;
|
|
520
|
+
align-items: start;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
.mode-toggle {
|
|
524
|
+
display: inline-flex;
|
|
525
|
+
gap: 0.45rem;
|
|
526
|
+
padding: 0.2rem;
|
|
527
|
+
border-radius: 999px;
|
|
528
|
+
background: #e6edf9;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
.mode-toggle button {
|
|
532
|
+
background: transparent;
|
|
533
|
+
color: #36527b;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
.mode-toggle button.active {
|
|
537
|
+
background: #0e5de0;
|
|
538
|
+
color: white;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
.preview-stage {
|
|
542
|
+
padding: 1rem;
|
|
543
|
+
border-radius: 1rem;
|
|
544
|
+
background:
|
|
545
|
+
linear-gradient(180deg, rgba(255, 255, 255, 0.84), rgba(245, 248, 252, 0.94)),
|
|
546
|
+
radial-gradient(circle at top, rgba(106, 164, 255, 0.12), transparent 28rem);
|
|
547
|
+
border: 1px solid rgba(15, 23, 34, 0.06);
|
|
548
|
+
overflow: auto;
|
|
549
|
+
min-height: 24rem;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
.full-height {
|
|
553
|
+
min-height: 60vh;
|
|
554
|
+
align-content: center;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
@media (max-width: 1040px) {
|
|
558
|
+
.playground-shell,
|
|
559
|
+
.content__body {
|
|
560
|
+
grid-template-columns: 1fr;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
</style>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Component } from 'svelte';
|
|
2
|
+
import type { SmrtPlaygroundModule } from './types.js';
|
|
3
|
+
export interface Props {
|
|
4
|
+
modules?: SmrtPlaygroundModule[];
|
|
5
|
+
title?: string;
|
|
6
|
+
subtitle?: string;
|
|
7
|
+
}
|
|
8
|
+
declare const PlaygroundHost: Component<Props, {}, "">;
|
|
9
|
+
type PlaygroundHost = ReturnType<typeof PlaygroundHost>;
|
|
10
|
+
export default PlaygroundHost;
|
|
11
|
+
//# sourceMappingURL=PlaygroundHost.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PlaygroundHost.svelte.d.ts","sourceRoot":"","sources":["../../src/svelte/PlaygroundHost.svelte.ts"],"names":[],"mappings":"AAIA,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;AAiUD,QAAA,MAAM,cAAc,0BAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/svelte/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as PlaygroundHost } from './PlaygroundHost.svelte';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/svelte/runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { mergePlaygroundModules } from '../runtime.js';
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export type { PlaygroundComponentLoader, PlaygroundComponentModule, PlaygroundComponentType, PlaygroundModuleMeta, ResolvedSmrtPlaygroundEntry, ResolvedSmrtPlaygroundModule, SmrtPlaygroundEntry, SmrtPlaygroundMode, SmrtPlaygroundModeConfig, SmrtPlaygroundModule, SmrtPlaygroundModuleExport, } from '../types.js';
|
|
2
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/svelte/types.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,yBAAyB,EACzB,yBAAyB,EACzB,uBAAuB,EACvB,oBAAoB,EACpB,2BAA2B,EAC3B,4BAA4B,EAC5B,mBAAmB,EACnB,kBAAkB,EAClB,wBAAwB,EACxB,oBAAoB,EACpB,0BAA0B,GAC3B,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function createPackagePlaygroundTemplate(packageName: string): string;
|
|
2
|
+
export declare function createAppPlaygroundTemplate(packageName: string): string;
|
|
3
|
+
export declare function createAppPlaygroundRouteTemplate(): string;
|
|
4
|
+
//# sourceMappingURL=templates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../src/templates.ts"],"names":[],"mappings":"AAKA,wBAAgB,+BAA+B,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAe3E;AAED,wBAAgB,2BAA2B,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAkBvE;AAED,wBAAgB,gCAAgC,IAAI,MAAM,CAYzD"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
export type PlaygroundComponentType = (...args: any[]) => any;
|
|
2
|
+
export type PlaygroundComponentModule = PlaygroundComponentType | {
|
|
3
|
+
default: PlaygroundComponentType;
|
|
4
|
+
};
|
|
5
|
+
export type PlaygroundComponentLoader = () => Promise<PlaygroundComponentModule>;
|
|
6
|
+
export interface PlaygroundModuleMeta {
|
|
7
|
+
name: string;
|
|
8
|
+
displayName: string;
|
|
9
|
+
description?: string;
|
|
10
|
+
uiSlots?: Record<string, unknown>;
|
|
11
|
+
models?: string[];
|
|
12
|
+
collections?: string[];
|
|
13
|
+
}
|
|
14
|
+
export type SmrtPlaygroundMode = 'mock' | 'live';
|
|
15
|
+
export interface SmrtPlaygroundModeConfig {
|
|
16
|
+
label?: string;
|
|
17
|
+
description?: string;
|
|
18
|
+
props?: Record<string, unknown>;
|
|
19
|
+
}
|
|
20
|
+
export interface SmrtPlaygroundEntry {
|
|
21
|
+
id: string;
|
|
22
|
+
title: string;
|
|
23
|
+
description?: string;
|
|
24
|
+
component?: PlaygroundComponentType;
|
|
25
|
+
loadComponent?: PlaygroundComponentLoader;
|
|
26
|
+
slotId?: string;
|
|
27
|
+
order?: number;
|
|
28
|
+
props?: Record<string, unknown>;
|
|
29
|
+
tags?: string[];
|
|
30
|
+
modes?: Partial<Record<SmrtPlaygroundMode, SmrtPlaygroundModeConfig | true>>;
|
|
31
|
+
}
|
|
32
|
+
export interface SmrtPlaygroundModule {
|
|
33
|
+
packageName: string;
|
|
34
|
+
displayName?: string;
|
|
35
|
+
description?: string;
|
|
36
|
+
moduleMeta?: PlaygroundModuleMeta;
|
|
37
|
+
entries: SmrtPlaygroundEntry[];
|
|
38
|
+
}
|
|
39
|
+
export type SmrtPlaygroundModuleExport = SmrtPlaygroundModule | SmrtPlaygroundModule[] | {
|
|
40
|
+
modules: SmrtPlaygroundModule[];
|
|
41
|
+
};
|
|
42
|
+
export interface ResolvedSmrtPlaygroundEntry extends Omit<SmrtPlaygroundEntry, 'modes'> {
|
|
43
|
+
packageName: string;
|
|
44
|
+
displayName: string;
|
|
45
|
+
qualifiedId: string;
|
|
46
|
+
availableModes: SmrtPlaygroundMode[];
|
|
47
|
+
modes: Partial<Record<SmrtPlaygroundMode, SmrtPlaygroundModeConfig>>;
|
|
48
|
+
}
|
|
49
|
+
export interface ResolvedSmrtPlaygroundModule extends Omit<SmrtPlaygroundModule, 'displayName' | 'entries'> {
|
|
50
|
+
displayName: string;
|
|
51
|
+
entries: ResolvedSmrtPlaygroundEntry[];
|
|
52
|
+
}
|
|
53
|
+
export interface DiscoveredWorkspacePlayground {
|
|
54
|
+
packageName: string;
|
|
55
|
+
packageDir: string;
|
|
56
|
+
sourcePath: string;
|
|
57
|
+
runtimePath: string | null;
|
|
58
|
+
}
|
|
59
|
+
export interface DiscoveredInstalledPlayground {
|
|
60
|
+
packageName: string;
|
|
61
|
+
importSpecifier: string;
|
|
62
|
+
}
|
|
63
|
+
export interface DiscoveredPlaygroundTarget {
|
|
64
|
+
packageName?: string;
|
|
65
|
+
source: 'workspace' | 'package' | 'app';
|
|
66
|
+
sourcePath?: string;
|
|
67
|
+
runtimePath?: string;
|
|
68
|
+
importSpecifier?: string;
|
|
69
|
+
}
|
|
70
|
+
export interface SmrtPlaygroundVitePluginOptions {
|
|
71
|
+
mode?: 'auto' | 'workspace' | 'consumer';
|
|
72
|
+
workspaceRoot?: string;
|
|
73
|
+
packagesPattern?: string;
|
|
74
|
+
localPlaygroundPath?: string;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=types.d.ts.map
|