@lapikit/repl 0.0.0-insiders.24a3260 → 0.0.0-insiders.c8fbb29
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/Repl.svelte +205 -61
- package/dist/Repl.svelte.d.ts +5 -2
- package/dist/assets/icons/check.svg +1 -0
- package/dist/assets/icons/code.svg +1 -0
- package/dist/assets/icons/codesandbox.svg +1 -0
- package/dist/assets/icons/copy.svg +1 -0
- package/dist/utils.d.ts +0 -6
- package/dist/utils.js +0 -31
- package/package.json +1 -1
- package/dist/Button.svelte +0 -32
- package/dist/Button.svelte.d.ts +0 -5
- package/dist/Files.svelte +0 -67
- package/dist/Files.svelte.d.ts +0 -4
- package/dist/Toolbar.svelte +0 -93
- package/dist/Toolbar.svelte.d.ts +0 -4
- package/dist/types.d.ts +0 -25
- package/dist/types.js +0 -1
- /package/dist/{languages/shell.svg → assets/languages/code.svg} +0 -0
- /package/dist/{languages → assets/languages}/css.svg +0 -0
- /package/dist/{languages → assets/languages}/html.svg +0 -0
- /package/dist/{languages → assets/languages}/javascript.svg +0 -0
- /package/dist/{languages → assets/languages}/svelte.svg +0 -0
- /package/dist/{languages → assets/languages}/typescript.svg +0 -0
package/dist/Repl.svelte
CHANGED
|
@@ -1,28 +1,32 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { copyToClipboard } from './utils.js';
|
|
3
|
-
import { getHighlighterSingleton } from './shiki.js';
|
|
4
|
-
import type { FileItem, ReplProps } from './types.js';
|
|
5
|
-
|
|
6
|
-
// components
|
|
7
|
-
import Toolbar from './Toolbar.svelte';
|
|
8
|
-
import Files from './Files.svelte';
|
|
9
3
|
|
|
10
|
-
|
|
4
|
+
import { Copy, Check, Code, Codesandbox, Moon, Sun } from '@lucide/svelte';
|
|
11
5
|
|
|
12
|
-
|
|
13
|
-
|
|
6
|
+
import CodeIcon from './assets/languages/code.svg';
|
|
7
|
+
import JavaScriptIcon from './assets/languages/javascript.svg';
|
|
8
|
+
import TypeScriptIcon from './assets/languages/typescript.svg';
|
|
9
|
+
import SvelteIcon from './assets/languages/svelte.svg';
|
|
10
|
+
import CssIcon from './assets/languages/css.svg';
|
|
11
|
+
import HtmlIcon from './assets/languages/html.svg';
|
|
12
|
+
import { getHighlighterSingleton } from './shiki.js';
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
interface FileItem {
|
|
15
|
+
name: string;
|
|
16
|
+
content: string;
|
|
17
|
+
lang?: string;
|
|
18
|
+
}
|
|
17
19
|
|
|
18
|
-
let
|
|
20
|
+
let { title, content, children } = $props();
|
|
21
|
+
let codeHTML = $state('');
|
|
19
22
|
let copyState = $state(false);
|
|
20
|
-
let
|
|
21
|
-
let
|
|
23
|
+
let viewMode = $state('editor');
|
|
24
|
+
let themeMode = $state('light');
|
|
22
25
|
|
|
23
|
-
let
|
|
24
|
-
let
|
|
26
|
+
let ref: null | HTMLElement = $state(null);
|
|
27
|
+
let typeContent = $state('code');
|
|
25
28
|
|
|
29
|
+
// multiple content types
|
|
26
30
|
let files = $derived.by<FileItem[]>(() => {
|
|
27
31
|
if (typeof content === 'object' && content !== null && 'code' in content) {
|
|
28
32
|
return [
|
|
@@ -37,14 +41,8 @@
|
|
|
37
41
|
if (typeof content === 'object' && content !== null && !Array.isArray(content)) {
|
|
38
42
|
return Object.entries(content).map(([name, fileContent]) => ({
|
|
39
43
|
name,
|
|
40
|
-
content:
|
|
41
|
-
|
|
42
|
-
? fileContent
|
|
43
|
-
: (fileContent as Record<string, unknown>).code || '',
|
|
44
|
-
lang:
|
|
45
|
-
typeof fileContent === 'object'
|
|
46
|
-
? ((fileContent as Record<string, unknown>).lang as string)
|
|
47
|
-
: 'javascript'
|
|
44
|
+
content: typeof fileContent === 'string' ? fileContent : (fileContent as any).code || '',
|
|
45
|
+
lang: typeof fileContent === 'object' ? (fileContent as any).lang : 'javascript'
|
|
48
46
|
}));
|
|
49
47
|
}
|
|
50
48
|
|
|
@@ -58,23 +56,21 @@
|
|
|
58
56
|
|
|
59
57
|
return [{ name: 'code', content: content || '', lang: 'javascript' }];
|
|
60
58
|
});
|
|
59
|
+
|
|
60
|
+
let activeFileIndex = $state(0);
|
|
61
61
|
let activeFile = $derived(files[activeFileIndex]);
|
|
62
|
+
let hasMultipleFiles = $derived(files.length > 1);
|
|
62
63
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
} else {
|
|
74
|
-
modeState = 'code';
|
|
75
|
-
viewState = 'code';
|
|
76
|
-
}
|
|
77
|
-
});
|
|
64
|
+
let iconMap = {
|
|
65
|
+
code: CodeIcon,
|
|
66
|
+
javascript: JavaScriptIcon,
|
|
67
|
+
typescript: TypeScriptIcon,
|
|
68
|
+
svelte: SvelteIcon,
|
|
69
|
+
css: CssIcon,
|
|
70
|
+
html: HtmlIcon
|
|
71
|
+
} as const;
|
|
72
|
+
|
|
73
|
+
let currentIcon = $derived(iconMap[typeContent as keyof typeof iconMap] || CodeIcon);
|
|
78
74
|
|
|
79
75
|
$effect(() => {
|
|
80
76
|
if (copyState) {
|
|
@@ -91,16 +87,16 @@
|
|
|
91
87
|
|
|
92
88
|
$effect(() => {
|
|
93
89
|
const file = activeFile;
|
|
94
|
-
const theme =
|
|
90
|
+
const theme = themeMode;
|
|
95
91
|
|
|
96
92
|
if (file?.content) {
|
|
97
93
|
(async () => {
|
|
94
|
+
console.log('Rendering file:', file);
|
|
98
95
|
const highlighter = await getHighlighterSingleton();
|
|
99
96
|
|
|
100
|
-
language = file.lang || 'javascript';
|
|
101
97
|
const html = highlighter.codeToHtml(file.content, {
|
|
102
98
|
theme: theme === 'light' ? 'github-light' : 'github-dark',
|
|
103
|
-
lang: file.lang ||
|
|
99
|
+
lang: file.lang || 'javascript'
|
|
104
100
|
});
|
|
105
101
|
|
|
106
102
|
codeHTML = html;
|
|
@@ -110,32 +106,76 @@
|
|
|
110
106
|
</script>
|
|
111
107
|
|
|
112
108
|
<div class="repl-container">
|
|
113
|
-
<
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
bind:viewState
|
|
119
|
-
bind:themeState
|
|
120
|
-
bind:modeState
|
|
121
|
-
/>
|
|
122
|
-
|
|
123
|
-
{#if modeState !== 'code'}
|
|
124
|
-
<hr />
|
|
125
|
-
{/if}
|
|
109
|
+
<div class="repl-toolbar">
|
|
110
|
+
<div class="repl-toolbar--title">
|
|
111
|
+
<img src={currentIcon} alt="{typeContent} icon" class="toolbar-icon" />
|
|
112
|
+
<span>{title || 'REPL Toolbar'}</span>
|
|
113
|
+
</div>
|
|
126
114
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
115
|
+
<div class="repl-toolbar--actions">
|
|
116
|
+
{#if viewMode !== 'editor'}
|
|
117
|
+
<button
|
|
118
|
+
class="repl-btn--icon"
|
|
119
|
+
onclick={() => (themeMode = themeMode === 'light' ? 'dark' : 'light')}
|
|
120
|
+
title="Toggle Theme"
|
|
121
|
+
>
|
|
122
|
+
{#if themeMode === 'light'}
|
|
123
|
+
<Moon class="toolbar-icon" />
|
|
124
|
+
{:else}
|
|
125
|
+
<Sun class="toolbar-icon" />
|
|
126
|
+
{/if}
|
|
127
|
+
</button>
|
|
128
|
+
{/if}
|
|
129
|
+
<button
|
|
130
|
+
class="repl-btn--icon"
|
|
131
|
+
title={viewMode === 'editor' ? 'Code' : 'Playground'}
|
|
132
|
+
onclick={() => (viewMode = viewMode === 'editor' ? 'playground' : 'editor')}
|
|
133
|
+
>
|
|
134
|
+
{#if viewMode === 'editor'}
|
|
135
|
+
<Code class="toolbar-icon" />
|
|
136
|
+
{:else}
|
|
137
|
+
<Codesandbox class="toolbar-icon" />
|
|
138
|
+
{/if}
|
|
139
|
+
</button>
|
|
140
|
+
<button
|
|
141
|
+
class="repl-btn--icon"
|
|
142
|
+
onclick={() => (copyState = true)}
|
|
143
|
+
title={copyState ? 'Copied!' : 'Copy'}
|
|
144
|
+
>
|
|
145
|
+
{#if copyState}
|
|
146
|
+
<Check class="toolbar-icon" />
|
|
147
|
+
{:else}
|
|
148
|
+
<Copy class="toolbar-icon" />
|
|
149
|
+
{/if}
|
|
150
|
+
</button>
|
|
130
151
|
</div>
|
|
152
|
+
</div>
|
|
153
|
+
|
|
154
|
+
<hr />
|
|
131
155
|
|
|
156
|
+
{#if hasMultipleFiles && viewMode === 'editor'}
|
|
157
|
+
<div class="sub-toolbar">
|
|
158
|
+
{#each files as file, index (index)}
|
|
159
|
+
<button
|
|
160
|
+
class="file-tab"
|
|
161
|
+
class:active={activeFileIndex === index}
|
|
162
|
+
onclick={() => (activeFileIndex = index)}
|
|
163
|
+
title={file.name}
|
|
164
|
+
>
|
|
165
|
+
<img
|
|
166
|
+
src={iconMap[file.lang as keyof typeof iconMap] || CodeIcon}
|
|
167
|
+
alt="{file.lang} icon"
|
|
168
|
+
class="file-icon"
|
|
169
|
+
/>
|
|
170
|
+
<span>{file.name}</span>
|
|
171
|
+
</button>
|
|
172
|
+
{/each}
|
|
173
|
+
</div>
|
|
132
174
|
<hr />
|
|
133
175
|
{/if}
|
|
134
176
|
|
|
135
|
-
<Files {files} bind:activeIndex={activeFileIndex} />
|
|
136
|
-
|
|
137
177
|
<div class="repl-content">
|
|
138
|
-
{#if
|
|
178
|
+
{#if viewMode === 'editor'}
|
|
139
179
|
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
|
140
180
|
<div class="wrapper-highlight" bind:this={ref}>{@html codeHTML}</div>
|
|
141
181
|
{:else}
|
|
@@ -166,6 +206,74 @@
|
|
|
166
206
|
background-color: var(--repl-background) !important;
|
|
167
207
|
}
|
|
168
208
|
|
|
209
|
+
div.repl-toolbar {
|
|
210
|
+
display: flex;
|
|
211
|
+
align-items: center;
|
|
212
|
+
justify-content: space-between;
|
|
213
|
+
gap: calc(var(--repl-spacing) * 3);
|
|
214
|
+
padding-left: calc(5 * var(--repl-spacing));
|
|
215
|
+
padding-right: calc(var(--repl-spacing) * 2);
|
|
216
|
+
padding-block: calc(var(--repl-spacing) * 1.5);
|
|
217
|
+
border-top-left-radius: var(--repl-radius);
|
|
218
|
+
border-top-right-radius: var(--repl-radius);
|
|
219
|
+
min-height: 36px;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
div.repl-toolbar--actions {
|
|
223
|
+
display: flex;
|
|
224
|
+
align-items: center;
|
|
225
|
+
gap: calc(var(--repl-spacing) * 2);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.sub-toolbar button {
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
div button.repl-btn--icon {
|
|
232
|
+
background: none;
|
|
233
|
+
border: none;
|
|
234
|
+
cursor: pointer;
|
|
235
|
+
display: flex;
|
|
236
|
+
align-self: center;
|
|
237
|
+
justify-content: center;
|
|
238
|
+
font-size: 0.875rem;
|
|
239
|
+
border-radius: 0.375rem;
|
|
240
|
+
transition: background-color 0.2s ease;
|
|
241
|
+
padding: 8px;
|
|
242
|
+
color: var(--repl-secondary);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
div button.repl-btn--icon:hover {
|
|
246
|
+
color: var(--repl-primary);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
div button.repl-btn--icon :global(svg) {
|
|
250
|
+
height: 20px;
|
|
251
|
+
width: 20px;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
.repl-toolbar--title {
|
|
255
|
+
display: flex;
|
|
256
|
+
align-items: center;
|
|
257
|
+
gap: calc(var(--repl-spacing) * 2);
|
|
258
|
+
font-weight: 600;
|
|
259
|
+
color: var(--repl-secondary);
|
|
260
|
+
max-width: 80%;
|
|
261
|
+
min-width: 0;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.repl-toolbar--title span {
|
|
265
|
+
overflow: hidden;
|
|
266
|
+
text-overflow: ellipsis;
|
|
267
|
+
white-space: nowrap;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.repl-toolbar--title .toolbar-icon {
|
|
271
|
+
width: 20px;
|
|
272
|
+
height: 20px;
|
|
273
|
+
object-fit: contain;
|
|
274
|
+
flex-shrink: 0;
|
|
275
|
+
}
|
|
276
|
+
|
|
169
277
|
.repl-content {
|
|
170
278
|
display: flow-root;
|
|
171
279
|
margin-top: calc(var(--repl-spacing) * 0);
|
|
@@ -192,4 +300,40 @@
|
|
|
192
300
|
white-space: pre-wrap;
|
|
193
301
|
word-break: break-word;
|
|
194
302
|
}
|
|
303
|
+
|
|
304
|
+
.sub-toolbar {
|
|
305
|
+
display: flex;
|
|
306
|
+
gap: calc(var(--repl-spacing) * 2);
|
|
307
|
+
padding-left: calc(5 * var(--repl-spacing));
|
|
308
|
+
padding-right: calc(5 * var(--repl-spacing));
|
|
309
|
+
padding-block: calc(var(--repl-spacing) * 2);
|
|
310
|
+
overflow-x: auto;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
.file-tab {
|
|
314
|
+
display: flex;
|
|
315
|
+
align-items: center;
|
|
316
|
+
gap: calc(var(--repl-spacing) * 2);
|
|
317
|
+
padding: calc(var(--repl-spacing) * 2) calc(var(--repl-spacing) * 3);
|
|
318
|
+
border-radius: 0.375rem;
|
|
319
|
+
font-size: 0.875rem;
|
|
320
|
+
transition: all 0.2s ease;
|
|
321
|
+
border: 1px solid transparent;
|
|
322
|
+
white-space: nowrap;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.file-tab:hover {
|
|
326
|
+
background-color: #f5f5f5;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
.file-tab.active {
|
|
330
|
+
background-color: #f0f0f0;
|
|
331
|
+
border-color: #d0d0d0;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
.file-icon {
|
|
335
|
+
width: 16px;
|
|
336
|
+
height: 16px;
|
|
337
|
+
object-fit: contain;
|
|
338
|
+
}
|
|
195
339
|
</style>
|
package/dist/Repl.svelte.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
declare const Repl: import("svelte").Component<{
|
|
2
|
+
title: any;
|
|
3
|
+
content: any;
|
|
4
|
+
children: any;
|
|
5
|
+
}, {}, "">;
|
|
3
6
|
type Repl = ReturnType<typeof Repl>;
|
|
4
7
|
export default Repl;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-check-icon lucide-check"><path d="M20 6 9 17l-5-5"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-code-icon lucide-code"><path d="m16 18 6-6-6-6"/><path d="m8 6-6 6 6 6"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-codesandbox-icon lucide-codesandbox"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/><polyline points="7.5 4.21 12 6.81 16.5 4.21"/><polyline points="7.5 19.79 7.5 14.6 3 12"/><polyline points="21 12 16.5 14.6 16.5 19.79"/><polyline points="3.27 6.96 12 12.01 20.73 6.96"/><line x1="12" x2="12" y1="22.08" y2="12"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-copy-icon lucide-copy"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>
|
package/dist/utils.d.ts
CHANGED
package/dist/utils.js
CHANGED
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
import javascript from './languages/javascript.svg';
|
|
2
|
-
import typescript from './languages/typescript.svg';
|
|
3
|
-
import svelte from './languages/svelte.svg';
|
|
4
|
-
import css from './languages/css.svg';
|
|
5
|
-
import html from './languages/html.svg';
|
|
6
|
-
import shell from './languages/shell.svg';
|
|
7
1
|
export const copyToClipboard = (value) => {
|
|
8
2
|
if (navigator.clipboard && window.isSecureContext) {
|
|
9
3
|
navigator.clipboard
|
|
@@ -34,28 +28,3 @@ export const copyToClipboard = (value) => {
|
|
|
34
28
|
document.body.removeChild(zoneTexte);
|
|
35
29
|
}
|
|
36
30
|
};
|
|
37
|
-
export const dictionary = {
|
|
38
|
-
javascript: ['js', 'javascript'],
|
|
39
|
-
typescript: ['ts', 'typescript'],
|
|
40
|
-
svelte: ['svelte', 'svelte.ts', 'svelte.js'],
|
|
41
|
-
css: ['css', 'scss', 'less'],
|
|
42
|
-
html: ['html', 'htm'],
|
|
43
|
-
json: ['json'],
|
|
44
|
-
shell: ['bash', 'sh', 'shell']
|
|
45
|
-
};
|
|
46
|
-
export const dictionaryIcons = {
|
|
47
|
-
js: javascript,
|
|
48
|
-
ts: typescript,
|
|
49
|
-
'svelte.ts': svelte,
|
|
50
|
-
'svelte.js': svelte,
|
|
51
|
-
svelte: svelte,
|
|
52
|
-
shell: shell,
|
|
53
|
-
bash: shell,
|
|
54
|
-
sh: shell,
|
|
55
|
-
css: css,
|
|
56
|
-
scss: css,
|
|
57
|
-
less: css,
|
|
58
|
-
html: html,
|
|
59
|
-
htm: html,
|
|
60
|
-
json: shell
|
|
61
|
-
};
|
package/package.json
CHANGED
package/dist/Button.svelte
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
let { children, ...rest } = $props();
|
|
3
|
-
</script>
|
|
4
|
-
|
|
5
|
-
<button {...rest}>
|
|
6
|
-
{@render children?.()}
|
|
7
|
-
</button>
|
|
8
|
-
|
|
9
|
-
<style>
|
|
10
|
-
button {
|
|
11
|
-
background: none;
|
|
12
|
-
border: none;
|
|
13
|
-
cursor: pointer;
|
|
14
|
-
display: flex;
|
|
15
|
-
align-self: center;
|
|
16
|
-
justify-content: center;
|
|
17
|
-
font-size: 0.875rem;
|
|
18
|
-
border-radius: 0.375rem;
|
|
19
|
-
transition: background-color 0.2s ease;
|
|
20
|
-
padding: 8px;
|
|
21
|
-
color: var(--repl-secondary);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
button:hover {
|
|
25
|
-
color: var(--repl-primary);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
button :global(svg) {
|
|
29
|
-
height: 20px;
|
|
30
|
-
width: 20px;
|
|
31
|
-
}
|
|
32
|
-
</style>
|
package/dist/Button.svelte.d.ts
DELETED
package/dist/Files.svelte
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { FilesProps } from './types.js';
|
|
3
|
-
import { dictionaryIcons } from './utils.js';
|
|
4
|
-
|
|
5
|
-
let { files, activeIndex = $bindable() }: FilesProps = $props();
|
|
6
|
-
</script>
|
|
7
|
-
|
|
8
|
-
{#if files && files.length > 1}
|
|
9
|
-
<div>
|
|
10
|
-
{#each files as file, index (index)}
|
|
11
|
-
<button class:active={activeIndex === index} onclick={() => (activeIndex = index)}>
|
|
12
|
-
{#if file.lang && dictionaryIcons[file.lang]}
|
|
13
|
-
<img src={dictionaryIcons[file.lang]} alt="{file.lang} icon" />
|
|
14
|
-
{/if}
|
|
15
|
-
<span>{file.name}</span>
|
|
16
|
-
</button>
|
|
17
|
-
{/each}
|
|
18
|
-
</div>
|
|
19
|
-
|
|
20
|
-
<hr />
|
|
21
|
-
{/if}
|
|
22
|
-
|
|
23
|
-
<style>
|
|
24
|
-
div {
|
|
25
|
-
display: flex;
|
|
26
|
-
gap: calc(var(--repl-spacing) * 2);
|
|
27
|
-
padding-left: calc(5 * var(--repl-spacing));
|
|
28
|
-
padding-right: calc(5 * var(--repl-spacing));
|
|
29
|
-
padding-block: calc(var(--repl-spacing) * 2);
|
|
30
|
-
overflow-x: auto;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
button {
|
|
34
|
-
display: flex;
|
|
35
|
-
align-items: center;
|
|
36
|
-
gap: calc(var(--repl-spacing) * 2);
|
|
37
|
-
padding: calc(var(--repl-spacing) * 2) calc(var(--repl-spacing) * 3);
|
|
38
|
-
border-radius: 0.375rem;
|
|
39
|
-
font-size: 0.875rem;
|
|
40
|
-
transition: all 0.2s ease;
|
|
41
|
-
border: 1px solid transparent;
|
|
42
|
-
white-space: nowrap;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
button img {
|
|
46
|
-
width: 16px;
|
|
47
|
-
height: 16px;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
button:hover {
|
|
51
|
-
background-color: #f5f5f5;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
button.active {
|
|
55
|
-
background-color: #f0f0f0;
|
|
56
|
-
border-color: #d0d0d0;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
hr {
|
|
60
|
-
max-width: calc(100% - 4.5rem);
|
|
61
|
-
margin-inline-start: calc(4.5rem / 2);
|
|
62
|
-
display: block;
|
|
63
|
-
border: thin solid var(--repl-border-color);
|
|
64
|
-
margin-top: 0;
|
|
65
|
-
margin-bottom: 0;
|
|
66
|
-
}
|
|
67
|
-
</style>
|
package/dist/Files.svelte.d.ts
DELETED
package/dist/Toolbar.svelte
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { ToolbarProps } from './types.js';
|
|
3
|
-
import Button from './Button.svelte';
|
|
4
|
-
import { dictionary } from './utils.js';
|
|
5
|
-
import { Copy, Check, Code, Codesandbox, Moon, Sun } from '@lucide/svelte';
|
|
6
|
-
|
|
7
|
-
let {
|
|
8
|
-
title,
|
|
9
|
-
language,
|
|
10
|
-
presentation,
|
|
11
|
-
copyState = $bindable(),
|
|
12
|
-
viewState = $bindable(),
|
|
13
|
-
themeState = $bindable(),
|
|
14
|
-
modeState = $bindable()
|
|
15
|
-
}: ToolbarProps = $props();
|
|
16
|
-
|
|
17
|
-
let languageKey = $derived(
|
|
18
|
-
Object.entries(dictionary).find(([, values]) => values.includes(language))?.[0] || language
|
|
19
|
-
);
|
|
20
|
-
</script>
|
|
21
|
-
|
|
22
|
-
<div class="lpk-repl--toolbar">
|
|
23
|
-
<div class="lpk-repl--toolbar-title">
|
|
24
|
-
{#if title}
|
|
25
|
-
<span>{title}</span>
|
|
26
|
-
{:else if language}
|
|
27
|
-
<span>{languageKey}</span>
|
|
28
|
-
{/if}
|
|
29
|
-
</div>
|
|
30
|
-
|
|
31
|
-
<div class="lpk-repl--toolbar-actions">
|
|
32
|
-
{#if (modeState !== 'code' && viewState === 'preview') || presentation}
|
|
33
|
-
<Button onclick={() => (themeState = themeState === 'light' ? 'dark' : 'light')}>
|
|
34
|
-
{#if themeState === 'light'}
|
|
35
|
-
<Moon />
|
|
36
|
-
{:else}
|
|
37
|
-
<Sun />
|
|
38
|
-
{/if}
|
|
39
|
-
</Button>
|
|
40
|
-
{/if}
|
|
41
|
-
|
|
42
|
-
{#if modeState === 'mixed' && !presentation}
|
|
43
|
-
<Button onclick={() => (viewState = viewState === 'code' ? 'preview' : 'code')}>
|
|
44
|
-
{#if viewState === 'code'}
|
|
45
|
-
<Code />
|
|
46
|
-
{:else}
|
|
47
|
-
<Codesandbox />
|
|
48
|
-
{/if}
|
|
49
|
-
</Button>
|
|
50
|
-
{/if}
|
|
51
|
-
|
|
52
|
-
{#if modeState !== 'playground'}
|
|
53
|
-
<Button onclick={() => (copyState = true)}>
|
|
54
|
-
{#if copyState}
|
|
55
|
-
<Check />
|
|
56
|
-
{:else}
|
|
57
|
-
<Copy />
|
|
58
|
-
{/if}
|
|
59
|
-
</Button>
|
|
60
|
-
{/if}
|
|
61
|
-
</div>
|
|
62
|
-
</div>
|
|
63
|
-
|
|
64
|
-
<style>
|
|
65
|
-
.lpk-repl--toolbar {
|
|
66
|
-
display: flex;
|
|
67
|
-
align-items: center;
|
|
68
|
-
justify-content: space-between;
|
|
69
|
-
gap: calc(var(--repl-spacing) * 3);
|
|
70
|
-
padding-left: calc(5 * var(--repl-spacing));
|
|
71
|
-
padding-right: calc(var(--repl-spacing) * 2);
|
|
72
|
-
padding-block: calc(var(--repl-spacing) * 1.5);
|
|
73
|
-
border-top-left-radius: var(--repl-radius);
|
|
74
|
-
border-top-right-radius: var(--repl-radius);
|
|
75
|
-
min-height: 36px;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
.lpk-repl--toolbar .lpk-repl--toolbar-title {
|
|
79
|
-
display: flex;
|
|
80
|
-
align-items: center;
|
|
81
|
-
gap: calc(var(--repl-spacing) * 2);
|
|
82
|
-
font-weight: 600;
|
|
83
|
-
color: var(--repl-secondary);
|
|
84
|
-
max-width: 80%;
|
|
85
|
-
min-width: 0;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
.lpk-repl--toolbar .lpk-repl--toolbar-actions {
|
|
89
|
-
display: flex;
|
|
90
|
-
align-items: center;
|
|
91
|
-
gap: calc(var(--repl-spacing) * 2);
|
|
92
|
-
}
|
|
93
|
-
</style>
|
package/dist/Toolbar.svelte.d.ts
DELETED
package/dist/types.d.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import type { Snippet } from 'svelte';
|
|
2
|
-
export interface ReplProps {
|
|
3
|
-
title?: string;
|
|
4
|
-
content?: string | Record<string, string | Record<string, unknown>>;
|
|
5
|
-
children?: Snippet;
|
|
6
|
-
presentation?: boolean;
|
|
7
|
-
}
|
|
8
|
-
export interface ToolbarProps {
|
|
9
|
-
title?: string;
|
|
10
|
-
language: string;
|
|
11
|
-
copyState?: boolean;
|
|
12
|
-
presentation?: boolean;
|
|
13
|
-
viewState?: 'code' | 'preview';
|
|
14
|
-
themeState?: 'light' | 'dark';
|
|
15
|
-
modeState?: 'code' | 'playground' | 'mixed';
|
|
16
|
-
}
|
|
17
|
-
export interface FilesProps {
|
|
18
|
-
files?: FileItem[];
|
|
19
|
-
activeIndex: number;
|
|
20
|
-
}
|
|
21
|
-
export interface FileItem {
|
|
22
|
-
name: string;
|
|
23
|
-
content: string;
|
|
24
|
-
lang?: string;
|
|
25
|
-
}
|
package/dist/types.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|