@quillmark/svelte 0.26.2 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/NOTICE +4 -4
  2. package/README.md +26 -8
  3. package/THEMING.md +40 -4
  4. package/dist/core/address.d.ts +35 -64
  5. package/dist/core/address.js +35 -55
  6. package/dist/core/bloom.d.ts +4 -10
  7. package/dist/core/bloom.js +14 -27
  8. package/dist/core/codec/blocks.d.ts +41 -43
  9. package/dist/core/codec/blocks.js +97 -130
  10. package/dist/core/codec/code.d.ts +7 -10
  11. package/dist/core/codec/code.js +37 -46
  12. package/dist/core/codec/decode.d.ts +19 -23
  13. package/dist/core/codec/decode.js +76 -111
  14. package/dist/core/codec/encode.d.ts +11 -15
  15. package/dist/core/codec/encode.js +60 -67
  16. package/dist/core/codec/field.d.ts +62 -95
  17. package/dist/core/codec/field.js +107 -179
  18. package/dist/core/codec/islands.d.ts +33 -41
  19. package/dist/core/codec/islands.js +76 -86
  20. package/dist/core/codec/lists.d.ts +17 -26
  21. package/dist/core/codec/lists.js +117 -157
  22. package/dist/core/codec/marks.d.ts +4 -3
  23. package/dist/core/codec/marks.js +8 -3
  24. package/dist/core/codec/prose.css +84 -46
  25. package/dist/core/codec/schema.d.ts +18 -23
  26. package/dist/core/codec/schema.js +84 -76
  27. package/dist/core/codec/slash.d.ts +42 -48
  28. package/dist/core/codec/slash.js +0 -0
  29. package/dist/core/codec/table-copy.d.ts +4 -3
  30. package/dist/core/codec/table-copy.js +25 -7
  31. package/dist/core/codec/table-view.d.ts +12 -12
  32. package/dist/core/codec/table-view.js +460 -383
  33. package/dist/core/codec/table.d.ts +94 -61
  34. package/dist/core/codec/table.js +331 -83
  35. package/dist/core/codec/tasks.d.ts +6 -0
  36. package/dist/core/codec/tasks.js +30 -3
  37. package/dist/core/errors.d.ts +15 -30
  38. package/dist/core/errors.js +2 -6
  39. package/dist/core/index.js +7 -12
  40. package/dist/core/lifecycle.d.ts +7 -16
  41. package/dist/core/lifecycle.js +10 -21
  42. package/dist/core/rebind.svelte.d.ts +10 -20
  43. package/dist/core/rebind.svelte.js +15 -27
  44. package/dist/core/rungs.d.ts +14 -11
  45. package/dist/core/rungs.js +17 -19
  46. package/dist/core/teardown.d.ts +4 -6
  47. package/dist/core/teardown.js +7 -10
  48. package/dist/core/theme.css +74 -54
  49. package/dist/index.js +3 -8
  50. package/dist/preset/app.css +71 -0
  51. package/dist/preset/index.css +8 -7
  52. package/dist/preset/recipes.css +19 -164
  53. package/dist/preset/scale.css +28 -18
  54. package/dist/preset/shell.css +157 -0
  55. package/dist/preview/Preview.svelte +8 -0
  56. package/dist/preview/bridge.d.ts +18 -22
  57. package/dist/preview/bridge.js +29 -58
  58. package/dist/preview/controller.d.ts +21 -29
  59. package/dist/preview/controller.js +14 -39
  60. package/dist/preview/geometry.d.ts +13 -34
  61. package/dist/preview/geometry.js +13 -34
  62. package/dist/preview/index.js +4 -16
  63. package/dist/preview/paint.d.ts +3 -3
  64. package/dist/preview/paint.js +28 -68
  65. package/dist/preview/strings.d.ts +1 -1
  66. package/dist/preview/strings.js +2 -14
  67. package/dist/preview/viewport.js +20 -15
  68. package/dist/preview/zoom.d.ts +21 -22
  69. package/dist/preview/zoom.js +53 -30
  70. package/dist/visual/ArrayField.svelte +77 -16
  71. package/dist/visual/BooleanField.svelte +28 -15
  72. package/dist/visual/Card.svelte +66 -51
  73. package/dist/visual/CardControls.svelte +5 -11
  74. package/dist/visual/DateField.svelte +20 -4
  75. package/dist/visual/EnumField.svelte +3 -0
  76. package/dist/visual/FieldHint.svelte +2 -1
  77. package/dist/visual/FormatPopover.svelte +82 -15
  78. package/dist/visual/FormatPopover.svelte.d.ts +4 -0
  79. package/dist/visual/MatrixAdd.svelte +30 -12
  80. package/dist/visual/MatrixField.svelte +24 -16
  81. package/dist/visual/NumberField.svelte +7 -0
  82. package/dist/visual/ObjectField.svelte +4 -4
  83. package/dist/visual/ProseField.svelte +0 -5
  84. package/dist/visual/TipsCard.svelte +11 -10
  85. package/dist/visual/VariantField.svelte +3 -1
  86. package/dist/visual/VisualEditorInner.svelte +19 -3
  87. package/dist/visual/controls.css +7 -2
  88. package/dist/visual/fonts.d.ts +18 -0
  89. package/dist/visual/fonts.js +59 -0
  90. package/dist/visual/icons/nodes.d.ts +0 -5
  91. package/dist/visual/icons/nodes.js +0 -4
  92. package/dist/visual/props.d.ts +14 -1
  93. package/dist/visual/strings.d.ts +7 -0
  94. package/dist/visual/strings.js +5 -2
  95. package/dist/visual/structure.d.ts +43 -87
  96. package/dist/visual/structure.js +42 -83
  97. package/package.json +2 -2
@@ -0,0 +1,18 @@
1
+ import type { FontFace as LibraryFace } from '@quillmark/wasm';
2
+ import type { Command, EditorState } from 'prosemirror-state';
3
+ /** The families `faces` offer, each once, in the library's order. */
4
+ export declare function familiesOf(faces: readonly LibraryFace[]): string[];
5
+ /**
6
+ * Register `faces` with `set` and return what takes them back out. A face past the
7
+ * first in a collection is left out, a CSS face drawing a collection's first alone, so
8
+ * its family draws in the root face here while the preview sets it. A face the browser
9
+ * refuses draws the same way, and a page with no Font Loading API registers nothing.
10
+ */
11
+ export declare function registerFaces(faces: readonly LibraryFace[], set?: FontFaceSet | undefined): () => void;
12
+ /**
13
+ * The family the selection's text is set in: its name, `''` where it sets none, `null`
14
+ * where it sets more than one or holds no text.
15
+ */
16
+ export declare function familyInSelection(state: EditorState): string | null;
17
+ /** Set the selection in `name`, or in the surrounding face where `name` is `''`. */
18
+ export declare function setFamily(name: string): Command;
@@ -0,0 +1,59 @@
1
+ /** The families `faces` offer, each once, in the library's order. */
2
+ export function familiesOf(faces) {
3
+ return [...new Set(faces.map((face) => face.family))];
4
+ }
5
+ /**
6
+ * Register `faces` with `set` and return what takes them back out. A face past the
7
+ * first in a collection is left out, a CSS face drawing a collection's first alone, so
8
+ * its family draws in the root face here while the preview sets it. A face the browser
9
+ * refuses draws the same way, and a page with no Font Loading API registers nothing.
10
+ */
11
+ export function registerFaces(faces, set = globalThis.document?.fonts) {
12
+ if (!set || typeof FontFace === 'undefined')
13
+ return () => { };
14
+ const added = [];
15
+ for (const face of faces) {
16
+ if (face.index !== 0)
17
+ continue;
18
+ const css = new FontFace(face.family, face.data, {
19
+ weight: String(face.weight),
20
+ style: face.style
21
+ });
22
+ css.loaded.catch(() => set.delete(css));
23
+ set.add(css);
24
+ added.push(css);
25
+ }
26
+ return () => {
27
+ for (const css of added)
28
+ set.delete(css);
29
+ };
30
+ }
31
+ /**
32
+ * The family the selection's text is set in: its name, `''` where it sets none, `null`
33
+ * where it sets more than one or holds no text.
34
+ */
35
+ export function familyInSelection(state) {
36
+ const type = state.schema.marks.font_family;
37
+ const { from, to } = state.selection;
38
+ const seen = new Set();
39
+ state.doc.nodesBetween(from, to, (node) => {
40
+ if (!node.isText)
41
+ return;
42
+ seen.add(type ? String(type.isInSet(node.marks)?.attrs.name ?? '') : '');
43
+ });
44
+ return seen.size === 1 ? [...seen][0] : null;
45
+ }
46
+ /** Set the selection in `name`, or in the surrounding face where `name` is `''`. */
47
+ export function setFamily(name) {
48
+ return (state, dispatch) => {
49
+ const type = state.schema.marks.font_family;
50
+ const { from, to, empty } = state.selection;
51
+ if (!type || empty)
52
+ return false;
53
+ if (dispatch) {
54
+ const tr = state.tr.removeMark(from, to, type);
55
+ dispatch(name ? tr.addMark(from, to, type.create({ name })) : tr);
56
+ }
57
+ return true;
58
+ };
59
+ }
@@ -127,11 +127,6 @@ export declare const ICONS: {
127
127
  }], readonly ["path", {
128
128
  readonly d: "M12 5v14";
129
129
  }]];
130
- readonly x: readonly [readonly ["path", {
131
- readonly d: "M18 6 6 18";
132
- }], readonly ["path", {
133
- readonly d: "m6 6 12 12";
134
- }]];
135
130
  readonly 'trash-2': readonly [readonly ["path", {
136
131
  readonly d: "M10 11v6";
137
132
  }], readonly ["path", {
@@ -70,10 +70,6 @@ export const ICONS = {
70
70
  ['path', { d: 'M5 12h14' }],
71
71
  ['path', { d: 'M12 5v14' }]
72
72
  ],
73
- x: [
74
- ['path', { d: 'M18 6 6 18' }],
75
- ['path', { d: 'm6 6 12 12' }]
76
- ],
77
73
  'trash-2': [
78
74
  ['path', { d: 'M10 11v6' }],
79
75
  ['path', { d: 'M14 11v6' }],
@@ -1,4 +1,4 @@
1
- import type { Document, Quill, Addr, Diagnostic } from '@quillmark/wasm';
1
+ import type { Document, Quill, Addr, Diagnostic, FontFace } from '@quillmark/wasm';
2
2
  import type { Place } from '../core/address.js';
3
3
  import type { EditorErrorHandler } from '../core/errors.js';
4
4
  import type { ActiveLeaf, EditorChange } from './signals.js';
@@ -81,6 +81,19 @@ export interface VisualEditorProps {
81
81
  * (VISUAL_EDITOR §"Enum policy").
82
82
  */
83
83
  enumDisallowed?: 'hide' | 'disable';
84
+ /**
85
+ * The faces a `font_family` mark may set: `await engine.fontFaces(quill)`, over an
86
+ * engine built with the host's `fonts`. The format popover offers each family, and
87
+ * the editor registers each face with the page for as long as it is mounted, so a
88
+ * run draws in the face the preview sets it in. Absent or empty, no family is
89
+ * offered, and a family the document already sets still edits and can be cleared.
90
+ */
91
+ fonts?: FontFace[];
92
+ /**
93
+ * The name the picker shows for a family, keyed by the family the mark saves. A
94
+ * family missing here shows as itself.
95
+ */
96
+ fontLabels?: Readonly<Record<string, string>>;
84
97
  /**
85
98
  * Every word the surface says, keyed and partial: unset keys take the package's
86
99
  * English. Several are accessible names rather than decoration, so this is what
@@ -81,6 +81,13 @@ export interface VisualStrings extends TableChromeStrings, SlashStrings {
81
81
  formatLink: string;
82
82
  formatNumberedList: string;
83
83
  formatBulletedList: string;
84
+ /** The font picker's accessible name; drawn only where the host hands the editor a
85
+ * font library or the selection sets a family. */
86
+ formatFont: string;
87
+ /** The picker's option that sets no family: the text takes the surrounding face. */
88
+ fontDefault: string;
89
+ /** What the picker reads over a selection setting more than one family. */
90
+ fontMixed: string;
84
91
  /** The anchor button's accessible name. The popover withholds the button, so
85
92
  * nothing draws this or the title below. */
86
93
  formatAnchor: string;
@@ -60,11 +60,14 @@ export const DEFAULT_VISUAL_STRINGS = {
60
60
  formatBold: `Bold (${chord('B')})`,
61
61
  formatEmphasis: `Italic (${chord('I')})`,
62
62
  formatUnderline: `Underline (${chord('U')})`,
63
- formatStrikethrough: 'Strikethrough',
64
- formatCode: 'Code',
63
+ formatStrikethrough: `Strikethrough (${chord('Shift-X')})`,
64
+ formatCode: `Code (${chord('E')})`,
65
65
  formatLink: `Link (${chord('K')})`,
66
66
  formatNumberedList: `Numbered list (${chord('Shift-7')})`,
67
67
  formatBulletedList: `Bulleted list (${chord('Shift-8')})`,
68
+ formatFont: 'Font',
69
+ fontDefault: 'Default font',
70
+ fontMixed: 'Mixed fonts',
68
71
  formatAnchor: 'Anchor',
69
72
  formatAnchorTitle: 'Anchor — an identity handle over the selection',
70
73
  linkPlaceholder: 'https://…',
@@ -10,19 +10,15 @@ export interface FieldModel {
10
10
  name: string;
11
11
  schema: QuillFieldSchema;
12
12
  control: ControlKind;
13
- /** `ui.group` (undefined = ungrouped). */
14
13
  group: string | undefined;
15
14
  /** Asks to share a row with adjacent compacts: `ui.compact` when declared, else
16
15
  * {@link packsByDefault}. A request, not a guarantee: `placeFields` declines it for
17
16
  * the shapes that grow (see `packable`). */
18
17
  compact: boolean;
19
- /** Display label: `title` when set, else the humanized field name. */
20
18
  label: string;
21
- /** Schema `description`: authoring help rendered beside the label,
22
- * undefined when the field declares none. Chrome-only; never gates. */
19
+ /** Chrome-only; never gates. */
23
20
  description: string | undefined;
24
- /** Prose-leaf flags (only meaningful when `control === 'prose'` / array items):
25
- * one line (`oneLine`), and the literal codec (`literalText`). */
21
+ /** Prose-leaf flags: {@link oneLine} and {@link literalText}. */
26
22
  inline: boolean;
27
23
  plaintext: boolean;
28
24
  }
@@ -37,13 +33,9 @@ export interface GroupSection {
37
33
  * `object`. Its properties draw flat, the panel being their frame. */
38
34
  head?: FieldModel;
39
35
  }
40
- /**
41
- * One card instance projected for rendering: the schema × payload join result
42
- * the VisualEditor's `$derived` produces and hands to `<Card>`. Positional
43
- * identity is carried by `id` (a session key), not by array index.
44
- */
36
+ /** One card instance projected for rendering. Identity is `id` (a session key), not array index. */
45
37
  export interface CardModel {
46
- /** Stable session id (`'main'` for the main card). */
38
+ /** `'main'` for the main card. */
47
39
  id: string;
48
40
  isMain: boolean;
49
41
  kind: string;
@@ -60,7 +52,6 @@ export interface CardModel {
60
52
  /** The header an unrenamed card shows ({@link cardTitle} below its rename rung),
61
53
  * which the rename input ghosts (composable cards). */
62
54
  titlePlaceholder: string;
63
- /** Field name → current stored value (absent fields missing). */
64
55
  values: Record<string, unknown>;
65
56
  /**
66
57
  * Field name → its resolved provenance row (`{ value, source }`), parallel to
@@ -80,43 +71,33 @@ export interface CardModel {
80
71
  */
81
72
  bodyGhost?: string;
82
73
  }
83
- /**
84
- * A card's resolved rows keyed by field name: the provenance channel parallel to
85
- * {@link CardModel.values}. `resolve` returns rows in declaration order; the
86
- * editor keys them the same way `values` keys its payload walk, so a field's value
87
- * and its provenance resolve under one name.
88
- */
74
+ /** A card's resolved rows keyed by field name, parallel to {@link CardModel.values}. */
89
75
  export declare function provenanceMap(fields: ResolvedField[]): Record<string, ResolvedField>;
90
- /** A card's resolved rows: its declared fields, and the `body` sibling `resolve`
91
- * hangs off each card. */
76
+ /** A card's resolved fields and its `body` sibling. */
92
77
  export interface ResolvedCardRows {
93
78
  fields: ResolvedField[];
94
79
  body: ResolvedField | null;
95
80
  }
96
- /** The empty rows a card with no resolve entry reads: a shared constant so the
97
- * per-card miss allocates nothing. */
81
+ /** Shared so a per-card miss allocates nothing. */
98
82
  export declare const NO_RESOLVED_ROWS: ResolvedCardRows;
99
83
  /**
100
- * Composable cards' resolved rows keyed by document index (`ResolvedCard.index`,
101
- * not array position, so it holds whatever order the resolve view returns): built
102
- * once per derive, so the per-card provenance join is O(1). Both channels ride one
103
- * entry: a card reads its fields and its body from a single lookup. Empty map when
104
- * `resolved` is absent (a `resolve` failure degrades to no ghosts, never a blank
105
- * form).
84
+ * Resolved rows keyed by `ResolvedCard.index`, not array position. Empty when `resolved` is absent:
85
+ * a `resolve` failure degrades to no ghosts, never a blank form.
106
86
  */
107
87
  export declare function resolvedByCardIndex(resolved: Resolved | undefined): Map<number, ResolvedCardRows>;
108
88
  /** What an unset field shows of its `default:`: the resolved value the render would
109
89
  * use (`source === 'default'`), else undefined: an `authored` field shows its value,
110
90
  * a `blank` field has no default to show. */
111
91
  export declare function ghostDefault(row: ResolvedField | undefined): unknown;
112
- /** A stored `boolean` cell as the render reads it: a boolean, `true` or `false` in any
113
- * case, or a number by whether it is non-zero; undefined where the render refuses the
114
- * value. Quillmark's coercion, restated, so the suite holds it to `reader.resolve()`. */
92
+ /**
93
+ * A stored `boolean` cell as the render reads it (Quillmark's coercion, held to `reader.resolve()`
94
+ * by the suite); undefined where the render refuses it.
95
+ */
115
96
  export declare function renderedBoolean(value: unknown): boolean | undefined;
116
- /** A ghost value's string form, or undefined for null/object (only text ghosts
117
- * render a placeholder). A scalar's resolved default reads through it; a content
118
- * field's resolves as `Content`, which a prose leaf reads by its text instead
119
- * ({@link titleText}). */
97
+ /**
98
+ * A ghost value's string form, or undefined for null/object. A content field's default resolves as
99
+ * `Content` and is read by its text ({@link titleText}).
100
+ */
120
101
  export declare function stringifyGhost(ghost: unknown): string | undefined;
121
102
  /** What a {@link BodyPlaceholder} is told about the body it words. The card's
122
103
  * identity, not its chrome: `cardId` is what per-card wording keys off, `kind` keys
@@ -153,13 +134,15 @@ export declare function resolveBodyGhost(resolvedDefault: string | undefined, cu
153
134
  /** Whether a cell is optional: a `t?` type, which renders `none` unanswered and so
154
135
  * never declares a `default:` (canon `SCHEMAS.md` §"Optional cells"). */
155
136
  export declare function optionalCell(f: QuillFieldSchema): boolean;
156
- /** The type a cell's control reads: the declared one, an optional cell's `?` stripped.
157
- * The `?` moves the render floor and nothing else, so every read of a type is this. */
137
+ /**
138
+ * The declared type with an optional cell's `?` stripped; the `?` moves the render floor and
139
+ * nothing else.
140
+ */
158
141
  export declare function baseType(f: QuillFieldSchema): QuillFieldType;
159
142
  /** Whether a content field is one line: one paragraph, no container, no island. A `text`
160
143
  * or `richtext` field is one line unless it declares `multiline: true`. */
161
144
  export declare function oneLine(f: QuillFieldSchema): boolean;
162
- /** Whether a content field's codec is the literal one, its value text with no marks: `text`. */
145
+ /** Whether a content field's codec is the literal one: `text`. */
163
146
  export declare function literalText(f: QuillFieldSchema): boolean;
164
147
  /** The character cap a content field's `max:` declares, `undefined` on any other. */
165
148
  export declare function textCap(f: QuillFieldSchema | undefined): TextCap | undefined;
@@ -182,8 +165,7 @@ export declare function declaredContent(v: unknown, markdown: boolean): Content
182
165
  * any of them under a name remounts the field, where a kept leaf would commit on the old
183
166
  * schema. */
184
167
  export declare function mountKey(name: string, f: QuillFieldSchema): string;
185
- /** Map a field schema to its control. An array's element control is this over `items`;
186
- * a type this build does not know takes the text input. */
168
+ /** An array's element control is this over `items`; an unknown type takes the text input. */
187
169
  export declare function controlKind(f: QuillFieldSchema): ControlKind;
188
170
  /** The discriminant cell of a variant container, off the boundary's own constant: it
189
171
  * crosses inside untyped container data with no type to read it off, so a literal here
@@ -233,7 +215,6 @@ export declare function memberWrite(columns: Record<string, unknown>, title?: st
233
215
  /** Whether `id` is spelled as a matrix id: snake_case, the rule the roster's ids and
234
216
  * an added item's key share. */
235
217
  export declare function matrixId(id: string): boolean;
236
- /** Whether `id` is on the roster. */
237
218
  export declare function onRoster(matrix: QuillFieldSchema, id: string): boolean;
238
219
  /**
239
220
  * Whether a step under the matrix names a member, judged on the schema alone as an
@@ -268,11 +249,11 @@ export declare function matrixMemberSchema(matrix: QuillFieldSchema, id: string)
268
249
  * before it asks the mounted tree for it (VISUAL_EDITOR §Surface).
269
250
  */
270
251
  export declare function schemaAt(field: QuillFieldSchema, steps: readonly PathStep[]): QuillFieldSchema | undefined;
271
- /** Whether a cell is one line tall by declaration: the shape a table column and a row
272
- * summary can hold. A prose cell is one where it is {@link oneLine}. */
252
+ /**
253
+ * Whether a cell is one line tall by declaration: what a table column and a row summary can hold.
254
+ */
273
255
  export declare function shortCell(sub: QuillFieldSchema): boolean;
274
- /** A collapsed row's own words ({@link firstShortText}); `undefined` while the row has
275
- * nothing to say for itself. */
256
+ /** A collapsed row's own words ({@link firstShortText}). */
276
257
  export declare function rowSummary(items: QuillFieldSchema | undefined, row: unknown): string | undefined;
277
258
  /** How an `array` draws its elements. */
278
259
  export type ArrayLayout = 'list' | 'table';
@@ -302,30 +283,21 @@ export declare function variantCells(schema: QuillFieldSchema, member: string |
302
283
  * `undefined`.
303
284
  */
304
285
  export declare function commitDiscriminant(value: Record<string, unknown> | undefined, member: string | undefined): Record<string, unknown> | undefined;
305
- /** `foo_bar` → `Foo bar`: the label fallback when a field declares no `title`. */
286
+ /** `foo_bar` → `Foo bar`. */
306
287
  export declare function humanize(name: string): string;
307
288
  /** Project a card schema's `fields` map (declaration = key order) into models. A
308
289
  * card-level object's `properties` project the same way. */
309
290
  export declare function fieldModels(cardSchema: Pick<QuillCardSchema, 'fields'>): FieldModel[];
310
291
  /**
311
- * Group-section order (VISUAL_EDITOR §"Structure mirrors the schema"): the schema's `ui.groups` registry
312
- * key order when present: `QuillCardUi.groups` is a typed `Record` at the
313
- * boundary, so this reads it uncast: else the first-appearance order of each
314
- * field's `ui.group`.
292
+ * Group-section order (VISUAL_EDITOR §"Structure mirrors the schema"): the `ui.groups` key order,
293
+ * else first appearance of each field's `ui.group`.
315
294
  */
316
295
  export declare function groupOrder(cardSchema: QuillCardSchema): string[];
317
- /**
318
- * A group's display label: the `ui.groups[g].title` override when the registry
319
- * declares one, else the humanized id (`memo_for` → "Memo for"): the same
320
- * id-derives-the-label rule a field's key follows.
321
- */
296
+ /** A group's `ui.groups[g].title`, else the humanized id. */
322
297
  export declare function groupLabel(cardSchema: QuillCardSchema, group: string): string;
323
298
  /**
324
- * Sort field models into ordered group sections. Declared groups first (in
325
- * `order`), each carrying its fields in declaration order; then any remaining
326
- * groups (including the ungrouped bucket) in first-appearance order. `labelFor`
327
- * resolves a group id to its display label: always {@link groupLabel} bound to
328
- * the card schema, which falls back to {@link humanize} itself.
299
+ * Declared groups first (in `order`), then any remaining groups, including the ungrouped bucket, in
300
+ * first-appearance order.
329
301
  */
330
302
  export declare function groupSections(fields: FieldModel[], order: string[], labelFor: (group: string) => string): GroupSection[];
331
303
  /**
@@ -342,18 +314,9 @@ export declare function objectSections(fields: FieldModel[]): GroupSection[];
342
314
  */
343
315
  export declare function cardSections(cardSchema: QuillCardSchema): GroupSection[];
344
316
  /**
345
- * The group section a card's accordion opens on first mount: the first in
346
- * order, or `null` when the card declares none. Ungrouped fields render outside
347
- * the accordion, so only `group != null` sections count.
348
- *
349
- * A card opens on fields. All-collapsed paints as a stack of chevrons that name
350
- * their sections and disclose nothing of what is behind them, and a body leaf is
351
- * no substitute: on a card carrying both, the fields are what the card is for.
352
- * The first section is the one `ui.groups` already ranks highest, and it is the
353
- * same section on every mount: a rule keyed on document state would move the
354
- * opening under a user as they fill.
355
- *
356
- * State is ephemeral session state the Card owns; this only seeds it.
317
+ * The group section a card's accordion opens on first mount, or `null` when the card declares none.
318
+ * All-collapsed would disclose nothing of what is behind the chevrons, and a rule keyed on document
319
+ * state would move the opening under a user as they fill.
357
320
  */
358
321
  export declare function initialExpandedGroup(sections: GroupSection[]): string | null;
359
322
  /** How wide a field sits in its section grid. */
@@ -363,15 +326,9 @@ export interface PlacedField {
363
326
  span: FieldSpan;
364
327
  }
365
328
  /**
366
- * Assign each field its span in the section grid. Consecutive packable fields are
367
- * `cell`s the grid auto-places: capacity and wrapping are the container query's
368
- * business, so a trailing orphan keeps its column width rather than growing to fill.
369
- * A run of one is stranded — nothing packed beside it, and no row above to align to —
370
- * so it is `full` like the shapes that declined: a lone narrow track reads as truncated
371
- * against the width it leaves empty, and sharing was the whole of what asked for it.
372
- * Everything else is `full`.
373
- *
374
- * Pure, and stays pure: no width, no measurement, nothing to re-derive on resize.
329
+ * Consecutive packable fields are `cell`s the grid auto-places; a trailing orphan keeps its column
330
+ * width. A run of one is `full`: a lone narrow track reads as truncated against the width it leaves
331
+ * empty. Everything else is `full`. No width is measured.
375
332
  */
376
333
  export declare function placeFields(fields: FieldModel[]): PlacedField[];
377
334
  /** A card's field values by key, off its payload items. */
@@ -391,12 +348,11 @@ export declare function kindTitle(cardSchema: QuillCardSchema | undefined, kind:
391
348
  * renames fall through, so a cleared rename reverts to what the schema says.
392
349
  */
393
350
  export declare function cardTitle(cardSchema: QuillCardSchema | undefined, kind: string, values: Record<string, unknown>, extTitle: string | undefined): string;
394
- /** Whether a card kind renders a body leaf: gated by `body.enabled !== false`. */
395
351
  export declare function bodyEnabled(cardSchema: QuillCardSchema | undefined): boolean;
396
- /** A monotonic per-session id source. Ids are opaque strings, stable for the
397
- * session; a fresh array for N existing instances is `seq.take(N)`, and an id
398
- * resolves to its current index by `ids.indexOf(id)` (-1 once the instance is
399
- * gone): read at the mutation boundary, never cached. */
352
+ /**
353
+ * A monotonic per-session id source of opaque strings. An id resolves to its index by
354
+ * `ids.indexOf(id)` at the mutation boundary, never cached.
355
+ */
400
356
  export declare class IdSeq {
401
357
  #private;
402
358
  next(): string;