@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.
Files changed (116) hide show
  1. package/README.md +2 -2
  2. package/THEMING.md +11 -7
  3. package/dist/core/address.d.ts +7 -7
  4. package/dist/core/address.js +6 -6
  5. package/dist/core/bloom.d.ts +5 -5
  6. package/dist/core/bloom.js +8 -8
  7. package/dist/core/codec/anchor.d.ts +1 -1
  8. package/dist/core/codec/anchor.js +1 -1
  9. package/dist/core/codec/atoms.d.ts +10 -0
  10. package/dist/core/codec/atoms.js +78 -0
  11. package/dist/core/codec/clipboard.d.ts +59 -0
  12. package/dist/core/codec/clipboard.js +202 -0
  13. package/dist/core/codec/code.d.ts +1 -1
  14. package/dist/core/codec/code.js +4 -4
  15. package/dist/core/codec/decode.d.ts +1 -1
  16. package/dist/core/codec/decode.js +8 -8
  17. package/dist/core/codec/encode.d.ts +4 -4
  18. package/dist/core/codec/encode.js +10 -10
  19. package/dist/core/codec/field.d.ts +21 -26
  20. package/dist/core/codec/field.js +33 -32
  21. package/dist/core/codec/index.js +5 -8
  22. package/dist/core/codec/inputrules.js +56 -18
  23. package/dist/core/codec/islands.d.ts +11 -7
  24. package/dist/core/codec/islands.js +16 -10
  25. package/dist/core/codec/keymap.d.ts +5 -6
  26. package/dist/core/codec/keymap.js +8 -7
  27. package/dist/core/codec/lists.d.ts +3 -3
  28. package/dist/core/codec/lists.js +32 -13
  29. package/dist/core/codec/marks.d.ts +1 -1
  30. package/dist/core/codec/marks.js +1 -1
  31. package/dist/core/codec/positions.js +1 -1
  32. package/dist/core/codec/prose.css +230 -215
  33. package/dist/core/codec/schema.js +4 -4
  34. package/dist/core/codec/slash.d.ts +39 -41
  35. package/dist/core/codec/slash.js +0 -0
  36. package/dist/core/codec/table-view.d.ts +12 -16
  37. package/dist/core/codec/table-view.js +488 -292
  38. package/dist/core/codec/table.d.ts +42 -15
  39. package/dist/core/codec/table.js +70 -26
  40. package/dist/core/errors.d.ts +5 -5
  41. package/dist/core/index.js +2 -2
  42. package/dist/core/lifecycle.js +1 -1
  43. package/dist/core/rebind.svelte.d.ts +2 -2
  44. package/dist/core/rebind.svelte.js +4 -4
  45. package/dist/core/teardown.d.ts +1 -1
  46. package/dist/core/teardown.js +1 -1
  47. package/dist/core/theme.css +144 -54
  48. package/dist/preset/index.css +1 -1
  49. package/dist/preset/recipes.css +31 -29
  50. package/dist/preset/scale.css +36 -25
  51. package/dist/preview/Preview.svelte +12 -10
  52. package/dist/preview/Preview.svelte.d.ts +3 -3
  53. package/dist/preview/bridge.js +4 -4
  54. package/dist/preview/controller.js +3 -3
  55. package/dist/preview/geometry.d.ts +2 -2
  56. package/dist/preview/geometry.js +2 -2
  57. package/dist/preview/index.js +3 -3
  58. package/dist/preview/overlay.d.ts +1 -1
  59. package/dist/preview/overlay.js +3 -3
  60. package/dist/preview/paint.js +15 -17
  61. package/dist/visual/ArrayField.svelte +80 -66
  62. package/dist/visual/ArrayField.svelte.d.ts +1 -1
  63. package/dist/visual/BooleanField.svelte +8 -6
  64. package/dist/visual/BooleanField.svelte.d.ts +2 -2
  65. package/dist/visual/Card.svelte +151 -325
  66. package/dist/visual/Card.svelte.d.ts +2 -6
  67. package/dist/visual/CardControls.svelte +1 -1
  68. package/dist/visual/DateField.svelte +19 -19
  69. package/dist/visual/DateField.svelte.d.ts +3 -3
  70. package/dist/visual/DiagnosticList.svelte +1 -1
  71. package/dist/visual/EnumField.svelte +16 -16
  72. package/dist/visual/EnumField.svelte.d.ts +2 -2
  73. package/dist/visual/Field.svelte +128 -115
  74. package/dist/visual/Field.svelte.d.ts +1 -1
  75. package/dist/visual/FieldHint.svelte +24 -42
  76. package/dist/visual/FieldHint.svelte.d.ts +1 -1
  77. package/dist/visual/FieldLabel.svelte +8 -8
  78. package/dist/visual/FormatPopover.svelte +80 -35
  79. package/dist/visual/NumberField.svelte +5 -5
  80. package/dist/visual/NumberField.svelte.d.ts +1 -1
  81. package/dist/visual/ObjectField.svelte +9 -9
  82. package/dist/visual/ObjectField.svelte.d.ts +1 -1
  83. package/dist/visual/ProseArrayElement.svelte +11 -13
  84. package/dist/visual/ProseArrayElement.svelte.d.ts +1 -1
  85. package/dist/visual/ProseField.svelte +53 -84
  86. package/dist/visual/ProseField.svelte.d.ts +12 -17
  87. package/dist/visual/SlashMenu.svelte +42 -16
  88. package/dist/visual/TextField.svelte +5 -5
  89. package/dist/visual/TextField.svelte.d.ts +1 -1
  90. package/dist/visual/TipsCard.svelte +43 -28
  91. package/dist/visual/VisualEditor.svelte +6 -6
  92. package/dist/visual/VisualEditorInner.svelte +122 -129
  93. package/dist/visual/controls.css +74 -30
  94. package/dist/visual/diagnostics.d.ts +5 -5
  95. package/dist/visual/diagnostics.js +3 -3
  96. package/dist/visual/domid.js +3 -3
  97. package/dist/visual/ext.d.ts +1 -1
  98. package/dist/visual/ext.js +1 -1
  99. package/dist/visual/icons/nodes.d.ts +3 -0
  100. package/dist/visual/icons/nodes.js +2 -1
  101. package/dist/visual/index.js +4 -4
  102. package/dist/visual/leaves.d.ts +3 -3
  103. package/dist/visual/leaves.js +1 -1
  104. package/dist/visual/links.d.ts +24 -0
  105. package/dist/visual/links.js +67 -0
  106. package/dist/visual/props.d.ts +8 -8
  107. package/dist/visual/signals.d.ts +6 -6
  108. package/dist/visual/strings.d.ts +14 -19
  109. package/dist/visual/strings.js +5 -7
  110. package/dist/visual/structure.d.ts +24 -17
  111. package/dist/visual/structure.js +8 -8
  112. package/dist/visual/synced.svelte.d.ts +1 -1
  113. package/dist/visual/synced.svelte.js +4 -4
  114. package/dist/visual/tips.d.ts +2 -2
  115. package/dist/visual/tips.js +3 -3
  116. package/package.json +1 -1
@@ -2,7 +2,7 @@ import type { Diagnostic } from '@quillmark/wasm';
2
2
  import { type SlashStrings, type TableChromeStrings } from '../core/codec/index.js';
3
3
  import type { BodyPlaceholder } from './structure.js';
4
4
  /**
5
- * The island and the insert menu's keys come from the CODEC, which owns both models
5
+ * The island and the insert menu's keys come from the codec, which owns both models
6
6
  * (a NodeView inside the leaf, and the trigger the leaf's keymap drives). Extending
7
7
  * rather than restating them is what keeps one English list: a consumer overrides an
8
8
  * island handle's name beside the card controls' and the codec still has a default
@@ -14,16 +14,11 @@ export interface VisualStrings extends TableChromeStrings, SlashStrings {
14
14
  cardDelete: string;
15
15
  /** The card-title input's accessible name. */
16
16
  cardTitle: string;
17
- /** The multi-kind trigger, which names no kind because it opens a menu of them. */
17
+ /** The trailing strip's visible words, which are also every strip's accessible
18
+ * name; the glyph rides the wording, as the array foot's does. One string over
19
+ * one kind and many: the trigger seeds A card, and which kind is the menu's word
20
+ * to say or the schema's to have already settled. */
18
21
  addCard: string;
19
- /** The single-kind trigger, whose accessible name IS the kind it seeds. */
20
- addCardOfKind: (kind: string) => string;
21
- /** The trailing strip's VISIBLE words, which are also its accessible name; the
22
- * glyph rides the wording, as the array foot's does. A pair of their own rather
23
- * than a prefix over the two above, because a language reading the mark as one
24
- * phrase has nothing to prefix. */
25
- addCardMark: (kind: string) => string;
26
- addCardMarkAny: string;
27
22
  arrayAdd: string;
28
23
  arrayRemove: string;
29
24
  /** The required marker's accessible name; the glyph itself is a `*`. */
@@ -37,10 +32,12 @@ export interface VisualStrings extends TableChromeStrings, SlashStrings {
37
32
  formatLink: string;
38
33
  /** The anchor button's accessible name. */
39
34
  formatAnchor: string;
40
- /** Its hover title, which says what an anchor IS; the name above only says what. */
35
+ /** Its hover title, which says what an anchor is; the name above only says what. */
41
36
  formatAnchorTitle: string;
42
37
  linkPlaceholder: string;
43
38
  linkApply: string;
39
+ /** Drawn only where the selection carries a link. */
40
+ linkRemove: string;
44
41
  linkCancel: string;
45
42
  tipsLabel: string;
46
43
  tipsDismiss: string;
@@ -57,10 +54,8 @@ export interface VisualStrings extends TableChromeStrings, SlashStrings {
57
54
  */
58
55
  bodyGhost: string;
59
56
  /**
60
- * Per-KIND wording, in place of {@link VisualStrings.bodyGhost}; `undefined`
61
- * takes it. Consulted once per kind per session and cached by the editor, so a
62
- * hook that samples a set at random still reads as one deliberate string.
63
- * Impurity is expected, and the cache is what contains it.
57
+ * Per-CARD wording, in place of {@link VisualStrings.bodyGhost}; `undefined`
58
+ * takes it. Pure and uncached ({@link BodyPlaceholder}).
64
59
  */
65
60
  bodyPlaceholder: BodyPlaceholder;
66
61
  }
@@ -72,22 +67,22 @@ export interface VisualStrings extends TableChromeStrings, SlashStrings {
72
67
  * lane (VISUAL_EDITOR §Diagnostics for why each lands where it does):
73
68
  *
74
69
  * - **`validation::enum_violation`, `type_mismatch`, `format_violation`,
75
- * `must_fill`**: the CONSTRAINT re-words from the quill's schema at `path`, the
76
- * offending VALUE from `args` (`value` / `sourceToken` / `actual`, the engine
70
+ * `must_fill`**: the constraint re-words from the quill's schema at `path`, the
71
+ * offending value from `args` (`value` / `sourceToken` / `actual`, the engine
77
72
  * testifying to what it saw) and never from the document at `path`: validation
78
73
  * runs post-coercion, so the validator read a value the document does not hold and
79
74
  * a sentence built from `path` names a spelling the user never typed.
80
75
  * - **`edit::field_coercion_failed`**: re-words from the app's own control state, the
81
76
  * refused value being in neither document (unchanged on throw) nor schema.
82
77
  * - **`parse::yaml_error_with_location`, `invalid_structure`**: does not re-word. No
83
- * `path`, and `args` carries the LOCATION (`blockIndex`, `line`) and nothing else,
78
+ * `path`, and `args` carries the location (`blockIndex`, `line`) and nothing else,
84
79
  * engine prose riding under no key: the parser's own text, its column and its caret
85
80
  * snippet exist only inside `message`.
86
81
  * - **`LiveSession.warnings`**: does not re-word. Backend text, an external feed.
87
82
  *
88
83
  * The last two are the boundary's shape, not a gap in it, so the fallback arm is
89
84
  * permanent: returning `undefined` renders `d.message` unchanged. `code` is optional
90
- * at this pin, so that arm is reachable by TYPE and not only in principle.
85
+ * at this pin, so that arm is reachable by type and not only in principle.
91
86
  *
92
87
  * Displayed text is that message or this replacement and nothing beside it: `hint` is
93
88
  * the tail of the message it accompanies, so rendering it too ships a two-language
@@ -1,9 +1,9 @@
1
1
  // Every word the visual surface says, in one place, so a product shipping in
2
- // another language can replace them. Keyed and PARTIAL: a consumer sets the keys
2
+ // another language can replace them. Keyed and partial: a consumer sets the keys
3
3
  // it has translations for and the rest take the package's English, which is what
4
4
  // makes wording an override rather than a fork.
5
5
  //
6
- // Several of these are ACCESSIBLE NAMES rather than decoration — the card
6
+ // Several of these are accessible names rather than decoration — the card
7
7
  // controls, the add trigger, the required marker — so an untranslated surface is
8
8
  // not merely inconsistent, it reads the wrong language to a screen reader. That is
9
9
  // why this exists as a seam and not as a list of literals to grep for.
@@ -12,7 +12,7 @@
12
12
  // a parametric string cannot be assembled from fragments and stay translatable,
13
13
  // since the word order is the translator's to choose.
14
14
  //
15
- // The strings reach the tree through CONTEXT, not props. They are ambient,
15
+ // The strings reach the tree through context, not props. They are ambient,
16
16
  // read-only, and wanted eight components deep (a card's controls, a field's
17
17
  // required marker, the formatting popover, the tips card); threading them by hand
18
18
  // would put a `strings` prop on every component between the root and each leaf,
@@ -27,10 +27,7 @@ export const DEFAULT_VISUAL_STRINGS = {
27
27
  cardMoveDown: 'Move down',
28
28
  cardDelete: 'Delete card',
29
29
  cardTitle: 'Card title',
30
- addCard: 'Add card',
31
- addCardOfKind: (kind) => `Add ${kind}`,
32
- addCardMark: (kind) => `+ Add ${kind}`,
33
- addCardMarkAny: '+ Add Card',
30
+ addCard: '+ Add Card',
34
31
  arrayAdd: '+ Add',
35
32
  arrayRemove: 'Remove',
36
33
  fieldRequired: 'required',
@@ -45,6 +42,7 @@ export const DEFAULT_VISUAL_STRINGS = {
45
42
  formatAnchorTitle: 'Anchor — an identity handle over the selection',
46
43
  linkPlaceholder: 'https://…',
47
44
  linkApply: 'Apply',
45
+ linkRemove: 'Remove',
48
46
  linkCancel: 'Cancel',
49
47
  tipsLabel: 'Editor tips',
50
48
  tipsDismiss: 'Dismiss',
@@ -17,7 +17,7 @@ export interface FieldModel {
17
17
  * undefined when the field declares none. Chrome-only; never gates. */
18
18
  description: string | undefined;
19
19
  /**
20
- * Required-ness: a field with NO `default:` is "Unendorsed": its
20
+ * Required-ness: a field with no `default:` is "Unendorsed": its
21
21
  * seed carries a `!must_fill` marker (DOCUMENT_MODEL: there is no separate
22
22
  * `required` axis). Drives a persistent label `*`, complementary to the ghosted
23
23
  * `default:` (a required field has no default to ghost). Persistent (schema-
@@ -38,7 +38,7 @@ export interface GroupSection {
38
38
  /**
39
39
  * One card instance projected for rendering: the schema × payload join result
40
40
  * the VisualEditor's `$derived` produces and hands to `<Card>`. Positional
41
- * identity is carried by `id` (a session key), NOT by array index.
41
+ * identity is carried by `id` (a session key), not by array index.
42
42
  */
43
43
  export interface CardModel {
44
44
  /** Stable session id (`'main'` for the main card). */
@@ -48,7 +48,7 @@ export interface CardModel {
48
48
  /**
49
49
  * The card's `kind` has no projectable schema: a foreign kind under
50
50
  * a schema that declares others, or a card under a schema with no `card_kinds` at
51
- * all. Such a card renders a RECOVERY SHELL (humanized title + retype + delete)
51
+ * all. Such a card renders a recovery shell (humanized title + retype + delete)
52
52
  * instead of a field list, so its content is never dropped or trapped: retyping
53
53
  * to a declared kind re-projects it, delete removes it. Always `false` for `main`.
54
54
  */
@@ -62,7 +62,7 @@ export interface CardModel {
62
62
  /**
63
63
  * Field name → its resolved provenance row (`{ value, source }`), parallel to
64
64
  * `values` (FIELD_PROVENANCE). The channel that feeds chrome (the ghosted
65
- * `default:` and any authored/default/zero affordance), NEVER the control
65
+ * `default:` and any authored/default/zero affordance), never the control
66
66
  * value. Empty when `quill.resolve` is unavailable.
67
67
  */
68
68
  provenance: Record<string, ResolvedField>;
@@ -73,7 +73,7 @@ export interface CardModel {
73
73
  * empty for a card that does: the resolved body `default:` when there is one,
74
74
  * else the consumer's wording, else the built-in invitation
75
75
  * ({@link resolveBodyGhost}). A body leaf therefore always has something in it
76
- * to write into, which the inline fields deliberately do not: their ghost IS
76
+ * to write into, which the inline fields deliberately do not: their ghost is
77
77
  * the resolved default, and an invented one would read as a value.
78
78
  */
79
79
  bodyGhost?: string;
@@ -114,25 +114,32 @@ export declare function ghostDefault(row: ResolvedField | undefined): unknown;
114
114
  * thing to display as a placeholder (FIELD_PROVENANCE). */
115
115
  export declare function stringifyGhost(ghost: unknown): string | undefined;
116
116
  /** What a {@link BodyPlaceholder} is told about the body it words. The card's
117
- * IDENTITY, not its chrome: `kind` keys the consumer's own `quill.schema` for
118
- * anything richer, and a renamed card must not shift its ghost. */
117
+ * identity, not its chrome: `cardId` is what per-card wording keys off, `kind` keys
118
+ * the consumer's own `quill.schema` for anything richer, and a renamed card must not
119
+ * shift its ghost. */
119
120
  export interface BodyPlaceholderContext {
121
+ /**
122
+ * The card's session key (`CardId`), `'main'` for the main card. Follows its card
123
+ * across a reorder and a retype, and is re-minted when the surface re-keys on a new
124
+ * document handle. Opaque: wording keyed off it hashes it rather than reads it.
125
+ */
126
+ cardId: string;
120
127
  /** The card's kind; `'main'` for the main card. */
121
128
  kind: string;
122
129
  /** The main card: whose `kind` is not a `card_kinds` key. */
123
130
  isMain: boolean;
124
131
  }
125
132
  /**
126
- * Consumer wording for an empty body, per KIND, in place of the flat `bodyGhost`
127
- * string; returning `undefined` takes it. Consulted ONCE PER KIND per session and
128
- * cached by the editor, so a hook that samples a set at random still reads as one
129
- * deliberate string: two empty cards of a kind ghost the same, and a remount does
130
- * not re-roll. Impurity is expected, and the cache is what contains it.
133
+ * Consumer wording for an empty body, in place of the flat `bodyGhost` string;
134
+ * returning `undefined` takes it. Consulted per card on every derive and never
135
+ * cached, so it must be pure: a hook sampling a set at random re-rolls on every
136
+ * keystroke. Per-card wording is a function of `cardId`, per-kind wording a function
137
+ * of `kind`, and either is stable because the function is.
131
138
  */
132
139
  export type BodyPlaceholder = (ctx: BodyPlaceholderContext) => string | undefined;
133
140
  /**
134
- * The empty body's ghost: the resolved body `default:`, else per-kind consumer
135
- * wording, else the flat built-in. The `default:` WINS because it is the only one
141
+ * The empty body's ghost: the resolved body `default:`, else the consumer's
142
+ * wording, else the flat built-in. The `default:` wins because it is the only one
136
143
  * of the three that describes the render: it promises what prints if nothing is
137
144
  * written, and wording placed over it would make that promise unreadable. The
138
145
  * other two are invitations, and an invitation belongs only where there is no
@@ -140,7 +147,7 @@ export type BodyPlaceholder = (ctx: BodyPlaceholderContext) => string | undefine
140
147
  */
141
148
  export declare function resolveBodyGhost(resolvedDefault: string | undefined, custom: string | undefined, builtIn: string): string;
142
149
  /** Map a field schema to its control (precedence: prose › enum › text › …).
143
- * An array's ELEMENT control is this over `items`: a missing `items` is a text
150
+ * An array's element control is this over `items`: a missing `items` is a text
144
151
  * element. */
145
152
  export declare function controlKind(f: QuillFieldSchema): ControlKind;
146
153
  /** The closed value domain of an enum/enum-string field, or undefined. */
@@ -151,7 +158,7 @@ export declare function humanize(name: string): string;
151
158
  export declare function fieldModels(cardSchema: QuillCardSchema): FieldModel[];
152
159
  /**
153
160
  * Group-section order (VISUAL_EDITOR §"Structure mirrors the schema"): the schema's `ui.groups` registry
154
- * KEY ORDER when present: `QuillCardUi.groups` is a typed `Record` at the
161
+ * key order when present: `QuillCardUi.groups` is a typed `Record` at the
155
162
  * boundary, so this reads it uncast: else the first-appearance order of each
156
163
  * field's `ui.group`.
157
164
  */
@@ -195,7 +202,7 @@ export interface PlacedField {
195
202
  * Assign each field its span in the section grid. Consecutive packable fields are
196
203
  * `cell`s the grid auto-places: capacity and wrapping are the container query's
197
204
  * business, so a trailing orphan keeps its column width rather than growing to fill.
198
- * A packable run of ONE is `lone`: with no row above to align to, one column reads as
205
+ * A packable run of one is `lone`: with no row above to align to, one column reads as
199
206
  * truncated, so it takes half the capacity from column 1. Everything else is `full`.
200
207
  *
201
208
  * Pure, and stays pure: no width, no measurement, nothing to re-derive on resize.
@@ -36,8 +36,8 @@ export function stringifyGhost(ghost) {
36
36
  return ghost != null && typeof ghost !== 'object' ? String(ghost) : undefined;
37
37
  }
38
38
  /**
39
- * The empty body's ghost: the resolved body `default:`, else per-kind consumer
40
- * wording, else the flat built-in. The `default:` WINS because it is the only one
39
+ * The empty body's ghost: the resolved body `default:`, else the consumer's
40
+ * wording, else the flat built-in. The `default:` wins because it is the only one
41
41
  * of the three that describes the render: it promises what prints if nothing is
42
42
  * written, and wording placed over it would make that promise unreadable. The
43
43
  * other two are invitations, and an invitation belongs only where there is no
@@ -47,7 +47,7 @@ export function resolveBodyGhost(resolvedDefault, custom, builtIn) {
47
47
  return resolvedDefault || custom || builtIn;
48
48
  }
49
49
  /** Map a field schema to its control (precedence: prose › enum › text › …).
50
- * An array's ELEMENT control is this over `items`: a missing `items` is a text
50
+ * An array's element control is this over `items`: a missing `items` is a text
51
51
  * element. */
52
52
  export function controlKind(f) {
53
53
  switch (f.type) {
@@ -102,7 +102,7 @@ export function fieldModels(cardSchema) {
102
102
  }
103
103
  /**
104
104
  * Group-section order (VISUAL_EDITOR §"Structure mirrors the schema"): the schema's `ui.groups` registry
105
- * KEY ORDER when present: `QuillCardUi.groups` is a typed `Record` at the
105
+ * key order when present: `QuillCardUi.groups` is a typed `Record` at the
106
106
  * boundary, so this reads it uncast: else the first-appearance order of each
107
107
  * field's `ui.group`.
108
108
  */
@@ -174,13 +174,13 @@ export function initialExpandedGroup(sections) {
174
174
  }
175
175
  /**
176
176
  * Whether a field can share a row. `ui.compact` asks; a shape declines when the
177
- * DOCUMENT sets its height, because a row is as tall as its tallest cell and the cell
177
+ * document sets its height, because a row is as tall as its tallest cell and the cell
178
178
  * beside it does not grow in step: an object nests a whole field set, block richtext
179
179
  * (`inline` absent) holds paragraphs, and an array holds however many elements the
180
180
  * document carries. Any of them stands its neighbour in a column of whitespace. An
181
181
  * inline prose leaf is one line tall and packs like any scalar.
182
182
  *
183
- * An array declines WHATEVER ITS ITEMS ARE: one-line elements make a one-line step,
183
+ * An array declines whatever its items are: one-line elements make a one-line step,
184
184
  * but nothing holds two arrays to the same number of them, so the shorter of a packed
185
185
  * pair pays a cell of whitespace for every element the taller one has past it, and
186
186
  * pays more of it as the document is filled.
@@ -196,7 +196,7 @@ function packable(f) {
196
196
  * Assign each field its span in the section grid. Consecutive packable fields are
197
197
  * `cell`s the grid auto-places: capacity and wrapping are the container query's
198
198
  * business, so a trailing orphan keeps its column width rather than growing to fill.
199
- * A packable run of ONE is `lone`: with no row above to align to, one column reads as
199
+ * A packable run of one is `lone`: with no row above to align to, one column reads as
200
200
  * truncated, so it takes half the capacity from column 1. Everything else is `full`.
201
201
  *
202
202
  * Pure, and stays pure: no width, no measurement, nothing to re-derive on resize.
@@ -250,7 +250,7 @@ export function bodyEnabled(cardSchema) {
250
250
  return cardSchema?.body?.enabled !== false;
251
251
  }
252
252
  // ── Session identity (VISUAL_EDITOR §"The address is the spine") ─────────────
253
- // Cards are POSITIONAL in the content and `doc.cards` re-allocates on each read,
253
+ // Cards are positional in the content and `doc.cards` re-allocates on each read,
254
254
  // so a stable card-instance key cannot be the card object (a fresh object every
255
255
  // derive): it is a session id held in a parallel array, reordered in lockstep
256
256
  // with the structure ops and resolved to an index only at the mutation boundary.
@@ -4,7 +4,7 @@ export interface SyncedLocal<T> {
4
4
  value: T;
5
5
  }
6
6
  /**
7
- * Seed a local from `project` and reconcile only an EXTERNAL change into it.
7
+ * Seed a local from `project` and reconcile only an external change into it.
8
8
  * `project` reads the reactive source (a prop) and maps it to the local's type:
9
9
  * ` => value ?? ''`, ` => (value != null ? String(value) : '')`, etc. The
10
10
  * seed is `untrack`ed (the ongoing sync is the `$effect`, not the initializer),
@@ -1,12 +1,12 @@
1
1
  // The controlled-local reconcile shared by the scalar controls (TextField /
2
2
  // NumberField / DateField / BooleanField / EnumField). Each seeds a local from a
3
- // projection of its `value` prop and reconciles ONLY an external change back into
3
+ // projection of its `value` prop and reconciles only an external change back into
4
4
  // the local: own edits stay `untrack`ed, so typing never re-runs the sync and
5
- // resets the caret. The five controls carried a character-identical block; this
6
- // is the one copy (VISUAL_EDITOR §Surface).
5
+ // resets the caret. One copy for all five, rather than a character-identical block
6
+ // in each (VISUAL_EDITOR §Surface).
7
7
  import { untrack } from 'svelte';
8
8
  /**
9
- * Seed a local from `project` and reconcile only an EXTERNAL change into it.
9
+ * Seed a local from `project` and reconcile only an external change into it.
10
10
  * `project` reads the reactive source (a prop) and maps it to the local's type:
11
11
  * ` => value ?? ''`, ` => (value != null ? String(value) : '')`, etc. The
12
12
  * seed is `untrack`ed (the ongoing sync is the `$effect`, not the initializer),
@@ -12,14 +12,14 @@ export declare function tipsChannel(raw: unknown): string[];
12
12
  * (`strong`/`emph`/`code`/`link`) rather than by a second markdown renderer that
13
13
  * would drift from it.
14
14
  *
15
- * The INLINE schema, not the block one: a tip is a one-line hint, and
15
+ * The inline schema, not the block one: a tip is a one-line hint, and
16
16
  * `decodeInline` folds stray lines to a space and drops island slots, so any string
17
17
  * produces one paragraph: no tip can change the card's block structure as the
18
18
  * cursor advances.
19
19
  *
20
20
  * Raw HTML does not survive the round-trip, so this is not the injection seam an
21
21
  * `{@html}` of the same string would be. A throw degrades to the literal text:
22
- * chrome never breaks the editor. The gate is read OUTSIDE that catch — an
22
+ * chrome never breaks the editor. The gate is read outside that catch — an
23
23
  * uninitialized core is not a tip that failed to render, and would otherwise be
24
24
  * reported as one.
25
25
  */
@@ -1,5 +1,5 @@
1
1
  // The tips channel: `$ext.editor.tips`, a list of authoring hints a
2
- // quill or consumer seeds, which the editor only ever RENDERS and CLEARS.
2
+ // quill or consumer seeds, which the editor only ever renders and clears.
3
3
  // Editor-only chrome; never reaches the render backend, never gates, absent when
4
4
  // the channel is empty (VISUAL_EDITOR §"Card operations").
5
5
  //
@@ -25,14 +25,14 @@ export function tipsChannel(raw) {
25
25
  * (`strong`/`emph`/`code`/`link`) rather than by a second markdown renderer that
26
26
  * would drift from it.
27
27
  *
28
- * The INLINE schema, not the block one: a tip is a one-line hint, and
28
+ * The inline schema, not the block one: a tip is a one-line hint, and
29
29
  * `decodeInline` folds stray lines to a space and drops island slots, so any string
30
30
  * produces one paragraph: no tip can change the card's block structure as the
31
31
  * cursor advances.
32
32
  *
33
33
  * Raw HTML does not survive the round-trip, so this is not the injection seam an
34
34
  * `{@html}` of the same string would be. A throw degrades to the literal text:
35
- * chrome never breaks the editor. The gate is read OUTSIDE that catch — an
35
+ * chrome never breaks the editor. The gate is read outside that catch — an
36
36
  * uninitialized core is not a tip that failed to render, and would otherwise be
37
37
  * reported as one.
38
38
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quillmark/svelte",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Editor, live-preview and source surfaces over a Quillmark WASM session.",
5
5
  "repository": {
6
6
  "type": "git",