@quillmark/svelte 0.21.0 → 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.
Files changed (67) hide show
  1. package/NOTICE +6 -7
  2. package/README.md +1 -1
  3. package/dist/core/address.d.ts +6 -1
  4. package/dist/core/address.js +12 -3
  5. package/dist/core/bloom.d.ts +9 -4
  6. package/dist/core/bloom.js +18 -49
  7. package/dist/core/codec/atoms.d.ts +1 -1
  8. package/dist/core/codec/atoms.js +1 -1
  9. package/dist/core/codec/blocks.js +4 -2
  10. package/dist/core/codec/code.d.ts +1 -1
  11. package/dist/core/codec/code.js +1 -1
  12. package/dist/core/codec/decode.d.ts +5 -5
  13. package/dist/core/codec/decode.js +18 -12
  14. package/dist/core/codec/encode.js +6 -1
  15. package/dist/core/codec/field.d.ts +15 -10
  16. package/dist/core/codec/field.js +46 -17
  17. package/dist/core/codec/index.d.ts +1 -1
  18. package/dist/core/codec/index.js +2 -2
  19. package/dist/core/codec/inputrules.js +1 -1
  20. package/dist/core/codec/lists.d.ts +3 -2
  21. package/dist/core/codec/lists.js +21 -5
  22. package/dist/core/codec/nesting.d.ts +20 -0
  23. package/dist/core/codec/nesting.js +62 -0
  24. package/dist/core/codec/prose.css +74 -20
  25. package/dist/core/codec/schema.d.ts +2 -2
  26. package/dist/core/codec/schema.js +16 -7
  27. package/dist/core/codec/table-copy.d.ts +17 -0
  28. package/dist/core/codec/table-copy.js +84 -0
  29. package/dist/core/codec/table-view.d.ts +1 -7
  30. package/dist/core/codec/table-view.js +70 -119
  31. package/dist/core/codec/table.d.ts +2 -9
  32. package/dist/core/codec/table.js +10 -19
  33. package/dist/core/codec/tasks.d.ts +19 -0
  34. package/dist/core/codec/tasks.js +140 -0
  35. package/dist/core/errors.d.ts +2 -2
  36. package/dist/visual/ArrayField.svelte +101 -63
  37. package/dist/visual/ArrayField.svelte.d.ts +0 -2
  38. package/dist/visual/Card.svelte +9 -3
  39. package/dist/visual/Card.svelte.d.ts +2 -2
  40. package/dist/visual/Field.svelte +20 -16
  41. package/dist/visual/Field.svelte.d.ts +4 -2
  42. package/dist/visual/FieldLabel.svelte +5 -33
  43. package/dist/visual/FieldLabel.svelte.d.ts +0 -2
  44. package/dist/visual/FormatPopover.svelte +54 -73
  45. package/dist/visual/MatrixField.svelte +18 -12
  46. package/dist/visual/NumberField.svelte +32 -3
  47. package/dist/visual/ObjectField.svelte +38 -20
  48. package/dist/visual/ObjectField.svelte.d.ts +6 -0
  49. package/dist/visual/ProseField.svelte +10 -13
  50. package/dist/visual/ProseField.svelte.d.ts +5 -2
  51. package/dist/visual/ProseValue.svelte +25 -19
  52. package/dist/visual/ProseValue.svelte.d.ts +4 -4
  53. package/dist/visual/TextField.svelte +3 -2
  54. package/dist/visual/TipsCard.svelte +5 -2
  55. package/dist/visual/VariantField.svelte +1 -1
  56. package/dist/visual/VariantField.svelte.d.ts +1 -1
  57. package/dist/visual/VisualEditorInner.svelte +13 -13
  58. package/dist/visual/controls.css +19 -1
  59. package/dist/visual/icons/nodes.d.ts +0 -21
  60. package/dist/visual/icons/nodes.js +1 -7
  61. package/dist/visual/leaves.d.ts +12 -9
  62. package/dist/visual/leaves.js +19 -0
  63. package/dist/visual/strings.d.ts +10 -5
  64. package/dist/visual/strings.js +16 -9
  65. package/dist/visual/structure.d.ts +21 -31
  66. package/dist/visual/structure.js +54 -51
  67. package/package.json +3 -3
@@ -11,22 +11,17 @@ export interface FieldModel {
11
11
  control: ControlKind;
12
12
  /** `ui.group` (undefined = ungrouped). */
13
13
  group: string | undefined;
14
- /** `ui.compact`: asks to share a row with adjacent compacts. A request, not a
15
- * guarantee: `placeFields` declines it for the shapes that grow (see `packable`). */
14
+ /** Asks to share a row with adjacent compacts: `ui.compact` when declared, else
15
+ * {@link packsByDefault}. A request, not a guarantee: `placeFields` declines it for
16
+ * the shapes that grow (see `packable`). */
16
17
  compact: boolean;
17
18
  /** Display label: `title` when set, else the humanized field name. */
18
19
  label: string;
19
20
  /** Schema `description`: authoring help rendered beside the label,
20
21
  * undefined when the field declares none. Chrome-only; never gates. */
21
22
  description: string | undefined;
22
- /**
23
- * Required-ness: {@link obliged}. Drives a persistent label `*`; a field never
24
- * carries both it and a ghosted `default:`, that default being the whole of what
25
- * retires the obligation. Persistent (schema-derived, survives filling). Label
26
- * chrome only; never gates.
27
- */
28
- required: boolean;
29
- /** Prose-leaf flags (only meaningful when `control === 'prose'` / array items). */
23
+ /** Prose-leaf flags (only meaningful when `control === 'prose'` / array items):
24
+ * one line (`oneLine`), and the literal codec (`literalText`). */
30
25
  inline: boolean;
31
26
  plaintext: boolean;
32
27
  }
@@ -161,6 +156,11 @@ export declare function optionalCell(f: QuillFieldSchema): boolean;
161
156
  /** The type a cell's control reads: the declared one, an optional cell's `?` stripped.
162
157
  * The `?` moves the render floor and nothing else, so every read of a type is this. */
163
158
  export declare function baseType(f: QuillFieldSchema): QuillFieldType;
159
+ /** Whether a content field is one line: one paragraph, no container, no island. A `text`
160
+ * or `richtext` field is one line unless it declares `multiline: true`. */
161
+ 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`. */
163
+ export declare function literalText(f: QuillFieldSchema): boolean;
164
164
  /**
165
165
  * A scalar `default:` as the text an unset control holds, where it prints: as
166
166
  * declared, `undefined` for none, a blank or a non-scalar. A default of spaces prints
@@ -169,19 +169,18 @@ export declare function baseType(f: QuillFieldSchema): QuillFieldType;
169
169
  export declare function printedText(v: unknown): string | undefined;
170
170
  /**
171
171
  * A declared content literal as the `Content` it holds: a `richtext` one's markdown
172
- * imported, a `plaintext` one's text taken literally, one paragraph whose later lines
172
+ * imported, a `text` one's text taken literally, one paragraph whose later lines
173
173
  * continue it, as the literal codec reads a stored one. What a cell's static
174
174
  * `default:` stands in its leaf as, where no resolved row reaches it. `undefined` for
175
175
  * a blank or a non-scalar.
176
176
  */
177
177
  export declare function declaredContent(v: unknown, markdown: boolean): Content | undefined;
178
178
  /** A field's `{#each}` key: its name and what a mounted leaf reads once, its type and
179
- * `inline` and its elements'. A retype or a quill swap that changes any of them under a
180
- * name remounts the field, where a kept leaf would commit on the old schema. */
179
+ * {@link oneLine} and its elements'. A retype or a quill swap that changes any of them
180
+ * under a name remounts the field, where a kept leaf would commit on the old schema. */
181
181
  export declare function mountKey(name: string, f: QuillFieldSchema): string;
182
- /** Map a field schema to its control (precedence: prose › enum › text › …).
183
- * An array's element control is this over `items`: a missing `items` is a text
184
- * element. */
182
+ /** Map a field schema to its control. An array's element control is this over `items`;
183
+ * a type this build does not know takes the text input. */
185
184
  export declare function controlKind(f: QuillFieldSchema): ControlKind;
186
185
  /** The discriminant cell of a variant container, off the boundary's own constant: it
187
186
  * crosses inside untyped container data with no type to read it off, so a literal here
@@ -254,8 +253,8 @@ export declare function addedItems(matrix: QuillFieldSchema, map: Record<string,
254
253
  */
255
254
  export declare function addedId(title: string, taken: (id: string) => boolean): string;
256
255
  /** The `object` a matrix member is, for the schema walk: the declared columns, and an
257
- * added item's `title` beside them. Composed here because the boundary serializes the
258
- * roster and the columns alone. */
256
+ * added item's `title`, a one-line `text` cell, beside them. Composed here because the
257
+ * boundary serializes the roster and the columns alone. */
259
258
  export declare function matrixMemberSchema(matrix: QuillFieldSchema, id: string): QuillFieldSchema;
260
259
  /**
261
260
  * The schema at `steps` under `field`, or `undefined` where the schema declares no such
@@ -267,8 +266,7 @@ export declare function matrixMemberSchema(matrix: QuillFieldSchema, id: string)
267
266
  */
268
267
  export declare function schemaAt(field: QuillFieldSchema, steps: readonly PathStep[]): QuillFieldSchema | undefined;
269
268
  /** Whether a cell is one line tall by declaration: the shape a table column and a row
270
- * summary can hold. A prose cell is one where it declares `inline`, `richtext` or
271
- * `plaintext` alike. */
269
+ * summary can hold. A prose cell is one where it is {@link oneLine}. */
272
270
  export declare function shortCell(sub: QuillFieldSchema): boolean;
273
271
  /** A collapsed row's own words ({@link firstShortText}); `undefined` while the row has
274
272
  * nothing to say for itself. */
@@ -301,19 +299,11 @@ export declare function variantCells(schema: QuillFieldSchema, member: string |
301
299
  * `undefined`.
302
300
  */
303
301
  export declare function commitDiscriminant(value: Record<string, unknown> | undefined, member: string | undefined): Record<string, unknown> | undefined;
304
- /**
305
- * Whether the schema obliges a cell: `default:`'s absence, which is the whole of the
306
- * obligation (DOCUMENT_MODEL). Exempt are the cells whose absence of one says nothing:
307
- * a typed dictionary, since a namespace declares no `default:` at all and `validate`
308
- * anchors obligation on the leaves under it; a matrix, whose blank is nothing held, a
309
- * whole answer; and an optional cell, which can declare none, its unanswered render
310
- * being `none`.
311
- */
312
- export declare function obliged(schema: QuillFieldSchema): boolean;
313
302
  /** `foo_bar` → `Foo bar`: the label fallback when a field declares no `title`. */
314
303
  export declare function humanize(name: string): string;
315
- /** Project a card schema's `fields` map (declaration = key order) into models. */
316
- export declare function fieldModels(cardSchema: QuillCardSchema): FieldModel[];
304
+ /** Project a card schema's `fields` map (declaration = key order) into models. A
305
+ * card-level object's `properties` project the same way. */
306
+ export declare function fieldModels(cardSchema: Pick<QuillCardSchema, 'fields'>): FieldModel[];
317
307
  /**
318
308
  * Group-section order (VISUAL_EDITOR §"Structure mirrors the schema"): the schema's `ui.groups` registry
319
309
  * key order when present: `QuillCardUi.groups` is a typed `Record` at the
@@ -84,6 +84,15 @@ export function optionalCell(f) {
84
84
  export function baseType(f) {
85
85
  return (optionalCell(f) ? f.type.slice(0, -1) : f.type);
86
86
  }
87
+ /** Whether a content field is one line: one paragraph, no container, no island. A `text`
88
+ * or `richtext` field is one line unless it declares `multiline: true`. */
89
+ export function oneLine(f) {
90
+ return f.multiline !== true;
91
+ }
92
+ /** Whether a content field's codec is the literal one, its value text with no marks: `text`. */
93
+ export function literalText(f) {
94
+ return baseType(f) === 'text';
95
+ }
87
96
  /**
88
97
  * A scalar `default:` as the text an unset control holds, where it prints: as
89
98
  * declared, `undefined` for none, a blank or a non-scalar. A default of spaces prints
@@ -95,7 +104,7 @@ export function printedText(v) {
95
104
  }
96
105
  /**
97
106
  * A declared content literal as the `Content` it holds: a `richtext` one's markdown
98
- * imported, a `plaintext` one's text taken literally, one paragraph whose later lines
107
+ * imported, a `text` one's text taken literally, one paragraph whose later lines
99
108
  * continue it, as the literal codec reads a stored one. What a cell's static
100
109
  * `default:` stands in its leaf as, where no resolved row reaches it. `undefined` for
101
110
  * a blank or a non-scalar.
@@ -118,25 +127,23 @@ export function declaredContent(v, markdown) {
118
127
  };
119
128
  }
120
129
  /** A field's `{#each}` key: its name and what a mounted leaf reads once, its type and
121
- * `inline` and its elements'. A retype or a quill swap that changes any of them under a
122
- * name remounts the field, where a kept leaf would commit on the old schema. */
130
+ * {@link oneLine} and its elements'. A retype or a quill swap that changes any of them
131
+ * under a name remounts the field, where a kept leaf would commit on the old schema. */
123
132
  export function mountKey(name, f) {
124
- return `${name}\u0000${f.type}\u0000${f.inline === true}\u0000${f.items?.type ?? ''}\u0000${f.items?.inline === true}`;
133
+ const items = f.items;
134
+ return `${name}\u0000${f.type}\u0000${oneLine(f)}\u0000${items?.type ?? ''}\u0000${items ? oneLine(items) : ''}`;
125
135
  }
126
- /** Map a field schema to its control (precedence: prose › enum › text › …).
127
- * An array's element control is this over `items`: a missing `items` is a text
128
- * element. */
136
+ /** Map a field schema to its control. An array's element control is this over `items`;
137
+ * a type this build does not know takes the text input. */
129
138
  export function controlKind(f) {
130
139
  switch (baseType(f)) {
131
140
  case 'richtext':
132
- case 'plaintext':
141
+ case 'text':
133
142
  return 'prose';
134
143
  case 'enum':
135
144
  // `variants:` is the one key that changes a field's resting shape (canon
136
145
  // `SCHEMAS.md`): with it the field rests as a container, without it a bare string.
137
146
  return f.variants ? 'variant' : 'enum';
138
- case 'string':
139
- return 'text';
140
147
  case 'number':
141
148
  case 'integer':
142
149
  return 'number';
@@ -300,13 +307,13 @@ export function addedId(title, taken) {
300
307
  return `${base}_${n}`;
301
308
  }
302
309
  /** The `object` a matrix member is, for the schema walk: the declared columns, and an
303
- * added item's `title` beside them. Composed here because the boundary serializes the
304
- * roster and the columns alone. */
310
+ * added item's `title`, a one-line `text` cell, beside them. Composed here because the
311
+ * boundary serializes the roster and the columns alone. */
305
312
  export function matrixMemberSchema(matrix, id) {
306
313
  const columns = matrix.properties ?? {};
307
314
  return {
308
315
  type: 'object',
309
- properties: onRoster(matrix, id) ? columns : { [MATRIX_TITLE]: { type: 'string' }, ...columns }
316
+ properties: onRoster(matrix, id) ? columns : { [MATRIX_TITLE]: { type: 'text' }, ...columns }
310
317
  };
311
318
  }
312
319
  // ── The schema walk ──────────────────────────────────────────────────────────
@@ -330,7 +337,7 @@ export function schemaAt(field, steps) {
330
337
  /** What an array declaring no `items` holds, the walk's copy of the element control
331
338
  * {@link controlKind} names for one: a text element, so an index into such an array is
332
339
  * a place and not a refusal. */
333
- const UNDECLARED_ELEMENT = { type: 'string' };
340
+ const UNDECLARED_ELEMENT = { type: 'text' };
334
341
  function stepInto(schema, step) {
335
342
  switch (controlKind(schema)) {
336
343
  case 'array':
@@ -361,17 +368,16 @@ function stepInto(schema, step) {
361
368
  }
362
369
  // ── Row summaries and layouts ────────────────────────────────────────────────
363
370
  /** Whether a cell is one line tall by declaration: the shape a table column and a row
364
- * summary can hold. A prose cell is one where it declares `inline`, `richtext` or
365
- * `plaintext` alike. */
371
+ * summary can hold. A prose cell is one where it is {@link oneLine}. */
366
372
  export function shortCell(sub) {
367
373
  const kind = controlKind(sub);
368
374
  if (kind === 'prose')
369
- return !!sub.inline;
375
+ return oneLine(sub);
370
376
  return (kind === 'text' || kind === 'enum' || kind === 'number' || kind === 'boolean' || kind === 'date');
371
377
  }
372
378
  /**
373
- * The first short text cell's words — the first `string`, or inline `richtext` /
374
- * `plaintext`, in declaration order — read through {@link titleText}; `undefined` where
379
+ * The first short text cell's words — the first one-line `text` or `richtext`, in
380
+ * declaration order — read through {@link titleText}; `undefined` where
375
381
  * there is no such cell or it is empty. The cell is picked by the schema alone, so an
376
382
  * instance is named by one cell whatever the others hold. What names an instance from
377
383
  * its own values: a collapsed row, and a card whose kind declares no `title`.
@@ -435,39 +441,36 @@ export function commitDiscriminant(value, member) {
435
441
  delete next[VARIANT_DISCRIMINANT];
436
442
  return Object.keys(next).length ? next : undefined;
437
443
  }
438
- /**
439
- * Whether the schema obliges a cell: `default:`'s absence, which is the whole of the
440
- * obligation (DOCUMENT_MODEL). Exempt are the cells whose absence of one says nothing:
441
- * a typed dictionary, since a namespace declares no `default:` at all and `validate`
442
- * anchors obligation on the leaves under it; a matrix, whose blank is nothing held, a
443
- * whole answer; and an optional cell, which can declare none, its unanswered render
444
- * being `none`.
445
- */
446
- export function obliged(schema) {
447
- return (schema.type !== 'object' &&
448
- schema.type !== 'matrix' &&
449
- !optionalCell(schema) &&
450
- schema.default === undefined);
451
- }
452
444
  /** `foo_bar` → `Foo bar`: the label fallback when a field declares no `title`. */
453
445
  export function humanize(name) {
454
446
  const spaced = name.replace(/_/g, ' ').trim();
455
447
  return spaced ? spaced[0].toUpperCase() + spaced.slice(1) : spaced;
456
448
  }
457
- /** Project a card schema's `fields` map (declaration = key order) into models. */
449
+ /**
450
+ * Whether a field asks to share a row when its `ui.compact` is undeclared: a control
451
+ * whose type bounds its width. Text never does, its type saying nothing of whether a
452
+ * value is a rank or a subject line, so a short text field asks with `compact: true`.
453
+ */
454
+ function packsByDefault(control) {
455
+ return control === 'date' || control === 'enum' || control === 'number' || control === 'boolean';
456
+ }
457
+ /** Project a card schema's `fields` map (declaration = key order) into models. A
458
+ * card-level object's `properties` project the same way. */
458
459
  export function fieldModels(cardSchema) {
459
- return Object.entries(cardSchema.fields).map(([name, schema]) => ({
460
- name,
461
- schema,
462
- control: controlKind(schema),
463
- group: schema.ui?.group,
464
- compact: !!schema.ui?.compact,
465
- label: schema.title ?? humanize(name),
466
- description: schema.description,
467
- required: obliged(schema),
468
- inline: !!schema.inline,
469
- plaintext: baseType(schema) === 'plaintext'
470
- }));
460
+ return Object.entries(cardSchema.fields).map(([name, schema]) => {
461
+ const control = controlKind(schema);
462
+ return {
463
+ name,
464
+ schema,
465
+ control,
466
+ group: schema.ui?.group,
467
+ compact: schema.ui?.compact ?? packsByDefault(control),
468
+ label: schema.title ?? humanize(name),
469
+ description: schema.description,
470
+ inline: oneLine(schema),
471
+ plaintext: literalText(schema)
472
+ };
473
+ });
471
474
  }
472
475
  /**
473
476
  * Group-section order (VISUAL_EDITOR §"Structure mirrors the schema"): the schema's `ui.groups` registry
@@ -543,12 +546,12 @@ export function initialExpandedGroup(sections) {
543
546
  return sections.find((s) => s.group != null)?.group ?? null;
544
547
  }
545
548
  /**
546
- * Whether a field can share a row. `ui.compact` asks; a shape declines when the
549
+ * Whether a field can share a row. `compact` asks; a shape declines when the
547
550
  * document sets its height, because a row is as tall as its tallest cell and the cell
548
- * beside it does not grow in step: an object nests a whole field set, block richtext
549
- * (`inline` absent) holds paragraphs, and an array holds however many elements the
550
- * document carries. Any of them stands its neighbour in a column of whitespace. An
551
- * inline prose leaf is one line tall and packs like any scalar.
551
+ * beside it does not grow in step: an object nests a whole field set, a multiline prose
552
+ * leaf holds paragraphs or lines, and an array holds however many elements the
553
+ * document carries. Any of them stands its neighbour in a column of whitespace. A
554
+ * one-line prose leaf packs like any scalar.
552
555
  *
553
556
  * A variant declines for the same reason one step further in: its height is the live
554
557
  * world's cell count, so it is set by a pick rather than only by the document, and a
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quillmark/svelte",
3
- "version": "0.21.0",
3
+ "version": "0.22.0",
4
4
  "description": "Editor, live-preview and source surfaces over a Quillmark WASM session.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -23,7 +23,7 @@
23
23
  "author": "Quillmark Contributors",
24
24
  "type": "module",
25
25
  "engines": {
26
- "node": ">=24"
26
+ "node": ">=22"
27
27
  },
28
28
  "svelte": "./dist/index.js",
29
29
  "types": "./dist/index.d.ts",
@@ -69,7 +69,7 @@
69
69
  "check": "svelte-check --tsconfig ./tsconfig.json --fail-on-warnings"
70
70
  },
71
71
  "peerDependencies": {
72
- "@quillmark/wasm": ">=0.125.0-0",
72
+ "@quillmark/wasm": ">=0.126.0-0",
73
73
  "svelte": "^5.33.0"
74
74
  },
75
75
  "dependencies": {