@atom-forge/brickee 0.0.1 → 0.0.3
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 +59 -1
- package/README-AI.md +34 -28
- package/dist/Editor.svelte +713 -867
- package/dist/Editor.svelte.d.ts +0 -3
- package/dist/LinkPrompt.svelte +1 -14
- package/dist/Preview.svelte +27 -58
- package/dist/Preview.svelte.d.ts +2 -7
- package/dist/PropsBar.svelte +75 -249
- package/dist/PropsBar.svelte.d.ts +0 -3
- package/dist/code.d.ts +12 -0
- package/dist/code.js +15 -0
- package/dist/dom.d.ts +8 -0
- package/dist/dom.js +9 -0
- package/dist/editor/BlockMenu.svelte +102 -0
- package/dist/editor/BlockMenu.svelte.d.ts +32 -0
- package/dist/editor/FormatBar.svelte +41 -0
- package/dist/editor/FormatBar.svelte.d.ts +16 -0
- package/dist/editor/drag.svelte.d.ts +63 -0
- package/dist/editor/drag.svelte.js +95 -0
- package/dist/editor/history.d.ts +24 -0
- package/dist/editor/history.js +86 -0
- package/dist/editor/sweep.svelte.d.ts +21 -0
- package/dist/editor/sweep.svelte.js +56 -0
- package/dist/html.d.ts +12 -0
- package/dist/html.js +206 -0
- package/dist/i18n.js +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +4 -3
- package/dist/kit/Empty.svelte +4 -15
- package/dist/kit/Frame.svelte +7 -37
- package/dist/locales/hu.js +6 -8
- package/dist/markdown.d.ts +20 -6
- package/dist/markdown.js +380 -85
- package/dist/model.js +2 -3
- package/dist/plugins/Gap.svelte +5 -8
- package/dist/plugins/GapPreview.svelte +4 -6
- package/dist/plugins/Map.svelte +2 -17
- package/dist/plugins/MapPreview.svelte +8 -10
- package/dist/plugins/Table.svelte +233 -282
- package/dist/plugins/TablePreview.svelte +28 -28
- package/dist/plugins/YouTube.svelte +3 -31
- package/dist/plugins/YouTubePreview.svelte +45 -43
- package/dist/plugins/index.js +15 -2
- package/dist/schema.js +1 -1
- package/dist/types.d.ts +27 -10
- package/dist/types.js +8 -1
- package/dist/view.js +1 -1
- package/docs/en/bundled-plugins.md +1 -1
- package/docs/en/documents-and-markdown.md +24 -19
- package/docs/en/editor-and-preview.md +7 -10
- package/docs/en/getting-started.md +14 -2
- package/docs/en/host-contexts.md +26 -132
- package/docs/en/index.md +5 -5
- package/docs/en/recipes-and-pitfalls.md +12 -11
- package/docs/en/server-side.md +0 -17
- package/docs/en/upgrading.md +34 -4
- package/docs/en/writing-plugins.md +147 -21
- package/docs/hu/bundled-plugins.md +1 -1
- package/docs/hu/documents-and-markdown.md +24 -19
- package/docs/hu/editor-and-preview.md +7 -10
- package/docs/hu/getting-started.md +14 -2
- package/docs/hu/host-contexts.md +26 -132
- package/docs/hu/index.md +5 -5
- package/docs/hu/recipes-and-pitfalls.md +12 -11
- package/docs/hu/server-side.md +0 -17
- package/docs/hu/upgrading.md +34 -4
- package/docs/hu/writing-plugins.md +147 -21
- package/package.json +14 -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
|
@@ -14,13 +14,11 @@
|
|
|
14
14
|
<iframe class="map" title={tr('Map: {place}', { place: String(props.q ?? '') })} {src} loading="lazy" referrerpolicy="no-referrer-when-downgrade"></iframe>
|
|
15
15
|
{/if}
|
|
16
16
|
|
|
17
|
-
<style
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
</style>
|
|
17
|
+
<style>.map {
|
|
18
|
+
display: block;
|
|
19
|
+
width: 100%;
|
|
20
|
+
height: 300px;
|
|
21
|
+
margin: 0 0 1em;
|
|
22
|
+
border: 0;
|
|
23
|
+
border-radius: 10px;
|
|
24
|
+
}</style>
|
|
@@ -52,12 +52,9 @@
|
|
|
52
52
|
BetweenVerticalEnd,
|
|
53
53
|
BetweenVerticalStart,
|
|
54
54
|
Columns3,
|
|
55
|
-
Info,
|
|
56
55
|
Rows3,
|
|
57
56
|
GripHorizontal,
|
|
58
57
|
GripVertical,
|
|
59
|
-
PanelBottom,
|
|
60
|
-
PanelTop,
|
|
61
58
|
Plus,
|
|
62
59
|
TextAlignCenter,
|
|
63
60
|
TextAlignEnd,
|
|
@@ -65,6 +62,7 @@
|
|
|
65
62
|
Trash2
|
|
66
63
|
} from '@lucide/svelte';
|
|
67
64
|
import { tick } from 'svelte';
|
|
65
|
+
import { inline } from '../markdown';
|
|
68
66
|
import type { PluginViewProps } from '../types';
|
|
69
67
|
|
|
70
68
|
let { props = $bindable(), readonly }: PluginViewProps<TableProps> = $props();
|
|
@@ -78,17 +76,6 @@
|
|
|
78
76
|
let at = $state<{ r: number; c: number } | null>(null);
|
|
79
77
|
const heads = $derived(tableHeads(props));
|
|
80
78
|
const headOf = (r: number) => rowHead(heads, r, rows.length);
|
|
81
|
-
function toggleHead(h: Head) {
|
|
82
|
-
const next = new Set(heads);
|
|
83
|
-
if (!next.delete(h)) next.add(h);
|
|
84
|
-
const { header: _, ...rest } = props;
|
|
85
|
-
props = { ...rest, heads: HEADS.filter((x) => next.has(x)) } as TableProps;
|
|
86
|
-
}
|
|
87
|
-
const HEAD_TOGGLES: { head: Head; icon: typeof PanelTop; label: string }[] = [
|
|
88
|
-
{ head: 'top', icon: PanelTop, label: 'Header row' },
|
|
89
|
-
{ head: 'bottom', icon: PanelBottom, label: 'Footer row (e.g. sums)' }
|
|
90
|
-
];
|
|
91
|
-
|
|
92
79
|
/* Dragging a row or a column by its grip: `to` is the slot it would go to (0…count), shown as a blue line. */
|
|
93
80
|
let drag = $state<{ kind: 'row' | 'col'; from: number; to: number } | null>(null);
|
|
94
81
|
|
|
@@ -124,7 +111,14 @@
|
|
|
124
111
|
};
|
|
125
112
|
addEventListener('pointermove', move);
|
|
126
113
|
addEventListener('pointerup', up);
|
|
114
|
+
stopDrag = () => {
|
|
115
|
+
removeEventListener('pointermove', move);
|
|
116
|
+
removeEventListener('pointerup', up);
|
|
117
|
+
};
|
|
127
118
|
}
|
|
119
|
+
// A table removed in the middle of a drag leaves no listener behind.
|
|
120
|
+
let stopDrag = () => {};
|
|
121
|
+
$effect(() => () => stopDrag());
|
|
128
122
|
/** The drop line of a row or column: before it, after it (the last one), or none. */
|
|
129
123
|
function dropMark(kind: 'row' | 'col', i: number, count: number) {
|
|
130
124
|
if (drag?.kind !== kind || drag.to === drag.from || drag.to === drag.from + 1) return null;
|
|
@@ -165,9 +159,38 @@
|
|
|
165
159
|
}
|
|
166
160
|
const setAlign = (c: number, a: Align) => set({ align: align.map((x, j) => (j === c ? a : x)) });
|
|
167
161
|
|
|
162
|
+
/**
|
|
163
|
+
* Wraps the selected text of a cell in a mark (Ctrl+B and the like); then selects the text again, or, for a link,
|
|
164
|
+
* the address to type over.
|
|
165
|
+
*/
|
|
166
|
+
async function mark(t: HTMLTextAreaElement, r: number, c: number, open: string, close: string, link = false) {
|
|
167
|
+
const { selectionStart: a, selectionEnd: b, value } = t;
|
|
168
|
+
const text = value.slice(a, b);
|
|
169
|
+
edit(r, c, value.slice(0, a) + open + text + close + value.slice(b));
|
|
170
|
+
await tick();
|
|
171
|
+
const cell = root.querySelector<HTMLTextAreaElement>(`textarea[data-cell="${r}:${c}"]`);
|
|
172
|
+
if (!cell) return;
|
|
173
|
+
cell.focus();
|
|
174
|
+
if (link) cell.setSelectionRange(a + open.length + text.length + 2, a + open.length + text.length + close.length - 1);
|
|
175
|
+
else cell.setSelectionRange(a + open.length, a + open.length + text.length);
|
|
176
|
+
}
|
|
177
|
+
const MARKS: Record<string, [string, string]> = { b: ['**', '**'], i: ['*', '*'], e: ['`', '`'] };
|
|
178
|
+
|
|
168
179
|
function onKey(e: KeyboardEvent, r: number, c: number) {
|
|
169
180
|
const t = e.currentTarget as HTMLTextAreaElement;
|
|
170
181
|
const last = r === rows.length - 1;
|
|
182
|
+
const k = e.key.toLowerCase();
|
|
183
|
+
if ((e.ctrlKey || e.metaKey) && !e.altKey) {
|
|
184
|
+
const m = e.shiftKey ? (k === 'x' ? (['~~', '~~'] as [string, string]) : null) : MARKS[k];
|
|
185
|
+
if (m) {
|
|
186
|
+
e.preventDefault();
|
|
187
|
+
return void mark(t, r, c, m[0], m[1]);
|
|
188
|
+
}
|
|
189
|
+
if (k === 'k' && !e.shiftKey) {
|
|
190
|
+
e.preventDefault();
|
|
191
|
+
return void mark(t, r, c, '[', '](https://)', true);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
171
194
|
if (e.key === 'Enter' && !e.shiftKey) {
|
|
172
195
|
// Enter goes down a row (a new one after the last); Shift+Enter breaks the line inside the cell.
|
|
173
196
|
e.preventDefault();
|
|
@@ -213,6 +236,18 @@
|
|
|
213
236
|
return { update: fit, destroy: () => node.removeEventListener('input', fit) };
|
|
214
237
|
}
|
|
215
238
|
|
|
239
|
+
// The toolbar's look (Tailwind; whole class names, so Tailwind finds them): segments of small buttons.
|
|
240
|
+
const SEG = 'inline-flex items-center gap-px rounded-lg bg-muted p-0.5';
|
|
241
|
+
const LABEL = 'inline-grid place-items-center pr-1 pl-[5px] text-muted-contrast';
|
|
242
|
+
const TOOL =
|
|
243
|
+
'inline-grid h-6 min-w-[26px] cursor-pointer place-items-center rounded-md border-0 bg-transparent px-[5px] text-surface-contrast enabled:hover:bg-surface enabled:hover:shadow-[0_1px_2px_rgb(0_0_0/0.08)] disabled:cursor-default disabled:opacity-30';
|
|
244
|
+
const TOOL_ON =
|
|
245
|
+
'inline-grid h-6 min-w-[26px] cursor-pointer place-items-center rounded-md border-0 bg-surface px-[5px] text-accent shadow-[0_1px_2px_rgb(0_0_0/0.08)]';
|
|
246
|
+
const DANGER = `${TOOL} enabled:hover:text-[#dc2626]`;
|
|
247
|
+
const ADD = $derived(
|
|
248
|
+
`grid cursor-pointer place-items-center rounded-md border-0 bg-muted p-0 text-muted-contrast transition-[opacity,background] duration-[120ms] hover:bg-accent/12 hover:text-accent ${at ? 'opacity-100' : 'opacity-0 group-hover/table:opacity-100'}`
|
|
249
|
+
);
|
|
250
|
+
|
|
216
251
|
const ALIGNS: { value: Align; icon: typeof TextAlignStart; label: string }[] = [
|
|
217
252
|
{ value: 'left', icon: TextAlignStart, label: 'Align column left' },
|
|
218
253
|
{ value: 'center', icon: TextAlignCenter, label: 'Center column' },
|
|
@@ -221,46 +256,42 @@
|
|
|
221
256
|
</script>
|
|
222
257
|
|
|
223
258
|
<div
|
|
224
|
-
class="table"
|
|
225
|
-
class:editing={!!at}
|
|
259
|
+
class="table-editor group/table text-[15px] leading-[1.45]"
|
|
226
260
|
bind:this={root}
|
|
227
261
|
onfocusout={(e) => {
|
|
228
262
|
if (!root.contains(e.relatedTarget as Node)) at = null;
|
|
229
263
|
}}
|
|
230
264
|
>
|
|
231
265
|
{#if !readonly}
|
|
232
|
-
|
|
266
|
+
<!-- The row and column tools of the cell being edited; when it wraps, it pushes the table down. -->
|
|
267
|
+
<div class="mb-2 flex min-h-7 flex-wrap items-center gap-1.5" role="toolbar" aria-label={tr('Table')}>
|
|
233
268
|
{#if at}
|
|
234
269
|
{@const { r, c } = at}
|
|
235
|
-
<div class=
|
|
236
|
-
<span class=
|
|
237
|
-
<button type="button" title={tr('Insert a row above')} onmousedown={(e) => e.preventDefault()} onclick={() => { insertRow(r); focusCell(r, c); }}><BetweenHorizontalStart size={15} /></button>
|
|
238
|
-
<button type="button" title={tr('Insert a row below')} onmousedown={(e) => e.preventDefault()} onclick={() => { insertRow(r + 1); focusCell(r + 1, c); }}><BetweenHorizontalEnd size={15} /></button>
|
|
239
|
-
<button type="button" class=
|
|
270
|
+
<div class={SEG}>
|
|
271
|
+
<span class={LABEL} title={tr('Row')}><Rows3 size={14} /></span>
|
|
272
|
+
<button type="button" class={TOOL} title={tr('Insert a row above')} onmousedown={(e) => e.preventDefault()} onclick={() => { insertRow(r); focusCell(r, c); }}><BetweenHorizontalStart size={15} /></button>
|
|
273
|
+
<button type="button" class={TOOL} title={tr('Insert a row below')} onmousedown={(e) => e.preventDefault()} onclick={() => { insertRow(r + 1); focusCell(r + 1, c); }}><BetweenHorizontalEnd size={15} /></button>
|
|
274
|
+
<button type="button" class={DANGER} title={tr('Delete this row')} disabled={rows.length < 2} onclick={() => dropRow(r)}><Trash2 size={14} /></button>
|
|
240
275
|
</div>
|
|
241
|
-
<div class=
|
|
242
|
-
<span class=
|
|
243
|
-
<button type="button" title={tr('Insert a column left')} onmousedown={(e) => e.preventDefault()} onclick={() => { insertCol(c); focusCell(r, c); }}><BetweenVerticalStart size={15} /></button>
|
|
244
|
-
<button type="button" title={tr('Insert a column right')} onmousedown={(e) => e.preventDefault()} onclick={() => { insertCol(c + 1); focusCell(r, c + 1); }}><BetweenVerticalEnd size={15} /></button>
|
|
245
|
-
<button type="button" class=
|
|
276
|
+
<div class={SEG}>
|
|
277
|
+
<span class={LABEL} title={tr('Column')}><Columns3 size={14} /></span>
|
|
278
|
+
<button type="button" class={TOOL} title={tr('Insert a column left')} onmousedown={(e) => e.preventDefault()} onclick={() => { insertCol(c); focusCell(r, c); }}><BetweenVerticalStart size={15} /></button>
|
|
279
|
+
<button type="button" class={TOOL} title={tr('Insert a column right')} onmousedown={(e) => e.preventDefault()} onclick={() => { insertCol(c + 1); focusCell(r, c + 1); }}><BetweenVerticalEnd size={15} /></button>
|
|
280
|
+
<button type="button" class={DANGER} title={tr('Delete this column')} disabled={width < 2} onclick={() => dropCol(c)}><Trash2 size={14} /></button>
|
|
246
281
|
</div>
|
|
247
|
-
<div class=
|
|
282
|
+
<div class={SEG}>
|
|
248
283
|
{#each ALIGNS as a (a.value)}
|
|
249
|
-
<button type="button"
|
|
284
|
+
<button type="button" class={align[c] === a.value ? TOOL_ON : TOOL} title={tr(a.label)} onmousedown={(e) => e.preventDefault()} onclick={() => setAlign(c, a.value)}><a.icon size={15} /></button>
|
|
250
285
|
{/each}
|
|
251
286
|
</div>
|
|
252
287
|
{:else}
|
|
253
|
-
<span class="
|
|
288
|
+
<span class="text-[12px] text-muted-contrast">{tr('Click a cell to edit its row and column')}</span>
|
|
254
289
|
{/if}
|
|
255
|
-
<div class="seg heads">
|
|
256
|
-
{#each HEAD_TOGGLES as h (h.head)}
|
|
257
|
-
<button type="button" title={tr(h.label)} aria-pressed={heads.has(h.head)} class:on={heads.has(h.head)} onmousedown={(e) => e.preventDefault()} onclick={() => toggleHead(h.head)}><h.icon size={15} /></button>
|
|
258
|
-
{/each}
|
|
259
|
-
</div>
|
|
260
290
|
</div>
|
|
261
291
|
{/if}
|
|
262
|
-
|
|
263
|
-
|
|
292
|
+
<!-- The table, with a + bar on the right (column) and below (row) that shows on hover. -->
|
|
293
|
+
<div class="grid grid-cols-[minmax(0,1fr)_18px] grid-rows-[auto_18px] gap-1">
|
|
294
|
+
<div class="overflow-x-auto rounded-[10px] border border-frame bg-surface">
|
|
264
295
|
<table class:dragging={!!drag}>
|
|
265
296
|
{#if !readonly}
|
|
266
297
|
<!-- the column grips -->
|
|
@@ -284,12 +315,16 @@
|
|
|
284
315
|
</td>
|
|
285
316
|
{/if}
|
|
286
317
|
{#each row as cell, c (c)}
|
|
318
|
+
{@const editing = at?.r === r && at?.c === c}
|
|
287
319
|
<td
|
|
288
320
|
class={dropMark('col', c, width) ? 'c-' + dropMark('col', c, width) : ''}
|
|
289
321
|
class:col-on={at?.c === c}
|
|
290
322
|
class:moving={drag?.kind === 'col' && drag.from === c}
|
|
291
323
|
>
|
|
324
|
+
<!-- Out of editing a cell shows its text formatted (sizing the cell, over its textarea); editing shows the
|
|
325
|
+
markdown. -->
|
|
292
326
|
<textarea
|
|
327
|
+
class:hidden-text={!editing && !!cell.trim()}
|
|
293
328
|
rows="1"
|
|
294
329
|
value={cell}
|
|
295
330
|
{readonly}
|
|
@@ -303,6 +338,9 @@
|
|
|
303
338
|
onkeydown={(e) => onKey(e, r, c)}
|
|
304
339
|
onpaste={(e) => onPaste(e, r, c)}
|
|
305
340
|
></textarea>
|
|
341
|
+
{#if !editing && cell.trim()}
|
|
342
|
+
<div class="shown" style:text-align={align[c]} aria-hidden="true">{@html inline(cell)}</div>
|
|
343
|
+
{/if}
|
|
306
344
|
</td>
|
|
307
345
|
{/each}
|
|
308
346
|
</tr>
|
|
@@ -311,253 +349,166 @@
|
|
|
311
349
|
</table>
|
|
312
350
|
</div>
|
|
313
351
|
{#if !readonly}
|
|
314
|
-
<button type="button" class=
|
|
315
|
-
<button type="button" class="
|
|
352
|
+
<button type="button" class={ADD} title={tr('Add a column')} aria-label={tr('Add a column')} onclick={() => { insertCol(width); focusCell(0, width); }}><Plus size={14} /></button>
|
|
353
|
+
<button type="button" class="col-start-1 {ADD}" title={tr('Add a row')} aria-label={tr('Add a row')} onclick={() => { insertRow(rows.length); focusCell(rows.length, 0); }}><Plus size={14} /></button>
|
|
316
354
|
{/if}
|
|
317
355
|
</div>
|
|
318
356
|
</div>
|
|
319
357
|
|
|
320
|
-
<style>
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
flex-wrap: wrap;
|
|
329
|
-
align-items: center;
|
|
330
|
-
gap: 6px;
|
|
331
|
-
min-height: 28px;
|
|
332
|
-
}
|
|
333
|
-
.seg {
|
|
334
|
-
display: inline-flex;
|
|
335
|
-
align-items: center;
|
|
336
|
-
gap: 1px;
|
|
337
|
-
padding: 2px;
|
|
338
|
-
border-radius: 8px;
|
|
339
|
-
background: #f4f4f6;
|
|
340
|
-
}
|
|
341
|
-
.label {
|
|
342
|
-
display: inline-grid;
|
|
343
|
-
place-items: center;
|
|
344
|
-
padding: 0 4px 0 5px;
|
|
345
|
-
color: #a0a0a8;
|
|
346
|
-
}
|
|
347
|
-
.bar button {
|
|
348
|
-
display: inline-grid;
|
|
349
|
-
place-items: center;
|
|
350
|
-
height: 24px;
|
|
351
|
-
min-width: 26px;
|
|
352
|
-
padding: 0 5px;
|
|
353
|
-
border: 0;
|
|
354
|
-
border-radius: 6px;
|
|
355
|
-
background: none;
|
|
356
|
-
color: #4b4b55;
|
|
357
|
-
cursor: pointer;
|
|
358
|
-
}
|
|
359
|
-
.bar button:hover:not(:disabled) {
|
|
360
|
-
background: #fff;
|
|
361
|
-
color: #1d1d1f;
|
|
362
|
-
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
|
|
363
|
-
}
|
|
364
|
-
.bar button.on {
|
|
365
|
-
background: #fff;
|
|
366
|
-
color: #2563eb;
|
|
367
|
-
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
|
|
368
|
-
}
|
|
369
|
-
.bar button.danger:hover:not(:disabled) {
|
|
370
|
-
color: #dc2626;
|
|
371
|
-
}
|
|
372
|
-
.bar button:disabled {
|
|
373
|
-
opacity: 0.3;
|
|
374
|
-
cursor: default;
|
|
375
|
-
}
|
|
376
|
-
.bar .toggle {
|
|
377
|
-
display: inline-flex;
|
|
378
|
-
gap: 5px;
|
|
379
|
-
height: 28px;
|
|
380
|
-
padding: 0 10px;
|
|
381
|
-
border: 1px solid #e5e5ea;
|
|
382
|
-
border-radius: 8px;
|
|
383
|
-
font-size: 12px;
|
|
384
|
-
font-weight: 500;
|
|
385
|
-
}
|
|
386
|
-
.bar .toggle.on {
|
|
387
|
-
border-color: #bfdbfe;
|
|
388
|
-
background: #eff6ff;
|
|
389
|
-
box-shadow: none;
|
|
390
|
-
}
|
|
391
|
-
.hint {
|
|
392
|
-
display: inline-grid;
|
|
393
|
-
place-items: center;
|
|
394
|
-
color: #a0a0a8;
|
|
395
|
-
cursor: help;
|
|
396
|
-
opacity: 0;
|
|
397
|
-
transition: opacity 0.12s;
|
|
398
|
-
}
|
|
399
|
-
.table:hover .hint {
|
|
400
|
-
opacity: 1;
|
|
401
|
-
}
|
|
358
|
+
<style>table {
|
|
359
|
+
width: 100%;
|
|
360
|
+
border-collapse: collapse;
|
|
361
|
+
}
|
|
362
|
+
table.dragging, table.dragging * {
|
|
363
|
+
cursor: grabbing !important;
|
|
364
|
+
user-select: none;
|
|
365
|
+
}
|
|
402
366
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
}
|
|
552
|
-
.table:hover .add-col,
|
|
553
|
-
.table:hover .add-row,
|
|
554
|
-
.table.editing .add-col,
|
|
555
|
-
.table.editing .add-row {
|
|
556
|
-
opacity: 1;
|
|
557
|
-
}
|
|
558
|
-
.add-col:hover,
|
|
559
|
-
.add-row:hover {
|
|
560
|
-
background: #e8eefc;
|
|
561
|
-
color: #2563eb;
|
|
562
|
-
}
|
|
563
|
-
</style>
|
|
367
|
+
td {
|
|
368
|
+
height: 1px;
|
|
369
|
+
padding: 0;
|
|
370
|
+
border-right: 1px solid var(--color-frame, #ececf0);
|
|
371
|
+
border-bottom: 1px solid var(--color-frame, #ececf0);
|
|
372
|
+
vertical-align: top;
|
|
373
|
+
transition: background 0.1s;
|
|
374
|
+
}
|
|
375
|
+
td:last-child {
|
|
376
|
+
border-right: 0;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
tr:last-child td {
|
|
380
|
+
border-bottom: 0;
|
|
381
|
+
}
|
|
382
|
+
tr.row-on td,
|
|
383
|
+
tr td.col-on {
|
|
384
|
+
background: color-mix(in srgb, var(--color-accent, #3b82f6) 4%, transparent);
|
|
385
|
+
}
|
|
386
|
+
tr.h-top td:not(.rgrip) {
|
|
387
|
+
background: var(--color-muted, #f1f1f4);
|
|
388
|
+
border-bottom: 2px solid var(--color-frame, #d8d8de);
|
|
389
|
+
}
|
|
390
|
+
tr.h-bottom td:not(.rgrip) {
|
|
391
|
+
background: var(--color-muted, #f1f1f4);
|
|
392
|
+
border-top: 2px solid var(--color-frame, #d8d8de);
|
|
393
|
+
}
|
|
394
|
+
tr.h-top textarea, tr.h-top .shown {
|
|
395
|
+
font-weight: 600;
|
|
396
|
+
font-size: 13px;
|
|
397
|
+
letter-spacing: 0.04em;
|
|
398
|
+
text-transform: uppercase;
|
|
399
|
+
color: var(--color-surface-contrast, #3a3a44);
|
|
400
|
+
}
|
|
401
|
+
tr.h-bottom textarea, tr.h-bottom .shown {
|
|
402
|
+
font-weight: 600;
|
|
403
|
+
color: var(--color-surface-contrast, #1d1d1f);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
td {
|
|
407
|
+
position: relative;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
textarea {
|
|
411
|
+
display: block;
|
|
412
|
+
width: 100%;
|
|
413
|
+
height: 100%;
|
|
414
|
+
min-width: 6em;
|
|
415
|
+
box-sizing: border-box;
|
|
416
|
+
padding: 8px 11px;
|
|
417
|
+
border: 0;
|
|
418
|
+
border-radius: 0;
|
|
419
|
+
background: none;
|
|
420
|
+
resize: none;
|
|
421
|
+
font: inherit;
|
|
422
|
+
color: inherit;
|
|
423
|
+
outline: none;
|
|
424
|
+
}
|
|
425
|
+
textarea::placeholder {
|
|
426
|
+
color: var(--color-muted-contrast, #b8b8c0);
|
|
427
|
+
}
|
|
428
|
+
textarea:focus {
|
|
429
|
+
background: var(--color-surface, #fff);
|
|
430
|
+
box-shadow: inset 0 0 0 2px var(--color-accent, #3b82f6);
|
|
431
|
+
}
|
|
432
|
+
textarea.hidden-text {
|
|
433
|
+
position: absolute;
|
|
434
|
+
inset: 0;
|
|
435
|
+
min-height: 0 !important;
|
|
436
|
+
color: transparent;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
.shown {
|
|
440
|
+
position: relative;
|
|
441
|
+
box-sizing: border-box;
|
|
442
|
+
min-width: 6em;
|
|
443
|
+
padding: 8px 11px;
|
|
444
|
+
overflow: hidden;
|
|
445
|
+
pointer-events: none;
|
|
446
|
+
white-space: pre-wrap;
|
|
447
|
+
word-break: break-word;
|
|
448
|
+
}
|
|
449
|
+
.shown :global(code) {
|
|
450
|
+
padding: 0.1em 0.35em;
|
|
451
|
+
border-radius: 4px;
|
|
452
|
+
background: rgba(120, 120, 140, 0.14);
|
|
453
|
+
font: 0.88em ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
454
|
+
}
|
|
455
|
+
.shown :global(a) {
|
|
456
|
+
color: var(--color-accent, #3b82f6);
|
|
457
|
+
text-decoration: underline;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
td.corner,
|
|
461
|
+
td.rgrip {
|
|
462
|
+
width: 14px;
|
|
463
|
+
border-right: 1px solid var(--color-frame, #ececf0);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
tr.grips td {
|
|
467
|
+
height: 14px;
|
|
468
|
+
border-bottom: 1px solid var(--color-frame, #ececf0);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
.grip {
|
|
472
|
+
display: grid;
|
|
473
|
+
place-items: center;
|
|
474
|
+
width: 100%;
|
|
475
|
+
height: 100%;
|
|
476
|
+
min-height: 14px;
|
|
477
|
+
padding: 0;
|
|
478
|
+
border: 0;
|
|
479
|
+
background: none;
|
|
480
|
+
color: var(--color-muted-contrast, #b0b0b8);
|
|
481
|
+
cursor: grab;
|
|
482
|
+
opacity: 0;
|
|
483
|
+
touch-action: none;
|
|
484
|
+
transition: opacity 0.12s;
|
|
485
|
+
}
|
|
486
|
+
.table-editor:hover .grip, table.dragging .grip {
|
|
487
|
+
opacity: 1;
|
|
488
|
+
}
|
|
489
|
+
.grip:hover {
|
|
490
|
+
color: var(--color-accent, #3b82f6);
|
|
491
|
+
background: color-mix(in srgb, var(--color-accent, #3b82f6) 9%, transparent);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
.moving {
|
|
495
|
+
opacity: 0.45;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
tr.before td {
|
|
499
|
+
box-shadow: inset 0 2px 0 var(--color-accent, #3b82f6);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
tr.after td {
|
|
503
|
+
box-shadow: inset 0 -2px 0 var(--color-accent, #3b82f6);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
td.before,
|
|
507
|
+
td.c-before {
|
|
508
|
+
box-shadow: inset 2px 0 0 var(--color-accent, #3b82f6);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
td.after,
|
|
512
|
+
td.c-after {
|
|
513
|
+
box-shadow: inset -2px 0 0 var(--color-accent, #3b82f6);
|
|
514
|
+
}</style>
|