@quillmark/svelte 0.10.1 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/THEMING.md +2 -2
- package/dist/core/address.d.ts +17 -10
- package/dist/core/address.js +26 -12
- package/dist/core/bloom.js +4 -3
- package/dist/core/codec/blocks.js +21 -1
- package/dist/core/codec/breaks.d.ts +10 -2
- package/dist/core/codec/breaks.js +65 -9
- package/dist/core/codec/code.d.ts +6 -4
- package/dist/core/codec/code.js +7 -4
- package/dist/core/codec/decode.js +103 -68
- package/dist/core/codec/encode.d.ts +5 -8
- package/dist/core/codec/encode.js +56 -86
- package/dist/core/codec/field.js +43 -24
- package/dist/core/codec/index.d.ts +2 -1
- package/dist/core/codec/index.js +6 -3
- package/dist/core/codec/islands.d.ts +16 -11
- package/dist/core/codec/islands.js +70 -59
- package/dist/core/codec/keymap.js +2 -1
- package/dist/core/codec/marks.d.ts +17 -13
- package/dist/core/codec/marks.js +39 -42
- package/dist/core/codec/positions.d.ts +4 -1
- package/dist/core/codec/positions.js +5 -1
- package/dist/core/codec/reconcile.d.ts +6 -0
- package/dist/core/codec/reconcile.js +19 -0
- package/dist/core/codec/schema.d.ts +5 -8
- package/dist/core/codec/schema.js +30 -156
- package/dist/core/codec/slash.js +0 -0
- package/dist/core/codec/table-view.js +77 -26
- package/dist/core/codec/table.d.ts +6 -5
- package/dist/core/codec/table.js +14 -31
- package/dist/core/codec/urls.d.ts +20 -0
- package/dist/core/codec/urls.js +45 -0
- package/dist/core/rungs.d.ts +8 -0
- package/dist/core/rungs.js +24 -0
- package/dist/core/theme.css +10 -0
- package/dist/preset/recipes.css +1 -1
- package/dist/preset/scale.css +7 -4
- package/dist/preview/bridge.d.ts +8 -1
- package/dist/preview/bridge.js +31 -25
- package/dist/preview/controller.js +13 -13
- package/dist/preview/geometry.d.ts +12 -1
- package/dist/preview/geometry.js +14 -1
- package/dist/preview/paint.js +6 -4
- package/dist/preview/strings.d.ts +0 -2
- package/dist/preview/strings.js +5 -6
- package/dist/visual/ArrayField.svelte +600 -173
- package/dist/visual/ArrayField.svelte.d.ts +14 -1
- package/dist/visual/BooleanField.svelte +10 -7
- package/dist/visual/Card.svelte +8 -30
- package/dist/visual/DateField.svelte +2 -2
- package/dist/visual/Field.svelte +76 -32
- package/dist/visual/FieldHint.svelte +1 -1
- package/dist/visual/MatrixField.svelte +352 -0
- package/dist/visual/MatrixField.svelte.d.ts +36 -0
- package/dist/visual/ObjectField.svelte +356 -133
- package/dist/visual/ObjectField.svelte.d.ts +17 -2
- package/dist/visual/VariantField.svelte +55 -2
- package/dist/visual/VariantField.svelte.d.ts +10 -1
- package/dist/visual/VisualEditor.svelte +1 -1
- package/dist/visual/VisualEditorInner.svelte +118 -67
- package/dist/visual/controls.css +39 -9
- package/dist/visual/diagnostics.d.ts +26 -2
- package/dist/visual/diagnostics.js +52 -5
- package/dist/visual/ext.d.ts +12 -13
- package/dist/visual/ext.js +22 -19
- package/dist/visual/hold.js +2 -2
- package/dist/visual/icons/nodes.d.ts +3 -0
- package/dist/visual/icons/nodes.js +2 -1
- package/dist/visual/index.js +2 -3
- package/dist/visual/leaves.d.ts +25 -12
- package/dist/visual/links.d.ts +4 -0
- package/dist/visual/links.js +15 -4
- package/dist/visual/motion.d.ts +14 -5
- package/dist/visual/motion.js +13 -11
- package/dist/visual/strings.d.ts +26 -13
- package/dist/visual/strings.js +7 -2
- package/dist/visual/structure.d.ts +101 -8
- package/dist/visual/structure.js +252 -13
- package/package.json +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { nearestAddrForFieldPath } from '../core/address.js';
|
|
1
|
+
import { nearestAddrForFieldPath, nestedAddrForFieldPath } from '../core/address.js';
|
|
2
2
|
/** Canonical string key for a `FieldKey`: the routing `Map`'s key space. */
|
|
3
3
|
export function fieldKeyToString(k) {
|
|
4
4
|
return `${k.card ?? 'main'}:${k.field ?? '$body'}`;
|
|
@@ -42,11 +42,53 @@ export function routeAndResolve(diagnostics, cardIds) {
|
|
|
42
42
|
}
|
|
43
43
|
return out;
|
|
44
44
|
}
|
|
45
|
+
/** A field's routed diagnostics, each with its steps past the field: none for a
|
|
46
|
+
* diagnostic anchored at the field itself, or one whose path is not a nested one
|
|
47
|
+
* (a local commit error carries the field's own path). */
|
|
48
|
+
export function deepen(diagnostics) {
|
|
49
|
+
return (diagnostics ?? []).map((d) => ({
|
|
50
|
+
steps: (d.path && nestedAddrForFieldPath(d.path)?.steps) || [],
|
|
51
|
+
diagnostic: d
|
|
52
|
+
}));
|
|
53
|
+
}
|
|
54
|
+
export function splitDeep(list) {
|
|
55
|
+
const here = [];
|
|
56
|
+
const below = new Map();
|
|
57
|
+
for (const d of list ?? []) {
|
|
58
|
+
if (d.steps.length === 0) {
|
|
59
|
+
here.push(d.diagnostic);
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
const [step, ...rest] = d.steps;
|
|
63
|
+
const bucket = below.get(step);
|
|
64
|
+
const next = { steps: rest, diagnostic: d.diagnostic };
|
|
65
|
+
if (bucket)
|
|
66
|
+
bucket.push(next);
|
|
67
|
+
else
|
|
68
|
+
below.set(step, [next]);
|
|
69
|
+
}
|
|
70
|
+
return { here, below };
|
|
71
|
+
}
|
|
72
|
+
/** The diagnostics a rung cannot hand down: the ones anchored here, plus every one
|
|
73
|
+
* whose next step names nothing in `held`. Drawn at the rung's own foot, so a leaf the
|
|
74
|
+
* tree does not draw still has its message read somewhere the user can see. */
|
|
75
|
+
export function unrouted(split, held) {
|
|
76
|
+
const out = [...split.here];
|
|
77
|
+
for (const [step, list] of split.below)
|
|
78
|
+
if (!held(step))
|
|
79
|
+
for (const d of list)
|
|
80
|
+
out.push(d.diagnostic);
|
|
81
|
+
return out;
|
|
82
|
+
}
|
|
45
83
|
/**
|
|
46
84
|
* Merge N routed groups into `Map<fieldKeyToString(key), Diagnostic[]>`.
|
|
47
|
-
* Dedupes an identical `(severity, message)`
|
|
85
|
+
* Dedupes an identical `(path, severity, message)` quad landing on the same key from
|
|
48
86
|
* more than one group (e.g. the same error present in both `validate()` and
|
|
49
87
|
* an external feed). Producer order within a key.
|
|
88
|
+
*
|
|
89
|
+
* The key is the field, but the walk past it is the `path`'s ({@link deepen}), so two
|
|
90
|
+
* cells of one container share a key and differ only there: without `path` in the
|
|
91
|
+
* quad, one message failing two rows draws on the first row alone.
|
|
50
92
|
*/
|
|
51
93
|
export function mergeDiagnostics(...groups) {
|
|
52
94
|
const byKey = new Map();
|
|
@@ -54,9 +96,14 @@ export function mergeDiagnostics(...groups) {
|
|
|
54
96
|
for (const group of groups) {
|
|
55
97
|
for (const { key, diagnostic } of group) {
|
|
56
98
|
const k = fieldKeyToString(key);
|
|
57
|
-
// Collision-proof key: JSON-encode the
|
|
58
|
-
// can never merge two distinct
|
|
59
|
-
const dedupeKey = JSON.stringify([
|
|
99
|
+
// Collision-proof key: JSON-encode the quad so arbitrary `message` text
|
|
100
|
+
// can never merge two distinct quads into one (a real diagnostic dropped).
|
|
101
|
+
const dedupeKey = JSON.stringify([
|
|
102
|
+
k,
|
|
103
|
+
diagnostic.path ?? null,
|
|
104
|
+
diagnostic.severity,
|
|
105
|
+
diagnostic.message
|
|
106
|
+
]);
|
|
60
107
|
if (seen.has(dedupeKey))
|
|
61
108
|
continue;
|
|
62
109
|
seen.add(dedupeKey);
|
package/dist/visual/ext.d.ts
CHANGED
|
@@ -4,23 +4,22 @@ import type { Document, CardAddr } from '@quillmark/wasm';
|
|
|
4
4
|
* main). A key whose patch value is `undefined` is dropped; every other key in the
|
|
5
5
|
* namespace is carried through untouched.
|
|
6
6
|
*
|
|
7
|
-
* **The
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* merely documented: key N+1 inherits the merge instead of re-deriving it.
|
|
7
|
+
* **The whole map is the write unit.** `storeExt` replaces `$ext` entire, so a writer
|
|
8
|
+
* that stores only its own key silently destroys every sibling namespace, and a
|
|
9
|
+
* namespace-replacing write destroys the sibling keys inside it. `tips` and `title`
|
|
10
|
+
* are siblings here, so either would wipe every renamed card's title. Routing every
|
|
11
|
+
* writer through this function is what makes that unexpressible rather than merely
|
|
12
|
+
* documented: key N+1 inherits the merge instead of re-deriving it.
|
|
14
13
|
*
|
|
15
14
|
* The drop is an explicit `delete`, not a stored `undefined`: whether a JS
|
|
16
15
|
* `undefined` survives the wasm-bindgen crossing is not a property worth depending
|
|
17
16
|
* on.
|
|
18
17
|
*
|
|
19
|
-
* **A namespace emptied of keys is removed, not stored empty
|
|
20
|
-
* `
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
18
|
+
* **A namespace emptied of keys is removed, not stored empty**, and `$ext` goes with
|
|
19
|
+
* it when `editor` was the last namespace — `removeExt` being the one call that drops
|
|
20
|
+
* the map, where `storeExt({})` records an explicit empty one. So a document nothing
|
|
21
|
+
* has renamed or hinted carries no editor slot rather than an empty one. A patch
|
|
22
|
+
* dropping keys the namespace does not have writes nothing, so dismissing tips on a
|
|
23
|
+
* document that carries none is not a mutation.
|
|
25
24
|
*/
|
|
26
25
|
export declare function patchEditorExt(doc: Document, addr: CardAddr, patch: Record<string, unknown>): void;
|
package/dist/visual/ext.js
CHANGED
|
@@ -3,29 +3,27 @@
|
|
|
3
3
|
* main). A key whose patch value is `undefined` is dropped; every other key in the
|
|
4
4
|
* namespace is carried through untouched.
|
|
5
5
|
*
|
|
6
|
-
* **The
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* merely documented: key N+1 inherits the merge instead of re-deriving it.
|
|
6
|
+
* **The whole map is the write unit.** `storeExt` replaces `$ext` entire, so a writer
|
|
7
|
+
* that stores only its own key silently destroys every sibling namespace, and a
|
|
8
|
+
* namespace-replacing write destroys the sibling keys inside it. `tips` and `title`
|
|
9
|
+
* are siblings here, so either would wipe every renamed card's title. Routing every
|
|
10
|
+
* writer through this function is what makes that unexpressible rather than merely
|
|
11
|
+
* documented: key N+1 inherits the merge instead of re-deriving it.
|
|
13
12
|
*
|
|
14
13
|
* The drop is an explicit `delete`, not a stored `undefined`: whether a JS
|
|
15
14
|
* `undefined` survives the wasm-bindgen crossing is not a property worth depending
|
|
16
15
|
* on.
|
|
17
16
|
*
|
|
18
|
-
* **A namespace emptied of keys is removed, not stored empty
|
|
19
|
-
* `
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
17
|
+
* **A namespace emptied of keys is removed, not stored empty**, and `$ext` goes with
|
|
18
|
+
* it when `editor` was the last namespace — `removeExt` being the one call that drops
|
|
19
|
+
* the map, where `storeExt({})` records an explicit empty one. So a document nothing
|
|
20
|
+
* has renamed or hinted carries no editor slot rather than an empty one. A patch
|
|
21
|
+
* dropping keys the namespace does not have writes nothing, so dismissing tips on a
|
|
22
|
+
* document that carries none is not a mutation.
|
|
24
23
|
*/
|
|
25
24
|
export function patchEditorExt(doc, addr, patch) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const current = doc.getExtNamespace(addr, 'editor');
|
|
25
|
+
const ext = doc.getExt(addr) ?? {};
|
|
26
|
+
const current = ext.editor;
|
|
29
27
|
const next = { ...(current ?? {}) };
|
|
30
28
|
for (const [key, value] of Object.entries(patch)) {
|
|
31
29
|
if (value === undefined)
|
|
@@ -34,7 +32,12 @@ export function patchEditorExt(doc, addr, patch) {
|
|
|
34
32
|
next[key] = value;
|
|
35
33
|
}
|
|
36
34
|
if (Object.keys(next).length > 0)
|
|
37
|
-
doc.
|
|
38
|
-
else if (current)
|
|
39
|
-
|
|
35
|
+
doc.storeExt(addr, { ...ext, editor: next });
|
|
36
|
+
else if (current) {
|
|
37
|
+
const { editor: _editor, ...rest } = ext;
|
|
38
|
+
if (Object.keys(rest).length > 0)
|
|
39
|
+
doc.storeExt(addr, rest);
|
|
40
|
+
else
|
|
41
|
+
doc.removeExt(addr);
|
|
42
|
+
}
|
|
40
43
|
}
|
package/dist/visual/hold.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// the layout, and what fills the viewport as a section collapses is that section's own
|
|
3
3
|
// content, whose top never moves.
|
|
4
4
|
import { flushSync } from 'svelte';
|
|
5
|
-
import { rungMs } from '
|
|
5
|
+
import { rungMs, rungStyle } from '../core/rungs.js';
|
|
6
6
|
/**
|
|
7
7
|
* Run `change` and keep `anchor` inside the fold for the length of the move.
|
|
8
8
|
*
|
|
@@ -26,7 +26,7 @@ export function holdInView(anchor, change) {
|
|
|
26
26
|
flushSync();
|
|
27
27
|
const reveal = () => anchor.scrollIntoView({ block: 'nearest', behavior: 'instant' });
|
|
28
28
|
reveal();
|
|
29
|
-
const rung = rungMs(
|
|
29
|
+
const rung = rungMs(rungStyle(anchor), '--_qm-duration-slow');
|
|
30
30
|
if (rung === undefined)
|
|
31
31
|
return;
|
|
32
32
|
const until = performance.now() + rung;
|
|
@@ -116,6 +116,9 @@ export declare const ICONS: {
|
|
|
116
116
|
readonly minus: readonly [readonly ["path", {
|
|
117
117
|
readonly d: "M5 12h14";
|
|
118
118
|
}]];
|
|
119
|
+
readonly check: readonly [readonly ["path", {
|
|
120
|
+
readonly d: "M20 6 9 17l-5-5";
|
|
121
|
+
}]];
|
|
119
122
|
};
|
|
120
123
|
/** The closed set. A name that is not here is a compile error at the call site,
|
|
121
124
|
* which is what a string key buys over thirteen imported components. */
|
package/dist/visual/index.js
CHANGED
|
@@ -25,7 +25,6 @@ export { createField } from '../core/codec/index.js';
|
|
|
25
25
|
// it. The empty body's per-card hook is the `bodyPlaceholder` key inside it.
|
|
26
26
|
export { DEFAULT_VISUAL_STRINGS } from './strings.js';
|
|
27
27
|
// The `$ext.editor` write unit. A consumer seeding editor-side chrome
|
|
28
|
-
// state (a card title, the tips channel) goes through this rather than
|
|
29
|
-
//
|
|
30
|
-
// it.
|
|
28
|
+
// state (a card title, the tips channel) goes through this rather than `storeExt`,
|
|
29
|
+
// which replaces the whole map and takes every sibling with it.
|
|
31
30
|
export { patchEditorExt } from './ext.js';
|
package/dist/visual/leaves.d.ts
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
|
+
import type { PathStep } from '@quillmark/wasm';
|
|
1
2
|
import type { FieldController } from '../core/codec/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* What a landing at depth hands back: the box the arrival wash blooms in, now or once
|
|
5
|
+
* the row it had to open has rendered. A row two closed boxes down does not exist
|
|
6
|
+
* until the row above it opens and flushes, so the innermost box is a promise wherever
|
|
7
|
+
* the walk had to open something on the way.
|
|
8
|
+
*/
|
|
9
|
+
export type LandingBox = HTMLElement | undefined | Promise<HTMLElement | undefined>;
|
|
2
10
|
/**
|
|
3
11
|
* A mounted field's landing handle: focus it, and the element the arrival wash blooms
|
|
4
12
|
* inside ({@link import('../core/bloom.js').bloomInside}).
|
|
@@ -10,22 +18,27 @@ import type { FieldController } from '../core/codec/index.js';
|
|
|
10
18
|
export interface FieldControl {
|
|
11
19
|
focus(): void;
|
|
12
20
|
/**
|
|
13
|
-
* Land
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
21
|
+
* Land at `steps` inside a control that has an inside — an array's element, an
|
|
22
|
+
* object's property, a variant's cell, a matrix's member, and any of them under any
|
|
23
|
+
* other — at USV `pos` where the leaf the walk ends in can take one. Each rung
|
|
24
|
+
* resolves its own step at the call (an index to a session id, a key to a mounted
|
|
25
|
+
* cell) and hands the rest to the control it opened, so nothing positional is
|
|
26
|
+
* carried. A step the tree does not hold falls back to that rung's own
|
|
27
|
+
* {@link focus}: the field is right and the row is gone. Absent on every control
|
|
28
|
+
* with no inside.
|
|
17
29
|
*
|
|
18
30
|
* A landing, not a focus: an absent `pos` is the placement rung, exactly as on
|
|
19
|
-
* `Landing`, and what a `pos` means is the
|
|
20
|
-
*
|
|
21
|
-
*
|
|
31
|
+
* `Landing`, and what a `pos` means is the leaf's, the same way focusing is. The
|
|
32
|
+
* place rides the call because the registry stays parent-keyed: a per-element key is
|
|
33
|
+
* positional, in a registry whose doctrine is dodging positional churn.
|
|
22
34
|
*
|
|
23
|
-
* Returns the
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* reads as
|
|
35
|
+
* Returns the innermost row the address named, which is what the wash blooms in: a
|
|
36
|
+
* box wider than the one the click resolved says the field where the pick said the
|
|
37
|
+
* row. `undefined` is a landing that named no row — a property under a field-level
|
|
38
|
+
* subform, or the fallback an index past the live list took — and reads as
|
|
39
|
+
* {@link el}.
|
|
27
40
|
*/
|
|
28
|
-
|
|
41
|
+
focusPath?(steps: readonly PathStep[], pos?: number): LandingBox;
|
|
29
42
|
readonly el: HTMLElement;
|
|
30
43
|
}
|
|
31
44
|
/**
|
package/dist/visual/links.d.ts
CHANGED
|
@@ -9,6 +9,10 @@ import type { Command, EditorState } from 'prosemirror-state';
|
|
|
9
9
|
* A rooted value is left alone, being the spelling that asks for the embedding
|
|
10
10
|
* page, and so is anything already carrying a scheme the link mark renders.
|
|
11
11
|
*
|
|
12
|
+
* `localhost:5173` names a host too, and `SCHEME` reads its host as the scheme: a
|
|
13
|
+
* colon followed by a port is a host with a port, so it takes the host prefix rather
|
|
14
|
+
* than the refusal a scheme nothing renders gets.
|
|
15
|
+
*
|
|
12
16
|
* `''` for a blank value and for a scheme the mark renders inert, both being nothing
|
|
13
17
|
* to apply: `setLink` declines an empty href, so the refusal lands at the prompt's
|
|
14
18
|
* own exit rather than storing a link that draws as plain text.
|
package/dist/visual/links.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { rendersHref } from '../core/codec/index.js';
|
|
1
|
+
import { rendersHref, storableUrl } from '../core/codec/index.js';
|
|
2
2
|
/** A scheme: a letter, then letters, digits, `+`, `-` or `.`, then `:` (RFC 3986). */
|
|
3
3
|
const SCHEME = /^[a-z][a-z0-9+.-]*:/i;
|
|
4
4
|
/** Rooted at the page rather than at a host: an absolute path, a query, a fragment,
|
|
@@ -6,6 +6,9 @@ const SCHEME = /^[a-z][a-z0-9+.-]*:/i;
|
|
|
6
6
|
const ROOTED = /^[/#?]/;
|
|
7
7
|
/** A bare mail address: one `@`, no scheme and no path. */
|
|
8
8
|
const ADDRESS = /^[^\s/@]+@[^\s/@]+$/;
|
|
9
|
+
/** A host carrying a port, which spells a scheme to `SCHEME` and is not one: what
|
|
10
|
+
* follows the colon is digits, and no scheme the mark renders takes a port. */
|
|
11
|
+
const HOST_PORT = /^[a-z0-9.-]+:\d+([/?#]|$)/i;
|
|
9
12
|
/**
|
|
10
13
|
* The href a typed value stands for. A value with no scheme names a host, and
|
|
11
14
|
* stored verbatim it is a relative href resolving against whatever page the editor
|
|
@@ -16,15 +19,23 @@ const ADDRESS = /^[^\s/@]+@[^\s/@]+$/;
|
|
|
16
19
|
* A rooted value is left alone, being the spelling that asks for the embedding
|
|
17
20
|
* page, and so is anything already carrying a scheme the link mark renders.
|
|
18
21
|
*
|
|
22
|
+
* `localhost:5173` names a host too, and `SCHEME` reads its host as the scheme: a
|
|
23
|
+
* colon followed by a port is a host with a port, so it takes the host prefix rather
|
|
24
|
+
* than the refusal a scheme nothing renders gets.
|
|
25
|
+
*
|
|
19
26
|
* `''` for a blank value and for a scheme the mark renders inert, both being nothing
|
|
20
27
|
* to apply: `setLink` declines an empty href, so the refusal lands at the prompt's
|
|
21
28
|
* own exit rather than storing a link that draws as plain text.
|
|
22
29
|
*/
|
|
23
30
|
export function normalizeHref(raw) {
|
|
24
|
-
const value = raw.trim();
|
|
25
|
-
if (!value
|
|
31
|
+
const value = storableUrl(raw.trim());
|
|
32
|
+
if (!value)
|
|
33
|
+
return '';
|
|
34
|
+
if (!rendersHref(value) && !HOST_PORT.test(value))
|
|
26
35
|
return '';
|
|
27
|
-
if (SCHEME.test(value)
|
|
36
|
+
if (SCHEME.test(value) && rendersHref(value))
|
|
37
|
+
return value;
|
|
38
|
+
if (ROOTED.test(value))
|
|
28
39
|
return value;
|
|
29
40
|
return ADDRESS.test(value) ? `mailto:${value}` : `https://${value}`;
|
|
30
41
|
}
|
package/dist/visual/motion.d.ts
CHANGED
|
@@ -3,11 +3,20 @@ import type { AnimationConfig } from 'svelte/animate';
|
|
|
3
3
|
* position for its whole length, so anything that measures the node's box waits on
|
|
4
4
|
* these rather than reading the one a transform is holding. */
|
|
5
5
|
export declare function reorderTrips(node: HTMLElement): Animation[];
|
|
6
|
-
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
|
|
6
|
+
/**
|
|
7
|
+
* The reorder gesture's arming window, for a keyed list that takes the trip. The
|
|
8
|
+
* reconcile that moves a slot is the trip, and every other reconcile that happens to
|
|
9
|
+
* move one is not; so the command arms the gesture and the frame it lands in disarms
|
|
10
|
+
* it, `animate:` asking at apply time, a microtask after the mutation and well inside
|
|
11
|
+
* that frame. `armed` is a getter rather than a value, so the flag stays out of the
|
|
12
|
+
* template and needs no reactivity for it. `cancel` is for the surface's teardown.
|
|
13
|
+
*/
|
|
14
|
+
export interface ReorderArm {
|
|
15
|
+
arm(): void;
|
|
16
|
+
armed(): boolean;
|
|
17
|
+
cancel(): void;
|
|
18
|
+
}
|
|
19
|
+
export declare function reorderArm(): ReorderArm;
|
|
11
20
|
/**
|
|
12
21
|
* Slide a keyed slot from where it was to where it now is.
|
|
13
22
|
*
|
package/dist/visual/motion.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
// cannot see (the rects either side of the reconciliation) and WAAPI paints the trip,
|
|
5
5
|
// the same seam `core/bloom.ts` takes to keep a duration in the derivation while a
|
|
6
6
|
// script runs the animation.
|
|
7
|
+
import { rungMs, rungStyle } from '../core/rungs.js';
|
|
7
8
|
/** Marks this module's runs, so a second reorder cancels the first rather than layering
|
|
8
9
|
* a second transform over it. */
|
|
9
10
|
const RUN_ID = 'qm-reorder';
|
|
@@ -15,16 +16,17 @@ export function reorderTrips(node) {
|
|
|
15
16
|
return [];
|
|
16
17
|
return node.getAnimations().filter((run) => run.id === RUN_ID);
|
|
17
18
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
19
|
+
export function reorderArm() {
|
|
20
|
+
let reordering = false;
|
|
21
|
+
let frame = 0;
|
|
22
|
+
return {
|
|
23
|
+
arm() {
|
|
24
|
+
reordering = true;
|
|
25
|
+
frame = requestAnimationFrame(() => (reordering = false));
|
|
26
|
+
},
|
|
27
|
+
armed: () => reordering,
|
|
28
|
+
cancel: () => cancelAnimationFrame(frame)
|
|
29
|
+
};
|
|
28
30
|
}
|
|
29
31
|
/**
|
|
30
32
|
* Slide a keyed slot from where it was to where it now is.
|
|
@@ -45,7 +47,7 @@ export function reorder(node, { from, to }, armed) {
|
|
|
45
47
|
// rung the derivation mints.
|
|
46
48
|
if (!armed() || typeof node.animate !== 'function')
|
|
47
49
|
return {};
|
|
48
|
-
const style =
|
|
50
|
+
const style = rungStyle(node);
|
|
49
51
|
const duration = rungMs(style, '--_qm-duration-slow');
|
|
50
52
|
const easing = style.getPropertyValue('--_qm-ease-reverse').trim();
|
|
51
53
|
if (duration === undefined || !easing)
|
package/dist/visual/strings.d.ts
CHANGED
|
@@ -16,27 +16,37 @@ export interface VisualStrings extends TableChromeStrings, SlashStrings {
|
|
|
16
16
|
cardTitle: string;
|
|
17
17
|
/** The trailing strip's visible words, which are also every strip's accessible
|
|
18
18
|
* name; the plus rides the wording. One string over
|
|
19
|
-
* one kind and many: the trigger seeds
|
|
19
|
+
* one kind and many: the trigger seeds a card, and which kind is the menu's word
|
|
20
20
|
* to say or the schema's to have already settled. */
|
|
21
21
|
addCard: string;
|
|
22
22
|
arrayAdd: string;
|
|
23
23
|
arrayRemove: string;
|
|
24
|
-
/** The
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
/** The reorder pair on an `object` row, accessible names: the buttons are glyphs. */
|
|
25
|
+
arrayMoveUp: string;
|
|
26
|
+
arrayMoveDown: string;
|
|
27
|
+
/**
|
|
28
|
+
* A row control's accessible name, the action and the row it acts on: `Remove
|
|
29
|
+
* Authors 2`. The action alone stays the tooltip. Parametric, so word order stays
|
|
30
|
+
* the translator's.
|
|
31
|
+
*/
|
|
32
|
+
arrayRowAction: (action: string, row: string) => string;
|
|
27
33
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* orders the kind within it.
|
|
34
|
+
* The count beside the add chip on an array declaring `max:`, the carrier a
|
|
35
|
+
* disabled chip has no other way to state: `2 / 3`. Parametric, so a translator
|
|
36
|
+
* spells the separator.
|
|
32
37
|
*/
|
|
33
|
-
|
|
38
|
+
arrayCount: (count: number, max: number) => string;
|
|
34
39
|
/**
|
|
35
|
-
* A collapsed array element
|
|
40
|
+
* A collapsed array element with nothing to summarize itself by: the label and the
|
|
36
41
|
* 1-based index, which is what its accessible name already says. Parametric, so
|
|
37
42
|
* word order stays the translator's.
|
|
38
43
|
*/
|
|
39
44
|
elementUntitled: (label: string, index: number) => string;
|
|
45
|
+
/** The tag on the unset sentinel's row, which is what tells it from the member it
|
|
46
|
+
* ghosts ({@link EnumField}). */
|
|
47
|
+
enumUnsetTag: string;
|
|
48
|
+
/** The count in the matrix's label row: how many of the roster are held. */
|
|
49
|
+
matrixHeld: (held: number, total: number) => string;
|
|
40
50
|
/** The required marker's accessible name; the glyph itself is a `*`. */
|
|
41
51
|
fieldRequired: string;
|
|
42
52
|
formatGroup: string;
|
|
@@ -64,6 +74,9 @@ export interface VisualStrings extends TableChromeStrings, SlashStrings {
|
|
|
64
74
|
retypeLabel: string;
|
|
65
75
|
retypePlaceholder: string;
|
|
66
76
|
noCardKinds: string;
|
|
77
|
+
/** The body leaf's accessible name: no label names it, the body being the one
|
|
78
|
+
* surface in a card that is paper ({@link Card}). */
|
|
79
|
+
bodyLabel: string;
|
|
67
80
|
/**
|
|
68
81
|
* The flat built-in invitation: the package's own words, kept to the one thing
|
|
69
82
|
* true of every body so it claims nothing about the card it sits in.
|
|
@@ -91,9 +104,9 @@ export interface VisualStrings extends TableChromeStrings, SlashStrings {
|
|
|
91
104
|
* - **`edit::field_coercion_failed`**: re-words from the app's own control state, the
|
|
92
105
|
* refused value being in neither document (unchanged on throw) nor schema.
|
|
93
106
|
* - **`parse::yaml_error_with_location`, `invalid_structure`**: does not re-word. No
|
|
94
|
-
* `path
|
|
95
|
-
* engine prose riding under no key: the parser's own
|
|
96
|
-
* snippet exist only inside `message`.
|
|
107
|
+
* `path`; `args` names the block (`blockIndex`) and `location` places the failure in
|
|
108
|
+
* the document's own coordinates, engine prose riding under no key: the parser's own
|
|
109
|
+
* text, its column and its caret snippet exist only inside `message`.
|
|
97
110
|
* - **`LiveSession.warnings`**: does not re-word. Backend text, an external feed.
|
|
98
111
|
*
|
|
99
112
|
* The last two are the boundary's shape, not a gap in it, so the fallback arm is
|
package/dist/visual/strings.js
CHANGED
|
@@ -30,9 +30,13 @@ export const DEFAULT_VISUAL_STRINGS = {
|
|
|
30
30
|
addCard: '+ Add Card',
|
|
31
31
|
arrayAdd: '+ Add',
|
|
32
32
|
arrayRemove: 'Remove',
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
arrayMoveUp: 'Move up',
|
|
34
|
+
arrayMoveDown: 'Move down',
|
|
35
|
+
arrayRowAction: (action, row) => `${action} ${row}`,
|
|
36
|
+
arrayCount: (count, max) => `${count} / ${max}`,
|
|
35
37
|
elementUntitled: (label, index) => `${label} ${index}`,
|
|
38
|
+
enumUnsetTag: 'default',
|
|
39
|
+
matrixHeld: (held, total) => `${held} of ${total} held`,
|
|
36
40
|
fieldRequired: 'required',
|
|
37
41
|
formatGroup: 'Formatting',
|
|
38
42
|
formatBold: 'Bold (Mod-B)',
|
|
@@ -55,6 +59,7 @@ export const DEFAULT_VISUAL_STRINGS = {
|
|
|
55
59
|
retypeLabel: 'Change to',
|
|
56
60
|
retypePlaceholder: 'Choose a type…',
|
|
57
61
|
noCardKinds: 'This document declares no card types — delete this card to remove it.',
|
|
62
|
+
bodyLabel: 'Body',
|
|
58
63
|
bodyGhost: 'Write…',
|
|
59
64
|
bodyPlaceholder: () => undefined
|
|
60
65
|
};
|