slotdeck 0.1.2 → 0.2.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 (104) hide show
  1. package/README.md +86 -6
  2. package/dist/deck/alternatives.d.ts +34 -0
  3. package/dist/deck/alternatives.js +370 -0
  4. package/dist/deck/alternatives.js.map +1 -0
  5. package/dist/deck/design.d.ts +40 -0
  6. package/dist/deck/design.js +112 -0
  7. package/dist/deck/design.js.map +1 -0
  8. package/dist/deck/validate.d.ts +18 -0
  9. package/dist/deck/validate.js +38 -2
  10. package/dist/deck/validate.js.map +1 -1
  11. package/dist/index.d.ts +22 -1
  12. package/dist/index.js +13 -0
  13. package/dist/index.js.map +1 -1
  14. package/dist/node.d.ts +7 -0
  15. package/dist/node.js +29 -0
  16. package/dist/node.js.map +1 -1
  17. package/dist/plan/catalog.js +3 -1
  18. package/dist/plan/catalog.js.map +1 -1
  19. package/dist/plan/edit.js +6 -2
  20. package/dist/plan/edit.js.map +1 -1
  21. package/dist/plan/plan.d.ts +10 -0
  22. package/dist/plan/plan.js +8 -0
  23. package/dist/plan/plan.js.map +1 -1
  24. package/dist/plan/review.d.ts +43 -0
  25. package/dist/plan/review.js +141 -0
  26. package/dist/plan/review.js.map +1 -0
  27. package/dist/plan/write.d.ts +5 -0
  28. package/dist/plan/write.js +11 -4
  29. package/dist/plan/write.js.map +1 -1
  30. package/dist/preview/pagus.d.ts +30 -0
  31. package/dist/preview/pagus.js +45 -0
  32. package/dist/preview/pagus.js.map +1 -0
  33. package/dist/preview/patterns.d.ts +27 -0
  34. package/dist/preview/patterns.js +35 -0
  35. package/dist/preview/patterns.js.map +1 -0
  36. package/dist/preview/provider.d.ts +30 -0
  37. package/dist/preview/provider.js +11 -0
  38. package/dist/preview/provider.js.map +1 -0
  39. package/dist/render/render.d.ts +18 -1
  40. package/dist/render/render.js +28 -8
  41. package/dist/render/render.js.map +1 -1
  42. package/dist/render/repeat.d.ts +17 -2
  43. package/dist/render/repeat.js +150 -4
  44. package/dist/render/repeat.js.map +1 -1
  45. package/dist/render/text.d.ts +6 -0
  46. package/dist/render/text.js +24 -0
  47. package/dist/render/text.js.map +1 -1
  48. package/dist/template/budgets.d.ts +33 -0
  49. package/dist/template/budgets.js +38 -0
  50. package/dist/template/budgets.js.map +1 -0
  51. package/dist/template/change.d.ts +18 -1
  52. package/dist/template/change.js +33 -3
  53. package/dist/template/change.js.map +1 -1
  54. package/dist/template/check.d.ts +3 -0
  55. package/dist/template/check.js +53 -3
  56. package/dist/template/check.js.map +1 -1
  57. package/dist/template/derive.d.ts +54 -0
  58. package/dist/template/derive.js +402 -0
  59. package/dist/template/derive.js.map +1 -0
  60. package/dist/template/draft.d.ts +7 -0
  61. package/dist/template/draft.js +17 -1
  62. package/dist/template/draft.js.map +1 -1
  63. package/dist/template/instruct.js +11 -5
  64. package/dist/template/instruct.js.map +1 -1
  65. package/dist/template/manifest.d.ts +22 -0
  66. package/dist/template/manifest.js +17 -1
  67. package/dist/template/manifest.js.map +1 -1
  68. package/dist/template/sample.d.ts +17 -0
  69. package/dist/template/sample.js +27 -2
  70. package/dist/template/sample.js.map +1 -1
  71. package/dist/text/fontkit.d.ts +18 -0
  72. package/dist/text/fontkit.js +91 -0
  73. package/dist/text/fontkit.js.map +1 -0
  74. package/dist/text/fonts.d.ts +45 -0
  75. package/dist/text/fonts.js +59 -0
  76. package/dist/text/fonts.js.map +1 -0
  77. package/dist/text/layout.d.ts +12 -0
  78. package/dist/text/layout.js +104 -0
  79. package/dist/text/layout.js.map +1 -0
  80. package/dist/text/measure.d.ts +85 -0
  81. package/dist/text/measure.js +369 -0
  82. package/dist/text/measure.js.map +1 -0
  83. package/dist/text/styles.d.ts +123 -0
  84. package/dist/text/styles.js +417 -0
  85. package/dist/text/styles.js.map +1 -0
  86. package/dist/tools.d.ts +12 -0
  87. package/dist/tools.js +32 -6
  88. package/dist/tools.js.map +1 -1
  89. package/docs/README.md +15 -5
  90. package/docs/api-reference.md +278 -8
  91. package/docs/changelog.md +135 -0
  92. package/docs/chat-tools.md +22 -5
  93. package/docs/deck-format.md +6 -0
  94. package/docs/design-checks.md +216 -0
  95. package/docs/generating.md +4 -1
  96. package/docs/layout-freedom.md +255 -3
  97. package/docs/manifest-format.md +19 -3
  98. package/docs/preview.md +217 -0
  99. package/docs/providers.md +1 -1
  100. package/docs/rendering.md +8 -0
  101. package/docs/template-studio.md +110 -11
  102. package/docs/text-fit.md +456 -0
  103. package/docs/troubleshooting.md +13 -2
  104. package/package.json +7 -1
@@ -5,10 +5,10 @@ manifest with a model, checking it, seeing whether its budgets hold, and changin
5
5
 
6
6
  ```ts
7
7
  import {
8
- draftManifest, checkManifest, sampleDeck, changeManifest, editManifest,
8
+ draftManifest, checkManifest, sampleDeck, changeManifest, editManifest, patternVariants, VARIANTS,
9
9
  studioView, describeManifest, describeSlot, inspectTemplate, ROLES, PptxPackage, loadTemplate, renderDeck,
10
10
  } from 'slotdeck';
11
- import type { ManifestChange, SlotPatch, ChangeResult, ManifestIssue, Role, StudioView } from 'slotdeck';
11
+ import type { ManifestChange, SlotPatch, ChangeResult, ManifestIssue, PatternVariant, Role, StudioView, VariantOption } from 'slotdeck';
12
12
  ```
13
13
 
14
14
  ## The workflow
@@ -21,8 +21,8 @@ import type { ManifestChange, SlotPatch, ChangeResult, ManifestIssue, Role, Stud
21
21
  5. Repeat 2 to 4 until the sample looks right. Store the manifest as JSON next to the pptx.
22
22
 
23
23
  A draft is a starting point for review, not a finished manifest. What a draft does not contain, and a person
24
- adds: budgets tuned by eye, derived patterns (a text-only variant, a native chart), wider rows, picture areas,
25
- chart colours, and alignment choices for decks that read the other way.
24
+ adds: budgets tuned by eye, derived patterns (a mirrored or text-only variant, a native chart), wider rows,
25
+ picture areas, chart colours, and alignment choices for decks that read the other way.
26
26
 
27
27
  ## `draftManifest(pptx, options)`
28
28
 
@@ -32,6 +32,7 @@ const { manifest, skipped, issues } = await draftManifest(pptxBytes, {
32
32
  name: 'marketing', // optional name for the manifest; default 'template'
33
33
  slideImage: (slide) => thumbnails.get(slide), // optional: { mimeType, data } of a picture of slide N (1-based); may be async
34
34
  slides: [1, 2, 5], // optional: only these slides; default all
35
+ variants: ['mirror', 'text-only'], // optional: also add these variants of every pattern that allows them; default none
35
36
  concurrency: 4, // optional: slides sent to the model at once; default 4
36
37
  onProgress: ({ done, total, slide }) => {}, // optional
37
38
  signal, // optional
@@ -71,6 +72,18 @@ Any PNG or JPEG of the slide works; 480 pixels wide is enough.
71
72
  To redo one slide after changing the pptx, call `draftManifest` with `slides: [n]` and add the pattern it
72
73
  returns to your manifest.
73
74
 
75
+ ### Variants in a draft
76
+
77
+ With `variants`, the draft also gets the mirror image and the text-only version of every drafted pattern whose
78
+ slide allows one (see `derivePattern` below). They are worked out by code after the model has labelled the
79
+ slides, so they cost no model call. A pattern that allows no variant simply gets none.
80
+
81
+ This is off by default, for three reasons. Every variant is one more layout to review in the sample deck.
82
+ Whether a mirrored slide suits a design is for a person to say. And a variant is only as good as the labels it
83
+ is derived from, which a draft has not had reviewed yet. The usual order is therefore: draft, review, then add
84
+ the variants you want with `derivePattern`. Use `variants` when a studio should show everything a template can
85
+ do in one pass. The `without` variant is never added by a draft, because it needs a slot to be named.
86
+
74
87
  ### Roles
75
88
 
76
89
  `ROLES` lists them. A role says what a shape is for and decides the kind of slot it becomes.
@@ -106,6 +119,12 @@ kind of shape, names are unique, rows are consistent. The rules are listed in
106
119
  [manifest-format.md](manifest-format.md). Run it when a template is loaded, so a template that someone changed
107
120
  shows up there and not in the middle of a render.
108
121
 
122
+ For a template loaded with fonts it also tries every text budget out and warns about one that lets text run
123
+ over its box. A row with `widen` gives its texts a larger budget when a slide has fewer items; that budget is
124
+ tried in the wider box, for each number of items that widens the row, and a warning then says which
125
+ (`on a slide with 2 of its 4 items`). See "The studio: checking and setting budgets" in
126
+ [text-fit.md](text-fit.md).
127
+
109
128
  ## `sampleDeck(template, options?)`
110
129
 
111
130
  ```ts
@@ -120,6 +139,10 @@ filler words and plain coloured rectangles for pictures.
120
139
  | --- | --- | --- |
121
140
  | `fill` | `0.95` | How full to make each text slot, as a share of its budget. |
122
141
  | `items` | `'drawn'` | For patterns with a row or grid: `'drawn'` uses the template's number, `'max'` the most allowed, `'min'` the fewest. |
142
+ | `fit` | `'budget'` | What "full" means for a text slot: `'budget'` is its character budget; `'box'` is what its box holds as measured with the template's fonts (see [text-fit.md](text-fit.md)). |
143
+
144
+ To look at the sample deck without opening PowerPoint, draw it with a preview provider:
145
+ `previewDeck(template, deck, preview, { assets, layout: 'adaptive' })`. See [preview.md](preview.md).
123
146
 
124
147
  ## `changeManifest(template, changes)`
125
148
 
@@ -167,7 +190,38 @@ instead to get a complete pattern.
167
190
  { op: 'copyPattern', pattern: string, id: string, description?: string }
168
191
  ```
169
192
 
170
- A second pattern from the same slide, to turn into a variant with further operations.
193
+ A second pattern from the same slide, to turn into a variant by hand with further operations. For the mirror
194
+ image, a text-only version or a version without an optional line, use `derivePattern`, which works out the
195
+ positions.
196
+
197
+ #### `derivePattern`
198
+
199
+ ```ts
200
+ { op: 'derivePattern', pattern: string, variant: 'mirror' | 'text-only' | 'without', slot?: string, id?: string, description?: string }
201
+ ```
202
+
203
+ A second pattern from the same slide, laid out by the code. You name the variant; every position and budget is
204
+ worked out from the shapes of the slide. `VARIANTS` lists the variant names.
205
+
206
+ | Variant | What it makes | Default id |
207
+ | --- | --- | --- |
208
+ | `mirror` | The picture and what sits beside it change sides. | `<pattern>-mirrored` |
209
+ | `text-only` | The picture is left out, and the text beside it widens over the room it leaves. | `<pattern>-text-only` |
210
+ | `without` | The optional text named in `slot` is left out, and what sits under it moves up. | `<pattern>-no-<slot>` |
211
+
212
+ - `slot` is needed for `without` only, and must name an optional text slot (`"empty": "remove"`).
213
+ - `id` and `description` replace the defaults. The default description is the source's with a sentence added,
214
+ such as `Mirrored: here the picture is on the left and the text on the right. Alternate it with "photo-stat" for variety.`
215
+ Write your own when the source's description names a side ("a photo on the right"), so that the planner
216
+ reads one clear statement.
217
+ - The new pattern is placed right after its source. The source is not changed.
218
+ - A variant can be derived from a variant: the mirror image, then that without its subtitle.
219
+ - A variant the slide does not allow is refused with the reason, such as
220
+ `"cover" has no photo, graphic or chart of its own, so there is nothing to change sides with`.
221
+
222
+ How each variant is worked out, what it leaves alone and when it is refused is described under "Variants the
223
+ code works out" in [layout-freedom.md](layout-freedom.md). `patternVariants` (below) says in advance which
224
+ variants a pattern allows.
171
225
 
172
226
  #### `removePattern`
173
227
 
@@ -234,13 +288,18 @@ A property that does not apply to the slot's kind is refused (`"title" is a text
234
288
  #### `setRepeat`
235
289
 
236
290
  ```ts
237
- { op: 'setRepeat', pattern: string, min?: number, max?: number, item?: string, span?: { left: number, right: number } | null }
291
+ { op: 'setRepeat', pattern: string, min?: number, max?: number, item?: string, span?: { left: number, right: number } | null, widen?: number | null }
238
292
  ```
239
293
 
240
294
  Sets how many items a row or grid takes. When the pattern has no row yet, it is found from numbered slot names:
241
295
  name the slots of each item alike with a number (`card1Heading`, `card1Text`, `card2Heading`, `card2Text`) and
242
296
  they become a row.
243
297
 
298
+ `widen` lets the items grow wider when a line holds fewer of them than the template draws, so that two or
299
+ three cards fill a row drawn for four. It is the most an item may grow, as a factor on its drawn width,
300
+ between 1 and 4; `null` or `1` turns it off. See "Fewer items that fill the row" in
301
+ [layout-freedom.md](layout-freedom.md). Render `sampleDeck(template, { items: 'min' })` to look at the result.
302
+
244
303
  #### `removeRepeat`
245
304
 
246
305
  ```ts
@@ -259,6 +318,8 @@ The items stop being a row whose number can change.
259
318
  with the most that do: `5 cards do not fit side by side: each is 21% of the slide wide and the row has 93%. The most is 4`.
260
319
  - **Row items stay alike.** A `setSlot` on one item's slot (`card1Icon`) is made to that slot of every item.
261
320
  Slots of a row cannot be renamed, moved or removed one by one; remove the row first.
321
+ - **Variants are laid out.** `derivePattern` moves and resizes the shapes of a variant by itself, measures
322
+ the budgets of every text that changed size, and writes a description the planner can choose the variant by.
262
323
  - **Nothing is left broken.** After each change the manifest is checked against the pptx. A change that
263
324
  introduces a new error is refused.
264
325
 
@@ -283,16 +344,34 @@ A native chart in place of a sample chart picture, as a second pattern:
283
344
  ]
284
345
  ```
285
346
 
286
- A text-only slide from a slide with a photo:
347
+ The mirror image of a slide with a photo, for variety in a deck with several such slides:
348
+
349
+ ```ts
350
+ { op: 'derivePattern', pattern: 'photo-stat', variant: 'mirror', description: 'One key figure with a title and a short explanation on the left, and a photo on the right.' }
351
+ ```
352
+
353
+ A text-only slide from a slide with a photo, then larger text with room for three paragraphs (the budget
354
+ follows the new size):
287
355
 
288
356
  ```ts
289
357
  [
290
- { op: 'copyPattern', pattern: 'text-and-photo', id: 'text-only' },
291
- { op: 'addSlot', pattern: 'text-only', shape: '2', role: 'decoration' }, // the photo
292
- { op: 'setSlot', pattern: 'text-only', slot: 'body', box: { x: 0.04, y: 0.49, w: 0.72, h: 0.39 }, fontSize: 20, maxParagraphs: 3 },
358
+ { op: 'derivePattern', pattern: 'text-and-photo', variant: 'text-only', id: 'text-only' },
359
+ { op: 'setSlot', pattern: 'text-only', slot: 'body', fontSize: 20, maxParagraphs: 3, paragraphGap: 12 },
293
360
  ]
294
361
  ```
295
362
 
363
+ The same slide for decks that have no subtitle, with the body moved up into its place:
364
+
365
+ ```ts
366
+ { op: 'derivePattern', pattern: 'text-and-photo', variant: 'without', slot: 'subtitle' }
367
+ ```
368
+
369
+ Two or three cards that fill a row drawn for four, each holding more text:
370
+
371
+ ```ts
372
+ { op: 'setRepeat', pattern: 'icon-cards', widen: 2.2 }
373
+ ```
374
+
296
375
  Smaller table text and fewer columns (the cell budget is measured for you):
297
376
 
298
377
  ```ts
@@ -329,7 +408,10 @@ by hand. One model call, and a second when some operations were refused, so the
329
408
 
330
409
  - Instructions can be in any language.
331
410
  - A person may refer to a slide by number or to a pattern by id.
332
- - The model cannot set positions: `box` and `span` exist only for changes made by hand.
411
+ - The model cannot set positions: `box` and `span` exist only for changes made by hand. It can ask for a
412
+ variant by name ("add a mirrored version of the photo slides", "a version of slide 2 without the picture"),
413
+ which becomes a `derivePattern` operation: the model names the variant, and the code works out where
414
+ everything goes.
333
415
  - An operation the model got wrong shows up in `rejected` with the reason; nothing of it is applied.
334
416
 
335
417
  `describeManifest(template)` returns the text the model reads: every pattern with its slots and limits, and the
@@ -362,6 +444,23 @@ that are slots, and on a click offers the shape's `roles` (sending `addSlot`) or
362
444
 
363
445
  `describeSlot(slot)` gives a slot in a few words, such as `text, up to 40 characters, required`.
364
446
 
447
+ ## `patternVariants(template, pattern)`
448
+
449
+ ```ts
450
+ const options = patternVariants(template, 'text-and-photo');
451
+ // [
452
+ // { variant: 'mirror', available: true, note: 'the mirror image of "text-and-photo", with the picture on the left and what sat beside it on the right. ...' },
453
+ // { variant: 'text-only', available: true, note: '"text-and-photo" without its picture "photo". Widened over the freed area, with budgets to match: ...' },
454
+ // { variant: 'without', slot: 'subtitle', available: true, note: '"text-and-photo" without "subtitle": body moves up and has more room (431 characters).' },
455
+ // ]
456
+ ```
457
+
458
+ No model, and nothing is changed. It lists the variants `derivePattern` could make from a pattern: the mirror
459
+ image, the text-only version, and one `without` for each optional text slot. An entry with `available: false`
460
+ carries the reason in `note`; an available one says there what the variant would do. A studio screen can show
461
+ the available ones as buttons that send `{ op: 'derivePattern', pattern, variant, slot }`. It throws when the
462
+ template has no pattern of that id.
463
+
365
464
  ## `inspectTemplate(pkg)`
366
465
 
367
466
  ```ts