@quillmark/svelte 0.20.1 → 0.22.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 +6 -7
- package/README.md +1 -1
- package/THEMING.md +1 -1
- package/dist/core/address.d.ts +6 -1
- package/dist/core/address.js +12 -3
- package/dist/core/bloom.d.ts +9 -4
- package/dist/core/bloom.js +18 -49
- package/dist/core/codec/atoms.d.ts +1 -1
- package/dist/core/codec/atoms.js +26 -11
- package/dist/core/codec/blocks.d.ts +5 -5
- package/dist/core/codec/blocks.js +27 -8
- package/dist/core/codec/code.d.ts +4 -4
- package/dist/core/codec/code.js +52 -22
- package/dist/core/codec/decode.d.ts +5 -5
- package/dist/core/codec/decode.js +18 -12
- package/dist/core/codec/encode.js +6 -1
- package/dist/core/codec/field.d.ts +22 -15
- package/dist/core/codec/field.js +66 -26
- package/dist/core/codec/index.d.ts +1 -1
- package/dist/core/codec/index.js +2 -2
- package/dist/core/codec/inputrules.d.ts +4 -0
- package/dist/core/codec/inputrules.js +44 -6
- package/dist/core/codec/link-paste.d.ts +11 -0
- package/dist/core/codec/link-paste.js +32 -0
- package/dist/core/codec/lists.d.ts +5 -4
- package/dist/core/codec/lists.js +87 -31
- package/dist/core/codec/nesting.d.ts +20 -0
- package/dist/core/codec/nesting.js +62 -0
- package/dist/core/codec/prose.css +145 -63
- package/dist/core/codec/schema.d.ts +2 -2
- package/dist/core/codec/schema.js +71 -18
- package/dist/core/codec/slash.js +0 -0
- package/dist/core/codec/table-copy.d.ts +17 -0
- package/dist/core/codec/table-copy.js +84 -0
- package/dist/core/codec/table-view.d.ts +6 -7
- package/dist/core/codec/table-view.js +281 -201
- package/dist/core/codec/table.d.ts +2 -9
- package/dist/core/codec/table.js +10 -19
- package/dist/core/codec/tasks.d.ts +19 -0
- package/dist/core/codec/tasks.js +140 -0
- package/dist/core/errors.d.ts +2 -2
- package/dist/core/rungs.d.ts +6 -0
- package/dist/core/rungs.js +11 -0
- package/dist/core/theme.css +24 -12
- package/dist/visual/ArrayField.svelte +236 -78
- package/dist/visual/ArrayField.svelte.d.ts +0 -2
- package/dist/visual/BooleanField.svelte +12 -1
- package/dist/visual/Card.svelte +41 -23
- package/dist/visual/Card.svelte.d.ts +3 -2
- package/dist/visual/CardControls.svelte +15 -15
- package/dist/visual/DateField.svelte +93 -64
- package/dist/visual/EnumField.svelte +9 -4
- package/dist/visual/Field.svelte +20 -16
- package/dist/visual/Field.svelte.d.ts +4 -2
- package/dist/visual/FieldHint.svelte +22 -5
- package/dist/visual/FieldLabel.svelte +5 -33
- package/dist/visual/FieldLabel.svelte.d.ts +0 -2
- package/dist/visual/FormatPopover.svelte +78 -81
- package/dist/visual/MatrixField.svelte +28 -19
- package/dist/visual/NumberField.svelte +32 -3
- package/dist/visual/ObjectField.svelte +40 -24
- package/dist/visual/ObjectField.svelte.d.ts +6 -0
- package/dist/visual/ProseField.svelte +10 -13
- package/dist/visual/ProseField.svelte.d.ts +5 -2
- package/dist/visual/ProseValue.svelte +25 -19
- package/dist/visual/ProseValue.svelte.d.ts +4 -4
- package/dist/visual/TextField.svelte +3 -2
- package/dist/visual/TipsCard.svelte +7 -7
- package/dist/visual/VariantField.svelte +1 -1
- package/dist/visual/VariantField.svelte.d.ts +1 -1
- package/dist/visual/VisualEditorInner.svelte +121 -39
- package/dist/visual/controls.css +21 -2
- package/dist/visual/icons/Icon.svelte +3 -2
- package/dist/visual/icons/Icon.svelte.d.ts +3 -2
- package/dist/visual/icons/nodes.d.ts +25 -21
- package/dist/visual/icons/nodes.js +9 -7
- package/dist/visual/leaves.d.ts +12 -9
- package/dist/visual/leaves.js +19 -0
- package/dist/visual/motion.d.ts +25 -3
- package/dist/visual/motion.js +58 -9
- package/dist/visual/strings.d.ts +15 -9
- package/dist/visual/strings.js +19 -12
- package/dist/visual/structure.d.ts +21 -31
- package/dist/visual/structure.js +54 -51
- package/package.json +3 -3
|
@@ -73,19 +73,12 @@ export declare function moveColumn(props: TableProps, c: number, by: number): Ta
|
|
|
73
73
|
* empties is text.
|
|
74
74
|
*/
|
|
75
75
|
export declare function clearCells(props: TableProps, r0: number, c0: number, r1: number, c1: number): TableProps;
|
|
76
|
-
/** Set column `c`'s alignment
|
|
77
|
-
* (`table-view.ts`). */
|
|
76
|
+
/** Set column `c`'s alignment and clear its cells' own `align`, which would outrank it:
|
|
77
|
+
* what the held column's cluster and Shift+arrow write (`table-view.ts`). */
|
|
78
78
|
export declare function setAlign(props: TableProps, c: number, align: TableAlign): TableProps;
|
|
79
79
|
/** Draw the first row as a header or as a body row: what the header toggle writes
|
|
80
80
|
* (`table-view.ts`). */
|
|
81
81
|
export declare function setHeadless(props: TableProps, headless: boolean): TableProps;
|
|
82
|
-
/** A cell's horizontal alignment, and its vertical one: the keys a cell holds beside
|
|
83
|
-
* its text, each absent at the default the column or the quill supplies. */
|
|
84
|
-
export type CellAlign = NonNullable<TableCell['align']>;
|
|
85
|
-
export type CellValign = NonNullable<TableCell['valign']>;
|
|
86
|
-
/** Every cell in the inclusive rectangle given `key`'s `value`, or cleared of it where
|
|
87
|
-
* `value` is absent, which returns the cell to its column's alignment or the quill's. */
|
|
88
|
-
export declare function setCellLayout<K extends 'align' | 'valign'>(props: TableProps, r0: number, c0: number, r1: number, c1: number, key: K, value: TableCell[K] | undefined): TableProps;
|
|
89
82
|
/** Set or clear the column weights: what a border drag and its double-click write
|
|
90
83
|
* (`table-view.ts`). `undefined` returns every column to auto-fit. */
|
|
91
84
|
export declare function setWidths(props: TableProps, widths: (number | null)[] | undefined): TableProps;
|
package/dist/core/codec/table.js
CHANGED
|
@@ -184,11 +184,19 @@ export function clearCells(props, r0, c0, r1, c1) {
|
|
|
184
184
|
rows: props.rows.map((row, i) => blank(row, i + 1))
|
|
185
185
|
});
|
|
186
186
|
}
|
|
187
|
-
/** Set column `c`'s alignment
|
|
188
|
-
* (`table-view.ts`). */
|
|
187
|
+
/** Set column `c`'s alignment and clear its cells' own `align`, which would outrank it:
|
|
188
|
+
* what the held column's cluster and Shift+arrow write (`table-view.ts`). */
|
|
189
189
|
export function setAlign(props, c, align) {
|
|
190
|
+
const release = (cells) => cells.map((cell, i) => {
|
|
191
|
+
if (i !== c || cell.align === undefined)
|
|
192
|
+
return cell;
|
|
193
|
+
const { align: _align, ...rest } = cell;
|
|
194
|
+
return rest;
|
|
195
|
+
});
|
|
190
196
|
return normalizeTable({
|
|
191
197
|
...props,
|
|
198
|
+
header: release(props.header),
|
|
199
|
+
rows: props.rows.map(release),
|
|
192
200
|
aligns: props.aligns.map((a, i) => (i === c ? align : a))
|
|
193
201
|
});
|
|
194
202
|
}
|
|
@@ -197,23 +205,6 @@ export function setAlign(props, c, align) {
|
|
|
197
205
|
export function setHeadless(props, headless) {
|
|
198
206
|
return normalizeTable({ ...props, headless: headless || undefined });
|
|
199
207
|
}
|
|
200
|
-
/** Every cell in the inclusive rectangle given `key`'s `value`, or cleared of it where
|
|
201
|
-
* `value` is absent, which returns the cell to its column's alignment or the quill's. */
|
|
202
|
-
export function setCellLayout(props, r0, c0, r1, c1, key, value) {
|
|
203
|
-
const lay = (cells, r) => cells.map((cell, c) => {
|
|
204
|
-
if (r < r0 || r > r1 || c < c0 || c > c1)
|
|
205
|
-
return cell;
|
|
206
|
-
const next = { ...cell, [key]: value };
|
|
207
|
-
if (value === undefined)
|
|
208
|
-
delete next[key];
|
|
209
|
-
return next;
|
|
210
|
-
});
|
|
211
|
-
return normalizeTable({
|
|
212
|
-
...props,
|
|
213
|
-
header: lay(props.header, 0),
|
|
214
|
-
rows: props.rows.map((row, i) => lay(row, i + 1))
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
208
|
/** Set or clear the column weights: what a border drag and its double-click write
|
|
218
209
|
* (`table-view.ts`). `undefined` returns every column to auto-fit. */
|
|
219
210
|
export function setWidths(props, widths) {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type DOMOutputSpec, type NodeType } from 'prosemirror-model';
|
|
2
|
+
import { Plugin, type Command } from 'prosemirror-state';
|
|
3
|
+
/** The `checked` an `<li>` states: `data-qm-checked`, which `toDOM` writes, else none. */
|
|
4
|
+
export declare function taskChecked(el: HTMLElement): boolean | null;
|
|
5
|
+
/** Where an `<li>`'s blocks are: a task item's body, past its checkbox; the item itself
|
|
6
|
+
* otherwise. */
|
|
7
|
+
export declare function taskBody(el: Node): HTMLElement;
|
|
8
|
+
/** A task item's `<li>`: the checkbox, unreachable by the caret, then the body holding
|
|
9
|
+
* the item's blocks, which names it. The mark is the check glyph a matrix tick draws. */
|
|
10
|
+
export declare function taskDOM(checked: boolean): DOMOutputSpec;
|
|
11
|
+
/** The node view a block leaf mounts its list items through. */
|
|
12
|
+
export declare function taskPlugin(): Plugin;
|
|
13
|
+
/**
|
|
14
|
+
* `splitListItem`, leaving the item that takes none of a task item's text an open task:
|
|
15
|
+
* the one below, or the one above where Enter is pressed at the head of the item's text.
|
|
16
|
+
* An empty item the split lifts out of a nested list keeps its own `checked`, as a
|
|
17
|
+
* Shift-Tab lift keeps it.
|
|
18
|
+
*/
|
|
19
|
+
export declare function splitTaskItem(itemType: NodeType): Command;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
// A task item is a `list_item` whose `checked` is a boolean (CODEC §"Task items"). Its
|
|
2
|
+
// `toDOM` draws a checkbox ahead of the item's blocks, disabled, which is the drawing a
|
|
3
|
+
// held leaf, a copy and `renderContent` take; a leaf that edits mounts the item through
|
|
4
|
+
// `taskItemView`, whose checkbox toggles. A task item is minted by source mode and by a
|
|
5
|
+
// paste alone: no shorthand, command or key makes one.
|
|
6
|
+
import { DOMSerializer } from 'prosemirror-model';
|
|
7
|
+
import { Plugin } from 'prosemirror-state';
|
|
8
|
+
import { splitListItem } from 'prosemirror-schema-list';
|
|
9
|
+
const SVG = 'http://www.w3.org/2000/svg';
|
|
10
|
+
/** The id the checkbox names its item's blocks by, fresh per drawing. */
|
|
11
|
+
let drawn = 0;
|
|
12
|
+
/** The `checked` an `<li>` states: `data-qm-checked`, which `toDOM` writes, else none. */
|
|
13
|
+
export function taskChecked(el) {
|
|
14
|
+
const stated = el.getAttribute('data-qm-checked');
|
|
15
|
+
return stated === null ? null : stated === 'true';
|
|
16
|
+
}
|
|
17
|
+
/** Where an `<li>`'s blocks are: a task item's body, past its checkbox; the item itself
|
|
18
|
+
* otherwise. */
|
|
19
|
+
export function taskBody(el) {
|
|
20
|
+
const li = el;
|
|
21
|
+
const body = li.hasAttribute('data-qm-checked')
|
|
22
|
+
? li.querySelector(':scope > [data-qm-task-body]')
|
|
23
|
+
: null;
|
|
24
|
+
return body ?? li;
|
|
25
|
+
}
|
|
26
|
+
/** A task item's `<li>`: the checkbox, unreachable by the caret, then the body holding
|
|
27
|
+
* the item's blocks, which names it. The mark is the check glyph a matrix tick draws. */
|
|
28
|
+
export function taskDOM(checked) {
|
|
29
|
+
const body = `qm-task-${++drawn}`;
|
|
30
|
+
return [
|
|
31
|
+
'li',
|
|
32
|
+
{ 'data-qm-checked': String(checked) },
|
|
33
|
+
[
|
|
34
|
+
'span',
|
|
35
|
+
{ class: 'qm-task', contenteditable: 'false' },
|
|
36
|
+
[
|
|
37
|
+
'input',
|
|
38
|
+
{
|
|
39
|
+
type: 'checkbox',
|
|
40
|
+
class: 'qm-task-box',
|
|
41
|
+
'aria-labelledby': body,
|
|
42
|
+
checked: checked ? '' : null,
|
|
43
|
+
disabled: ''
|
|
44
|
+
}
|
|
45
|
+
],
|
|
46
|
+
[
|
|
47
|
+
`${SVG} svg`,
|
|
48
|
+
{
|
|
49
|
+
class: 'qm-task-mark',
|
|
50
|
+
viewBox: '0 0 24 24',
|
|
51
|
+
fill: 'none',
|
|
52
|
+
stroke: 'currentColor',
|
|
53
|
+
'stroke-width': '2',
|
|
54
|
+
'stroke-linecap': 'round',
|
|
55
|
+
'stroke-linejoin': 'round',
|
|
56
|
+
'aria-hidden': 'true'
|
|
57
|
+
},
|
|
58
|
+
[`${SVG} path`, { d: 'M20 6 9 17l-5-5' }]
|
|
59
|
+
]
|
|
60
|
+
],
|
|
61
|
+
['div', { id: body, 'data-qm-task-body': '' }, 0]
|
|
62
|
+
];
|
|
63
|
+
}
|
|
64
|
+
const isTask = (node) => node.attrs.checked !== null;
|
|
65
|
+
/**
|
|
66
|
+
* Every `list_item` in a leaf that edits, drawn by its own `toDOM`. A task item's checkbox
|
|
67
|
+
* is enabled, and a change to it is one `checked` transaction, so one `Mod-z` takes it
|
|
68
|
+
* back; where the leaf declines the edit the box returns to the item's value. The box
|
|
69
|
+
* keeps the press from the caret: a mousedown leaves the selection and the focus where
|
|
70
|
+
* they were, and ProseMirror reads no event aimed at it.
|
|
71
|
+
*/
|
|
72
|
+
function taskItemView(node, view, getPos) {
|
|
73
|
+
const { dom, contentDOM } = DOMSerializer.renderSpec(document, node.type.spec.toDOM(node));
|
|
74
|
+
const box = isTask(node)
|
|
75
|
+
? dom.querySelector(':scope > .qm-task > input')
|
|
76
|
+
: null;
|
|
77
|
+
if (box) {
|
|
78
|
+
box.disabled = false;
|
|
79
|
+
box.addEventListener('mousedown', (e) => e.preventDefault());
|
|
80
|
+
box.addEventListener('change', () => {
|
|
81
|
+
const pos = getPos();
|
|
82
|
+
if (pos === undefined || !view.editable) {
|
|
83
|
+
box.checked = node.attrs.checked;
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
view.dispatch(view.state.tr.setNodeAttribute(pos, 'checked', box.checked));
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
dom,
|
|
91
|
+
contentDOM,
|
|
92
|
+
update(next) {
|
|
93
|
+
if (next.type !== node.type || isTask(next) !== isTask(node))
|
|
94
|
+
return false;
|
|
95
|
+
node = next;
|
|
96
|
+
if (box) {
|
|
97
|
+
box.checked = next.attrs.checked;
|
|
98
|
+
dom.setAttribute('data-qm-checked', String(next.attrs.checked));
|
|
99
|
+
}
|
|
100
|
+
return true;
|
|
101
|
+
},
|
|
102
|
+
stopEvent: (e) => box !== null && e.target === box,
|
|
103
|
+
ignoreMutation: (m) => m.type !== 'selection' && !contentDOM.contains(m.target)
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/** The node view a block leaf mounts its list items through. */
|
|
107
|
+
export function taskPlugin() {
|
|
108
|
+
return new Plugin({ props: { nodeViews: { list_item: taskItemView } } });
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* `splitListItem`, leaving the item that takes none of a task item's text an open task:
|
|
112
|
+
* the one below, or the one above where Enter is pressed at the head of the item's text.
|
|
113
|
+
* An empty item the split lifts out of a nested list keeps its own `checked`, as a
|
|
114
|
+
* Shift-Tab lift keeps it.
|
|
115
|
+
*/
|
|
116
|
+
export function splitTaskItem(itemType) {
|
|
117
|
+
const split = splitListItem(itemType);
|
|
118
|
+
return (state, dispatch, view) => {
|
|
119
|
+
const { $from, empty } = state.selection;
|
|
120
|
+
const item = $from.depth >= 2 ? $from.node(-1) : null;
|
|
121
|
+
if (!dispatch || item?.type !== itemType || !isTask(item))
|
|
122
|
+
return split(state, dispatch, view);
|
|
123
|
+
const lifted = $from.parent.content.size === 0 && item.childCount === 1;
|
|
124
|
+
const atHead = empty && $from.parentOffset === 0 && $from.index(-1) === 0;
|
|
125
|
+
return split(state, (tr) => {
|
|
126
|
+
const $at = tr.selection.$from;
|
|
127
|
+
const below = $at.before($at.depth - 1);
|
|
128
|
+
if (lifted)
|
|
129
|
+
tr.setNodeAttribute(below, 'checked', item.attrs.checked);
|
|
130
|
+
else if (atHead) {
|
|
131
|
+
const above = tr.doc.resolve(below).nodeBefore;
|
|
132
|
+
if (above)
|
|
133
|
+
tr.setNodeAttribute(below - above.nodeSize, 'checked', false);
|
|
134
|
+
}
|
|
135
|
+
else
|
|
136
|
+
tr.setNodeAttribute(below, 'checked', false);
|
|
137
|
+
dispatch(tr);
|
|
138
|
+
});
|
|
139
|
+
};
|
|
140
|
+
}
|
package/dist/core/errors.d.ts
CHANGED
|
@@ -11,8 +11,8 @@ export type EditorErrorCode =
|
|
|
11
11
|
* the whole projection instead, so the store is correct and this field's
|
|
12
12
|
* identity anchors were paid. */
|
|
13
13
|
| 'commit-fallback'
|
|
14
|
-
/** The overwrite fallback also failed, or the typed writer refused a `
|
|
15
|
-
*
|
|
14
|
+
/** The overwrite fallback also failed, or the typed writer refused a `text` leaf's
|
|
15
|
+
* text: the optimistic PM state stands and the store is stale for this
|
|
16
16
|
* field. The one code here that leaves damage. */
|
|
17
17
|
| 'commit-lost'
|
|
18
18
|
/** A card operation (add, move, remove, retype) that threw. The document is
|
package/dist/core/rungs.d.ts
CHANGED
|
@@ -6,3 +6,9 @@ export declare function rungStyle(node: Element): CSSStyleDeclaration;
|
|
|
6
6
|
* empty). No rung, no motion: a fallback here would be the scale restated in the one
|
|
7
7
|
* place `check:style` cannot read. */
|
|
8
8
|
export declare function rungMs(style: CSSStyleDeclaration, rung: string): number | undefined;
|
|
9
|
+
/** `steps` of the space rung off `node`'s root, in px: a floating surface's offset from
|
|
10
|
+
* its anchor. `--_qm-space` is registered, so it computes to px where the rungs derived
|
|
11
|
+
* from it compute to their expressions; hence the multiple rather than a read of
|
|
12
|
+
* `--_qm-space-2`. `undefined` where the derivation is out of reach, as for
|
|
13
|
+
* {@link rungMs}. */
|
|
14
|
+
export declare function spacePx(node: Element | undefined, steps?: number): number | undefined;
|
package/dist/core/rungs.js
CHANGED
|
@@ -22,3 +22,14 @@ export function rungMs(style, rung) {
|
|
|
22
22
|
return undefined;
|
|
23
23
|
return raw.endsWith('ms') ? n : n * 1000;
|
|
24
24
|
}
|
|
25
|
+
/** `steps` of the space rung off `node`'s root, in px: a floating surface's offset from
|
|
26
|
+
* its anchor. `--_qm-space` is registered, so it computes to px where the rungs derived
|
|
27
|
+
* from it compute to their expressions; hence the multiple rather than a read of
|
|
28
|
+
* `--_qm-space-2`. `undefined` where the derivation is out of reach, as for
|
|
29
|
+
* {@link rungMs}. */
|
|
30
|
+
export function spacePx(node, steps = 1) {
|
|
31
|
+
if (!node)
|
|
32
|
+
return undefined;
|
|
33
|
+
const n = Number.parseFloat(rungStyle(node).getPropertyValue('--_qm-space'));
|
|
34
|
+
return Number.isFinite(n) ? n * steps : undefined;
|
|
35
|
+
}
|
package/dist/core/theme.css
CHANGED
|
@@ -117,9 +117,9 @@
|
|
|
117
117
|
|
|
118
118
|
Two planes sink. `sunken` is the ground — the column behind the cards, the
|
|
119
119
|
desk behind the sheets — and lifting the plane above it takes very little
|
|
120
|
-
at the light pole. `well` is the hole cut into a card: a field,
|
|
121
|
-
|
|
122
|
-
|
|
120
|
+
at the light pole. `well` is the hole cut into a card: a field, the one
|
|
121
|
+
native select, neither of which draws an edge, so the step is the whole of
|
|
122
|
+
what says a value is typed there. The order at the
|
|
123
123
|
light pole is card, ground, well; at the dark pole the two sink to within
|
|
124
124
|
a channel of each other, which is where a card with little light left to
|
|
125
125
|
give up leaves them.
|
|
@@ -148,6 +148,10 @@
|
|
|
148
148
|
dark. */
|
|
149
149
|
--_qm-surface-raised: color-mix(in oklab, var(--_qm-bg), #fff 8%);
|
|
150
150
|
--_qm-surface-hover: color-mix(in oklab, var(--_qm-bg), var(--_qm-fg) 8%);
|
|
151
|
+
/* A band laid on the card rather than cut into it: a table's header, and the pill a
|
|
152
|
+
grip draws. It steps toward the ink at both poles, a shade under white in light
|
|
153
|
+
and a shade over the card in dark, where `well` sinks to a black stripe. */
|
|
154
|
+
--_qm-surface-band: color-mix(in oklab, var(--_qm-bg), var(--_qm-fg) 6%);
|
|
151
155
|
/* The one rung whose arms are not a single ratio: a stroke is read against what it
|
|
152
156
|
separates, and the mix that reads as a hairline on the dark default draws the
|
|
153
157
|
light card in a line heavier than the type it frames. The light arm is
|
|
@@ -157,12 +161,11 @@
|
|
|
157
161
|
color-mix(in oklab, var(--_qm-bg), var(--_qm-fg) 6%),
|
|
158
162
|
color-mix(in oklab, var(--_qm-bg), var(--_qm-fg) 17%)
|
|
159
163
|
);
|
|
160
|
-
/* A
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
--_qm-border-faint: color-mix(in oklab, var(--_qm-bg), var(--_qm-border) 50%);
|
|
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%);
|
|
166
169
|
/* Three rungs, and nothing under the last: a step below `label` lands under 3:1 on
|
|
167
170
|
the well a field draws it against, and what would take it — an unset value's word,
|
|
168
171
|
an invitation — is content a reader has to read (WCAG 1.4.3), not decoration.
|
|
@@ -186,6 +189,11 @@
|
|
|
186
189
|
stacks over whichever surface rung the cell already draws instead of replacing
|
|
187
190
|
it. */
|
|
188
191
|
--_qm-accent-tint: color-mix(in oklab, var(--_qm-accent) 12%, transparent);
|
|
192
|
+
/* The accent at the default rung: a mark's fill where the `default:` supplies it, a
|
|
193
|
+
switch's checked track and a held tick's box, stepped toward the card by the
|
|
194
|
+
ratio `default` steps the ink. What is drawn over it in the card's colour, the
|
|
195
|
+
thumb and the check, holds 3:1 at both poles, at 3.3:1 and 4.2:1. */
|
|
196
|
+
--_qm-accent-default: color-mix(in oklab, var(--_qm-accent), var(--_qm-bg) 20%);
|
|
189
197
|
/* The danger hue held: what a destructive control fills with where the family's
|
|
190
198
|
neutral hover rung would read as one more button. Mixed at the accent tint's
|
|
191
199
|
strength, so a held tint is a held tint whichever hue it carries. */
|
|
@@ -281,6 +289,10 @@
|
|
|
281
289
|
arrival settles into its rest instead of stopping at it, and long enough that a
|
|
282
290
|
control resting at nothing reads as arriving rather than as switching. */
|
|
283
291
|
--_qm-reveal: 500ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
292
|
+
/* A wait rather than a trip: how long a caret rests on an empty line before the
|
|
293
|
+
slash hint comes up. Longer than the gap between two keystrokes, so typing on
|
|
294
|
+
through an Enter never draws it. */
|
|
295
|
+
--_qm-hint-wait: 500ms;
|
|
284
296
|
|
|
285
297
|
/* ── Geometry ──────────────────────────────────────────────────────────*/
|
|
286
298
|
/* One stroke width for every edge the chrome draws and every rule it ranks
|
|
@@ -342,9 +354,9 @@
|
|
|
342
354
|
it does not move when `--qm-space` does. Every button family reads it, so the
|
|
343
355
|
floor is one number instead of one expression per control. */
|
|
344
356
|
--_qm-tap-min: 24px;
|
|
345
|
-
/* The chrome glyph: a chip's,
|
|
346
|
-
through the icon's `size`, so a stylesheet beats the SVG presentation
|
|
347
|
-
and one rung is the whole of what a control draws. */
|
|
357
|
+
/* The chrome glyph: a chip's, a glyph button's, the enum's chevron. Sized in CSS
|
|
358
|
+
rather than through the icon's `size`, so a stylesheet beats the SVG presentation
|
|
359
|
+
attribute and one rung is the whole of what a control draws. */
|
|
348
360
|
--_qm-glyph-control: 14px;
|
|
349
361
|
/* The narrowest track a control that fills its width stays usable in: a table's
|
|
350
362
|
column floors at it, rises no further than its content, and a row of them scrolls
|