@quillmark/svelte 0.5.0 → 0.6.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/README.md +8 -2
- package/THEMING.md +22 -27
- package/dist/core/address.d.ts +17 -3
- package/dist/core/address.js +20 -3
- package/dist/core/codec/blocks.d.ts +37 -0
- package/dist/core/codec/blocks.js +163 -0
- package/dist/core/codec/field.js +3 -5
- package/dist/core/codec/index.d.ts +1 -1
- package/dist/core/codec/index.js +3 -2
- package/dist/core/codec/inputrules.js +24 -144
- package/dist/core/codec/prose.css +14 -25
- package/dist/core/codec/schema.d.ts +8 -0
- package/dist/core/codec/schema.js +33 -1
- package/dist/core/codec/slash.d.ts +18 -16
- package/dist/core/codec/slash.js +0 -0
- package/dist/core/codec/table-view.js +127 -157
- package/dist/core/codec/table.d.ts +0 -10
- package/dist/core/codec/table.js +0 -15
- package/dist/core/theme.css +350 -347
- package/dist/preset/recipes.css +10 -21
- package/dist/preset/scale.css +6 -7
- package/dist/preview/Preview.svelte +4 -2
- package/dist/preview/geometry.d.ts +10 -9
- package/dist/preview/geometry.js +11 -13
- package/dist/visual/ArrayField.svelte +242 -63
- package/dist/visual/ArrayField.svelte.d.ts +5 -1
- package/dist/visual/Card.svelte +21 -2
- package/dist/visual/DiagnosticList.svelte +6 -11
- package/dist/visual/EnumField.svelte +33 -1
- package/dist/visual/Field.svelte +29 -5
- package/dist/visual/FieldLabel.svelte +2 -2
- package/dist/visual/FormatPopover.svelte +13 -1
- package/dist/visual/ObjectField.svelte +157 -35
- package/dist/visual/ObjectField.svelte.d.ts +13 -4
- package/dist/visual/ProseArrayElement.svelte +22 -2
- package/dist/visual/ProseArrayElement.svelte.d.ts +1 -0
- package/dist/visual/TipsCard.svelte +33 -13
- package/dist/visual/VariantField.svelte +98 -0
- package/dist/visual/VariantField.svelte.d.ts +21 -0
- package/dist/visual/VisualEditorInner.svelte +18 -15
- package/dist/visual/controls.css +282 -283
- package/dist/visual/diagnostics.d.ts +15 -24
- package/dist/visual/diagnostics.js +14 -30
- package/dist/visual/domid.d.ts +13 -0
- package/dist/visual/domid.js +16 -0
- package/dist/visual/leaves.d.ts +9 -7
- package/dist/visual/links.d.ts +5 -2
- package/dist/visual/links.js +9 -3
- package/dist/visual/props.d.ts +1 -1
- package/dist/visual/strings.d.ts +21 -6
- package/dist/visual/strings.js +3 -0
- package/dist/visual/structure.d.ts +32 -7
- package/dist/visual/structure.js +49 -3
- package/package.json +2 -2
- package/dist/core/codec/clipboard.d.ts +0 -59
- package/dist/core/codec/clipboard.js +0 -202
|
@@ -97,27 +97,34 @@
|
|
|
97
97
|
paints over the rest. The two read as one block, which is what document-level
|
|
98
98
|
guidance is: the main card's, not a card of its own. Still in-flow, no lift.
|
|
99
99
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
100
|
+
No stroke of its own. A tint below the card reads as a slip; the same tint inside an
|
|
101
|
+
outline reads as a second card, which is the one thing the tuck exists to deny. What
|
|
102
|
+
shows below the seam is fill, and `main`'s hairline is the pair's only edge.
|
|
103
103
|
|
|
104
104
|
The bottom corners take the inner rung where the card above takes the outer: a slip
|
|
105
105
|
is cut crisper than the thing it is tucked under, at every setting of the dial.
|
|
106
106
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
107
|
+
Down, the insets are the document's own rhythm and they are measured to the ink, not
|
|
108
|
+
to the boxes. The top is a block gap below the seam, what two of the body's paragraphs
|
|
109
|
+
take, so the tip reads as the block after the prose; the bottom is the card's inset
|
|
110
|
+
rung; and the foot sits at half of either, being the message's own foot rather than
|
|
111
|
+
the next thing after it. The control gives its tap floor back as margin for that to
|
|
112
|
+
hold: a box standing on the floor rather than on its one-line label carries a rung of
|
|
113
|
+
slack at each edge, and spent inside the gap that is enough to make the tightest space
|
|
114
|
+
in the card measure as the widest.
|
|
115
|
+
|
|
116
|
+
Across, the inset is `main`'s stroke and the two nested insets under it, the card's
|
|
117
|
+
own and the prose control's, so the tip starts on the prose's edge rather than short
|
|
118
|
+
of it. */
|
|
112
119
|
.qm-tips {
|
|
113
120
|
margin-top: calc(var(--_qm-radius) * -1);
|
|
114
|
-
border: var(--_qm-border-width) solid var(--_qm-border);
|
|
115
121
|
border-radius: 0 0 var(--_qm-radius-inner) var(--_qm-radius-inner);
|
|
116
|
-
padding: calc(var(--_qm-space-3) + var(--_qm-radius))
|
|
122
|
+
padding: calc(var(--_qm-space-3) + var(--_qm-radius))
|
|
123
|
+
calc(var(--_qm-border-width) + var(--_qm-space-3) * 2) var(--_qm-space-3);
|
|
117
124
|
background: var(--_qm-tips-surface);
|
|
118
125
|
display: flex;
|
|
119
126
|
flex-direction: column;
|
|
120
|
-
gap: var(--_qm-space
|
|
127
|
+
gap: var(--_qm-space);
|
|
121
128
|
font-family: var(--_qm-tips-font);
|
|
122
129
|
font-size: var(--_qm-text-body);
|
|
123
130
|
line-height: var(--_qm-leading-body);
|
|
@@ -168,7 +175,11 @@
|
|
|
168
175
|
the spacing one — the foot's button clears the floor and walks the whole set from
|
|
169
176
|
the tip the card opens on, so no tip is reachable only by a dot. State is three
|
|
170
177
|
steps of one ink on the recede ladder, never a second hue and never a size: a dot
|
|
171
|
-
that grew would move the row it sits in.
|
|
178
|
+
that grew would move the row it sits in.
|
|
179
|
+
|
|
180
|
+
`color` is restated because a button takes the UA's and not its parent's, so
|
|
181
|
+
`currentColor` is the card's ink only once it is inherited; left to the UA it is
|
|
182
|
+
`buttontext`, which is the one neutral on a card that carries no neutrals. */
|
|
172
183
|
.qm-tips-dot {
|
|
173
184
|
box-sizing: content-box;
|
|
174
185
|
width: 5px;
|
|
@@ -176,6 +187,7 @@
|
|
|
176
187
|
padding: var(--_qm-space-half);
|
|
177
188
|
border: none;
|
|
178
189
|
border-radius: var(--_qm-radius-pill);
|
|
190
|
+
color: inherit;
|
|
179
191
|
background: currentColor;
|
|
180
192
|
background-clip: content-box;
|
|
181
193
|
opacity: var(--_qm-opacity-idle);
|
|
@@ -192,8 +204,16 @@
|
|
|
192
204
|
overrides is everything the family sets for a glyph among callers of its own
|
|
193
205
|
colour, a labelled control on a warm card wanting none of it. The hover included:
|
|
194
206
|
the family's neutral step would read as lent from the document above. Unlayered,
|
|
195
|
-
so it beats the base rule without out-specifying it.
|
|
207
|
+
so it beats the base rule without out-specifying it.
|
|
208
|
+
|
|
209
|
+
The box is the tap target and the label is what the rhythm measures, so both axes
|
|
210
|
+
give the difference back as margin: the inline rung lands the label on the body's
|
|
211
|
+
edge above, and the block rung takes the floor's slack out of the foot's height.
|
|
212
|
+
The box, and the hover it paints, still reaches past the label the way a control
|
|
213
|
+
does. */
|
|
196
214
|
.qm-tips-action {
|
|
215
|
+
margin-block: calc(var(--_qm-space) * -1);
|
|
216
|
+
margin-right: calc(var(--_qm-space-2) * -1);
|
|
197
217
|
padding: var(--_qm-space-half) var(--_qm-space-2);
|
|
198
218
|
font-family: inherit;
|
|
199
219
|
font-size: inherit;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
An `enum` declaring `variants:` → the discriminant's select, and under it the cells
|
|
3
|
+
the chosen world brings into play (VISUAL_EDITOR §"Enum variants"). The field rests as
|
|
4
|
+
a container, `{value: <member>, …that member's fields}`, and commits whole: it is one
|
|
5
|
+
cell to `Addr`, so there is no per-cell write address.
|
|
6
|
+
|
|
7
|
+
The cells are {@link ObjectField}, which already draws a scalar field set keyed by
|
|
8
|
+
name over a container its parent commits by value. It takes the whole container as its
|
|
9
|
+
`value` and the world's declaration as its `properties`, so what it hands back is the
|
|
10
|
+
container with one cell written — and cells outside the drawn world ride through
|
|
11
|
+
untouched rather than needing to be merged back.
|
|
12
|
+
-->
|
|
13
|
+
<script lang="ts">
|
|
14
|
+
import type { QuillFieldSchema } from '@quillmark/wasm';
|
|
15
|
+
import EnumField from './EnumField.svelte';
|
|
16
|
+
import ObjectField from './ObjectField.svelte';
|
|
17
|
+
import {
|
|
18
|
+
VARIANT_DISCRIMINANT,
|
|
19
|
+
commitDiscriminant,
|
|
20
|
+
variantCells,
|
|
21
|
+
variantMember
|
|
22
|
+
} from './structure.js';
|
|
23
|
+
|
|
24
|
+
interface Props {
|
|
25
|
+
/** The stored container, or undefined while the field is unset. */
|
|
26
|
+
value: Record<string, unknown> | undefined;
|
|
27
|
+
schema: QuillFieldSchema;
|
|
28
|
+
/** The resolved `default:`'s member: what an unset field renders as. */
|
|
29
|
+
ghostMember: string | undefined;
|
|
30
|
+
/** Field label, the naming prefix the cells' controls compose with. */
|
|
31
|
+
label: string;
|
|
32
|
+
/** `<label for>` target: the discriminant trigger, this control's one labelable
|
|
33
|
+
* element. The cells are named by their own composed labels. */
|
|
34
|
+
id?: string;
|
|
35
|
+
labelledBy?: string;
|
|
36
|
+
describedBy?: string;
|
|
37
|
+
onCommit: (v: Record<string, unknown> | undefined) => void;
|
|
38
|
+
optionAllowed?: (value: string) => boolean;
|
|
39
|
+
enumDisallowed?: 'hide' | 'disable';
|
|
40
|
+
}
|
|
41
|
+
let {
|
|
42
|
+
value,
|
|
43
|
+
schema,
|
|
44
|
+
ghostMember,
|
|
45
|
+
label,
|
|
46
|
+
id,
|
|
47
|
+
labelledBy,
|
|
48
|
+
describedBy,
|
|
49
|
+
onCommit,
|
|
50
|
+
optionAllowed,
|
|
51
|
+
enumDisallowed
|
|
52
|
+
}: Props = $props();
|
|
53
|
+
|
|
54
|
+
const member = $derived(variantMember(value, ghostMember));
|
|
55
|
+
const cells = $derived(variantCells(schema, member));
|
|
56
|
+
const discriminant = $derived(value?.[VARIANT_DISCRIMINANT] as string | undefined);
|
|
57
|
+
</script>
|
|
58
|
+
|
|
59
|
+
<div class="qm-variant">
|
|
60
|
+
<EnumField
|
|
61
|
+
value={discriminant}
|
|
62
|
+
values={schema.values ?? []}
|
|
63
|
+
fallback={ghostMember}
|
|
64
|
+
{id}
|
|
65
|
+
{describedBy}
|
|
66
|
+
onCommit={(v) => onCommit(commitDiscriminant(value, v))}
|
|
67
|
+
{optionAllowed}
|
|
68
|
+
{enumDisallowed}
|
|
69
|
+
/>
|
|
70
|
+
<!-- Keyed on the member so a flip remounts the cells rather than re-targeting
|
|
71
|
+
them: two worlds' cells are different fields that happen to occupy one place,
|
|
72
|
+
and a control carrying local state (an unreconciled pick, a caret) across the
|
|
73
|
+
flip would carry it between them. -->
|
|
74
|
+
{#if cells}
|
|
75
|
+
{#key member}
|
|
76
|
+
<!-- `close`: the discriminant's box directly above IS the cells' top boundary,
|
|
77
|
+
so the band's opening stroke would state it twice. -->
|
|
78
|
+
<ObjectField
|
|
79
|
+
value={value ?? {}}
|
|
80
|
+
properties={cells}
|
|
81
|
+
{label}
|
|
82
|
+
idBase={id}
|
|
83
|
+
{labelledBy}
|
|
84
|
+
{describedBy}
|
|
85
|
+
edges="close"
|
|
86
|
+
onCommit={(obj) => onCommit(obj)}
|
|
87
|
+
/>
|
|
88
|
+
{/key}
|
|
89
|
+
{/if}
|
|
90
|
+
</div>
|
|
91
|
+
|
|
92
|
+
<style>
|
|
93
|
+
.qm-variant {
|
|
94
|
+
display: flex;
|
|
95
|
+
flex-direction: column;
|
|
96
|
+
gap: var(--_qm-space-2);
|
|
97
|
+
}
|
|
98
|
+
</style>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { QuillFieldSchema } from '@quillmark/wasm';
|
|
2
|
+
interface Props {
|
|
3
|
+
/** The stored container, or undefined while the field is unset. */
|
|
4
|
+
value: Record<string, unknown> | undefined;
|
|
5
|
+
schema: QuillFieldSchema;
|
|
6
|
+
/** The resolved `default:`'s member: what an unset field renders as. */
|
|
7
|
+
ghostMember: string | undefined;
|
|
8
|
+
/** Field label, the naming prefix the cells' controls compose with. */
|
|
9
|
+
label: string;
|
|
10
|
+
/** `<label for>` target: the discriminant trigger, this control's one labelable
|
|
11
|
+
* element. The cells are named by their own composed labels. */
|
|
12
|
+
id?: string;
|
|
13
|
+
labelledBy?: string;
|
|
14
|
+
describedBy?: string;
|
|
15
|
+
onCommit: (v: Record<string, unknown> | undefined) => void;
|
|
16
|
+
optionAllowed?: (value: string) => boolean;
|
|
17
|
+
enumDisallowed?: 'hide' | 'disable';
|
|
18
|
+
}
|
|
19
|
+
declare const VariantField: import("svelte").Component<Props, {}, "">;
|
|
20
|
+
type VariantField = ReturnType<typeof VariantField>;
|
|
21
|
+
export default VariantField;
|
|
@@ -58,7 +58,6 @@
|
|
|
58
58
|
} from './structure.js';
|
|
59
59
|
import {
|
|
60
60
|
fieldKeyToString,
|
|
61
|
-
inlineShown,
|
|
62
61
|
resolveCardKey,
|
|
63
62
|
routeAndResolve,
|
|
64
63
|
mergeDiagnostics,
|
|
@@ -487,11 +486,10 @@
|
|
|
487
486
|
|
|
488
487
|
// All three producers. The two positional ones resolve their `.path` to the live
|
|
489
488
|
// stable-id keying; commit errors are id-keyed already. Nothing is dropped for
|
|
490
|
-
// being unwelcome — diagnostics never gate — but
|
|
491
|
-
//
|
|
492
|
-
// states that (`inlineShown`).
|
|
489
|
+
// being unwelcome — diagnostics never gate — but warnings do not draw: only
|
|
490
|
+
// errors reach a control (`routeAndResolve`).
|
|
493
491
|
const diagByKey = $derived.by(() => {
|
|
494
|
-
const fromValidate = routeAndResolve(validation
|
|
492
|
+
const fromValidate = routeAndResolve(validation, cardIds);
|
|
495
493
|
const fromExternal = routeAndResolve(diagnostics, cardIds);
|
|
496
494
|
return mergeDiagnostics(fromValidate, fromExternal, [...commitErrors.values()]);
|
|
497
495
|
});
|
|
@@ -670,14 +668,15 @@
|
|
|
670
668
|
|
|
671
669
|
/**
|
|
672
670
|
* Put the caret in a revealed target, at the finest grain it can take: a USV offset
|
|
673
|
-
* in a prose leaf, a bare focus everywhere else.
|
|
674
|
-
*
|
|
675
|
-
*
|
|
676
|
-
*
|
|
671
|
+
* in a prose leaf or an array element, a bare focus everywhere else. A form control
|
|
672
|
+
* has no coordinate to spend an offset in (an `<input type="number">` refuses a
|
|
673
|
+
* selection outright), which is also the whole of what a click on plate-placed ink
|
|
674
|
+
* can mean. An element is no `createField` leaf, so the offset goes down the element
|
|
675
|
+
* lane instead, where what it means is the row control's (`leaves.ts`).
|
|
677
676
|
*/
|
|
678
677
|
function land(found: Landed, pos: number | undefined): void {
|
|
679
678
|
if (found.element != null && found.control.focusElement) {
|
|
680
|
-
return found.control.focusElement(found.element);
|
|
679
|
+
return found.control.focusElement(found.element, pos);
|
|
681
680
|
}
|
|
682
681
|
if (pos != null) {
|
|
683
682
|
const prose = leaves.prose(found.key);
|
|
@@ -900,9 +899,13 @@
|
|
|
900
899
|
|
|
901
900
|
The column, not only the cards in it: the gutter the stack sits in and the tone
|
|
902
901
|
behind it are the surface's own, so a bare `<div>` is a mounting site and nothing
|
|
903
|
-
is owed before the editor looks right.
|
|
904
|
-
|
|
905
|
-
|
|
902
|
+
is owed before the editor looks right. `border-box`, so a height from the caller is
|
|
903
|
+
the height this draws.
|
|
904
|
+
|
|
905
|
+
`:global(:where(…))` puts a promised class at zero rank, and both halves are
|
|
906
|
+
load-bearing: `:global` drops the scoping class, `:where` drops the rest
|
|
907
|
+
(ARCHITECTURE §Styling). The class is the surface's root wherever it mounts, so
|
|
908
|
+
leaving the component's scope costs nothing.
|
|
906
909
|
|
|
907
910
|
The sunken rung, which is what makes a card an island: the cards are the base
|
|
908
911
|
plane and this is the one they float on, so the gutter reads as ground rather
|
|
@@ -910,7 +913,7 @@
|
|
|
910
913
|
ramp, which is what gives the ground enough of itself to read as ground: at a
|
|
911
914
|
narrower one the stack meets whatever frames the surface and the islands are
|
|
912
915
|
back to being one block clipped at its edges. */
|
|
913
|
-
.qm-editor {
|
|
916
|
+
:global(:where(.qm-editor)) {
|
|
914
917
|
box-sizing: border-box;
|
|
915
918
|
display: flex;
|
|
916
919
|
flex-direction: column;
|
|
@@ -935,7 +938,7 @@
|
|
|
935
938
|
site with no height of its own, which is the page form kept. The cards do not
|
|
936
939
|
shrink to fit: a flex item's automatic minimum floors each at its own height, so
|
|
937
940
|
the stack overflows and scrolls rather than squashing. */
|
|
938
|
-
.qm-editor.qm-pane {
|
|
941
|
+
:global(:where(.qm-editor.qm-pane)) {
|
|
939
942
|
height: 100%;
|
|
940
943
|
overflow: auto;
|
|
941
944
|
overscroll-behavior: contain;
|