@quillmark/svelte 0.3.2 → 0.4.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 +1 -1
- package/THEMING.md +10 -6
- package/dist/core/address.d.ts +5 -11
- package/dist/core/address.js +7 -18
- package/dist/core/codec/inputrules.js +4 -5
- package/dist/core/codec/prose.css +8 -7
- package/dist/core/theme.css +52 -40
- package/dist/preset/recipes.css +3 -3
- package/dist/preset/scale.css +21 -19
- package/dist/preview/geometry.d.ts +4 -3
- package/dist/preview/geometry.js +7 -4
- package/dist/visual/ArrayField.svelte +11 -6
- package/dist/visual/Card.svelte +1 -1
- package/dist/visual/DateField.svelte +1 -1
- package/dist/visual/EnumField.svelte +4 -4
- package/dist/visual/Field.svelte +2 -2
- package/dist/visual/FieldHint.svelte +2 -2
- package/dist/visual/ObjectField.svelte +3 -3
- package/dist/visual/ProseArrayElement.svelte +5 -6
- package/dist/visual/ProseArrayElement.svelte.d.ts +0 -1
- package/dist/visual/ProseField.svelte +5 -3
- package/dist/visual/VisualEditorInner.svelte +5 -6
- package/dist/visual/controls.css +11 -7
- package/dist/visual/structure.d.ts +0 -2
- package/dist/visual/structure.js +1 -7
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -200,7 +200,7 @@ onPick: (at) => visualEditor.setCaret(at);
|
|
|
200
200
|
onCaretMove: preview.focusPosition;
|
|
201
201
|
```
|
|
202
202
|
|
|
203
|
-
A pick carries a caret where the compile tracks the content under the point, and the field alone where it tracks only the placement — a scalar the plate prints without tracking. `setCaret` takes both: an absent `pos` reveals and focuses the field, which is the whole of what a click on plate-placed ink can mean. The address may name an array element (`main.
|
|
203
|
+
A pick carries a caret where the compile tracks the content under the point, and the field alone where it tracks only the placement — a scalar the plate prints without tracking. `setCaret` takes both: an absent `pos` reveals and focuses the field, which is the whole of what a click on plate-placed ink can mean. The address may name an array element (`main.keywords[0]`), which lands on that row.
|
|
204
204
|
|
|
205
205
|
A consumer holding an `Addr` of its own maps it with `fieldPathForAddr` (from `@quillmark/svelte/core`). The playground app's split-pane route is the full reference shell: one session, both bridge directions, the preview following edits, and diagnostics routed inline.
|
|
206
206
|
|
package/THEMING.md
CHANGED
|
@@ -54,8 +54,8 @@ The poles take a colour, not `transparent` or `inherit`: the raised surfaces, th
|
|
|
54
54
|
| `--qm-bg` | `#fff` / `#272729` | Base surface: a card, and the preview's sheet. Fields, the popover and the column behind the cards each step off it. |
|
|
55
55
|
| `--qm-fg` | `#1c1c1c` / `#d7dadc` | Base ink. Body text, labels, and borders step off it. |
|
|
56
56
|
| `--qm-accent` | `#71717a` / `#a1a1aa` | Focus rings, active marks, the preview's active field box. The surface spends no hue of its own, so this is the one it wears. |
|
|
57
|
-
| `--qm-danger` | `#c5221f`
|
|
58
|
-
| `--qm-warning` | `#b25000`
|
|
57
|
+
| `--qm-danger` | `#c5221f` / `#ff9c94` | Error diagnostics, the required marker, the delete glyph. |
|
|
58
|
+
| `--qm-warning` | `#b25000` / `#e0b44c` | Warning diagnostics. |
|
|
59
59
|
| `--qm-font` | `ui-sans-serif, system-ui, sans-serif` | The editor surface's font family. Controls and buttons take it too, in place of the UA face. |
|
|
60
60
|
| `--qm-font-mono` | `ui-monospace, monospace` | The monospace face: the JSON array control, the tips card. |
|
|
61
61
|
| `--qm-font-size` | `0.875rem` | Chrome text: every control's size, the anchor the ramp derives up (title) and down (label/meta) from, and the anchor a document body sits one small step over. |
|
|
@@ -80,7 +80,7 @@ Declared before our sheet it fixes the order outright; declared after, `qm` is a
|
|
|
80
80
|
|
|
81
81
|
Ink steps `fg → bg` and the borders and hover fills step `bg → fg`, mixed in **oklab**, so inverting the two poles inverts all of them together.
|
|
82
82
|
|
|
83
|
-
**Planes are the exception**, and deliberately: the raised plane is the brighter one in both schemes, which is what makes a card read as a card rather than as a differently-tinted page. So the column under the cards sinks from `--qm-bg` toward shadow and a floating surface rises from it toward light, and neither reads the ink pole.
|
|
83
|
+
**Planes are the exception**, and deliberately: the raised plane is the brighter one in both schemes, which is what makes a card read as a card rather than as a differently-tinted page. So the column under the cards sinks from `--qm-bg` toward shadow and a floating surface rises from it toward light, and neither reads the ink pole. How far each steps is a function of the card's own lightness — a dark card has to spend more before the plane above it reads as lifted — so a palette pinned at neither pole takes a proportionate step without being told which scheme it is in.
|
|
84
84
|
|
|
85
85
|
Which way the poles default is **your `color-scheme`**, not the operating system's. Declare the scheme your app is in and the surface lands on it, along with native chrome, which reads the same property:
|
|
86
86
|
|
|
@@ -106,7 +106,11 @@ Setting the poles yourself wins over the default in both schemes, so a fixed pal
|
|
|
106
106
|
}
|
|
107
107
|
```
|
|
108
108
|
|
|
109
|
-
|
|
109
|
+
That cuts both ways for the status hues: `--qm-danger` and `--qm-warning` each default to a pair calibrated against the card at both poles, and one pinned value replaces both arms, so a red measured against white carries into the dark scheme unmeasured. Pin them under your own scheme rule (`.dark { --qm-danger: … }`) where the colour your app means by error is itself scheme-aware.
|
|
110
|
+
|
|
111
|
+
A palette **pinned against** your own scheme still wants a second line, for a smaller reason than it used to be: the planes read your card's lightness, so the surface itself lands right either way, but the poles' own defaults, the status hues and native chrome all still read `color-scheme`. Pin it with them (`.my-editor { color-scheme: dark }`). Skip that line and what the browser paints — the selection highlight, the scrollbar, the spinner — stays on whichever scheme the host inherits, and a status hue you left to us is measured against the wrong card.
|
|
112
|
+
|
|
113
|
+
Pinning **one mount** rather than a page is the `style` prop, which lands on the same root: `<Preview style="color-scheme: dark" />`. There is no `scheme` prop, and deliberately — an inline declaration of ours would be the one thing your own CSS could not beat.
|
|
110
114
|
|
|
111
115
|
No JS runs and no media query: the derivation resolves through the cascade at paint time, so there is no `dark` prop and no mode toggle. The consumer's palette decides.
|
|
112
116
|
|
|
@@ -121,7 +125,7 @@ import '@quillmark/svelte/preset';
|
|
|
121
125
|
```html
|
|
122
126
|
<body class="qm-page">
|
|
123
127
|
<p class="qm-label">quill</p>
|
|
124
|
-
<pre class="qm-readout">
|
|
128
|
+
<pre class="qm-readout">specimen@1.0.0</pre>
|
|
125
129
|
</body>
|
|
126
130
|
```
|
|
127
131
|
|
|
@@ -198,4 +202,4 @@ The derived surface scale (surface / border / ink rungs, the blur radius, the po
|
|
|
198
202
|
|
|
199
203
|
## Requirements
|
|
200
204
|
|
|
201
|
-
`@layer`, `color-mix()
|
|
205
|
+
`@layer`, `color-mix()`, `light-dark()` and relative colour syntax (`oklab(from …)`): Baseline since 2022, 2023, 2024 and 2024 respectively — the last is what lets a plane step by the card's own lightness. `@property` is the one feature the surface does not require: where it is missing, an invalid length dial collapses the surface rather than falling back.
|
package/dist/core/address.d.ts
CHANGED
|
@@ -63,7 +63,7 @@ export declare function cardPath(index: number, kinds: readonly string[]): DocPa
|
|
|
63
63
|
/**
|
|
64
64
|
* The inverse: a canonical `DocPath` back to the `Addr` the document verbs take, or
|
|
65
65
|
* `undefined` for a path that names no single commit address — a nested or
|
|
66
|
-
* array-element path (`main.
|
|
66
|
+
* array-element path (`main.keywords[0]`, which {@link elementAddrForFieldPath}
|
|
67
67
|
* takes instead), a field-rooted one, or a malformed one. A bare card and a `.body`
|
|
68
68
|
* terminal both land on the field-less `{card: i}` the body leaf answers to.
|
|
69
69
|
*
|
|
@@ -72,16 +72,10 @@ export declare function cardPath(index: number, kinds: readonly string[]): DocPa
|
|
|
72
72
|
*/
|
|
73
73
|
export declare function addrForFieldPath(path: DocPath): Addr | undefined;
|
|
74
74
|
/**
|
|
75
|
-
* An array element's address, split
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
* Both spellings, because the boundary mints one and formats the other: `regions()`
|
|
80
|
-
* and `positionAt` emit `main.references.0`, which `parseDocPath` reads as a field
|
|
81
|
-
* literally named `"0"`, while `formatDocPath` spells the index segment
|
|
82
|
-
* `main.references[0]`. A trailing all-digits field name is therefore an index that
|
|
83
|
-
* lost its brackets — but only under a field the schema declares an array, the
|
|
84
|
-
* caller's guard to apply: this module holds the grammar and no schema.
|
|
75
|
+
* An array element's address, split: `main.keywords[0]` lands here, and anything
|
|
76
|
+
* {@link addrForFieldPath} can name — or whose trailing segment is not an index —
|
|
77
|
+
* does not. `regions()`, `positionAt` and `formatDocPath` all spell the index
|
|
78
|
+
* segment bracketed, so there is one spelling to read and none to bridge.
|
|
85
79
|
*/
|
|
86
80
|
export declare function elementAddrForFieldPath(path: DocPath): ElementAddr | undefined;
|
|
87
81
|
/** An array element's address: the array's `Addr`, and which element of it. */
|
package/dist/core/address.js
CHANGED
|
@@ -37,7 +37,7 @@ export function cardPath(index, kinds) {
|
|
|
37
37
|
/**
|
|
38
38
|
* The inverse: a canonical `DocPath` back to the `Addr` the document verbs take, or
|
|
39
39
|
* `undefined` for a path that names no single commit address — a nested or
|
|
40
|
-
* array-element path (`main.
|
|
40
|
+
* array-element path (`main.keywords[0]`, which {@link elementAddrForFieldPath}
|
|
41
41
|
* takes instead), a field-rooted one, or a malformed one. A bare card and a `.body`
|
|
42
42
|
* terminal both land on the field-less `{card: i}` the body leaf answers to.
|
|
43
43
|
*
|
|
@@ -49,32 +49,21 @@ export function addrForFieldPath(path) {
|
|
|
49
49
|
return segs && addrForSegs(segs);
|
|
50
50
|
}
|
|
51
51
|
/**
|
|
52
|
-
* An array element's address, split
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
* Both spellings, because the boundary mints one and formats the other: `regions()`
|
|
57
|
-
* and `positionAt` emit `main.references.0`, which `parseDocPath` reads as a field
|
|
58
|
-
* literally named `"0"`, while `formatDocPath` spells the index segment
|
|
59
|
-
* `main.references[0]`. A trailing all-digits field name is therefore an index that
|
|
60
|
-
* lost its brackets — but only under a field the schema declares an array, the
|
|
61
|
-
* caller's guard to apply: this module holds the grammar and no schema.
|
|
52
|
+
* An array element's address, split: `main.keywords[0]` lands here, and anything
|
|
53
|
+
* {@link addrForFieldPath} can name — or whose trailing segment is not an index —
|
|
54
|
+
* does not. `regions()`, `positionAt` and `formatDocPath` all spell the index
|
|
55
|
+
* segment bracketed, so there is one spelling to read and none to bridge.
|
|
62
56
|
*/
|
|
63
57
|
export function elementAddrForFieldPath(path) {
|
|
64
58
|
const segs = segsOf(path);
|
|
65
59
|
if (!segs)
|
|
66
60
|
return undefined;
|
|
67
61
|
const last = segs[segs.length - 1];
|
|
68
|
-
|
|
69
|
-
? last.index
|
|
70
|
-
: last?.seg === 'field' && /^\d+$/.test(last.name)
|
|
71
|
-
? Number(last.name)
|
|
72
|
-
: undefined;
|
|
73
|
-
if (index == null)
|
|
62
|
+
if (last?.seg !== 'index')
|
|
74
63
|
return undefined;
|
|
75
64
|
const field = addrForSegs(segs.slice(0, -1));
|
|
76
65
|
// A body has no elements: the parent must name a field.
|
|
77
|
-
return field?.field != null ? { field, index } : undefined;
|
|
66
|
+
return field?.field != null ? { field, index: last.index } : undefined;
|
|
78
67
|
}
|
|
79
68
|
/** `parseDocPath`, with a malformed path as `undefined` rather than a throw. The gate
|
|
80
69
|
* is read outside the try: an uninitialized core is not a malformed path, and would
|
|
@@ -44,11 +44,10 @@ function markInputRule(regexp, markType, delimLen) {
|
|
|
44
44
|
* `heading` being wrapped becomes a `paragraph` first.
|
|
45
45
|
*
|
|
46
46
|
* `list_item` is `block+`, so `list_item > heading` is *representable* and a bare
|
|
47
|
-
* wrap mints it
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
* other, in {@link markdownInputRules}.
|
|
47
|
+
* wrap mints it — a shape markdown has no spelling for, so nothing downstream is
|
|
48
|
+
* obliged to typeset it and the gesture that made it cannot be read back. This is
|
|
49
|
+
* the wrap-side route into it; the `# ` rule guards the other, in
|
|
50
|
+
* {@link markdownInputRules}.
|
|
52
51
|
*
|
|
53
52
|
* `item` is the second guard, and it is about the gesture rather than the shape: the
|
|
54
53
|
* rule declines at the start of an item's own first block ({@link openingAnItem}).
|
|
@@ -84,16 +84,17 @@ li.ProseMirror-selectednode::after {
|
|
|
84
84
|
emits, minus the four the UA already renders correctly (`strong`, `em`, `u`, `s`)
|
|
85
85
|
and the blockquote above.
|
|
86
86
|
|
|
87
|
-
Each rule answers to the
|
|
87
|
+
Each rule answers to the leaf's own job rather than to a browser default or to a
|
|
88
88
|
web editor's chrome, because the leaf sits beside a live preview of the same
|
|
89
|
-
content.
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
at
|
|
89
|
+
content. A leaf shows *that* a span is code and a line is a heading: never a
|
|
90
|
+
prediction of the size paper will set it at, which the package cannot know for a
|
|
91
|
+
quill it has not seen. The reference quill is the case in point — it sets `raw` in
|
|
92
|
+
the face it bundles, scales a heading by its level and colours it, and gives a link
|
|
93
|
+
no decoration at all — and mirroring any of that here would be a guess about the
|
|
94
|
+
next quill.
|
|
94
95
|
|
|
95
96
|
Scoping is by tag, and the schema does the rest: `h1`–`h6`, `hr` and the lists
|
|
96
|
-
cannot exist under the inline schema, so no rule for them can land on
|
|
97
|
+
cannot exist under the inline schema, so no rule for them can land on an inline
|
|
97
98
|
field however that field is mounted. The two marks are the exception: `code` and
|
|
98
99
|
`link` are in both schemas, and a `plaintext` leaf strips them at decode while
|
|
99
100
|
mounting a schema that still carries them, so a paste can put either in one. The
|
package/dist/core/theme.css
CHANGED
|
@@ -89,8 +89,16 @@
|
|
|
89
89
|
/* Neutral: the surface spends no hue on a state it can draw in grey. The pair
|
|
90
90
|
clears WCAG 2.4.11's 3:1 against the card at both poles, at 4.8:1 and 5.8:1. */
|
|
91
91
|
--_qm-accent: var(--qm-accent, light-dark(#71717a, #a1a1aa));
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
/* The two hues the surface does spend, and it spends them on a state. Each pole
|
|
93
|
+
is its own figure rather than one ink shown twice: a hue calibrated against
|
|
94
|
+
white reads as a stain on a dark card. All four clear WCAG 1.4.3's 4.5:1
|
|
95
|
+
against the card, which is the bar the label rung asks for and the one the
|
|
96
|
+
glyphs drawn in these hues clear on the way past 1.4.11's 3:1 — 5.8:1 and
|
|
97
|
+
5.2:1 light, 7.4:1 and 7.7:1 dark. The figures are the host scale's
|
|
98
|
+
(`preset/scale.css`), so a page's status line and a card's diagnostic carry
|
|
99
|
+
one colour meaning error and one meaning warning. */
|
|
100
|
+
--_qm-danger: var(--qm-danger, light-dark(#c5221f, #ff9c94));
|
|
101
|
+
--_qm-warning: var(--qm-warning, light-dark(#b25000, #e0b44c));
|
|
94
102
|
--_qm-font: var(--qm-font, ui-sans-serif, system-ui, sans-serif);
|
|
95
103
|
--_qm-font-mono: var(--qm-font-mono, ui-monospace, monospace);
|
|
96
104
|
|
|
@@ -118,46 +126,45 @@
|
|
|
118
126
|
a channel of each other, which is where a card with little light left to
|
|
119
127
|
give up leaves them.
|
|
120
128
|
|
|
121
|
-
|
|
122
|
-
surface has to spend more of what little it has
|
|
123
|
-
|
|
124
|
-
the
|
|
125
|
-
|
|
126
|
-
|
|
129
|
+
How far each sinks is a function of the card's own L, not of the scheme the
|
|
130
|
+
host declared: a dark surface has to spend more of what little it has
|
|
131
|
+
before the card above it reads as lifted, so the two calibrated distances
|
|
132
|
+
— 0.0214 off white, 0.0553 off the dark default — interpolate linearly
|
|
133
|
+
between. A card pinned at neither pole takes a proportionate step whatever
|
|
134
|
+
`color-scheme` says, which is the half of the derivation that reads a
|
|
135
|
+
colour rather than a declaration.
|
|
127
136
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
neutral, and a ground is a fixed distance
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
`raised` is a no-op at the light pole, where the card is already white
|
|
137
|
-
and there is nowhere further to go, so a floating surface separates on
|
|
138
|
-
its hairline in light and on the step in dark. */
|
|
137
|
+
Both sink by subtraction where every other rung mixes: a mix toward black
|
|
138
|
+
is a ratio, so it scales what it takes and pulls the result toward
|
|
139
|
+
neutral, and a ground is a fixed distance. `a b` pass through, so the
|
|
140
|
+
plane keeps the pole's hue and a turned `--qm-bg` tints it. The defaults
|
|
141
|
+
land within a channel of `#f7f8f9` and `#1a1a1b`. Below L ≈ 0.065 the
|
|
142
|
+
ground clamps to black, which is where a near-black card leaves no room
|
|
143
|
+
for a ground of its own. */
|
|
139
144
|
--_qm-surface: var(--_qm-bg);
|
|
140
|
-
--_qm-surface-sunken:
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
color-mix(in oklab, var(--_qm-bg), #000 20%)
|
|
147
|
-
);
|
|
145
|
+
--_qm-surface-sunken: oklab(from var(--_qm-bg) calc(l - (0.0214 + 0.0467 * (1 - l))) a b);
|
|
146
|
+
--_qm-surface-well: oklab(from var(--_qm-bg) calc(l - (0.04 + 0.0202 * (1 - l))) a b);
|
|
147
|
+
/* `raised` is the same ramp spelled as a mix, its step 0.08 × (1 − l): the light
|
|
148
|
+
arm is zero, a white card having nowhere further to go, so a floating surface
|
|
149
|
+
separates on its hairline and `--_qm-lift` there and the step joins them in
|
|
150
|
+
dark. */
|
|
148
151
|
--_qm-surface-raised: color-mix(in oklab, var(--_qm-bg), #fff 8%);
|
|
149
152
|
--_qm-surface-hover: color-mix(in oklab, var(--_qm-bg), var(--_qm-fg) 8%);
|
|
150
153
|
--_qm-border: color-mix(in oklab, var(--_qm-bg), var(--_qm-fg) 17%);
|
|
151
154
|
/* A rule that separates without structuring: the lines between a table's cells,
|
|
152
|
-
where the frame around them is the structure. Half the border
|
|
153
|
-
than a
|
|
154
|
-
surface behind it, not a fill
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
155
|
+
where the frame around them is the structure. Half the border, and read off
|
|
156
|
+
it rather than restated as a percentage of its own, so the two hold their
|
|
157
|
+
relationship at any mix: a stroke against the surface behind it, not a fill
|
|
158
|
+
stacked on one. */
|
|
159
|
+
--_qm-border-faint: color-mix(in oklab, var(--_qm-bg), var(--_qm-border) 50%);
|
|
160
|
+
/* Two rungs, and there is no third: a step below `label` lands under 3:1 on the
|
|
161
|
+
well a field draws it against, and what would take it — a placeholder, an
|
|
162
|
+
unset value, the resolved `default:` — is content a reader has to read
|
|
163
|
+
(WCAG 1.4.3), not decoration. So tone carries hierarchy alone, and a leaf
|
|
164
|
+
saying shown-never-written says it against the `ink` a written value takes,
|
|
165
|
+
in italic where it has no written neighbour to be read against. */
|
|
158
166
|
--_qm-ink: var(--_qm-fg);
|
|
159
167
|
--_qm-ink-label: color-mix(in oklab, var(--_qm-fg), var(--_qm-bg) 35%);
|
|
160
|
-
--_qm-ink-ghost: color-mix(in oklab, var(--_qm-fg), var(--_qm-bg) 60%);
|
|
161
168
|
/* The arrival wash (`core/bloom.ts`). Its alpha is a peak, not a tint: the
|
|
162
169
|
wash animates from and back to zero, never held, so it reads over the leaf it
|
|
163
170
|
lands on while the leaf rests clean. */
|
|
@@ -208,16 +215,21 @@
|
|
|
208
215
|
--_qm-tips-font: 'Courier Prime', 'Courier New', Courier, ui-monospace, monospace;
|
|
209
216
|
|
|
210
217
|
/* ── Ratios and effects ──────────────────────────────────────────────────
|
|
211
|
-
No palette fixes these, so they are their own rungs.
|
|
212
|
-
rung: elevation is a tone rung and a hairline, which say the same thing at
|
|
213
|
-
both poles, where a shadow's offset states a light source the poles do not
|
|
214
|
-
carry. `check:style` forbids the property outright,
|
|
215
|
-
here as well as over the surfaces, so the absence is gated rather than
|
|
216
|
-
remembered. */
|
|
218
|
+
No palette fixes these, so they are their own rungs. */
|
|
217
219
|
--_qm-blur: 8px;
|
|
218
220
|
/* The popover's translucency: the raised surface mixed toward transparent, so
|
|
219
221
|
the page reads faintly through the pill. */
|
|
220
222
|
--_qm-surface-popover: color-mix(in oklab, var(--_qm-surface-raised) 82%, transparent);
|
|
223
|
+
/* What a surface with no plane under it lifts on. A tone rung cannot carry that at
|
|
224
|
+
both poles: `raised` is a no-op against a white card (§Colour), so in light the
|
|
225
|
+
hairline is otherwise the whole separation over the body prose these float on.
|
|
226
|
+
Offset-free is the whole of it: an offset states where the light is and no pole
|
|
227
|
+
carries that, where a halo states occlusion. Toward black at both poles for the
|
|
228
|
+
same reason — a crevice is darker than what surrounds it in a dark room too — so
|
|
229
|
+
the cue means one thing whichever way the scale runs. Spent only on what portals;
|
|
230
|
+
`check:style` holds the offsets at zero here and the rung as the only shadow
|
|
231
|
+
anywhere. */
|
|
232
|
+
--_qm-lift: 0 0 12px color-mix(in oklab, #000 16%, transparent);
|
|
221
233
|
/* The recede ladder: a hover-revealed or disabled affordance at rest, and a
|
|
222
234
|
muted one. Opacity recedes toward whatever is behind, so these invert
|
|
223
235
|
correctly given the element's own colour is a rung. */
|
package/dist/preset/recipes.css
CHANGED
|
@@ -183,7 +183,7 @@ html:has(.qm-workspace) {
|
|
|
183
183
|
/* ── Type ──────────────────────────────────────────────────────────────────── */
|
|
184
184
|
|
|
185
185
|
/* A run of chrome type: a section's label, a panel's caption, the name over a readout.
|
|
186
|
-
Uppercase and tracked, which is what keeps a run this small legible at the
|
|
186
|
+
Uppercase and tracked, which is what keeps a run this small legible at the meta
|
|
187
187
|
rung. */
|
|
188
188
|
.qm-label {
|
|
189
189
|
font-family: var(--qmh-font-mono);
|
|
@@ -191,7 +191,7 @@ html:has(.qm-workspace) {
|
|
|
191
191
|
line-height: var(--qmh-leading-tight);
|
|
192
192
|
letter-spacing: var(--qmh-track-label);
|
|
193
193
|
text-transform: uppercase;
|
|
194
|
-
color: var(--qmh-
|
|
194
|
+
color: var(--qmh-ink-meta);
|
|
195
195
|
margin: 0;
|
|
196
196
|
}
|
|
197
197
|
|
|
@@ -232,7 +232,7 @@ pre.qm-readout {
|
|
|
232
232
|
line-height: var(--qmh-leading-tight);
|
|
233
233
|
letter-spacing: var(--qmh-track-label);
|
|
234
234
|
text-transform: uppercase;
|
|
235
|
-
color: var(--qmh-
|
|
235
|
+
color: var(--qmh-ink-meta);
|
|
236
236
|
margin: 0;
|
|
237
237
|
}
|
|
238
238
|
|
package/dist/preset/scale.css
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/* The host'S derivation: the same public dials in, a closed `--qmh-*` scale for the
|
|
2
2
|
page around the surfaces out. `core/theme.css` is the same shape one level down
|
|
3
3
|
(dials in, `--_qm-*` out), and the two are calibrated against each other: the
|
|
4
|
-
figures here are the figures there (the ground step's
|
|
5
|
-
border, 45%
|
|
6
|
-
both, so a host plate and a card on it land on the same
|
|
7
|
-
host page meets an editor's own column exactly. The well
|
|
8
|
-
host's own controls are boxed and carry a
|
|
9
|
-
step an edgeless field does.
|
|
4
|
+
figures here are the figures there (the ground step's ramp, 8% hover, 17%
|
|
5
|
+
border, 45% ink, the ring's width, the status hues at both poles) and the
|
|
6
|
+
dial means the same plane in both, so a host plate and a card on it land on the same
|
|
7
|
+
tone at both poles and a host page meets an editor's own column exactly. The well
|
|
8
|
+
under the ground has no counterpart here: a host's own controls are boxed and carry a
|
|
9
|
+
hairline, so nothing on a page needs the step an edgeless field does.
|
|
10
10
|
|
|
11
11
|
Two scales rather than one because they answer to different roots. `--_qm-*` is
|
|
12
12
|
declared on each mounted root, out of reach from an ancestor, so a surface holds its
|
|
@@ -26,30 +26,32 @@
|
|
|
26
26
|
/* ── Colour ──────────────────────────────────────────────────────────────── */
|
|
27
27
|
/* The dial is the plate, exactly as it is the card one level down: a plate beside
|
|
28
28
|
a mounted editor is the same plane as a card in it, so both read the pole and
|
|
29
|
-
the page sinks from it by the same
|
|
29
|
+
the page sinks from it by the same ramp. That is what puts a host page and
|
|
30
30
|
an editor's own column on one tone rather than a plane apart. Planes step by
|
|
31
31
|
light and everything else by ink, which is the package's own split
|
|
32
|
-
(ARCHITECTURE §Styling); the figures are its figures.
|
|
32
|
+
(ARCHITECTURE §Styling); the figures are its figures. `Canvas` flips with the
|
|
33
|
+
declared scheme on its own, so the ramp reads whichever plane it resolved to
|
|
34
|
+
rather than trusting an arm to match. */
|
|
33
35
|
--qmh-surface: var(--qm-bg, Canvas);
|
|
34
|
-
--qmh-page:
|
|
35
|
-
oklab(from var(--qmh-surface) calc(l - 0.0214) calc(a - 0.00065) calc(b - 0.00158)),
|
|
36
|
-
oklab(from var(--qmh-surface) calc(l - 0.0553) calc(a - 0.00048) calc(b + 0.00165))
|
|
37
|
-
);
|
|
36
|
+
--qmh-page: oklab(from var(--qmh-surface) calc(l - (0.0214 + 0.0467 * (1 - l))) a b);
|
|
38
37
|
--qmh-ink: var(--qm-fg, CanvasText);
|
|
38
|
+
/* One step off the ink and no second: a page's chrome type is small, tracked and
|
|
39
|
+
uppercase, so a rung below this reads under 4.5:1 against the plate and the
|
|
40
|
+
label and status lines that would take it are text (WCAG 1.4.3). */
|
|
39
41
|
--qmh-ink-meta: color-mix(in oklab, var(--qmh-ink), var(--qmh-surface) 45%);
|
|
40
|
-
--qmh-ghost: color-mix(in oklab, var(--qmh-ink), var(--qmh-surface) 60%);
|
|
41
42
|
--qmh-surface-hover: color-mix(in oklab, var(--qmh-surface), var(--qmh-ink) 8%);
|
|
42
43
|
--qmh-border: color-mix(in oklab, var(--qmh-surface), var(--qmh-ink) 17%);
|
|
43
44
|
/* The edge that says "engaged" where the hairline says "edge": a pressed switch,
|
|
44
45
|
the underline under a link. */
|
|
45
46
|
--qmh-border-strong: color-mix(in oklab, var(--qmh-surface), var(--qmh-ink) 40%);
|
|
46
47
|
|
|
47
|
-
/* The two hues a host spends, and it spends them on a message.
|
|
48
|
-
so a page carries one colour meaning error and one meaning warning
|
|
49
|
-
second pair beside the surfaces'.
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
--qmh-
|
|
48
|
+
/* The two hues a host spends, and it spends them on a message. The figures are the
|
|
49
|
+
surfaces' own, so a page carries one colour meaning error and one meaning warning
|
|
50
|
+
rather than a second pair beside the surfaces'. Each pole is its own figure: a hue
|
|
51
|
+
calibrated against white reads as a stain on a dark page. The dial sits in front
|
|
52
|
+
of the pair, as every pole's does, so a host that turns one owns both schemes. */
|
|
53
|
+
--qmh-alert: var(--qm-danger, light-dark(#c5221f, #ff9c94));
|
|
54
|
+
--qmh-warn: var(--qm-warning, light-dark(#b25000, #e0b44c));
|
|
53
55
|
|
|
54
56
|
/* ── Rhythm ──────────────────────────────────────────────────────────────── */
|
|
55
57
|
/* One base and its multiples, the same four steps the surfaces derive. A host
|
|
@@ -22,9 +22,10 @@ export interface PdfPoint {
|
|
|
22
22
|
* its content and for a `richtext[]` element; runtime.d.ts says what such a field's
|
|
23
23
|
* box is, a single `regions()` rect. The third rung is that sentence one granularity
|
|
24
24
|
* down — an array's ink is its elements' — and is a fallback, not a union, so an
|
|
25
|
-
* address with rects of its own never also draws its children's. The
|
|
26
|
-
*
|
|
27
|
-
* `main.
|
|
25
|
+
* address with rects of its own never also draws its children's. The boundary
|
|
26
|
+
* character (`.` for a nested field, `[` for an array element) keeps the prefix a
|
|
27
|
+
* path boundary: `main.keywords` matches `main.keywords[0]`, not
|
|
28
|
+
* `main.keywords_note`.
|
|
28
29
|
*/
|
|
29
30
|
export declare function boxesForField(field: string, boxes: readonly FieldRegion[], regions: readonly FieldRegion[]): readonly FieldRegion[];
|
|
30
31
|
/**
|
package/dist/preview/geometry.js
CHANGED
|
@@ -7,15 +7,18 @@
|
|
|
7
7
|
* its content and for a `richtext[]` element; runtime.d.ts says what such a field's
|
|
8
8
|
* box is, a single `regions()` rect. The third rung is that sentence one granularity
|
|
9
9
|
* down — an array's ink is its elements' — and is a fallback, not a union, so an
|
|
10
|
-
* address with rects of its own never also draws its children's. The
|
|
11
|
-
*
|
|
12
|
-
* `main.
|
|
10
|
+
* address with rects of its own never also draws its children's. The boundary
|
|
11
|
+
* character (`.` for a nested field, `[` for an array element) keeps the prefix a
|
|
12
|
+
* path boundary: `main.keywords` matches `main.keywords[0]`, not
|
|
13
|
+
* `main.keywords_note`.
|
|
13
14
|
*/
|
|
14
15
|
export function boxesForField(field, boxes, regions) {
|
|
15
16
|
if (boxes.length)
|
|
16
17
|
return boxes;
|
|
17
18
|
const own = regions.filter((r) => r.field === field);
|
|
18
|
-
|
|
19
|
+
if (own.length)
|
|
20
|
+
return own;
|
|
21
|
+
return regions.filter((r) => r.field.startsWith(`${field}.`) || r.field.startsWith(`${field}[`));
|
|
19
22
|
}
|
|
20
23
|
/**
|
|
21
24
|
* Forward: a PDF-pt rect -> CSS % of the page box. Percent positioning tracks
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
An `array` field → an add/remove repeater. Elements commit by value: every
|
|
3
3
|
edit / add / remove rebuilds the whole array and hands it to the parent's typed
|
|
4
4
|
`writer.set(field, wholeArray)` (arrays are not op-addressed). Element control
|
|
5
|
-
by `items.type`: `string` → text input, `richtext` → a prose element
|
|
5
|
+
by `items.type`: `string` / `plaintext` → text input, `richtext` → a prose element
|
|
6
6
|
({@link ProseArrayElement}), `object` → a minimal JSON editor, keeping the prior
|
|
7
7
|
element value on an entry that does not parse. The add affordance sits in the
|
|
8
8
|
label header row (space-between with the field label); {@link Field} skips its
|
|
@@ -59,10 +59,16 @@
|
|
|
59
59
|
let { value, items, label, required, description, labelId, descriptionId, onCommit }: Props =
|
|
60
60
|
$props();
|
|
61
61
|
|
|
62
|
-
// The element control is the item schema's own
|
|
63
|
-
//
|
|
64
|
-
|
|
65
|
-
|
|
62
|
+
// The element control is the item schema's own, with one departure: a `plaintext`
|
|
63
|
+
// element is a text input where the scalar field of that type is a prose leaf. A
|
|
64
|
+
// `plaintext` value rests as its literal string (canon SCHEMAS.md §"Content fields
|
|
65
|
+
// rest per codec"), and the read that decodes a resting value to `Content` addresses
|
|
66
|
+
// a field, never an element (`getContent`; borb-sh/quillmark#1243), so a string is
|
|
67
|
+
// what the row is handed and a string is what it commits. The prose element stays
|
|
68
|
+
// the `richtext` arm, whose elements rest as `Content` and have one.
|
|
69
|
+
//
|
|
70
|
+
// An array declaring no `items` has text elements.
|
|
71
|
+
const control = $derived(items && items.type !== 'plaintext' ? controlKind(items) : 'text');
|
|
66
72
|
const arr = $derived((value ?? []) as unknown[]);
|
|
67
73
|
|
|
68
74
|
// Parallel stable ids, one per element, kept in lockstep with the data below.
|
|
@@ -243,7 +249,6 @@
|
|
|
243
249
|
<ProseArrayElement
|
|
244
250
|
bind:this={els[id]}
|
|
245
251
|
value={(arr[k] ?? emptyElement()) as Content}
|
|
246
|
-
{plaintext}
|
|
247
252
|
label={label != null ? `${label} ${k + 1}` : undefined}
|
|
248
253
|
onChange={(rt) => commitElement(k, rt)}
|
|
249
254
|
onKey={(e) => onElementKey(e, k)}
|
package/dist/visual/Card.svelte
CHANGED
|
@@ -198,6 +198,6 @@
|
|
|
198
198
|
never written, either way. The marker is the component's own (see the snippet):
|
|
199
199
|
the date primitive emits no placeholder attribute of its own. */
|
|
200
200
|
.qm-date-wrap :global(.qm-date-segment[data-ghosted]) {
|
|
201
|
-
color: var(--_qm-ink-
|
|
201
|
+
color: var(--_qm-ink-label);
|
|
202
202
|
}
|
|
203
203
|
</style>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
A `
|
|
3
|
-
|
|
2
|
+
A `type: enum` field → a styled listbox over its `values`, on bits-ui. When
|
|
3
|
+
nothing is authored the list shows a distinct unset
|
|
4
4
|
sentinel that ghosts the `default:` (muted, shown-never-written), distinguishable
|
|
5
5
|
from an authored pick and re-selectable; so re-picking the default fires a
|
|
6
6
|
change. The sentinel commits nothing; any real pick: including the
|
|
@@ -164,7 +164,7 @@
|
|
|
164
164
|
/* Shown-never-written: the closed control reads muted while unset, matching the
|
|
165
165
|
ghosted placeholder the text/number controls show. */
|
|
166
166
|
.qm-select-wrap :global(.qm-select[data-ghosted]) {
|
|
167
|
-
color: var(--_qm-ink-
|
|
167
|
+
color: var(--_qm-ink-label);
|
|
168
168
|
}
|
|
169
169
|
/* The open list is `.qm-menu-surface` and its rows `.qm-menu-item` (controls.css):
|
|
170
170
|
the lift, the inset and the highlight are the shared menu recipe. What a listbox
|
|
@@ -184,6 +184,6 @@
|
|
|
184
184
|
cursor: default;
|
|
185
185
|
}
|
|
186
186
|
.qm-select-ghost {
|
|
187
|
-
color: var(--_qm-ink-
|
|
187
|
+
color: var(--_qm-ink-label);
|
|
188
188
|
}
|
|
189
189
|
</style>
|
package/dist/visual/Field.svelte
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
import type { EditorErrorHandler } from '../core/errors.js';
|
|
19
19
|
import type { LeafRegistry } from './leaves.js';
|
|
20
20
|
import type { FieldModel, FieldSpan } from './structure.js';
|
|
21
|
-
import {
|
|
21
|
+
import { ghostDefault, stringifyGhost } from './structure.js';
|
|
22
22
|
import type { FieldDomIds } from './domid.js';
|
|
23
23
|
import ProseField from './ProseField.svelte';
|
|
24
24
|
import TextField from './TextField.svelte';
|
|
@@ -207,7 +207,7 @@
|
|
|
207
207
|
{:else if field.control === 'enum'}
|
|
208
208
|
<EnumField
|
|
209
209
|
value={value as string | undefined}
|
|
210
|
-
values={
|
|
210
|
+
values={field.schema.values ?? []}
|
|
211
211
|
fallback={ghost as string | undefined}
|
|
212
212
|
id={domIds.control}
|
|
213
213
|
{describedBy}
|
|
@@ -186,8 +186,8 @@
|
|
|
186
186
|
It takes no fill either: the ink step below says hover, and the surface itself
|
|
187
187
|
opens on it. */
|
|
188
188
|
.qm-field-hint {
|
|
189
|
-
/* The marker recedes to the label
|
|
190
|
-
color: var(--_qm-ink-
|
|
189
|
+
/* The marker recedes to the label rung; the surface carries the text. */
|
|
190
|
+
color: var(--_qm-ink-label);
|
|
191
191
|
/* Not the family's `pointer`: the glyph raises guidance, it does not act. */
|
|
192
192
|
cursor: help;
|
|
193
193
|
padding: 0;
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
-->
|
|
12
12
|
<script lang="ts">
|
|
13
13
|
import type { QuillFieldSchema } from '@quillmark/wasm';
|
|
14
|
-
import { controlKind,
|
|
14
|
+
import { controlKind, humanize } from './structure.js';
|
|
15
15
|
import TextField from './TextField.svelte';
|
|
16
16
|
import EnumField from './EnumField.svelte';
|
|
17
17
|
import NumberField from './NumberField.svelte';
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
<EnumField
|
|
80
80
|
label={propLabel}
|
|
81
81
|
value={obj[key] as string | undefined}
|
|
82
|
-
values={
|
|
82
|
+
values={sub.values ?? []}
|
|
83
83
|
fallback={sub.default as string | undefined}
|
|
84
84
|
onCommit={(v) => commitProp(key, v)}
|
|
85
85
|
/>
|
|
@@ -144,7 +144,7 @@
|
|
|
144
144
|
}
|
|
145
145
|
.qm-unsupported {
|
|
146
146
|
font-size: var(--_qm-text-body);
|
|
147
|
-
color: var(--_qm-ink-
|
|
147
|
+
color: var(--_qm-ink-label);
|
|
148
148
|
font-style: italic;
|
|
149
149
|
}
|
|
150
150
|
</style>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
One element of an array-of-`richtext` field (fixture `
|
|
2
|
+
One element of an array-of-`richtext` field (fixture `keywords`). Array
|
|
3
3
|
elements are not `applyChange`-addressable: `Addr.field` is a flat name, so
|
|
4
|
-
`
|
|
4
|
+
`keywords[0]` has no op address. So
|
|
5
5
|
this is not a `createField` leaf: it mounts a minimal PM view over the codec's
|
|
6
6
|
decode/encode + inline schema, and on every edit hands the re-encoded
|
|
7
7
|
`Content` up to the parent {@link ArrayField}, which commits the whole array
|
|
@@ -19,7 +19,6 @@
|
|
|
19
19
|
|
|
20
20
|
interface Props {
|
|
21
21
|
value: Content;
|
|
22
|
-
plaintext?: boolean;
|
|
23
22
|
/** Accessible name for the editable region (the array has no per-element label). */
|
|
24
23
|
label?: string;
|
|
25
24
|
onChange: (rt: Content) => void;
|
|
@@ -28,7 +27,7 @@
|
|
|
28
27
|
* keymap, so the state it reads is the one this keystroke has yet to change. */
|
|
29
28
|
onKey?: (e: KeyboardEvent) => void;
|
|
30
29
|
}
|
|
31
|
-
let { value,
|
|
30
|
+
let { value, label, onChange, onKey }: Props = $props();
|
|
32
31
|
|
|
33
32
|
let containerEl: HTMLDivElement | undefined = $state();
|
|
34
33
|
let view: EditorView | undefined;
|
|
@@ -45,10 +44,10 @@
|
|
|
45
44
|
// plugin stack a `createField` leaf mounts (shared `proseLeafPlugins`), minus
|
|
46
45
|
// the anchor-position plugin (element anchors are dropped on the array's value
|
|
47
46
|
// write, per the header). Its own `dispatchTransaction` hands `Content` up.
|
|
48
|
-
const pmDoc = decode(value, inlineSchema
|
|
47
|
+
const pmDoc = decode(value, inlineSchema);
|
|
49
48
|
const state = EditorState.create({
|
|
50
49
|
doc: pmDoc,
|
|
51
|
-
plugins: proseLeafPlugins(inlineSchema, { inline: true, plaintext:
|
|
50
|
+
plugins: proseLeafPlugins(inlineSchema, { inline: true, plaintext: false })
|
|
52
51
|
});
|
|
53
52
|
const mounted = new EditorView(containerEl, {
|
|
54
53
|
state,
|
|
@@ -2,7 +2,6 @@ import './controls.css';
|
|
|
2
2
|
import type { Content } from '@quillmark/wasm';
|
|
3
3
|
interface Props {
|
|
4
4
|
value: Content;
|
|
5
|
-
plaintext?: boolean;
|
|
6
5
|
/** Accessible name for the editable region (the array has no per-element label). */
|
|
7
6
|
label?: string;
|
|
8
7
|
onChange: (rt: Content) => void;
|
|
@@ -179,11 +179,13 @@
|
|
|
179
179
|
.qm-prose :global(.ProseMirror) {
|
|
180
180
|
outline: none;
|
|
181
181
|
}
|
|
182
|
-
/* Empty-leaf ghost, at the scalar
|
|
183
|
-
stays out of the document; `float`/`height: 0` keep it from
|
|
182
|
+
/* Empty-leaf ghost, at the rung every scalar's placeholder takes: a node decoration's
|
|
183
|
+
data attr, so it stays out of the document; `float`/`height: 0` keep it from
|
|
184
|
+
displacing the caret. The italic is what a leaf with no written neighbour has
|
|
185
|
+
instead of the step to `ink`. */
|
|
184
186
|
.qm-prose :global(.ProseMirror .qm-prose-placeholder::before) {
|
|
185
187
|
content: attr(data-placeholder);
|
|
186
|
-
color: var(--_qm-ink-
|
|
188
|
+
color: var(--_qm-ink-label);
|
|
187
189
|
font-style: italic;
|
|
188
190
|
float: left;
|
|
189
191
|
height: 0;
|
|
@@ -736,12 +736,11 @@
|
|
|
736
736
|
* diagnostics take.
|
|
737
737
|
*
|
|
738
738
|
* Two rungs, because the boundary mints addresses at a finer granularity than
|
|
739
|
-
* `Addr` can name: a `richtext[]` element surfaces as `main.
|
|
740
|
-
*
|
|
741
|
-
*
|
|
742
|
-
*
|
|
743
|
-
*
|
|
744
|
-
* `pos` is an offset into the element's own content.
|
|
739
|
+
* `Addr` can name: a `richtext[]` element surfaces as `main.keywords[0]`. The
|
|
740
|
+
* second rung reads that trailing index segment under a field the schema declares
|
|
741
|
+
* an array — which is why the ladder is the editor's (VISUAL_EDITOR.md §Surface):
|
|
742
|
+
* the preview carries no schema, and truncating the address there is worse than
|
|
743
|
+
* guessing, since `pos` is an offset into the element's own content.
|
|
745
744
|
*/
|
|
746
745
|
function leafTargetFor(field: DocPath): LeafTarget | undefined {
|
|
747
746
|
const direct = addrForFieldPath(field);
|
package/dist/visual/controls.css
CHANGED
|
@@ -106,12 +106,13 @@
|
|
|
106
106
|
width: 100%;
|
|
107
107
|
box-sizing: border-box;
|
|
108
108
|
}
|
|
109
|
-
/* The native placeholder is the
|
|
110
|
-
number control's placeholder is the resolved `default:` (Field's `defaultStr`)
|
|
111
|
-
and reads
|
|
112
|
-
|
|
109
|
+
/* The native placeholder is the label rung, not the UA's own grey: a text or
|
|
110
|
+
number control's placeholder is the resolved `default:` (Field's `defaultStr`),
|
|
111
|
+
which is content and reads at a content's contrast. What says shown-never-written
|
|
112
|
+
is the step from the `ink` a written value takes, the same step the prose leaf's
|
|
113
|
+
empty state reads (`ProseField`). */
|
|
113
114
|
.qm-input::placeholder {
|
|
114
|
-
color: var(--_qm-ink-
|
|
115
|
+
color: var(--_qm-ink-label);
|
|
115
116
|
}
|
|
116
117
|
|
|
117
118
|
/* The second recipe, and it is not the box above: a field is a box because you
|
|
@@ -242,13 +243,15 @@
|
|
|
242
243
|
|
|
243
244
|
A floating surface is the one place a hairline is still load-bearing: it hangs
|
|
244
245
|
over content the surface did not choose, so there is no plane under it for a
|
|
245
|
-
tone to step off (ARCHITECTURE §Styling).
|
|
246
|
-
|
|
246
|
+
tone to step off (ARCHITECTURE §Styling). The edge and `--_qm-lift` carry it
|
|
247
|
+
there, and the raised rung joins them in dark, where a tone still has somewhere
|
|
248
|
+
to go. */
|
|
247
249
|
.qm-menu-surface {
|
|
248
250
|
padding: var(--_qm-space-half);
|
|
249
251
|
border: var(--_qm-border-width) solid var(--_qm-border);
|
|
250
252
|
border-radius: var(--_qm-radius);
|
|
251
253
|
background: var(--_qm-surface-raised);
|
|
254
|
+
box-shadow: var(--_qm-lift);
|
|
252
255
|
font-size: var(--_qm-text-body);
|
|
253
256
|
color: var(--_qm-ink);
|
|
254
257
|
}
|
|
@@ -291,6 +294,7 @@
|
|
|
291
294
|
-webkit-backdrop-filter: blur(var(--_qm-blur));
|
|
292
295
|
border: var(--_qm-border-width) solid var(--_qm-border);
|
|
293
296
|
border-radius: var(--_qm-radius);
|
|
297
|
+
box-shadow: var(--_qm-lift);
|
|
294
298
|
animation: qm-pop-in var(--_qm-duration-fast) var(--_qm-ease-reverse);
|
|
295
299
|
}
|
|
296
300
|
.qm-popover-surface[data-ending-style] {
|
|
@@ -150,8 +150,6 @@ export declare function resolveBodyGhost(resolvedDefault: string | undefined, cu
|
|
|
150
150
|
* An array's element control is this over `items`: a missing `items` is a text
|
|
151
151
|
* element. */
|
|
152
152
|
export declare function controlKind(f: QuillFieldSchema): ControlKind;
|
|
153
|
-
/** The closed value domain of an enum/enum-string field, or undefined. */
|
|
154
|
-
export declare function enumValues(f: QuillFieldSchema): string[] | undefined;
|
|
155
153
|
/** `foo_bar` → `Foo bar`: the label fallback when a field declares no `ui.title`. */
|
|
156
154
|
export declare function humanize(name: string): string;
|
|
157
155
|
/** Project a card schema's `fields` map (declaration = key order) into models. */
|
package/dist/visual/structure.js
CHANGED
|
@@ -57,9 +57,7 @@ export function controlKind(f) {
|
|
|
57
57
|
case 'enum':
|
|
58
58
|
return 'enum';
|
|
59
59
|
case 'string':
|
|
60
|
-
|
|
61
|
-
// promotes a string to a select; a bare string is a text input.
|
|
62
|
-
return enumValues(f) ? 'enum' : 'text';
|
|
60
|
+
return 'text';
|
|
63
61
|
case 'number':
|
|
64
62
|
case 'integer':
|
|
65
63
|
return 'number';
|
|
@@ -76,10 +74,6 @@ export function controlKind(f) {
|
|
|
76
74
|
return 'text';
|
|
77
75
|
}
|
|
78
76
|
}
|
|
79
|
-
/** The closed value domain of an enum/enum-string field, or undefined. */
|
|
80
|
-
export function enumValues(f) {
|
|
81
|
-
return f.enum ?? f.values;
|
|
82
|
-
}
|
|
83
77
|
/** `foo_bar` → `Foo bar`: the label fallback when a field declares no `ui.title`. */
|
|
84
78
|
export function humanize(name) {
|
|
85
79
|
const spaced = name.replace(/_/g, ' ').trim();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quillmark/svelte",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Editor, live-preview and source surfaces over a Quillmark WASM session.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"check": "svelte-check --tsconfig ./tsconfig.json"
|
|
67
67
|
},
|
|
68
68
|
"peerDependencies": {
|
|
69
|
-
"@quillmark/wasm": ">=0.
|
|
69
|
+
"@quillmark/wasm": ">=0.104.0-0",
|
|
70
70
|
"svelte": "^5.0.0"
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|