@quillmark/svelte 0.2.0 → 0.3.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 +2 -2
- package/THEMING.md +11 -7
- package/dist/core/address.d.ts +7 -7
- package/dist/core/address.js +6 -6
- package/dist/core/bloom.d.ts +5 -5
- package/dist/core/bloom.js +8 -8
- package/dist/core/codec/anchor.d.ts +1 -1
- package/dist/core/codec/anchor.js +1 -1
- package/dist/core/codec/atoms.d.ts +10 -0
- package/dist/core/codec/atoms.js +78 -0
- package/dist/core/codec/clipboard.d.ts +59 -0
- package/dist/core/codec/clipboard.js +202 -0
- package/dist/core/codec/code.d.ts +1 -1
- package/dist/core/codec/code.js +4 -4
- package/dist/core/codec/decode.d.ts +1 -1
- package/dist/core/codec/decode.js +8 -8
- package/dist/core/codec/encode.d.ts +4 -4
- package/dist/core/codec/encode.js +10 -10
- package/dist/core/codec/field.d.ts +21 -26
- package/dist/core/codec/field.js +33 -32
- package/dist/core/codec/index.js +5 -8
- package/dist/core/codec/inputrules.js +56 -18
- package/dist/core/codec/islands.d.ts +11 -7
- package/dist/core/codec/islands.js +16 -10
- package/dist/core/codec/keymap.d.ts +5 -6
- package/dist/core/codec/keymap.js +8 -7
- package/dist/core/codec/lists.d.ts +3 -3
- package/dist/core/codec/lists.js +32 -13
- package/dist/core/codec/marks.d.ts +1 -1
- package/dist/core/codec/marks.js +1 -1
- package/dist/core/codec/positions.js +1 -1
- package/dist/core/codec/prose.css +230 -215
- package/dist/core/codec/schema.js +4 -4
- package/dist/core/codec/slash.d.ts +39 -41
- package/dist/core/codec/slash.js +0 -0
- package/dist/core/codec/table-view.d.ts +12 -16
- package/dist/core/codec/table-view.js +488 -292
- package/dist/core/codec/table.d.ts +42 -15
- package/dist/core/codec/table.js +70 -26
- package/dist/core/errors.d.ts +5 -5
- package/dist/core/index.js +2 -2
- package/dist/core/lifecycle.js +1 -1
- package/dist/core/rebind.svelte.d.ts +2 -2
- package/dist/core/rebind.svelte.js +4 -4
- package/dist/core/teardown.d.ts +1 -1
- package/dist/core/teardown.js +1 -1
- package/dist/core/theme.css +144 -54
- package/dist/preset/index.css +1 -1
- package/dist/preset/recipes.css +31 -29
- package/dist/preset/scale.css +36 -25
- package/dist/preview/Preview.svelte +12 -10
- package/dist/preview/Preview.svelte.d.ts +3 -3
- package/dist/preview/bridge.js +4 -4
- package/dist/preview/controller.js +3 -3
- package/dist/preview/geometry.d.ts +2 -2
- package/dist/preview/geometry.js +2 -2
- package/dist/preview/index.js +3 -3
- package/dist/preview/overlay.d.ts +1 -1
- package/dist/preview/overlay.js +3 -3
- package/dist/preview/paint.js +15 -17
- package/dist/visual/ArrayField.svelte +80 -66
- package/dist/visual/ArrayField.svelte.d.ts +1 -1
- package/dist/visual/BooleanField.svelte +8 -6
- package/dist/visual/BooleanField.svelte.d.ts +2 -2
- package/dist/visual/Card.svelte +151 -325
- package/dist/visual/Card.svelte.d.ts +2 -6
- package/dist/visual/CardControls.svelte +1 -1
- package/dist/visual/DateField.svelte +19 -19
- package/dist/visual/DateField.svelte.d.ts +3 -3
- package/dist/visual/DiagnosticList.svelte +1 -1
- package/dist/visual/EnumField.svelte +16 -16
- package/dist/visual/EnumField.svelte.d.ts +2 -2
- package/dist/visual/Field.svelte +128 -115
- package/dist/visual/Field.svelte.d.ts +1 -1
- package/dist/visual/FieldHint.svelte +24 -42
- package/dist/visual/FieldHint.svelte.d.ts +1 -1
- package/dist/visual/FieldLabel.svelte +8 -8
- package/dist/visual/FormatPopover.svelte +80 -35
- package/dist/visual/NumberField.svelte +5 -5
- package/dist/visual/NumberField.svelte.d.ts +1 -1
- package/dist/visual/ObjectField.svelte +9 -9
- package/dist/visual/ObjectField.svelte.d.ts +1 -1
- package/dist/visual/ProseArrayElement.svelte +11 -13
- package/dist/visual/ProseArrayElement.svelte.d.ts +1 -1
- package/dist/visual/ProseField.svelte +53 -84
- package/dist/visual/ProseField.svelte.d.ts +12 -17
- package/dist/visual/SlashMenu.svelte +42 -16
- package/dist/visual/TextField.svelte +5 -5
- package/dist/visual/TextField.svelte.d.ts +1 -1
- package/dist/visual/TipsCard.svelte +43 -28
- package/dist/visual/VisualEditor.svelte +6 -6
- package/dist/visual/VisualEditorInner.svelte +122 -129
- package/dist/visual/controls.css +74 -30
- package/dist/visual/diagnostics.d.ts +5 -5
- package/dist/visual/diagnostics.js +3 -3
- package/dist/visual/domid.js +3 -3
- package/dist/visual/ext.d.ts +1 -1
- package/dist/visual/ext.js +1 -1
- package/dist/visual/icons/nodes.d.ts +3 -0
- package/dist/visual/icons/nodes.js +2 -1
- package/dist/visual/index.js +4 -4
- package/dist/visual/leaves.d.ts +3 -3
- package/dist/visual/leaves.js +1 -1
- package/dist/visual/links.d.ts +24 -0
- package/dist/visual/links.js +67 -0
- package/dist/visual/props.d.ts +8 -8
- package/dist/visual/signals.d.ts +6 -6
- package/dist/visual/strings.d.ts +14 -19
- package/dist/visual/strings.js +5 -7
- package/dist/visual/structure.d.ts +24 -17
- package/dist/visual/structure.js +8 -8
- package/dist/visual/synced.svelte.d.ts +1 -1
- package/dist/visual/synced.svelte.js +4 -4
- package/dist/visual/tips.d.ts +2 -2
- package/dist/visual/tips.js +3 -3
- package/package.json +1 -1
|
@@ -4,18 +4,18 @@
|
|
|
4
4
|
hidden-selection and separator-image guards. It is imported whole; the rules are
|
|
5
5
|
interdependent and which ones a given schema needs is not visible from here.
|
|
6
6
|
|
|
7
|
-
What it does
|
|
7
|
+
What it does not carry is a block reset, so without the rules below every leaf
|
|
8
8
|
inherits the UA `p { margin: 1em 0 }` (32px of margin in a box drawn to hold one
|
|
9
9
|
line), which is enough on its own to make an inline richtext field twice the height
|
|
10
10
|
of the input beside it. The reset lives here rather than per component because every
|
|
11
11
|
prose leaf in the package mounts through the codec (a field, the body, an array
|
|
12
12
|
element) and picks it up without restating it, and a leaf that carries the
|
|
13
13
|
control recipe (`visual/ProseField.svelte`) can then match `.qm-input` by
|
|
14
|
-
construction instead of by a tuned `min-height`. The source view is
|
|
14
|
+
construction instead of by a tuned `min-height`. The source view is not one of
|
|
15
15
|
them: it is a `<pre>` holding `textContent` (`source/view.ts`), outside
|
|
16
16
|
`.ProseMirror` and so outside every rule in this file.
|
|
17
17
|
|
|
18
|
-
It also carries hard-coded
|
|
18
|
+
It also carries hard-coded values that answer to no rung: a `#8cf` node-selection
|
|
19
19
|
outline, twice, and the `-32px` placing a selected list item's. Retinted and
|
|
20
20
|
re-measured here rather than in `theme.css` because a layered rule loses to that
|
|
21
21
|
unlayered stylesheet: equal specificity and a later import is what wins. */
|
|
@@ -30,7 +30,7 @@ li.ProseMirror-selectednode::after {
|
|
|
30
30
|
left: calc(var(--_qm-space-4) * -1);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
/* The
|
|
33
|
+
/* The gap cursor (`prosemirror-gapcursor`, imported beside this file): a caret
|
|
34
34
|
between two blocks, where the document holds no text position for an ordinary one.
|
|
35
35
|
It is what a press beside an island lands, so it is drawn in the surface's ink
|
|
36
36
|
rather than the upstream sheet's `black`, which is the `#8cf` defect again. */
|
|
@@ -47,14 +47,28 @@ li.ProseMirror-selectednode::after {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
/* One rhythm between sibling blocks, in place of the UA's collapsed pair. Scoped by
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
parent rather than by tag, which is what keeps it true as the schema grows: the
|
|
51
|
+
containers below are every node whose content is `block+` (`schema.ts`), so
|
|
52
52
|
their children are blocks by definition, whatever kinds exist. `ul`/`ol` are
|
|
53
53
|
deliberately absent: a run of list items is tight, and the gap before a list is
|
|
54
|
-
the list's, not each item's.
|
|
54
|
+
the list's, not each item's.
|
|
55
|
+
|
|
56
|
+
An item is the exception to its own container. A list nested under an item is
|
|
57
|
+
part of the run that omission already keeps tight — `a. …` under `1. …` is the
|
|
58
|
+
next line of one list, not a new block after a paragraph — so an item's children
|
|
59
|
+
take the gap only up to the point where one of them is a list. Written as its own
|
|
60
|
+
arm rather than as a `:not()` over the shared one, because the exception is the
|
|
61
|
+
item's: a list after a paragraph inside a blockquote is an ordinary sibling pair
|
|
62
|
+
and keeps the gap.
|
|
63
|
+
|
|
64
|
+
A line box is ~22px at the paper size and the body leading, so the rung is a
|
|
65
|
+
little over half a line: enough that a break reads as a break, short of the full
|
|
66
|
+
blank line that doubles the leading and makes a short document read as a list of
|
|
67
|
+
fragments. */
|
|
55
68
|
.ProseMirror > * + *,
|
|
56
|
-
.ProseMirror :is(blockquote,
|
|
57
|
-
|
|
69
|
+
.ProseMirror :is(blockquote, [data-qm-unknown-container]) > * + *,
|
|
70
|
+
.ProseMirror li > * + :not(ul, ol) {
|
|
71
|
+
margin-top: var(--_qm-space-3);
|
|
58
72
|
}
|
|
59
73
|
|
|
60
74
|
/* A blockquote's UA indent was its only mark, and the reset above takes it. The rule
|
|
@@ -70,18 +84,18 @@ li.ProseMirror-selectednode::after {
|
|
|
70
84
|
emits, minus the four the UA already renders correctly (`strong`, `em`, `u`, `s`)
|
|
71
85
|
and the blockquote above.
|
|
72
86
|
|
|
73
|
-
Each rule answers to the
|
|
87
|
+
Each rule answers to the reference quill rather than to a browser default or to a
|
|
74
88
|
web editor's chrome, because the leaf sits beside a live preview of the same
|
|
75
89
|
content. `usaf_memo` sets `raw` in a monospace face and adds nothing; it renders a
|
|
76
|
-
heading as a bold
|
|
77
|
-
never read; it gives a link no decoration at all. So a leaf shows that a span
|
|
78
|
-
code and a line
|
|
90
|
+
heading as a bold run-in prepended to the following paragraph, with the level
|
|
91
|
+
never read; it gives a link no decoration at all. So a leaf shows that a span is
|
|
92
|
+
code and a line is a heading: never a prediction of the size paper will set it
|
|
79
93
|
at, which the package cannot know for a quill it has not seen.
|
|
80
94
|
|
|
81
|
-
Scoping is by
|
|
95
|
+
Scoping is by tag, and the schema does the rest: `h1`–`h6`, `hr` and the lists
|
|
82
96
|
cannot exist under the inline schema, so no rule for them can land on a `subject`
|
|
83
|
-
field however that field is mounted. The two
|
|
84
|
-
`link` are in both schemas, and a `plaintext` leaf strips them at
|
|
97
|
+
field however that field is mounted. The two marks are the exception: `code` and
|
|
98
|
+
`link` are in both schemas, and a `plaintext` leaf strips them at decode while
|
|
85
99
|
mounting a schema that still carries them, so a paste can put either in one. The
|
|
86
100
|
rules stand there too, and correctly: they say the leaf holds code, or a link,
|
|
87
101
|
which is exactly what it then holds.
|
|
@@ -89,22 +103,22 @@ li.ProseMirror-selectednode::after {
|
|
|
89
103
|
`visual/TipsCard.svelte` restates the two mark rules by hand, over the same
|
|
90
104
|
`toDOM` output injected outside any view. */
|
|
91
105
|
|
|
92
|
-
/* Code is a
|
|
106
|
+
/* Code is a face: no chip, no fill, no inset, no size step. The blockquote above
|
|
93
107
|
already argues the general form: a span reads as set apart without a fill or a
|
|
94
108
|
second box, on the one surface in the card with no edge of its own. A chip has
|
|
95
|
-
nowhere to come from in any case: the
|
|
96
|
-
|
|
97
|
-
|
|
109
|
+
nowhere to come from in any case: the body sits at `--_qm-surface` and the rungs
|
|
110
|
+
either side of it are the field well and the hover lane, so a chip at rest would
|
|
111
|
+
read as a hole in the paper or as a hovered button.
|
|
98
112
|
|
|
99
|
-
The withheld properties are
|
|
100
|
-
paragraph above true of a
|
|
113
|
+
The withheld properties are declared at their zero, which is what makes the
|
|
114
|
+
paragraph above true of a mounted leaf: a chip on these tags is an ordinary page
|
|
101
115
|
rule, so left off, these are the two tags the host draws rather than the surface.
|
|
102
116
|
The other marks are ink, weight and decoration, which the leaf sets or safely
|
|
103
117
|
inherits, so the box is this mark's alone and the zeros are not a reset.
|
|
104
118
|
|
|
105
|
-
|
|
119
|
+
Both tags, where the face alone needs only one: a `code_block` renders `pre > code`
|
|
106
120
|
(`schema.ts`), so every character is inside a `code` element and the face reaches it
|
|
107
|
-
there — but the block's
|
|
121
|
+
there — but the block's box is the `pre`, outside that element and styled by the
|
|
108
122
|
host on its own. `pre` still takes no `overflow-x`, because there is no overflow:
|
|
109
123
|
ProseMirror's own stylesheet sets `white-space: pre-wrap` there, so a long line
|
|
110
124
|
wraps. A scroller means overriding that to `pre` inside an editable `code`
|
|
@@ -118,10 +132,10 @@ li.ProseMirror-selectednode::after {
|
|
|
118
132
|
}
|
|
119
133
|
|
|
120
134
|
/* A link takes the surface's ink (the UA's blue is the `#8cf` defect again) and a
|
|
121
|
-
|
|
135
|
+
dotted underline. Dotted rather than solid because `underline` is a mark in the
|
|
122
136
|
same schema, and a solid rule renders an authored `<u>` and a link identically in a
|
|
123
137
|
paragraph that can hold both. An underline at all, where the tips card's link takes
|
|
124
|
-
none, because this leaf is
|
|
138
|
+
none, because this leaf is editable: the `href` is otherwise imperceptible, so
|
|
125
139
|
removing the rule loses an answer rather than ornament. No hue:
|
|
126
140
|
`--_qm-accent` already means focus, and a body of accent-coloured links collides
|
|
127
141
|
with the ring and with the correlation wash. */
|
|
@@ -144,13 +158,13 @@ li.ProseMirror-selectednode::after {
|
|
|
144
158
|
rather than the item: the sibling-gap rule deliberately omits `ul`/`ol`, and
|
|
145
159
|
padding on the container cannot reintroduce what it withholds.
|
|
146
160
|
|
|
147
|
-
The
|
|
161
|
+
The markers are the UA's, reclaimed rather than inherited. `disc` and `decimal`
|
|
148
162
|
are right and this restates neither: a host reset (Tailwind's preflight sets
|
|
149
163
|
`list-style: none` on `ol, ul, menu`) is the common case, and against one an
|
|
150
164
|
unstated default is no default at all — bullets and numbers vanish from the leaf
|
|
151
165
|
while the preview beside it still draws them, which is an editor/paper
|
|
152
166
|
divergence on the plainest formatting there is. `revert` over a named type
|
|
153
|
-
because the UA's markers step by
|
|
167
|
+
because the UA's markers step by depth (disc, circle, square) and the schema
|
|
154
168
|
nests (`lists.ts`: Tab sinks an item); naming `disc` would flatten that ramp to
|
|
155
169
|
hold the first level. Same reclaim for `strong`/`em`/`u`/`s` above if a reset
|
|
156
170
|
that takes those ever turns up: the positive half states what it leaves to the
|
|
@@ -169,56 +183,77 @@ li.ProseMirror-selectednode::after {
|
|
|
169
183
|
minting five more is the drift the scale exists to prevent. */
|
|
170
184
|
.ProseMirror :is(h1, h2, h3, h4, h5, h6) {
|
|
171
185
|
font-size: inherit;
|
|
172
|
-
font-weight: var(--_qm-weight-
|
|
186
|
+
font-weight: var(--_qm-weight-strong);
|
|
173
187
|
}
|
|
174
188
|
|
|
175
189
|
/* ── The table island ────────────────────────────────────────────────────────
|
|
176
190
|
|
|
177
|
-
The one construct in this file with
|
|
191
|
+
The one construct in this file with chrome in it. The rest of the stylesheet
|
|
178
192
|
states what a block is and lets paper set its size; a table island is edited
|
|
179
|
-
through controls that do not print, so it also has a
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
data cell, hanging into a band the scroller carries as
|
|
187
|
-
the box a paragraph would, the accessibility tree is the
|
|
188
|
-
|
|
189
|
-
overlay: it is inside the cell it names.
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
+
through controls that do not print, so it also has a target floor and a reveal.
|
|
194
|
+
Those live here rather than in `visual/controls.css` for the same reason the
|
|
195
|
+
NodeView is vanilla: the island is inside the leaf, and the leaf is the codec's.
|
|
196
|
+
What it does not restate is the surface's dials: every value below is a `--_qm-*`
|
|
197
|
+
rung, so the island retints with everything else.
|
|
198
|
+
|
|
199
|
+
The band is in no track. Every control in it is absolutely positioned inside a real
|
|
200
|
+
data cell or against the grid's frame, hanging into a band the scroller carries as
|
|
201
|
+
padding. So the grid holds the box a paragraph would, the accessibility tree is the
|
|
202
|
+
data's shape, and a grip still lines up with its line by construction rather than by
|
|
203
|
+
a measured overlay: it is inside the cell it names.
|
|
204
|
+
|
|
205
|
+
Each control comes up alone. A grip or a bar is drawn while the pointer is on that
|
|
206
|
+
control, while it holds the focus, or while it is the one the gesture is about — a
|
|
207
|
+
selected line, a lifted one. The target is there the whole time either way, an
|
|
208
|
+
invisible button being hit-tested like any other, so what the reveal decides is what
|
|
209
|
+
the table looks like under a passing pointer, not what it answers to. */
|
|
210
|
+
|
|
211
|
+
/* The band, and the whole of what it costs. `padding` opens it on all four sides,
|
|
212
|
+
because each axis begins with a grip and ends with an add bar; the island's negative
|
|
213
|
+
`margin` spends the card's own inset buying the left one back, so the grid sits one
|
|
193
214
|
inset from the prose edge instead of a tap target plus one.
|
|
194
215
|
|
|
195
216
|
`margin-top: 0` overrides the sibling-gap rule rather than going negative: the band
|
|
196
|
-
|
|
197
|
-
and an `opacity: 0` control is still hit-tested, so it would take
|
|
198
|
-
presses.
|
|
199
|
-
|
|
217
|
+
absorbs the gap, at both ends. A negative margin would hang the band over the
|
|
218
|
+
neighbouring block, and an `opacity: 0` control is still hit-tested, so it would take
|
|
219
|
+
that block's presses. The `.ProseMirror` qualifier is what makes the override hold
|
|
220
|
+
wherever the island lands: two of the gap rule's arms name a container, so a bare
|
|
221
|
+
class loses to them for an island inside a list item or a quote, both of which the
|
|
222
|
+
schema admits. */
|
|
223
|
+
.ProseMirror .qm-table-island {
|
|
200
224
|
margin-top: 0;
|
|
201
225
|
margin-left: calc(var(--_qm-space-3) * -1);
|
|
202
226
|
}
|
|
227
|
+
.ProseMirror > .qm-table-island + * {
|
|
228
|
+
margin-top: 0;
|
|
229
|
+
}
|
|
203
230
|
.qm-table-scroller {
|
|
204
231
|
/* The one horizontally scrolling box in a leaf: a table is as wide as its
|
|
205
232
|
columns, and a wide one must not push the card's own layout. `overflow-y` is
|
|
206
233
|
`hidden` rather than left alone, because a non-`visible` axis computes the other
|
|
207
234
|
to `auto` and a table has nothing to scroll vertically. */
|
|
208
|
-
position: relative;
|
|
209
235
|
overflow-x: auto;
|
|
210
236
|
overflow-y: hidden;
|
|
211
|
-
padding: var(--_qm-tap-min)
|
|
237
|
+
padding: var(--_qm-tap-min);
|
|
212
238
|
width: max-content;
|
|
213
239
|
max-width: 100%;
|
|
214
240
|
}
|
|
241
|
+
/* The containing block for everything out of flow, and the reason it exists rather
|
|
242
|
+
than the scroller serving: an absolute inside a scroll container is placed against a
|
|
243
|
+
padding box the scroll then slides out from under it, so a cap pinned to the grid's
|
|
244
|
+
far end would drift into the middle of a scrolled table. The frame is the grid's own
|
|
245
|
+
box and travels with it. */
|
|
246
|
+
.qm-table-frame {
|
|
247
|
+
position: relative;
|
|
248
|
+
width: max-content;
|
|
249
|
+
}
|
|
215
250
|
.qm-table {
|
|
216
251
|
border-collapse: separate;
|
|
217
252
|
border-spacing: 0;
|
|
218
253
|
border: var(--_qm-border-width) solid var(--_qm-border);
|
|
219
254
|
border-radius: var(--_qm-radius-inner);
|
|
220
255
|
}
|
|
221
|
-
/* Two tiers of rule, because a table draws two different things. The
|
|
256
|
+
/* Two tiers of rule, because a table draws two different things. The frame and the
|
|
222
257
|
header's rule are structure and keep the full hairline; the lines between cells are
|
|
223
258
|
rhythm and drop to the faint rung, so the grid reads as one object with divisions
|
|
224
259
|
rather than as a stack of boxes. `separate` with zero spacing rather than
|
|
@@ -239,20 +274,21 @@ li.ProseMirror-selectednode::after {
|
|
|
239
274
|
.qm-table tbody tr:last-child > .qm-table-cell {
|
|
240
275
|
border-bottom: none;
|
|
241
276
|
}
|
|
242
|
-
/* The header row is the
|
|
277
|
+
/* The header row is the one weight distinction the island draws: `header` is a
|
|
243
278
|
separate field in the model rather than a flag on a row, so the surface says so.
|
|
244
|
-
It takes a tone with it, which is the same
|
|
245
|
-
|
|
279
|
+
It takes a tone with it, which is the same move a field makes: the well rung, a
|
|
280
|
+
band cut into the paper rather than a layer stacked on it, and a rung either way
|
|
281
|
+
rather than a shadow. The rest of a table's type is paper's. */
|
|
246
282
|
.qm-table-header-row .qm-table-cell {
|
|
247
|
-
font-weight: var(--_qm-weight-
|
|
248
|
-
background: var(--_qm-surface-
|
|
283
|
+
font-weight: var(--_qm-weight-strong);
|
|
284
|
+
background: var(--_qm-surface-well);
|
|
249
285
|
border-bottom: var(--_qm-border-width) solid var(--_qm-border);
|
|
250
286
|
}
|
|
251
287
|
/* A cell holds a whole nested view. Its measure floor keeps an empty table from
|
|
252
288
|
collapsing to a row of hairlines with nothing to aim at, and the caret is the
|
|
253
289
|
focus indicator here exactly as it is in the leaf: no ring.
|
|
254
290
|
|
|
255
|
-
The
|
|
291
|
+
The height floor is one line box, named as size times leading so both factors move
|
|
256
292
|
with the type ramp (`.qm-prose-block` states the same expression for three). An
|
|
257
293
|
empty row is then the height it will be once typed, so the first keystroke changes
|
|
258
294
|
no geometry. */
|
|
@@ -264,201 +300,180 @@ li.ProseMirror-selectednode::after {
|
|
|
264
300
|
outline: none;
|
|
265
301
|
}
|
|
266
302
|
/* A selected island takes the node outline every leaf block does
|
|
267
|
-
(`.ProseMirror-selectednode`, above), and that is the state
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
/*
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
303
|
+
(`.ProseMirror-selectednode`, above), and that is the state Escape leaves a cell or a
|
|
304
|
+
line for: the caret is out, the island is what is selected, and Backspace deletes it.
|
|
305
|
+
A caret inside a cell is not that state and does not paint it. */
|
|
306
|
+
|
|
307
|
+
/* The selection, washed across the cells it covers: what Backspace acts on, and the
|
|
308
|
+
only thing on the island that says what the next command is about. The accent held,
|
|
309
|
+
not the hover rung: a hover is what the pointer is passing over and a selection is
|
|
310
|
+
what the next command will act on, and two states one tone apart on the same surface
|
|
311
|
+
ladder read as the same state at a glance. Translucent, so a selected header cell
|
|
312
|
+
keeps its raised tone under the tint instead of trading it away.
|
|
313
|
+
|
|
314
|
+
One attribute for both gestures, because there is one selection: a grip draws the
|
|
315
|
+
rectangle covering its line and a sweep draws the block the pointer crossed, and the
|
|
316
|
+
wash cannot tell them apart because nothing downstream needs to. */
|
|
317
|
+
.qm-table-cell[data-selected] {
|
|
318
|
+
background: var(--_qm-accent-tint);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/* ── The band ────────────────────────────────────────────────────────────────
|
|
322
|
+
Two control families, one geometry: absolutely positioned out of the grid, a
|
|
323
|
+
`--_qm-tap-min` target whatever is drawn inside it, and no box of their own at rest.
|
|
324
|
+
What differs is which edge each hangs off and what it draws. The grips take the
|
|
325
|
+
leading edges, where a line begins; the add bars take the trailing ones, past where
|
|
326
|
+
the axis ends. Position is the whole of what says which is which: the grip's marks are
|
|
327
|
+
the only glyph on the island, and they say draggable rather than which control this
|
|
328
|
+
is. */
|
|
329
|
+
:is(.qm-table-grip, .qm-table-add) {
|
|
330
|
+
position: absolute;
|
|
281
331
|
display: flex;
|
|
282
332
|
align-items: center;
|
|
283
333
|
justify-content: center;
|
|
334
|
+
padding: 0;
|
|
284
335
|
border: none;
|
|
285
336
|
background: none;
|
|
337
|
+
color: var(--_qm-ink);
|
|
286
338
|
cursor: pointer;
|
|
287
339
|
}
|
|
288
|
-
:
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
/* ONE control per line, and it is a bar rather than a glyph: what a handle acts on
|
|
294
|
-
is the row or column it sits against, and position says that better than an icon
|
|
295
|
-
would.
|
|
340
|
+
/* The bar every one of them draws: a pill the length of what it acts on, a rhythm rung
|
|
341
|
+
thick where the target is the tap floor. Stated once, so a grip and an add bar cannot
|
|
342
|
+
drift into two shapes.
|
|
296
343
|
|
|
297
|
-
|
|
298
|
-
the
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
.qm-table-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
touch-action: none;
|
|
306
|
-
}
|
|
307
|
-
.qm-table-handle[data-axis='column'] {
|
|
308
|
-
inset-inline: 0;
|
|
309
|
-
bottom: 100%;
|
|
310
|
-
height: var(--_qm-tap-min);
|
|
311
|
-
}
|
|
312
|
-
.qm-table-handle[data-axis='row'] {
|
|
313
|
-
inset-block: 0;
|
|
314
|
-
right: 100%;
|
|
315
|
-
width: var(--_qm-tap-min);
|
|
316
|
-
}
|
|
317
|
-
.qm-table-handle-bar {
|
|
318
|
-
display: block;
|
|
344
|
+
One tone, not a hover ladder: the control is drawn only while it is the one the
|
|
345
|
+
pointer is on or the one a gesture is about, so a resting tone under that would be a
|
|
346
|
+
rung nothing ever reaches. The selected grip's tint below is the one exception, and it
|
|
347
|
+
says which line the next command acts on rather than where the pointer is. */
|
|
348
|
+
:is(.qm-table-grip-bar, .qm-table-add-bar) {
|
|
349
|
+
display: flex;
|
|
350
|
+
align-items: center;
|
|
351
|
+
justify-content: center;
|
|
319
352
|
border-radius: var(--_qm-radius-pill);
|
|
320
353
|
background: var(--_qm-border);
|
|
321
|
-
|
|
322
|
-
|
|
354
|
+
transition:
|
|
355
|
+
background-color var(--_qm-duration-fast) var(--_qm-ease-reverse),
|
|
356
|
+
color var(--_qm-duration-fast) var(--_qm-ease-reverse);
|
|
357
|
+
}
|
|
358
|
+
/* The glyph is square and the bar is not: the marks sit in the bar's thickness and the
|
|
359
|
+
bar's length is its line's, so the frame is sized off the one axis both share. */
|
|
360
|
+
.qm-table-grip-bar svg {
|
|
361
|
+
width: var(--_qm-space-3);
|
|
362
|
+
height: var(--_qm-space-3);
|
|
363
|
+
}
|
|
364
|
+
/* A grip runs along the line it names; an add bar runs across the axis it appends to.
|
|
365
|
+
So the two families map one `data-axis` onto opposite orientations, and orientation
|
|
366
|
+
is the one thing the rule above cannot share with them: a column's grip is as wide as
|
|
367
|
+
its column, and the bar that adds a column is as tall as the table. */
|
|
368
|
+
.qm-table-grip[data-axis='column'] .qm-table-grip-bar,
|
|
369
|
+
.qm-table-add[data-axis='row'] .qm-table-add-bar {
|
|
323
370
|
width: 100%;
|
|
324
|
-
height:
|
|
371
|
+
height: var(--_qm-space-3);
|
|
325
372
|
}
|
|
326
|
-
.qm-table-
|
|
327
|
-
|
|
373
|
+
.qm-table-grip[data-axis='row'] .qm-table-grip-bar,
|
|
374
|
+
.qm-table-add[data-axis='column'] .qm-table-add-bar {
|
|
375
|
+
width: var(--_qm-space-3);
|
|
328
376
|
height: 100%;
|
|
329
|
-
min-height: 0.75rem;
|
|
330
|
-
}
|
|
331
|
-
/* A selected handle carries the line's ink, so the bar and the wash say the same
|
|
332
|
-
thing at both ends of the gesture. */
|
|
333
|
-
.qm-table-handle[aria-pressed='true'] .qm-table-handle-bar {
|
|
334
|
-
background: var(--_qm-ink-label);
|
|
335
377
|
}
|
|
336
378
|
|
|
337
|
-
/*
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
bottom: 100%;
|
|
343
|
-
width: var(--_qm-tap-min);
|
|
344
|
-
height: var(--_qm-tap-min);
|
|
345
|
-
}
|
|
346
|
-
.qm-table-corner-mark {
|
|
347
|
-
display: block;
|
|
348
|
-
width: 0.4375rem;
|
|
349
|
-
height: 0.4375rem;
|
|
350
|
-
border-radius: var(--_qm-radius-pill);
|
|
351
|
-
background: var(--_qm-border);
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
/* A SEAM: the boundary between two lines, and the whole of how a table grows. One per
|
|
355
|
-
boundary including the leading and trailing ones, so an append and an interior
|
|
356
|
-
insert are one gesture at different places.
|
|
379
|
+
/* One grip per line, and it is a bar rather than a glyph: what a grip acts on is the
|
|
380
|
+
row or column it sits against, and spanning that line says so better than an icon
|
|
381
|
+
could. The bar carries the grip's own marks — two rows of three, the shape a thing
|
|
382
|
+
you can pick up has everywhere else — so the control reads as draggable before it is
|
|
383
|
+
dragged.
|
|
357
384
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
border-radius: var(--_qm-radius-pill);
|
|
366
|
-
color: var(--_qm-accent);
|
|
385
|
+
The target is the band and the bar is drawn inside it: a grip spans its line on one
|
|
386
|
+
axis and the tap floor on the other, and the bar is drawn thinner inside that. A grip
|
|
387
|
+
sized to its own bar would be a target the thickness of the mark on it, on a control
|
|
388
|
+
the pointer has to find. */
|
|
389
|
+
.qm-table-grip {
|
|
390
|
+
/* The pointer owns this gesture, not the page's scroll: a grip drags. */
|
|
391
|
+
touch-action: none;
|
|
367
392
|
}
|
|
368
|
-
.qm-table-
|
|
393
|
+
.qm-table-grip[data-axis='column'] {
|
|
394
|
+
inset-inline: 0;
|
|
369
395
|
bottom: 100%;
|
|
370
|
-
|
|
371
|
-
}
|
|
372
|
-
/* The TRAILING seams sit flush inside their edge rather than centred on it: the last
|
|
373
|
-
boundary is the grid's own edge, and a seam centred on it would hang half outside
|
|
374
|
-
the scroller, where the padding does not reach and the clip does, making the append
|
|
375
|
-
affordance the one control that could not be pressed. */
|
|
376
|
-
.qm-table-seam[data-axis='column'][data-side='trail'] {
|
|
377
|
-
left: auto;
|
|
378
|
-
right: 0;
|
|
396
|
+
height: var(--_qm-tap-min);
|
|
379
397
|
}
|
|
380
|
-
.qm-table-
|
|
398
|
+
.qm-table-grip[data-axis='row'] {
|
|
399
|
+
inset-block: 0;
|
|
381
400
|
right: 100%;
|
|
382
|
-
|
|
401
|
+
width: var(--_qm-tap-min);
|
|
383
402
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
403
|
+
/* A selected grip takes the line's own tint and the accent for its marks, so the bar
|
|
404
|
+
and the wash say the same thing at both ends of the gesture. */
|
|
405
|
+
.qm-table-grip[aria-pressed='true'] .qm-table-grip-bar {
|
|
406
|
+
background: var(--_qm-accent-tint);
|
|
407
|
+
color: var(--_qm-accent);
|
|
387
408
|
}
|
|
388
409
|
|
|
389
|
-
/* The
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
left:
|
|
399
|
-
height: var(--_qm-tap-min);
|
|
400
|
-
background: var(--_qm-surface-raised);
|
|
401
|
-
border: var(--_qm-border-width) solid var(--_qm-border);
|
|
402
|
-
border-radius: var(--_qm-radius-pill);
|
|
403
|
-
}
|
|
404
|
-
/* The LAST column anchors right instead: a cluster is wider than a narrow column, and
|
|
405
|
-
one hung off the right edge would be the only chrome the scroller could clip. */
|
|
406
|
-
.qm-table-cell:last-child .qm-table-align {
|
|
407
|
-
left: auto;
|
|
408
|
-
right: 0;
|
|
409
|
-
}
|
|
410
|
-
.qm-table-align-item {
|
|
410
|
+
/* The add bars: one along each trailing edge, spanning it. A bar rather than a button
|
|
411
|
+
at the end of the band, because what it appends to is the axis and not a line — there
|
|
412
|
+
is no line out past the last one to sit against, and the whole edge is the easiest
|
|
413
|
+
target on the island to hit. They are the grips' mirror in every way but the edge and
|
|
414
|
+
the marks, which is what makes a bar out there read as one more of these rather than
|
|
415
|
+
as a control of its own: an empty bar past the last line is the table's own shape,
|
|
416
|
+
offered one line further on. */
|
|
417
|
+
.qm-table-add[data-axis='column'] {
|
|
418
|
+
inset-block: 0;
|
|
419
|
+
left: 100%;
|
|
411
420
|
width: var(--_qm-tap-min);
|
|
412
|
-
height: 100%;
|
|
413
|
-
padding: 0;
|
|
414
|
-
border-radius: var(--_qm-radius-pill);
|
|
415
|
-
color: var(--_qm-ink-label);
|
|
416
|
-
}
|
|
417
|
-
.qm-table-align-item:hover {
|
|
418
|
-
background: var(--_qm-surface-hover);
|
|
419
|
-
color: var(--_qm-ink);
|
|
420
421
|
}
|
|
421
|
-
.qm-table-
|
|
422
|
-
|
|
422
|
+
.qm-table-add[data-axis='row'] {
|
|
423
|
+
inset-inline: 0;
|
|
424
|
+
top: 100%;
|
|
425
|
+
height: var(--_qm-tap-min);
|
|
423
426
|
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
.
|
|
427
|
+
/* The reveal, in two rungs, one per question (CODEC §"The table island"). The band comes
|
|
428
|
+
up muted while the pointer is anywhere on the island, answering whether there is one at
|
|
429
|
+
all; a control raises to full while the pointer is on it, while it holds the focus, or
|
|
430
|
+
while it is what a gesture is about — the selected line's grip, and the lifted one,
|
|
431
|
+
which is drawn through a drag the pointer has travelled off — answering which line.
|
|
432
|
+
|
|
433
|
+
Opacity rather than absence, so every control keeps its box and is hit-tested wherever
|
|
434
|
+
it sits. A grip's reach is the pointer's — no Tab arrives at one, the cell traversal
|
|
435
|
+
claiming the key first (`table-view.ts` §`step`) — so it is out of the tab order, and
|
|
436
|
+
the focus rung there draws the focus the view takes itself. The two bars are in it, the
|
|
437
|
+
Tab that declines off the last cell landing on them, and the same rung is what draws
|
|
438
|
+
one a keyboard has reached. */
|
|
439
|
+
:is(.qm-table-grip, .qm-table-add) {
|
|
434
440
|
opacity: 0;
|
|
435
441
|
transition: opacity var(--_qm-duration-fast) var(--_qm-ease-reverse);
|
|
436
442
|
}
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
443
|
+
/* `:where` on the island, so the first rung carries the specificity of the control alone
|
|
444
|
+
and the second one outranks it. Unwrapped, the descendant selector is the heavier of
|
|
445
|
+
the two and a hovered grip stays muted under the pointer that is on it. */
|
|
446
|
+
:where(.qm-table-island:hover) :is(.qm-table-grip, .qm-table-add) {
|
|
447
|
+
opacity: var(--_qm-opacity-muted);
|
|
440
448
|
}
|
|
441
|
-
.qm-table-
|
|
442
|
-
.qm-table-
|
|
443
|
-
.qm-table-handle[aria-pressed='true'],
|
|
444
|
-
.qm-table-seam:hover,
|
|
445
|
-
.qm-table-seam:focus-visible {
|
|
449
|
+
:is(.qm-table-grip, .qm-table-add):is(:hover, :focus-visible),
|
|
450
|
+
.qm-table-grip:is([aria-pressed='true'], .qm-table-lifted) {
|
|
446
451
|
opacity: 1;
|
|
447
452
|
}
|
|
448
453
|
|
|
449
|
-
/* The ring, on the chrome and nowhere else in this file. A prose leaf's focus
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
it. Declared here rather than reached for as
|
|
453
|
-
visual tier's stylesheet, and the island is inside
|
|
454
|
-
.
|
|
455
|
-
|
|
456
|
-
.
|
|
454
|
+
/* The ring, on the chrome and nowhere else in this file. A prose leaf's focus indicator
|
|
455
|
+
is its caret and a cell's is too, so the outline is dropped there; a control that comes
|
|
456
|
+
up out of nothing has the reveal, and a ring under a keyboard is what says the focus is
|
|
457
|
+
there rather than on the paper behind it. Declared here rather than reached for as
|
|
458
|
+
`.qm-focus-ring`: that recipe is the visual tier's stylesheet, and the island is inside
|
|
459
|
+
the leaf, which is the codec's.
|
|
460
|
+
|
|
461
|
+
A selected grip takes none. Focus and selection arrive together there — the grip takes
|
|
462
|
+
the focus because the selection's keys bind on it — and the tint plus the wash already
|
|
463
|
+
say where the next command lands. A ring on top is a second box around the loudest
|
|
464
|
+
thing on the island, drawn on the press that made the selection: a pointer gesture
|
|
465
|
+
answering with a keyboard's indicator. Stated as `none` rather than left unset, because
|
|
466
|
+
what fills the gap is the browser's own ring, which is the same box in a colour the
|
|
467
|
+
surface does not own. */
|
|
468
|
+
:is(.qm-table-grip, .qm-table-add):focus-visible {
|
|
457
469
|
outline: var(--_qm-ring);
|
|
458
470
|
outline-offset: var(--_qm-ring-offset);
|
|
459
471
|
}
|
|
472
|
+
.qm-table-grip[aria-pressed='true']:focus-visible {
|
|
473
|
+
outline: none;
|
|
474
|
+
}
|
|
460
475
|
|
|
461
|
-
/* A
|
|
476
|
+
/* A drag in flight. The lifted line reads as picked up by tone, never a shadow:
|
|
462
477
|
elevation is a surface rung here, which says the same thing at both poles. The drop
|
|
463
478
|
rule is the accent, the surface's one saturated ink, spent where a change is about
|
|
464
479
|
to land. */
|