@atom-forge/brickee 0.0.1 → 0.0.2
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/CHANGELOG.md +19 -1
- package/README-AI.md +24 -21
- package/dist/Editor.svelte +52 -64
- package/dist/Editor.svelte.d.ts +0 -3
- package/dist/LinkPrompt.svelte +3 -3
- package/dist/Preview.svelte +1 -5
- package/dist/Preview.svelte.d.ts +0 -3
- package/dist/PropsBar.svelte +120 -110
- package/dist/PropsBar.svelte.d.ts +0 -3
- package/dist/code.d.ts +12 -0
- package/dist/code.js +15 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/kit/Empty.svelte +2 -2
- package/dist/kit/Frame.svelte +3 -3
- package/dist/locales/hu.js +2 -7
- package/dist/markdown.d.ts +0 -2
- package/dist/markdown.js +1 -1
- package/dist/plugins/Gap.svelte +1 -1
- package/dist/plugins/Map.svelte +1 -1
- package/dist/plugins/Table.svelte +36 -62
- package/dist/plugins/TablePreview.svelte +2 -2
- package/dist/plugins/YouTubePreview.svelte +1 -1
- package/dist/plugins/index.js +12 -1
- package/dist/schema.js +1 -1
- package/dist/types.d.ts +6 -7
- package/docs/en/bundled-plugins.md +1 -1
- package/docs/en/documents-and-markdown.md +4 -5
- package/docs/en/editor-and-preview.md +1 -3
- package/docs/en/getting-started.md +6 -2
- package/docs/en/host-contexts.md +26 -132
- package/docs/en/index.md +4 -4
- package/docs/en/recipes-and-pitfalls.md +10 -9
- package/docs/en/upgrading.md +20 -4
- package/docs/en/writing-plugins.md +111 -11
- package/docs/hu/bundled-plugins.md +1 -1
- package/docs/hu/documents-and-markdown.md +4 -5
- package/docs/hu/editor-and-preview.md +1 -3
- package/docs/hu/getting-started.md +6 -2
- package/docs/hu/host-contexts.md +26 -132
- package/docs/hu/index.md +4 -4
- package/docs/hu/recipes-and-pitfalls.md +10 -9
- package/docs/hu/upgrading.md +20 -4
- package/docs/hu/writing-plugins.md +111 -11
- package/package.json +6 -2
- package/dist/ImagePicker.svelte +0 -131
- package/dist/ImagePicker.svelte.d.ts +0 -13
- package/dist/media.d.ts +0 -17
- package/dist/media.js +0 -12
package/dist/PropsBar.svelte
CHANGED
|
@@ -1,31 +1,27 @@
|
|
|
1
|
-
<!-- The fields of a plugin block, on the top of its box. Closed: only a small header (the block's
|
|
2
|
-
opens the fields in place: a wrapping row (label and control side by side), text areas on their
|
|
3
|
-
|
|
1
|
+
<!-- The fields of a plugin block (or a code block), on the top of its box. Closed: only a small header (the block's
|
|
2
|
+
tag); a click on it opens the fields in place: a wrapping row (label and control side by side), text areas on their
|
|
3
|
+
own full-width rows. -->
|
|
4
4
|
<script lang="ts">
|
|
5
|
-
import { ColorPicker, Input, NativeSelect, Slider, Textarea
|
|
5
|
+
import { ColorPicker, Input, NativeSelect, Slider, Textarea } from '@atom-forge/ui';
|
|
6
6
|
import ChevronDown from '@lucide/svelte/icons/chevron-down';
|
|
7
7
|
import { slide } from 'svelte/transition';
|
|
8
|
-
import ImagePicker from './ImagePicker.svelte';
|
|
9
8
|
import { useView } from './view';
|
|
10
9
|
import type { Translate } from './i18n';
|
|
11
|
-
import type { MediaItem } from './media';
|
|
12
10
|
import type { Block, PropField } from './types';
|
|
13
11
|
|
|
14
12
|
interface Props {
|
|
15
13
|
block: Block;
|
|
16
14
|
tag: string;
|
|
17
15
|
fields: PropField[];
|
|
18
|
-
media: MediaItem[];
|
|
19
16
|
tr: Translate;
|
|
20
17
|
/** Sets one property from its field's text and returns the text as it is now kept. */
|
|
21
18
|
setProp: (b: Block, f: PropField, raw: string) => string;
|
|
22
19
|
/** Sets one property to a value as it is ('' or undefined removes it). */
|
|
23
20
|
setValue: (b: Block, key: string, v: unknown) => void;
|
|
24
|
-
pickMedia: (b: Block, f: PropField, id: string) => void;
|
|
25
21
|
/** Start with the fields open (a block just made). */
|
|
26
22
|
open?: boolean;
|
|
27
23
|
}
|
|
28
|
-
let { block, tag, fields,
|
|
24
|
+
let { block, tag, fields, tr, setProp, setValue, open: startOpen = false }: Props = $props();
|
|
29
25
|
// svelte-ignore state_referenced_locally
|
|
30
26
|
let open = $state(startOpen);
|
|
31
27
|
|
|
@@ -33,10 +29,18 @@
|
|
|
33
29
|
const v = block.props?.[f.key];
|
|
34
30
|
return f.format ? f.format(v) : v == null ? '' : String(v);
|
|
35
31
|
};
|
|
36
|
-
|
|
32
|
+
/** A text field's placeholder: its label, and its own placeholder (an example) after it. */
|
|
33
|
+
const hint = (f: PropField) => [tr(f.label), f.placeholder && tr(f.placeholder)].filter(Boolean).join(' · ');
|
|
34
|
+
/** Toggles: the values switched on, kept in the order of the options. */
|
|
35
|
+
const toggled = (f: PropField): string[] => {
|
|
37
36
|
const v = block.props?.[f.key];
|
|
38
|
-
return Array.isArray(v) ? v
|
|
37
|
+
return Array.isArray(v) ? v.map(String) : [];
|
|
39
38
|
};
|
|
39
|
+
function toggle(f: PropField, value: string) {
|
|
40
|
+
const on = new Set(toggled(f));
|
|
41
|
+
if (!on.delete(value)) on.add(value);
|
|
42
|
+
setValue(block, f.key, (f.options ?? []).map((o) => o.value).filter((x) => on.has(x)));
|
|
43
|
+
}
|
|
40
44
|
const optionLabel = (f: PropField, i: number) => {
|
|
41
45
|
const opt = f.options?.[i];
|
|
42
46
|
return opt ? tr(opt.label, { n: opt.value }) : '';
|
|
@@ -107,19 +111,9 @@
|
|
|
107
111
|
|
|
108
112
|
const short = $derived(fields.filter((f) => f.kind !== 'textarea'));
|
|
109
113
|
const long = $derived(fields.filter((f) => f.kind === 'textarea'));
|
|
110
|
-
|
|
111
|
-
const popups = getPopupManager();
|
|
112
|
-
const urlOf = (id: string) => media.find((m) => m.id === id);
|
|
113
|
-
function openPicker(e: MouseEvent, f: PropField) {
|
|
114
|
-
popups.open.component(
|
|
115
|
-
ImagePicker,
|
|
116
|
-
{ media, multiple: f.kind === 'images', getPicked: () => picked(f), pick: (id: string) => pickMedia(block, f, id), tr },
|
|
117
|
-
{ anchor: e, align: 'left' }
|
|
118
|
-
);
|
|
119
|
-
}
|
|
120
114
|
</script>
|
|
121
115
|
|
|
122
|
-
<div class="
|
|
116
|
+
<div class="bar" class:open>
|
|
123
117
|
<button type="button" class="head" aria-expanded={open} title={tr(open ? 'Hide settings' : 'Settings')} onmousedown={(e) => e.preventDefault()} onclick={() => (open = !open)}>
|
|
124
118
|
<span class="tag">{tag}</span>
|
|
125
119
|
<ChevronDown size={13} class="chev" />
|
|
@@ -128,36 +122,46 @@
|
|
|
128
122
|
<div class="body" transition:slide={{ duration: 180 }}>
|
|
129
123
|
<div class="grid">
|
|
130
124
|
{#each short as f (f.key)}
|
|
131
|
-
{#if f.kind === '
|
|
132
|
-
|
|
133
|
-
<
|
|
134
|
-
<span class="
|
|
135
|
-
<
|
|
136
|
-
|
|
137
|
-
{@const m = urlOf(id)}
|
|
138
|
-
{#if m}<img src={m.url} alt={m.name} />{:else}<span class="missing" title={id}>?</span>{/if}
|
|
139
|
-
{#if f.kind === 'images' && n === 5 && ids.length > 6}<span class="more">+{ids.length - 6}</span>{/if}
|
|
140
|
-
{:else}
|
|
141
|
-
<span class="empty">{tr('Choose…')}</span>
|
|
142
|
-
{/each}
|
|
143
|
-
</button>
|
|
144
|
-
</div>
|
|
125
|
+
{#if f.kind === 'text'}
|
|
126
|
+
<!-- the field shows the value as kept (a YouTube link becomes its id); its label is the placeholder -->
|
|
127
|
+
<label class="field" title={tr(f.label)}>
|
|
128
|
+
<span class="sr">{tr(f.label)}</span>
|
|
129
|
+
<Input small monospace placeholder={hint(f)} bind:value={() => text(f), (v: string) => setProp(block, f, v)} />
|
|
130
|
+
</label>
|
|
145
131
|
{:else}
|
|
146
|
-
<!-- not a label around buttons (a slider's view buttons, a colour's clear): a click on a label goes to its first button -->
|
|
147
|
-
<svelte:element this={f.kind === '
|
|
132
|
+
<!-- not a label around buttons (a slider's view buttons, a colour's clear, toggles): a click on a label goes to its first button -->
|
|
133
|
+
<svelte:element this={f.kind === 'select' ? 'label' : 'div'} class="field inline" role={f.kind === 'toggles' ? 'group' : undefined} aria-label={f.kind === 'toggles' ? tr(f.label) : undefined}>
|
|
148
134
|
<span class="name"
|
|
149
135
|
>{tr(f.label)}{#if viewLabel(f)}<span class="view" class:own={current(f).mine}>{viewLabel(f)}</span>{/if}</span
|
|
150
136
|
>
|
|
151
137
|
{#if f.kind === 'select'}
|
|
152
138
|
<NativeSelect
|
|
139
|
+
small
|
|
153
140
|
options={(f.options ?? []).map((opt) => ({ value: opt.value, label: tr(opt.label, { n: opt.value }) }))}
|
|
154
141
|
bind:value={() => text(f), (v: string) => setProp(block, f, v)}
|
|
155
142
|
/>
|
|
143
|
+
{:else if f.kind === 'toggles'}
|
|
144
|
+
{@const on = toggled(f)}
|
|
145
|
+
<span class="toggles">
|
|
146
|
+
{#each f.options ?? [] as opt (opt.value)}
|
|
147
|
+
<button
|
|
148
|
+
type="button"
|
|
149
|
+
class="toggle"
|
|
150
|
+
class:on={on.includes(opt.value)}
|
|
151
|
+
aria-pressed={on.includes(opt.value)}
|
|
152
|
+
title={tr(opt.label)}
|
|
153
|
+
aria-label={tr(opt.label)}
|
|
154
|
+
onmousedown={(e) => e.preventDefault()}
|
|
155
|
+
onclick={() => toggle(f, opt.value)}
|
|
156
|
+
>{#if opt.icon}<opt.icon size={15} />{:else}{tr(opt.label)}{/if}</button
|
|
157
|
+
>
|
|
158
|
+
{/each}
|
|
159
|
+
</span>
|
|
156
160
|
{:else if f.kind === 'slider'}
|
|
157
161
|
<span class="line">
|
|
158
162
|
<span class="slider">
|
|
159
163
|
<Slider
|
|
160
|
-
|
|
164
|
+
small
|
|
161
165
|
drawStops={!free(f) && (f.options?.length ?? 0) <= 10}
|
|
162
166
|
min={free(f) ? low(f) : 0}
|
|
163
167
|
max={free(f) ? f.max : (f.options?.length ?? 1) - 1}
|
|
@@ -175,25 +179,23 @@
|
|
|
175
179
|
<span class="swatch" aria-hidden="true"></span>{tr(f.none)}
|
|
176
180
|
</button>
|
|
177
181
|
{:else}
|
|
178
|
-
<ColorPicker bind:value={() => text(f) || '#000000', (v: string) => setProp(block, f, v)} />
|
|
182
|
+
<ColorPicker small bind:value={() => text(f) || '#000000', (v: string) => setProp(block, f, v)} />
|
|
179
183
|
{#if f.none}
|
|
180
184
|
<button type="button" class="clear" title={tr(f.none)} aria-label={tr(f.none)} onclick={() => setProp(block, f, '')}>×</button>
|
|
181
185
|
{/if}
|
|
182
186
|
{/if}
|
|
183
187
|
</span>
|
|
184
|
-
{:else}
|
|
185
|
-
<!-- the field shows the value as kept (a YouTube link becomes its id) -->
|
|
186
|
-
<Input monospace placeholder={f.placeholder && tr(f.placeholder)} bind:value={() => text(f), (v: string) => setProp(block, f, v)} />
|
|
187
188
|
{/if}
|
|
188
189
|
</svelte:element>
|
|
189
190
|
{/if}
|
|
190
191
|
{/each}
|
|
191
192
|
{#each long as f (f.key)}
|
|
192
|
-
<label class="field long" onfocusin={() => (editing = { key: f.key, text: text(f) })} onfocusout={() => (editing = null)}>
|
|
193
|
-
<span class="
|
|
193
|
+
<label class="field long" title={tr(f.label)} onfocusin={() => (editing = { key: f.key, text: text(f) })} onfocusout={() => (editing = null)}>
|
|
194
|
+
<span class="sr">{tr(f.label)}</span>
|
|
194
195
|
<Textarea
|
|
195
|
-
|
|
196
|
-
|
|
196
|
+
small
|
|
197
|
+
rows={2}
|
|
198
|
+
placeholder={hint(f)}
|
|
197
199
|
bind:value={() => (editing?.key === f.key ? editing.text : text(f)), (v: string) => {
|
|
198
200
|
if (editing?.key === f.key) editing.text = v;
|
|
199
201
|
setProp(block, f, v);
|
|
@@ -214,12 +216,12 @@
|
|
|
214
216
|
margin-bottom: 4px;
|
|
215
217
|
border-radius: 8px;
|
|
216
218
|
font: 12px/1.4 system-ui, sans-serif;
|
|
217
|
-
color: #1d1d1f;
|
|
219
|
+
color: var(--color-surface-contrast, #1d1d1f);
|
|
218
220
|
}
|
|
219
221
|
.bar.open {
|
|
220
222
|
justify-items: stretch;
|
|
221
223
|
margin-bottom: 8px;
|
|
222
|
-
padding: 8px
|
|
224
|
+
padding: 6px 8px 8px;
|
|
223
225
|
background: rgba(120, 120, 140, 0.07);
|
|
224
226
|
}
|
|
225
227
|
.bar {
|
|
@@ -227,12 +229,13 @@
|
|
|
227
229
|
padding 0.18s,
|
|
228
230
|
background 0.18s;
|
|
229
231
|
}
|
|
230
|
-
/* the fields in
|
|
232
|
+
/* the fields in columns as wide as the box allows; text fields carry their label as placeholder, the others a short
|
|
233
|
+
label beside the control */
|
|
231
234
|
.grid {
|
|
232
235
|
display: grid;
|
|
233
|
-
grid-template-columns: repeat(auto-fill, minmax(
|
|
234
|
-
gap:
|
|
235
|
-
padding-top:
|
|
236
|
+
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
|
|
237
|
+
gap: 6px 10px;
|
|
238
|
+
padding-top: 6px;
|
|
236
239
|
}
|
|
237
240
|
.head {
|
|
238
241
|
display: flex;
|
|
@@ -241,13 +244,13 @@
|
|
|
241
244
|
padding: 0;
|
|
242
245
|
border: 0;
|
|
243
246
|
background: none;
|
|
244
|
-
color: #8e8e96;
|
|
247
|
+
color: var(--color-muted-contrast, #8e8e96);
|
|
245
248
|
cursor: pointer;
|
|
246
249
|
justify-self: start;
|
|
247
250
|
}
|
|
248
251
|
.head:hover .tag {
|
|
249
252
|
background: rgba(120, 120, 140, 0.2);
|
|
250
|
-
color: #1d1d1f;
|
|
253
|
+
color: var(--color-surface-contrast, #1d1d1f);
|
|
251
254
|
}
|
|
252
255
|
.head :global(.chev) {
|
|
253
256
|
transition: rotate 0.15s;
|
|
@@ -259,7 +262,7 @@
|
|
|
259
262
|
padding: 1px 6px;
|
|
260
263
|
border-radius: 5px;
|
|
261
264
|
background: rgba(120, 120, 140, 0.12);
|
|
262
|
-
color: #6e6e76;
|
|
265
|
+
color: var(--color-muted-contrast, #6e6e76);
|
|
263
266
|
font: 500 11px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
264
267
|
white-space: nowrap;
|
|
265
268
|
user-select: none;
|
|
@@ -267,9 +270,56 @@
|
|
|
267
270
|
.field {
|
|
268
271
|
display: grid;
|
|
269
272
|
align-content: start;
|
|
270
|
-
gap: 4px;
|
|
271
273
|
min-width: 0;
|
|
272
274
|
}
|
|
275
|
+
.field.inline {
|
|
276
|
+
grid-template-columns: auto minmax(0, 1fr);
|
|
277
|
+
align-items: center;
|
|
278
|
+
gap: 8px;
|
|
279
|
+
}
|
|
280
|
+
/* compact controls: the bar's small type in the inputs too */
|
|
281
|
+
.field :global(input:not([type='range'])),
|
|
282
|
+
.field :global(textarea),
|
|
283
|
+
.field :global(select) {
|
|
284
|
+
font-size: 12px;
|
|
285
|
+
}
|
|
286
|
+
/* the label of a field whose placeholder shows it */
|
|
287
|
+
.sr {
|
|
288
|
+
position: absolute;
|
|
289
|
+
width: 1px;
|
|
290
|
+
height: 1px;
|
|
291
|
+
overflow: hidden;
|
|
292
|
+
clip-path: inset(50%);
|
|
293
|
+
white-space: nowrap;
|
|
294
|
+
}
|
|
295
|
+
.toggles {
|
|
296
|
+
display: inline-flex;
|
|
297
|
+
justify-self: start;
|
|
298
|
+
gap: 1px;
|
|
299
|
+
padding: 2px;
|
|
300
|
+
border-radius: 7px;
|
|
301
|
+
background: var(--color-muted, #f4f4f6);
|
|
302
|
+
}
|
|
303
|
+
.toggle {
|
|
304
|
+
display: inline-grid;
|
|
305
|
+
place-items: center;
|
|
306
|
+
min-width: 26px;
|
|
307
|
+
height: 24px;
|
|
308
|
+
padding: 0 4px;
|
|
309
|
+
border: 0;
|
|
310
|
+
border-radius: 5px;
|
|
311
|
+
background: none;
|
|
312
|
+
color: var(--color-muted-contrast, #6e6e76);
|
|
313
|
+
cursor: pointer;
|
|
314
|
+
}
|
|
315
|
+
.toggle:hover {
|
|
316
|
+
color: var(--color-surface-contrast, #1d1d1f);
|
|
317
|
+
}
|
|
318
|
+
.toggle.on {
|
|
319
|
+
background: var(--color-surface, #fff);
|
|
320
|
+
color: #3b82f6;
|
|
321
|
+
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
|
|
322
|
+
}
|
|
273
323
|
/* text areas take a whole row */
|
|
274
324
|
.field.long {
|
|
275
325
|
grid-column: 1 / -1;
|
|
@@ -283,7 +333,7 @@
|
|
|
283
333
|
.name {
|
|
284
334
|
font-size: 11.5px;
|
|
285
335
|
font-weight: 600;
|
|
286
|
-
color: #8e8e96;
|
|
336
|
+
color: var(--color-muted-contrast, #8e8e96);
|
|
287
337
|
white-space: nowrap;
|
|
288
338
|
user-select: none;
|
|
289
339
|
}
|
|
@@ -291,15 +341,15 @@
|
|
|
291
341
|
.view {
|
|
292
342
|
margin-left: 6px;
|
|
293
343
|
padding: 0 5px;
|
|
294
|
-
border: 1px dashed #c8c8d0;
|
|
344
|
+
border: 1px dashed var(--color-frame, #c8c8d0);
|
|
295
345
|
border-radius: 4px;
|
|
296
|
-
color: #6e6e76;
|
|
346
|
+
color: var(--color-muted-contrast, #6e6e76);
|
|
297
347
|
font-weight: 500;
|
|
298
348
|
}
|
|
299
349
|
.view.own {
|
|
300
350
|
border-style: solid;
|
|
301
|
-
border-color: #1d1d1f;
|
|
302
|
-
color: #1d1d1f;
|
|
351
|
+
border-color: var(--color-surface-contrast, #1d1d1f);
|
|
352
|
+
color: var(--color-surface-contrast, #1d1d1f);
|
|
303
353
|
}
|
|
304
354
|
.slider {
|
|
305
355
|
display: block;
|
|
@@ -308,7 +358,7 @@
|
|
|
308
358
|
}
|
|
309
359
|
.value {
|
|
310
360
|
min-width: 4.5em;
|
|
311
|
-
color: #3a3a40;
|
|
361
|
+
color: var(--color-surface-contrast, #3a3a40);
|
|
312
362
|
font-variant-numeric: tabular-nums;
|
|
313
363
|
white-space: nowrap;
|
|
314
364
|
}
|
|
@@ -318,21 +368,21 @@
|
|
|
318
368
|
gap: 6px;
|
|
319
369
|
height: 30px;
|
|
320
370
|
padding: 0 10px 0 6px;
|
|
321
|
-
border: 1px dashed #c8c8d0;
|
|
371
|
+
border: 1px dashed var(--color-frame, #c8c8d0);
|
|
322
372
|
border-radius: 7px;
|
|
323
|
-
background: #fff;
|
|
324
|
-
color: #8e8e96;
|
|
373
|
+
background: var(--color-surface, #fff);
|
|
374
|
+
color: var(--color-muted-contrast, #8e8e96);
|
|
325
375
|
cursor: pointer;
|
|
326
376
|
}
|
|
327
377
|
.nocolor:hover {
|
|
328
378
|
border-color: var(--color-accent, #ea580c);
|
|
329
|
-
color: #3a3a40;
|
|
379
|
+
color: var(--color-surface-contrast, #3a3a40);
|
|
330
380
|
}
|
|
331
381
|
/* an empty swatch, struck through */
|
|
332
382
|
.swatch {
|
|
333
383
|
width: 16px;
|
|
334
384
|
height: 16px;
|
|
335
|
-
border: 1px solid #c8c8d0;
|
|
385
|
+
border: 1px solid var(--color-frame, #c8c8d0);
|
|
336
386
|
border-radius: 4px;
|
|
337
387
|
background: linear-gradient(to top right, transparent calc(50% - 1px), #e5484d calc(50% - 1px), #e5484d calc(50% + 1px), transparent calc(50% + 1px));
|
|
338
388
|
}
|
|
@@ -343,53 +393,13 @@
|
|
|
343
393
|
border: 0;
|
|
344
394
|
border-radius: 6px;
|
|
345
395
|
background: none;
|
|
346
|
-
color: #8e8e96;
|
|
396
|
+
color: var(--color-muted-contrast, #8e8e96);
|
|
347
397
|
font-size: 16px;
|
|
348
398
|
line-height: 1;
|
|
349
399
|
cursor: pointer;
|
|
350
400
|
}
|
|
351
401
|
.clear:hover {
|
|
352
402
|
background: rgba(120, 120, 140, 0.14);
|
|
353
|
-
color: #1d1d1f;
|
|
354
|
-
}
|
|
355
|
-
.chosen {
|
|
356
|
-
display: flex;
|
|
357
|
-
align-items: center;
|
|
358
|
-
gap: 3px;
|
|
359
|
-
min-height: 30px;
|
|
360
|
-
padding: 2px;
|
|
361
|
-
border: 1px solid #dcdce2;
|
|
362
|
-
border-radius: 7px;
|
|
363
|
-
background: #fff;
|
|
364
|
-
cursor: pointer;
|
|
365
|
-
}
|
|
366
|
-
.chosen:hover {
|
|
367
|
-
border-color: var(--color-accent, #ea580c);
|
|
368
|
-
}
|
|
369
|
-
/* images after the sixth are a "+n" */
|
|
370
|
-
.chosen > img:nth-of-type(n + 7) {
|
|
371
|
-
display: none;
|
|
372
|
-
}
|
|
373
|
-
.chosen img,
|
|
374
|
-
.chosen .missing {
|
|
375
|
-
width: 40px;
|
|
376
|
-
height: 24px;
|
|
377
|
-
object-fit: cover;
|
|
378
|
-
border-radius: 4px;
|
|
379
|
-
}
|
|
380
|
-
.chosen .missing {
|
|
381
|
-
display: grid;
|
|
382
|
-
place-items: center;
|
|
383
|
-
background: #eee;
|
|
384
|
-
color: #8e8e96;
|
|
385
|
-
}
|
|
386
|
-
.chosen .more {
|
|
387
|
-
padding: 0 4px;
|
|
388
|
-
color: #6e6e76;
|
|
389
|
-
font-size: 11px;
|
|
390
|
-
}
|
|
391
|
-
.chosen .empty {
|
|
392
|
-
padding: 0 8px;
|
|
393
|
-
color: #8e8e96;
|
|
403
|
+
color: var(--color-surface-contrast, #1d1d1f);
|
|
394
404
|
}
|
|
395
405
|
</style>
|
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
import type { Translate } from './i18n';
|
|
2
|
-
import type { MediaItem } from './media';
|
|
3
2
|
import type { Block, PropField } from './types';
|
|
4
3
|
interface Props {
|
|
5
4
|
block: Block;
|
|
6
5
|
tag: string;
|
|
7
6
|
fields: PropField[];
|
|
8
|
-
media: MediaItem[];
|
|
9
7
|
tr: Translate;
|
|
10
8
|
/** Sets one property from its field's text and returns the text as it is now kept. */
|
|
11
9
|
setProp: (b: Block, f: PropField, raw: string) => string;
|
|
12
10
|
/** Sets one property to a value as it is ('' or undefined removes it). */
|
|
13
11
|
setValue: (b: Block, key: string, v: unknown) => void;
|
|
14
|
-
pickMedia: (b: Block, f: PropField, id: string) => void;
|
|
15
12
|
/** Start with the fields open (a block just made). */
|
|
16
13
|
open?: boolean;
|
|
17
14
|
}
|
package/dist/code.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** A language: its value is stored in the block (`props.lang`, the opening fence's info string). */
|
|
2
|
+
export interface CodeLanguage {
|
|
3
|
+
value: string;
|
|
4
|
+
/** Shown in the dropdown; defaults to the value. */
|
|
5
|
+
label?: string;
|
|
6
|
+
}
|
|
7
|
+
type Get = () => CodeLanguage[];
|
|
8
|
+
/** Call in a component's init (around the editor). Without its own list, a nested editor keeps its parent's. */
|
|
9
|
+
export declare function provideCodeLanguages(own: () => (string | CodeLanguage)[] | undefined): void;
|
|
10
|
+
/** Call in a component's init; the returned function reads the current list (empty: free text). */
|
|
11
|
+
export declare const useCodeLanguages: () => Get;
|
|
12
|
+
export {};
|
package/dist/code.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// The languages a code block offers. Without a list (the default) its language is free text; with one, the field is a
|
|
2
|
+
// dropdown of these. Which languages make sense is the host's business (what its site can highlight).
|
|
3
|
+
import { getContext, setContext } from 'svelte';
|
|
4
|
+
const KEY = 'block-editor:code-languages';
|
|
5
|
+
const normalize = (list) => list.map((l) => (typeof l === 'string' ? { value: l } : l));
|
|
6
|
+
/** Call in a component's init (around the editor). Without its own list, a nested editor keeps its parent's. */
|
|
7
|
+
export function provideCodeLanguages(own) {
|
|
8
|
+
const parent = getContext(KEY);
|
|
9
|
+
setContext(KEY, () => {
|
|
10
|
+
const list = own();
|
|
11
|
+
return list ? normalize(list) : (parent?.() ?? []);
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
/** Call in a component's init; the returned function reads the current list (empty: free text). */
|
|
15
|
+
export const useCodeLanguages = () => getContext(KEY) ?? (() => []);
|
package/dist/index.d.ts
CHANGED
|
@@ -5,8 +5,8 @@ export { default as Empty } from './kit/Empty.svelte';
|
|
|
5
5
|
export * from './kit/util';
|
|
6
6
|
export * from './model';
|
|
7
7
|
export { inline, fromStored, toStored, fromMarkdown, toMarkdown } from './markdown';
|
|
8
|
-
export { provideMedia, useMedia, findMedia, type MediaItem } from './media';
|
|
9
8
|
export { provideView, useView } from './view';
|
|
9
|
+
export { provideCodeLanguages, useCodeLanguages, type CodeLanguage } from './code';
|
|
10
10
|
export { scrollSync, scrollFraction, setScrollFraction, type ScrollSync } from './scroll';
|
|
11
11
|
export { provideText, useText, translator, type Messages, type Translate } from './i18n';
|
|
12
12
|
export { PALETTE_ITEMS, BUILT_IN_IDS, narrowPalette, type Icon, type PaletteItem } from './palette';
|
package/dist/index.js
CHANGED
|
@@ -9,8 +9,8 @@ export { default as Empty } from './kit/Empty.svelte';
|
|
|
9
9
|
export * from './kit/util';
|
|
10
10
|
export * from './model';
|
|
11
11
|
export { inline, fromStored, toStored, fromMarkdown, toMarkdown } from './markdown';
|
|
12
|
-
export { provideMedia, useMedia, findMedia } from './media';
|
|
13
12
|
export { provideView, useView } from './view';
|
|
13
|
+
export { provideCodeLanguages, useCodeLanguages } from './code';
|
|
14
14
|
export { scrollSync, scrollFraction, setScrollFraction } from './scroll';
|
|
15
15
|
export { provideText, useText, translator } from './i18n';
|
|
16
16
|
export { PALETTE_ITEMS, BUILT_IN_IDS, narrowPalette } from './palette';
|
package/dist/kit/Empty.svelte
CHANGED
|
@@ -16,9 +16,9 @@
|
|
|
16
16
|
justify-content: center;
|
|
17
17
|
gap: 8px;
|
|
18
18
|
min-height: 96px;
|
|
19
|
-
border: 1px dashed #d4d4da;
|
|
19
|
+
border: 1px dashed var(--color-frame, #d4d4da);
|
|
20
20
|
border-radius: 10px;
|
|
21
|
-
color: #a0a0a8;
|
|
21
|
+
color: var(--color-muted-contrast, #a0a0a8);
|
|
22
22
|
font: 14px system-ui, sans-serif;
|
|
23
23
|
}
|
|
24
24
|
</style>
|
package/dist/kit/Frame.svelte
CHANGED
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
<style>
|
|
47
47
|
.frame {
|
|
48
48
|
position: relative;
|
|
49
|
-
border: 1px solid #e5e5ea;
|
|
49
|
+
border: 1px solid var(--color-frame, #e5e5ea);
|
|
50
50
|
border-radius: 10px;
|
|
51
51
|
/* left: room for the inner blocks' handle bar (22px left of the row, which reaches 8px out) */
|
|
52
52
|
padding: 0.8em 1.1em 0.4em calc(30px + 0.5em);
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
gap: 8px;
|
|
62
62
|
margin: 0 9em 0.3em 0;
|
|
63
63
|
font: 600 13px/1.4 system-ui, sans-serif;
|
|
64
|
-
color: #1d1d1f;
|
|
64
|
+
color: var(--color-surface-contrast, #1d1d1f);
|
|
65
65
|
}
|
|
66
66
|
.head img {
|
|
67
67
|
height: 28px;
|
|
@@ -71,6 +71,6 @@
|
|
|
71
71
|
}
|
|
72
72
|
.muted {
|
|
73
73
|
font-weight: 400;
|
|
74
|
-
color: #a0a0a8;
|
|
74
|
+
color: var(--color-muted-contrast, #a0a0a8);
|
|
75
75
|
}
|
|
76
76
|
</style>
|
package/dist/locales/hu.js
CHANGED
|
@@ -8,12 +8,6 @@ export const hu = {
|
|
|
8
8
|
Settings: 'Beállítások',
|
|
9
9
|
'Hide settings': 'Beállítások elrejtése',
|
|
10
10
|
None: 'Nincs',
|
|
11
|
-
Images: 'Képek',
|
|
12
|
-
Choose: 'Választás',
|
|
13
|
-
'Choose…': 'Válassz…',
|
|
14
|
-
'{n} picked': '{n} kiválasztva',
|
|
15
|
-
language: 'nyelv',
|
|
16
|
-
'No images attached to this page yet.': 'Még nincs kép csatolva.',
|
|
17
11
|
'New block at the end': 'Új blokk a végére',
|
|
18
12
|
Formatting: 'Formázás',
|
|
19
13
|
'Turn into': 'Átalakítás',
|
|
@@ -131,9 +125,10 @@ export const hu = {
|
|
|
131
125
|
'Align column right': 'Az oszlop jobbra zárva',
|
|
132
126
|
'Header row': 'Fejléc (első sor)',
|
|
133
127
|
'Footer row (e.g. sums)': 'Lábléc (utolsó sor, pl. összesítő)',
|
|
128
|
+
'Header and footer': 'Fejléc és lábléc',
|
|
129
|
+
'Click a cell to edit its row and column': 'Kattints egy cellába a sora és oszlopa szerkesztéséhez',
|
|
134
130
|
'Drag to move the row': 'Húzd a sor áthelyezéséhez',
|
|
135
131
|
'Drag to move the column': 'Húzd az oszlop áthelyezéséhez',
|
|
136
|
-
'Enter: next row · Shift+Enter: line break · paste from a spreadsheet': 'Enter: következő sor · Shift+Enter: sortörés · táblázatból be is illeszthető',
|
|
137
132
|
Heading: 'Fejléc',
|
|
138
133
|
'Row {r}, column {c}': '{r}. sor, {c}. oszlop',
|
|
139
134
|
'Add a column': 'Új oszlop',
|
package/dist/markdown.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { MediaItem } from './media';
|
|
2
1
|
import { type Block, type BlockPlugin, type StoredBlock } from './types';
|
|
3
2
|
/** Inline markdown -> inline html (b, i, u, sub, sup, strike, code, a, br). Backslash escapes are honoured; links are
|
|
4
3
|
* http(s), mailto, tel or site-relative only. */
|
|
@@ -21,5 +20,4 @@ export declare function fromMarkdown(src: string): Block[];
|
|
|
21
20
|
* plugin's `markdown`; one without it is left out. */
|
|
22
21
|
export declare function toMarkdown(blocks: Block[], opts?: {
|
|
23
22
|
plugins?: BlockPlugin[];
|
|
24
|
-
media?: MediaItem[];
|
|
25
23
|
}): string;
|
package/dist/markdown.js
CHANGED
|
@@ -202,7 +202,7 @@ export function toMarkdown(blocks, opts = {}) {
|
|
|
202
202
|
if (!plugin?.markdown)
|
|
203
203
|
return '';
|
|
204
204
|
const inner = b.blocks?.length ? toMarkdown(b.blocks.map(fromStored), opts) : '';
|
|
205
|
-
return plugin.markdown(b.props ?? {}, { inner
|
|
205
|
+
return plugin.markdown(b.props ?? {}, { inner }).trim();
|
|
206
206
|
};
|
|
207
207
|
let out = '';
|
|
208
208
|
let prev;
|
package/dist/plugins/Gap.svelte
CHANGED
|
@@ -23,6 +23,6 @@
|
|
|
23
23
|
<style>
|
|
24
24
|
.gap {
|
|
25
25
|
border-radius: 6px;
|
|
26
|
-
background: repeating-linear-gradient(-45deg, transparent 0 6px,
|
|
26
|
+
background: repeating-linear-gradient(-45deg, transparent 0 6px, color-mix(in srgb, currentColor 7%, transparent) 6px 12px);
|
|
27
27
|
}
|
|
28
28
|
</style>
|