@quillmark/svelte 0.26.2 → 0.28.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/NOTICE +4 -4
- package/README.md +26 -8
- package/THEMING.md +40 -4
- package/dist/core/address.d.ts +35 -64
- package/dist/core/address.js +35 -55
- package/dist/core/bloom.d.ts +4 -10
- package/dist/core/bloom.js +14 -27
- package/dist/core/codec/blocks.d.ts +41 -43
- package/dist/core/codec/blocks.js +97 -130
- package/dist/core/codec/code.d.ts +7 -10
- package/dist/core/codec/code.js +37 -46
- package/dist/core/codec/decode.d.ts +19 -23
- package/dist/core/codec/decode.js +76 -111
- package/dist/core/codec/encode.d.ts +11 -15
- package/dist/core/codec/encode.js +60 -67
- package/dist/core/codec/field.d.ts +62 -95
- package/dist/core/codec/field.js +107 -179
- package/dist/core/codec/islands.d.ts +33 -41
- package/dist/core/codec/islands.js +76 -86
- package/dist/core/codec/lists.d.ts +17 -26
- package/dist/core/codec/lists.js +117 -157
- package/dist/core/codec/marks.d.ts +4 -3
- package/dist/core/codec/marks.js +8 -3
- package/dist/core/codec/prose.css +84 -46
- package/dist/core/codec/schema.d.ts +18 -23
- package/dist/core/codec/schema.js +84 -76
- package/dist/core/codec/slash.d.ts +42 -48
- package/dist/core/codec/slash.js +0 -0
- package/dist/core/codec/table-copy.d.ts +4 -3
- package/dist/core/codec/table-copy.js +25 -7
- package/dist/core/codec/table-view.d.ts +12 -12
- package/dist/core/codec/table-view.js +460 -383
- package/dist/core/codec/table.d.ts +94 -61
- package/dist/core/codec/table.js +331 -83
- package/dist/core/codec/tasks.d.ts +6 -0
- package/dist/core/codec/tasks.js +30 -3
- package/dist/core/errors.d.ts +15 -30
- package/dist/core/errors.js +2 -6
- package/dist/core/index.js +7 -12
- package/dist/core/lifecycle.d.ts +7 -16
- package/dist/core/lifecycle.js +10 -21
- package/dist/core/rebind.svelte.d.ts +10 -20
- package/dist/core/rebind.svelte.js +15 -27
- package/dist/core/rungs.d.ts +14 -11
- package/dist/core/rungs.js +17 -19
- package/dist/core/teardown.d.ts +4 -6
- package/dist/core/teardown.js +7 -10
- package/dist/core/theme.css +74 -54
- package/dist/index.js +3 -8
- package/dist/preset/app.css +71 -0
- package/dist/preset/index.css +8 -7
- package/dist/preset/recipes.css +19 -164
- package/dist/preset/scale.css +28 -18
- package/dist/preset/shell.css +157 -0
- package/dist/preview/Preview.svelte +8 -0
- package/dist/preview/bridge.d.ts +18 -22
- package/dist/preview/bridge.js +29 -58
- package/dist/preview/controller.d.ts +21 -29
- package/dist/preview/controller.js +14 -39
- package/dist/preview/geometry.d.ts +13 -34
- package/dist/preview/geometry.js +13 -34
- package/dist/preview/index.js +4 -16
- package/dist/preview/paint.d.ts +3 -3
- package/dist/preview/paint.js +28 -68
- package/dist/preview/strings.d.ts +1 -1
- package/dist/preview/strings.js +2 -14
- package/dist/preview/viewport.js +20 -15
- package/dist/preview/zoom.d.ts +21 -22
- package/dist/preview/zoom.js +53 -30
- package/dist/visual/ArrayField.svelte +77 -16
- package/dist/visual/BooleanField.svelte +28 -15
- package/dist/visual/Card.svelte +66 -51
- package/dist/visual/CardControls.svelte +5 -11
- package/dist/visual/DateField.svelte +20 -4
- package/dist/visual/EnumField.svelte +3 -0
- package/dist/visual/FieldHint.svelte +2 -1
- package/dist/visual/FormatPopover.svelte +82 -15
- package/dist/visual/FormatPopover.svelte.d.ts +4 -0
- package/dist/visual/MatrixAdd.svelte +30 -12
- package/dist/visual/MatrixField.svelte +24 -16
- package/dist/visual/NumberField.svelte +7 -0
- package/dist/visual/ObjectField.svelte +4 -4
- package/dist/visual/ProseField.svelte +0 -5
- package/dist/visual/TipsCard.svelte +11 -10
- package/dist/visual/VariantField.svelte +3 -1
- package/dist/visual/VisualEditorInner.svelte +19 -3
- package/dist/visual/controls.css +7 -2
- package/dist/visual/fonts.d.ts +18 -0
- package/dist/visual/fonts.js +59 -0
- package/dist/visual/icons/nodes.d.ts +0 -5
- package/dist/visual/icons/nodes.js +0 -4
- package/dist/visual/props.d.ts +14 -1
- package/dist/visual/strings.d.ts +7 -0
- package/dist/visual/strings.js +5 -2
- package/dist/visual/structure.d.ts +43 -87
- package/dist/visual/structure.js +42 -83
- package/package.json +2 -2
package/dist/core/theme.css
CHANGED
|
@@ -101,11 +101,10 @@
|
|
|
101
101
|
--_qm-font-mono: var(--qm-font-mono, ui-monospace, monospace);
|
|
102
102
|
|
|
103
103
|
/* ── Colour ──────────────────────────────────────────────────────────────
|
|
104
|
-
Ink steps fg → bg
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
for (17% ≈ #d4d4d4, 35% ≈ #555).
|
|
104
|
+
Ink steps fg → bg and the hover rung steps bg → fg, both mixed in oklab;
|
|
105
|
+
sRGB muddies the mid-tones and the label rung is exactly mid-tone. So
|
|
106
|
+
inverting the poles inverts that half of the scale. The percentages are
|
|
107
|
+
calibrated to the light-mode literals they stand in for (35% ≈ #555).
|
|
109
108
|
|
|
110
109
|
Planes are the half that does not read the ink pole, because what makes a
|
|
111
110
|
card read as a card is that it is the brighter plane, in both schemes
|
|
@@ -115,57 +114,68 @@
|
|
|
115
114
|
light, and the base plane — a card, the preview's paper — is the pole
|
|
116
115
|
itself.
|
|
117
116
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
117
|
+
One plane sinks, in two roles. `well` is the hole cut into a card: a field,
|
|
118
|
+
the one native select, neither of which draws an edge, so the step is the
|
|
119
|
+
whole of what says a value is typed there. `sunken` is the ground — the
|
|
120
|
+
column behind the cards, the desk behind the sheets — and it is the same
|
|
121
|
+
tone: a card draws no edge either, so the step off the ground is the whole
|
|
122
|
+
of where one card stops and the next starts, and the well's step is one
|
|
123
|
+
that carries that at the light pole. The order is card, then ground
|
|
124
|
+
and well together, at both poles.
|
|
126
125
|
|
|
127
|
-
How far
|
|
126
|
+
How far it sinks is a function of the card's own L, not of the scheme the
|
|
128
127
|
host declared: a dark surface has to spend more of what little it has
|
|
129
128
|
before the card above it reads as lifted, so the two calibrated distances
|
|
130
|
-
— 0.
|
|
129
|
+
— 0.04 off white, 0.0547 off the dark default — interpolate linearly
|
|
131
130
|
between. A card pinned at neither pole takes a proportionate step whatever
|
|
132
131
|
`color-scheme` says, which is the half of the derivation that reads a
|
|
133
132
|
colour rather than a declaration.
|
|
134
133
|
|
|
135
|
-
|
|
134
|
+
It sinks by subtraction where every other rung mixes: a mix toward black
|
|
136
135
|
is a ratio, so it scales what it takes and pulls the result toward
|
|
137
136
|
neutral, and a ground is a fixed distance. `a b` pass through, so the
|
|
138
137
|
plane keeps the pole's hue and a turned `--qm-bg` tints it. The defaults
|
|
139
|
-
land within a channel of `#
|
|
140
|
-
|
|
138
|
+
land within a channel of `#f2f2f2` and `#1a1a1c`. Below L ≈ 0.06 the
|
|
139
|
+
plane clamps to black, which is where a near-black card leaves no room
|
|
141
140
|
for a ground of its own. */
|
|
142
141
|
--_qm-surface: var(--_qm-bg);
|
|
143
|
-
--_qm-surface-sunken: oklab(from var(--_qm-bg) calc(l - (0.0214 + 0.0467 * (1 - l))) a b);
|
|
144
142
|
--_qm-surface-well: oklab(from var(--_qm-bg) calc(l - (0.04 + 0.0202 * (1 - l))) a b);
|
|
143
|
+
--_qm-surface-sunken: var(--_qm-surface-well);
|
|
145
144
|
/* `raised` is the same ramp spelled as a mix, its step 0.08 × (1 − l): the light
|
|
146
145
|
arm is zero, a white card having nowhere further to go, so a floating surface
|
|
147
146
|
separates on its hairline and `--_qm-lift` there and the step joins them in
|
|
148
147
|
dark. */
|
|
149
148
|
--_qm-surface-raised: color-mix(in oklab, var(--_qm-bg), #fff 8%);
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
--_qm-surface-
|
|
155
|
-
/*
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
149
|
+
/* A step toward the ink laid over whatever plane is under it, rather than a tone off
|
|
150
|
+
the card: a hover lands on the card, a well, a band and a floating surface, and a
|
|
151
|
+
fixed tone stepped off the first sits level with `raised` in dark. Translucent, as
|
|
152
|
+
the accent's tint is, so the step is the same over each. */
|
|
153
|
+
--_qm-surface-hover: color-mix(in oklab, var(--_qm-fg) 8%, transparent);
|
|
154
|
+
/* A band laid on the card rather than cut into it: a table's header, the pill a
|
|
155
|
+
grip draws, the off switch's track and the unticked box. A resting fill, where
|
|
156
|
+
`hover` above is a state, so the two have to be told apart on a card that shows
|
|
157
|
+
both at once: each arm stands one ground step past the hover step at its pole,
|
|
158
|
+
which lands the band two steps off the card in dark and a little over in light.
|
|
159
|
+
It steps toward the ink at both poles, a shade under white in light and a shade
|
|
160
|
+
over the card in dark, where `well` sinks to a black stripe. */
|
|
161
|
+
--_qm-surface-band: light-dark(
|
|
162
|
+
color-mix(in oklab, var(--_qm-bg), var(--_qm-fg) 12%),
|
|
163
|
+
color-mix(in oklab, var(--_qm-bg), var(--_qm-fg) 18%)
|
|
164
|
+
);
|
|
165
|
+
/* The one stroke: a card's two horizontals, a section's and a subform's verticals,
|
|
166
|
+
a table's frame and the lines between its cells, a floating surface's edge, the
|
|
167
|
+
popover's divider. One and a half ground steps off the card at both poles, the
|
|
168
|
+
same derivation the well takes, so a hairline stands off the card by the same
|
|
169
|
+
measure a card stands off the ground whatever the scheme. Toward the ink, which
|
|
170
|
+
is the half of the step `light-dark()` carries: the well always sinks, a stroke
|
|
171
|
+
darkens a light card and lightens a dark one. On the defaults the arms land near
|
|
172
|
+
#ececec and #3b3c3e. The multiple is the whole calibration: at it a stroke reads
|
|
173
|
+
in light without outweighing the type beside it, and reads in dark without being
|
|
174
|
+
the loudest line on the card. */
|
|
160
175
|
--_qm-border: light-dark(
|
|
161
|
-
|
|
162
|
-
|
|
176
|
+
oklab(from var(--_qm-bg) calc(l - 1.5 * (0.04 + 0.0202 * (1 - l))) a b),
|
|
177
|
+
oklab(from var(--_qm-bg) calc(l + 1.5 * (0.04 + 0.0202 * (1 - l))) a b)
|
|
163
178
|
);
|
|
164
|
-
/* A stroke ruled through content rather than round it: a table's frame and every
|
|
165
|
-
line between its cells. The light arm of `border` is a card's edge against the
|
|
166
|
-
ground, and drawn between lines of type it vanishes, so a grid takes one ratio at
|
|
167
|
-
both poles, which lands within a few points of `border` in dark. */
|
|
168
|
-
--_qm-rule: color-mix(in oklab, var(--_qm-bg), var(--_qm-fg) 14%);
|
|
169
179
|
/* Three rungs, and nothing under the last: a step below `label` lands under 3:1 on
|
|
170
180
|
the well a field draws it against, and what would take it — an unset value's word,
|
|
171
181
|
an invitation — is content a reader has to read (WCAG 1.4.3), not decoration.
|
|
@@ -259,7 +269,7 @@
|
|
|
259
269
|
only up to the point where it is assembled. One width: focus is the only
|
|
260
270
|
state that draws a ring anywhere, so there is no held-back tier under it.
|
|
261
271
|
Sub-pixel, because at two it reads as a second border on a card whose every
|
|
262
|
-
other
|
|
272
|
+
other stroke is a hairline. */
|
|
263
273
|
--_qm-ring-width: 1.5px;
|
|
264
274
|
/* Every ring the surface draws, focus and selection alike, which is why the name
|
|
265
275
|
carries neither. Assembled here because the parts spelled out at a use site pass
|
|
@@ -296,17 +306,17 @@
|
|
|
296
306
|
|
|
297
307
|
/* ── Geometry ──────────────────────────────────────────────────────────*/
|
|
298
308
|
/* One stroke width for every edge the chrome draws and every rule it ranks
|
|
299
|
-
with: a
|
|
300
|
-
rather than a rhythm choice, like the tap floor: a hairline is a
|
|
301
|
-
any `--qm-space`, so neither derives from a dial. Both exist as rungs because
|
|
309
|
+
with: a control's, a floating surface's, the two closing a card's payload. A
|
|
310
|
+
threshold rather than a rhythm choice, like the tap floor: a hairline is a
|
|
311
|
+
hairline at any `--qm-space`, so neither derives from a dial. Both exist as rungs because
|
|
302
312
|
`check:style`'s border-width axis can only hold a stroke against a token. */
|
|
303
313
|
--_qm-border-width: 1px;
|
|
304
314
|
/* Half a step over it, for the verticals alone — a section's, a subform's, a
|
|
305
315
|
blockquote's. What a vertical states is depth, and depth is the one thing a
|
|
306
|
-
reader has to find in a dense card; the strokes that
|
|
307
|
-
stay at the hairline, so the ladder is what carries the extra
|
|
308
|
-
because a whole step reads as a different kind of line rather
|
|
309
|
-
one doing more work. */
|
|
316
|
+
reader has to find in a dense card; the strokes that rank two or edge a
|
|
317
|
+
floating surface stay at the hairline, so the ladder is what carries the extra
|
|
318
|
+
weight. Half, because a whole step reads as a different kind of line rather
|
|
319
|
+
than the same one doing more work. */
|
|
310
320
|
--_qm-vertical-width: 1.5px;
|
|
311
321
|
--_qm-radius: var(--qm-radius, 8px);
|
|
312
322
|
/* The interior corner, and half is the relationship rather than the number: a
|
|
@@ -342,6 +352,15 @@
|
|
|
342
352
|
`check:style`'s rhythm axis sees each of them read a rung, never that they read
|
|
343
353
|
the same one — the case `--_qm-inset-control` above is cut for. */
|
|
344
354
|
--_qm-nest: var(--_qm-space-3);
|
|
355
|
+
/* The numerals a list marker is given room for: two digits, so a tenth item's number
|
|
356
|
+
stands inside the leaf as the first's does. In `ch`, so it tracks the face the
|
|
357
|
+
numbers are set in. */
|
|
358
|
+
--_qm-marker-digits: 2ch;
|
|
359
|
+
/* The text column, measured in from a block's own inline inset: a section's vertical
|
|
360
|
+
plus the rung its heading stands off it, so a heading riding that vertical and a
|
|
361
|
+
line beside it start on one edge. A rung for the reason the nesting step is: the
|
|
362
|
+
card and the tip tucked under `main` are two components holding one edge. */
|
|
363
|
+
--_qm-column: calc(var(--_qm-space) + var(--_qm-vertical-width));
|
|
345
364
|
/* The scroll tail: dead space under the last card, so it can be read at the
|
|
346
365
|
middle of a pane rather than at its bottom edge. A fraction of the viewport
|
|
347
366
|
rather than a step on the ramp, because what it answers is how far the eye
|
|
@@ -358,6 +377,10 @@
|
|
|
358
377
|
rather than through the icon's `size`, so a stylesheet beats the SVG presentation
|
|
359
378
|
attribute and one rung is the whole of what a control draws. */
|
|
360
379
|
--_qm-glyph-control: 14px;
|
|
380
|
+
/* The stroke a control glyph draws, in screen length: the frame's 2 units of 24 at
|
|
381
|
+
the control rung. A glyph drawn at another edge reads it under
|
|
382
|
+
`vector-effect: non-scaling-stroke`, so every glyph strokes at one weight. */
|
|
383
|
+
--_qm-glyph-stroke: calc(var(--_qm-glyph-control) / 12);
|
|
361
384
|
/* The narrowest track a control that fills its width stays usable in: a table's
|
|
362
385
|
column floors at it, rises no further than its content, and a row of them scrolls
|
|
363
386
|
sideways rather than crushing a cell. A column drawing a mark takes no floor — a
|
|
@@ -374,22 +397,19 @@
|
|
|
374
397
|
--_qm-track-prose: calc(var(--_qm-track-min) * 2);
|
|
375
398
|
|
|
376
399
|
/* ── Type ────────────────────────────────────────────────────────────────
|
|
377
|
-
`--qm-font-size` anchors the chrome rung
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
already is. */
|
|
400
|
+
`--qm-font-size` anchors the chrome rung and `label` stands one 1.125 step under
|
|
401
|
+
it. The ratio and the weight are fixed conventions, not dials: no consumer tunes
|
|
402
|
+
a typographic ratio, and a dial nobody turns is a name every reader still holds.
|
|
403
|
+
Two chrome rungs: nothing the chrome names ranks above the value it names, a card
|
|
404
|
+
title being body at the mid weight, and a second step below `label` lands near
|
|
405
|
+
11px, under a size anything here wants to be read at. */
|
|
384
406
|
--_qm-text-body: var(--qm-font-size, 0.875rem);
|
|
385
|
-
--_qm-text-title: calc(var(--_qm-text-body) * 1.125);
|
|
386
407
|
--_qm-text-label: calc(var(--_qm-text-body) / 1.125);
|
|
387
408
|
/* Paper: the document body answers to the preview's paper where every other
|
|
388
409
|
surface here answers to the control beside it, so a rung shared with the chrome
|
|
389
410
|
makes a consumer asking for larger prose take larger inputs with it. 16/15 where
|
|
390
411
|
the ramp steps at 9/8: small enough to read as a change of register rather than
|
|
391
|
-
a rung of hierarchy
|
|
392
|
-
exactly. */
|
|
412
|
+
a rung of hierarchy. */
|
|
393
413
|
--_qm-text-paper: calc(var(--_qm-text-body) * 16 / 15);
|
|
394
414
|
/* Two weights over the regular, and only one of them is chrome. `mid` names
|
|
395
415
|
everything the surface names — a card title, a section header, a field
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
// `@quillmark/svelte` root: the substrate, free of any UI framework.
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
// `/visual`) so a bundler pulls only what an entry reaches; the root
|
|
5
|
-
// re-exports `/core` (the address vocabulary, the error channel, `init`) for a
|
|
6
|
-
// consumer that wants one import for the substrate. It carries no framework code.
|
|
7
|
-
// The `@quillmark/wasm` API is imported from the peer dependency directly, never
|
|
8
|
-
// from here.
|
|
1
|
+
// `@quillmark/svelte` root: the substrate, free of any UI framework. The headline surfaces mount
|
|
2
|
+
// from their own subpaths (`/preview`, `/visual`); the root re-exports `/core` for a consumer that
|
|
3
|
+
// wants one import for the substrate.
|
|
9
4
|
export * from './core/index.js';
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/* An app's own chrome: the band that names it, the line that signs it, and the one
|
|
2
|
+
action it exists for. The shell gives a band its row; these give the app's bands their
|
|
3
|
+
look, for a host whose page is one form rather than a workroom. quillkit's app client
|
|
4
|
+
wears them, and an author's `app.css` restyles them (THEMING §"The app chrome").
|
|
5
|
+
|
|
6
|
+
Specificity zero throughout, as the shell's: a rule of the host's own on the same
|
|
7
|
+
element wins at any specificity and in any sheet order. `check:style` holds the rank.
|
|
8
|
+
This file mints nothing. */
|
|
9
|
+
|
|
10
|
+
/* The head: the plate the title stands on, a hairline under it, and the ink everything on
|
|
11
|
+
it takes, so a host recolouring the band recolours its name with it. */
|
|
12
|
+
:where(.qm-app-header) {
|
|
13
|
+
padding: var(--qmh-space-2) var(--qmh-space-4);
|
|
14
|
+
color: var(--qmh-ink);
|
|
15
|
+
background: var(--qmh-surface);
|
|
16
|
+
border-block-end: var(--qmh-border-width) solid var(--qmh-border);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/* What the app is called. Display type rather than chrome type: it is the one line on
|
|
20
|
+
the screen a reader reads as a name. */
|
|
21
|
+
:where(.qm-app-title) {
|
|
22
|
+
margin: 0;
|
|
23
|
+
font-size: var(--qmh-text-title);
|
|
24
|
+
font-weight: var(--qmh-weight-strong);
|
|
25
|
+
line-height: var(--qmh-leading-tight);
|
|
26
|
+
color: inherit;
|
|
27
|
+
overflow-wrap: anywhere;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* The foot: a line of meta type on the head's plate under a hairline, its links in the
|
|
31
|
+
line's own ink. The two bands framing the panes stand on one plate. */
|
|
32
|
+
:where(.qm-app-footer) {
|
|
33
|
+
padding: var(--qmh-space-2) var(--qmh-space-4);
|
|
34
|
+
background: var(--qmh-surface);
|
|
35
|
+
border-block-start: var(--qmh-border-width) solid var(--qmh-border);
|
|
36
|
+
font-size: var(--qmh-text-meta);
|
|
37
|
+
line-height: var(--qmh-leading-tight);
|
|
38
|
+
color: var(--qmh-ink-meta);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
:where(.qm-app-footer a) {
|
|
42
|
+
color: inherit;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/* The primary action: the one control on the screen that wears the accent, at the touch
|
|
46
|
+
floor, since it is the press the whole page leads to. */
|
|
47
|
+
:where(.qm-app-primary) {
|
|
48
|
+
font: inherit;
|
|
49
|
+
font-size: var(--qmh-text-label);
|
|
50
|
+
font-weight: var(--qmh-weight-strong);
|
|
51
|
+
line-height: var(--qmh-leading-tight);
|
|
52
|
+
min-height: var(--qmh-tap);
|
|
53
|
+
padding: var(--qmh-space-2) var(--qmh-space-4);
|
|
54
|
+
color: var(--qmh-on-accent);
|
|
55
|
+
background: var(--qmh-accent);
|
|
56
|
+
border: var(--qmh-border-width) solid var(--qmh-accent);
|
|
57
|
+
border-radius: var(--qmh-radius-inner);
|
|
58
|
+
cursor: pointer;
|
|
59
|
+
transition: background-color var(--qmh-duration) var(--qmh-ease-reverse);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
:where(.qm-app-primary:hover) {
|
|
63
|
+
background: var(--qmh-accent-hover);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
:where(.qm-app-primary:disabled) {
|
|
67
|
+
color: var(--qmh-ink-meta);
|
|
68
|
+
background: var(--qmh-surface-hover);
|
|
69
|
+
border-color: var(--qmh-border);
|
|
70
|
+
cursor: default;
|
|
71
|
+
}
|
package/dist/preset/index.css
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
/*
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
minted, `recipes.css` is held to reading them. */
|
|
1
|
+
/*
|
|
2
|
+
* `@quillmark/svelte/preset`, the package's one CSS entry point: the endorsed look for the page a
|
|
3
|
+
* surface is mounted on. Opt-in: the surface barrels pull `core/theme.css` and never this, because
|
|
4
|
+
* this styles the document. `scale.css` is where the literals are minted; the rest read them.
|
|
5
|
+
* `recipes.css` ranks at ordinary specificity, `shell.css` and `app.css` at zero.
|
|
6
|
+
*/
|
|
8
7
|
|
|
9
8
|
@import './scale.css';
|
|
10
9
|
@import './recipes.css';
|
|
10
|
+
@import './shell.css';
|
|
11
|
+
@import './app.css';
|
package/dist/preset/recipes.css
CHANGED
|
@@ -1,17 +1,15 @@
|
|
|
1
|
-
/*
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
specificity too, not the surfaces' `:where()` zero: a consumer takes these classes on
|
|
14
|
-
purpose, so a rule of their own beside one is aimed rather than incidental. */
|
|
1
|
+
/*
|
|
2
|
+
* The endorsed look: the rules a host draws around a mounted surface, as classes it puts on its
|
|
3
|
+
* own elements. The shell is `shell.css` and an app's chrome `app.css`; the rungs in `scale.css`
|
|
4
|
+
* are the invisible half. This file mints nothing; `check:style` runs its axes here.
|
|
5
|
+
*
|
|
6
|
+
* These are host classes: they land on the consumer's DOM, never on a mounted root, so they freeze
|
|
7
|
+
* nothing about the surfaces' interior.
|
|
8
|
+
*
|
|
9
|
+
* Unlayered, at ordinary specificity (not the surfaces' `:where()` zero): a consumer takes these
|
|
10
|
+
* classes on purpose, so a rule of their own beside one is aimed rather than incidental, and a
|
|
11
|
+
* layer of the preset's own would put a name in the contract.
|
|
12
|
+
*/
|
|
15
13
|
|
|
16
14
|
/* ── The page ──────────────────────────────────────────────────────────────── */
|
|
17
15
|
|
|
@@ -40,156 +38,6 @@
|
|
|
40
38
|
max-width: var(--qmh-measure);
|
|
41
39
|
}
|
|
42
40
|
|
|
43
|
-
/* ── The workspace ─────────────────────────────────────────────────────────── */
|
|
44
|
-
|
|
45
|
-
/* The rules above dress the page a surface sits on; these four are the shell it is
|
|
46
|
-
mounted in, a tool where `.qm-page` is a document: the screen an app that mounts two
|
|
47
|
-
surfaces over one session is, drawn once (ARCHITECTURE §Styling).
|
|
48
|
-
|
|
49
|
-
Pinned to the viewport rather than sized to it: a page-height box still leaves the
|
|
50
|
-
root scroller counting the overflow its panes clip, and a wheel over the chrome drags
|
|
51
|
-
the whole app off the top. Three bands (a head, the body, an optional foot), and the
|
|
52
|
-
body takes what is left and may shrink below its content, so the panes in it own
|
|
53
|
-
their overflow and hold still while their contents move.
|
|
54
|
-
|
|
55
|
-
The one column is stated for the same reason the rows are: an implicit track is `auto`,
|
|
56
|
-
which is sized by what a band holds, and a `.qm-split` under one contributes its items'
|
|
57
|
-
max-content through its `fr` tracks. The shell would take the width of the widest thing
|
|
58
|
-
mounted in it instead of the viewport's, and every band would be that wide with the
|
|
59
|
-
second pane past the edge. A host holding its content to a maximum never sees it; one
|
|
60
|
-
spending the whole screen sees it on the first surface it mounts. */
|
|
61
|
-
.qm-workspace {
|
|
62
|
-
position: fixed;
|
|
63
|
-
inset: 0;
|
|
64
|
-
display: grid;
|
|
65
|
-
grid-template-columns: minmax(0, 1fr);
|
|
66
|
-
grid-template-rows: auto minmax(0, 1fr) auto;
|
|
67
|
-
overflow: hidden;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/* A gesture past the end of a pane chains out to the viewport and bounces the empty
|
|
71
|
-
document, which is the last way a pinned shell moves. Conditioned on the workspace, so
|
|
72
|
-
a host's other routes keep a page's own feel. */
|
|
73
|
-
html:has(.qm-workspace) {
|
|
74
|
-
overscroll-behavior: none;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/* A band's line: the row a head or a foot puts its parts on, wrapping, centred. That is
|
|
78
|
-
the whole of it. What a band is made of is the host's: the rule under it, the gutter
|
|
79
|
-
beside it, and the depth of it, because where a band ends and how tall it stands are
|
|
80
|
-
page-shell decisions: a site holding its content to a maximum runs the rule past it at
|
|
81
|
-
its own rhythm, and a one-screen tool has no maximum to hold to. */
|
|
82
|
-
.qm-bar {
|
|
83
|
-
display: flex;
|
|
84
|
-
flex-wrap: wrap;
|
|
85
|
-
align-items: center;
|
|
86
|
-
gap: var(--qmh-space-2) var(--qmh-space-4);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/* Two even tracks for two surfaces, and no resizer, since a divider that can be dragged
|
|
90
|
-
is a control competing with what it divides. Each track may shrink below its content,
|
|
91
|
-
which is what lets the frame in it clip rather than grow.
|
|
92
|
-
|
|
93
|
-
The gap is the endorsed default and not a fact about splitting: two surfaces standing
|
|
94
|
-
apart on a page read as two things, which is what a host showing its instruments wants.
|
|
95
|
-
A host that spends the whole screen on the mounts closes it to nothing and carries a
|
|
96
|
-
hairline on one pane instead: one property, and the tracks are untouched. */
|
|
97
|
-
.qm-split {
|
|
98
|
-
display: grid;
|
|
99
|
-
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
|
100
|
-
grid-template-rows: minmax(0, 1fr);
|
|
101
|
-
gap: var(--qmh-space-4);
|
|
102
|
-
min-height: 0;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/* The band that switches them, and nothing at the widths where both tracks are showing
|
|
106
|
-
and there is nothing to switch. Where it stands is the host's, like any other band; what
|
|
107
|
-
goes in it is a pair of `.qm-control`s, which already carry the on-state a pressed
|
|
108
|
-
control takes. Its visibility is the preset's because the threshold is: a host hiding
|
|
109
|
-
its own tab row writes this file's number a second time, which is the one thing the
|
|
110
|
-
single source is for. */
|
|
111
|
-
.qm-switch {
|
|
112
|
-
display: none;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/* One mount at a time under the threshold, rather than two of them abreast. Half a narrow
|
|
116
|
-
viewport is under the width either surface reads at, so the split stops being one and
|
|
117
|
-
the tracks become views of the same room: the host says which with `data-qm-show`, and
|
|
118
|
-
the attribute names the track rather than what is in it, so nothing here knows an editor
|
|
119
|
-
from a preview. No attribute is the first track.
|
|
120
|
-
|
|
121
|
-
The other track is `display: none` and not a clip, which is the whole of the hiding: it
|
|
122
|
-
leaves the tab order, hit-testing and the accessibility tree in one property, so the
|
|
123
|
-
pane needs no `inert` and the host needs no breakpoint in JS. Both stay mounted (a
|
|
124
|
-
preview binds its handle once, an editor holds a caret, a history and a scroll), so
|
|
125
|
-
the switch is presentational, never conditional. A pane hidden this way keeps the
|
|
126
|
-
pixels it had: the paint loop's band sweep no-ops on an empty visible set, and its
|
|
127
|
-
resize observer holds the last real width rather than rastering at the 0×0 box a hidden
|
|
128
|
-
pane reports, so what comes back at the width it left needs no paint at all. The
|
|
129
|
-
preview's caret follow spans the same window — a trip asked for against a pane with no
|
|
130
|
-
box is held and run when it has one (`preview/bridge.ts`), the pane opening at the
|
|
131
|
-
caret rather than several edits behind it.
|
|
132
|
-
|
|
133
|
-
Height is the second clause because a landscape phone passes the first one: it clears
|
|
134
|
-
the width with room for two tracks and has no body left to put them in. A desktop window
|
|
135
|
-
that short wants one mount for the same reason. */
|
|
136
|
-
@media (width < 50rem), (height < 30rem) {
|
|
137
|
-
.qm-switch {
|
|
138
|
-
display: flex;
|
|
139
|
-
gap: var(--qmh-space);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/* Even halves of the band, at the height a thumb needs. The floor is the recipe's and
|
|
143
|
-
not the host's, because the band exists only at the sizes where the pointer is a
|
|
144
|
-
finger: a host is free to stand the band deeper, and has nothing to gain from
|
|
145
|
-
standing it shallower than the thing it is tapping. */
|
|
146
|
-
.qm-switch > * {
|
|
147
|
-
flex: 1 1 0;
|
|
148
|
-
min-height: var(--qmh-tap);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/* Centred, which is what a control filling half a band reads as; `.qm-control` itself
|
|
152
|
-
reads left, for the menus it also dresses. */
|
|
153
|
-
.qm-switch > .qm-control {
|
|
154
|
-
text-align: center;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
.qm-split {
|
|
158
|
-
grid-template-columns: minmax(0, 1fr);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
.qm-split:not([data-qm-show='2']) > :nth-child(2),
|
|
162
|
-
.qm-split[data-qm-show='2'] > :nth-child(1) {
|
|
163
|
-
display: none;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/* The mounting site: an edge, a corner, and the clip that holds a surface to them, which
|
|
168
|
-
is all a surface painting its own column needs. No tone and no gutter: those are the
|
|
169
|
-
surface's own (THEMING §"Drop it in"). `border-box`, so a stated height is the height
|
|
170
|
-
it draws.
|
|
171
|
-
|
|
172
|
-
Positioned, because a clip reaches only what it is the containing block for: a
|
|
173
|
-
surface's out-of-flow parts (a parked description, an overlay) resolve against the
|
|
174
|
-
nearest positioned ancestor, and with none between them and the document they land at
|
|
175
|
-
their static position unclipped, leaving the page to scroll past its own foot by
|
|
176
|
-
however far the frame's contents run over.
|
|
177
|
-
|
|
178
|
-
The two minimums are what let a frame in a track clip rather than push: a grid or flex
|
|
179
|
-
item floors at its content, so a mount that paints wider than its column widens the
|
|
180
|
-
column instead. They ride the frame rather than the split's children, which keeps every
|
|
181
|
-
rule in this file landing where the host put a class. Outside a track they are the
|
|
182
|
-
initial value and do nothing. */
|
|
183
|
-
.qm-frame {
|
|
184
|
-
box-sizing: border-box;
|
|
185
|
-
position: relative;
|
|
186
|
-
min-width: 0;
|
|
187
|
-
min-height: 0;
|
|
188
|
-
border: var(--qmh-border-width) solid var(--qmh-border);
|
|
189
|
-
border-radius: var(--qmh-radius);
|
|
190
|
-
overflow: hidden;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
41
|
/* ── Type ──────────────────────────────────────────────────────────────────── */
|
|
194
42
|
|
|
195
43
|
/* A run of chrome type: a section's label, a panel's caption, the name over a readout.
|
|
@@ -306,6 +154,13 @@ pre.qm-readout {
|
|
|
306
154
|
background: var(--qmh-surface-hover);
|
|
307
155
|
}
|
|
308
156
|
|
|
157
|
+
/* Centred in the shell's switch band, which is what a control filling half a band reads
|
|
158
|
+
as; `.qm-control` itself reads left, for the menus it also dresses. Here rather than
|
|
159
|
+
beside the band in `shell.css`, which ranks at zero and so could not outrank this. */
|
|
160
|
+
.qm-switch > .qm-control {
|
|
161
|
+
text-align: center;
|
|
162
|
+
}
|
|
163
|
+
|
|
309
164
|
/* One choice means nothing to pick: the control stays, because what it reads is a fact
|
|
310
165
|
worth having, and it recedes to say it is not a choice. */
|
|
311
166
|
.qm-control:disabled {
|
package/dist/preset/scale.css
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
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 ramp, 8% hover, the
|
|
5
|
-
ring's width, the status hue at both poles) and the
|
|
4
|
+
figures here are the figures there (the poles, the ground step's ramp, 8% hover, the
|
|
5
|
+
label ink's 35%, the ring's width, the status hue at both poles) and the
|
|
6
6
|
dial means the same plane in both, so a host plate and a card on it land on the same
|
|
7
7
|
tone at both poles and a host page meets an editor's own column exactly. The border
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
is calibrated for its own plane rather than shared: a page's controls are boxed and
|
|
9
|
+
read against one ground, a card's strokes at several weights against the rungs
|
|
10
|
+
under it, so the mixes are not the same figure. The well
|
|
11
11
|
under the ground has no counterpart here: a host's own controls are boxed and carry a
|
|
12
12
|
hairline, so nothing on a page needs the step an edgeless field does.
|
|
13
13
|
|
|
@@ -18,11 +18,10 @@
|
|
|
18
18
|
could not be both.
|
|
19
19
|
|
|
20
20
|
Literals live here and nowhere else in the preset: `check:style` runs its axes over
|
|
21
|
-
|
|
21
|
+
the sheets beside it, with this file exempt as the place the defaults are minted.
|
|
22
22
|
|
|
23
|
-
The poles fall back to the
|
|
24
|
-
|
|
25
|
-
painted a page with, which is what a plate should be. The dials sit in front, so
|
|
23
|
+
The poles fall back to the surfaces' own pair, so a host that turns no dial lands on
|
|
24
|
+
the plane an editor mounted in it paints at both poles. The dials sit in front, so
|
|
26
25
|
`--qm-bg`/`--qm-fg` on an ancestor retunes page and surface together. */
|
|
27
26
|
|
|
28
27
|
:root {
|
|
@@ -32,21 +31,28 @@
|
|
|
32
31
|
the page sinks from it by the same ramp. That is what puts a host page and
|
|
33
32
|
an editor's own column on one tone rather than a plane apart. Planes step by
|
|
34
33
|
light and everything else by ink, which is the package's own split
|
|
35
|
-
(ARCHITECTURE §Styling); the figures are its figures.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
--qmh-
|
|
39
|
-
--qmh-page: oklab(from var(--qmh-surface) calc(l - (0.0214 + 0.0467 * (1 - l))) a b);
|
|
40
|
-
--qmh-ink: var(--qm-fg, CanvasText);
|
|
34
|
+
(ARCHITECTURE §Styling); the figures are its figures. */
|
|
35
|
+
--qmh-surface: var(--qm-bg, light-dark(#fff, #272729));
|
|
36
|
+
--qmh-page: oklab(from var(--qmh-surface) calc(l - (0.04 + 0.0202 * (1 - l))) a b);
|
|
37
|
+
--qmh-ink: var(--qm-fg, light-dark(#1c1c1c, #d7dadc));
|
|
41
38
|
/* One step off the ink and no second: a page's chrome type is small, tracked and
|
|
42
39
|
uppercase, so a rung below this reads under 4.5:1 against the plate and the
|
|
43
40
|
label and status lines that would take it are text (WCAG 1.4.3). */
|
|
44
|
-
--qmh-ink-meta: color-mix(in oklab, var(--qmh-ink), var(--qmh-surface)
|
|
41
|
+
--qmh-ink-meta: color-mix(in oklab, var(--qmh-ink), var(--qmh-surface) 35%);
|
|
45
42
|
--qmh-surface-hover: color-mix(in oklab, var(--qmh-surface), var(--qmh-ink) 8%);
|
|
46
43
|
--qmh-border: color-mix(in oklab, var(--qmh-surface), var(--qmh-ink) 17%);
|
|
47
44
|
/* The edge that says "engaged" where the hairline says "edge": a pressed switch,
|
|
48
|
-
the underline under a link.
|
|
49
|
-
|
|
45
|
+
the underline under a link. Half way to the ink, which clears WCAG 1.4.11's 3:1
|
|
46
|
+
against the page and the plate at both poles. */
|
|
47
|
+
--qmh-border-strong: color-mix(in oklab, var(--qmh-surface), var(--qmh-ink) 50%);
|
|
48
|
+
|
|
49
|
+
/* The one hue a host's page spends on purpose: the primary action wears it. The
|
|
50
|
+
figures are the surfaces' own default for the same dial, so a page that turns no
|
|
51
|
+
dial and a card's focus ring agree; the ink on it is the plate's, the pole the
|
|
52
|
+
accent's default contrasts against in both schemes. */
|
|
53
|
+
--qmh-accent: var(--qm-accent, light-dark(#71717a, #a1a1aa));
|
|
54
|
+
--qmh-on-accent: var(--qmh-surface);
|
|
55
|
+
--qmh-accent-hover: color-mix(in oklab, var(--qmh-accent), var(--qmh-ink) 15%);
|
|
50
56
|
|
|
51
57
|
/* The hue a host spends on a failure. The figures are the surfaces' own, so a
|
|
52
58
|
page's status line and a card's diagnostic carry one colour meaning error.
|
|
@@ -54,6 +60,9 @@
|
|
|
54
60
|
on a dark page. The dial sits in front of the pair, as every pole's does, so
|
|
55
61
|
a host that turns one owns both schemes. */
|
|
56
62
|
--qmh-alert: var(--qm-danger, light-dark(#9e1518, #f9786c));
|
|
63
|
+
/* What a modal's backdrop lays over the page: the ground held translucent, so the
|
|
64
|
+
page recedes under the dialog without a second tone to read. */
|
|
65
|
+
--qmh-scrim: color-mix(in srgb, var(--qmh-page) 80%, transparent);
|
|
57
66
|
|
|
58
67
|
/* ── Rhythm ──────────────────────────────────────────────────────────────── */
|
|
59
68
|
/* One base and its multiples, the same four steps the surfaces derive. A host
|
|
@@ -92,6 +101,7 @@
|
|
|
92
101
|
surfaces' ramp, which is chrome inside a card, and a page's body text is a
|
|
93
102
|
different job at a different size. A host that wants them locked sets both. */
|
|
94
103
|
--qmh-text: 1rem;
|
|
104
|
+
--qmh-text-title: 1.125rem;
|
|
95
105
|
--qmh-text-label: 0.8125rem;
|
|
96
106
|
--qmh-text-meta: 0.6875rem;
|
|
97
107
|
--qmh-weight-strong: 600;
|