@openpresentation/opf 0.15.1 → 0.16.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 (73) hide show
  1. package/README.md +4 -0
  2. package/dist/{catalog-refs-BSfGELpt.d.ts → catalog-refs-_anZs-Qz.d.ts} +1 -1
  3. package/dist/{catalog-schemas-CinPh5WA.d.ts → catalog-schemas-BZCjgAxu.d.ts} +1 -1
  4. package/dist/catalog.d.ts +2 -2
  5. package/dist/catalog.js +609 -121
  6. package/dist/{chunk-5FTUIDUH.js → chunk-3XDRQYWZ.js} +1 -1
  7. package/dist/{chunk-O744SXXA.js → chunk-5PDN7BN6.js} +202 -95
  8. package/dist/{chunk-VGAOJEY7.js → chunk-5TO6I3GB.js} +1 -1
  9. package/dist/{chunk-3RKB4RDJ.js → chunk-5UEUAW57.js} +4 -2
  10. package/dist/{chunk-ZPU46TFA.js → chunk-6OR326EA.js} +1 -1
  11. package/dist/{chunk-UBFJ2QHH.js → chunk-BSYQDWT4.js} +12 -2
  12. package/dist/{chunk-3JG4YXWF.js → chunk-FQSIIADJ.js} +12 -5
  13. package/dist/chunk-K4DQQIT4.js +319 -0
  14. package/dist/chunk-KINQFU6X.js +51 -0
  15. package/dist/{chunk-374R35TJ.js → chunk-NAWQR7MN.js} +1 -1
  16. package/dist/{chunk-QDI75P2M.js → chunk-PX5AWL7Y.js} +141 -13
  17. package/dist/{chunk-U4J75TRG.js → chunk-SMLMI6IZ.js} +5 -2
  18. package/dist/{chunk-TWQJLI6E.js → chunk-UM24JFUE.js} +2 -2
  19. package/dist/{chunk-2CJPC4HI.js → chunk-WEDGVC5W.js} +185 -11
  20. package/dist/{composition-D2tghM82.d.ts → composition-D4ADF5c-.d.ts} +88 -9
  21. package/dist/composition.d.ts +2 -2
  22. package/dist/composition.js +1 -1
  23. package/dist/convert.d.ts +3 -3
  24. package/dist/convert.js +7 -7
  25. package/dist/data.d.ts +27 -10
  26. package/dist/data.js +2 -2
  27. package/dist/deck.d.ts +77 -0
  28. package/dist/deck.js +12 -0
  29. package/dist/diff.js +5 -5
  30. package/dist/docs.js +24 -24
  31. package/dist/examples.d.ts +1 -1
  32. package/dist/examples.js +2992 -748
  33. package/dist/format.js +2 -2
  34. package/dist/index.d.ts +9 -8
  35. package/dist/index.js +15 -13
  36. package/dist/markdown.d.ts +6 -7
  37. package/dist/markdown.js +7 -7
  38. package/dist/{pagination-wedbe7eq.d.ts → pagination-DzZPFheM.d.ts} +2 -2
  39. package/dist/pagination.d.ts +3 -3
  40. package/dist/pagination.js +4 -4
  41. package/dist/patch.js +4 -4
  42. package/dist/{presentation-CDKQVkyI.d.ts → presentation-COrFuj2g.d.ts} +16 -8
  43. package/dist/repo-readme.js +1 -1
  44. package/dist/schemas.d.ts +14 -0
  45. package/dist/schemas.js +1 -1
  46. package/dist/spec/catalogs/layouts/business-model-canvas.json +66 -1
  47. package/dist/spec/catalogs/layouts/capability-map.json +53 -3
  48. package/dist/spec/catalogs/layouts/chart-2x.json +32 -8
  49. package/dist/spec/catalogs/layouts/chart-3x-bottom-vertical-title-left.json +16 -10
  50. package/dist/spec/catalogs/layouts/chart-3x-left-title-center.json +16 -10
  51. package/dist/spec/catalogs/layouts/chart-3x-left.json +16 -10
  52. package/dist/spec/catalogs/layouts/chart-3x-right-title-center.json +16 -10
  53. package/dist/spec/catalogs/layouts/chart-3x-right.json +16 -10
  54. package/dist/spec/catalogs/layouts/chart-3x-top-vertical-title-left.json +16 -10
  55. package/dist/spec/catalogs/layouts/chart-3x.json +48 -12
  56. package/dist/spec/catalogs/layouts/dashboard.json +37 -5
  57. package/dist/spec/catalogs/layouts/image-2x.json +32 -8
  58. package/dist/spec/catalogs/layouts/image-3x.json +48 -12
  59. package/dist/spec/catalogs/layouts/index.json +1 -1
  60. package/dist/spec/catalogs/layouts/kpi-scorecard.json +48 -3
  61. package/dist/spec/catalogs/layouts/logic-tree.json +69 -0
  62. package/dist/spec/catalogs/layouts/market-size.json +26 -2
  63. package/dist/spec/catalogs/layouts/org-chart.json +53 -6
  64. package/dist/spec/catalogs/manifest.json +3 -3
  65. package/dist/spec/schemas/layout.schema.json +172 -5
  66. package/dist/spec/schemas/opf.schema.json +11 -6
  67. package/dist/types.d.ts +9 -31
  68. package/dist/{validation-types-BOcY9GTs.d.ts → validation-types-HxIgJfKx.d.ts} +2 -2
  69. package/dist/validator.d.ts +6 -6
  70. package/dist/validator.js +3 -3
  71. package/dist/yaml.d.ts +4 -4
  72. package/dist/yaml.js +8 -321
  73. package/package.json +5 -1
@@ -16,6 +16,68 @@
16
16
  },
17
17
  {
18
18
  "type": "text"
19
+ },
20
+ {
21
+ "type": "group",
22
+ "composition": {
23
+ "mode": "row"
24
+ },
25
+ "placeholders": [
26
+ {
27
+ "type": "group",
28
+ "composition": {
29
+ "mode": "column",
30
+ "weights": [
31
+ 1,
32
+ 2
33
+ ]
34
+ },
35
+ "placeholders": [
36
+ {
37
+ "type": "text"
38
+ },
39
+ {
40
+ "type": "list"
41
+ }
42
+ ]
43
+ },
44
+ {
45
+ "type": "group",
46
+ "composition": {
47
+ "mode": "column",
48
+ "weights": [
49
+ 1,
50
+ 2
51
+ ]
52
+ },
53
+ "placeholders": [
54
+ {
55
+ "type": "text"
56
+ },
57
+ {
58
+ "type": "list"
59
+ }
60
+ ]
61
+ },
62
+ {
63
+ "type": "group",
64
+ "composition": {
65
+ "mode": "column",
66
+ "weights": [
67
+ 1,
68
+ 2
69
+ ]
70
+ },
71
+ "placeholders": [
72
+ {
73
+ "type": "text"
74
+ },
75
+ {
76
+ "type": "list"
77
+ }
78
+ ]
79
+ }
80
+ ]
19
81
  }
20
82
  ],
21
83
  "tags": [
@@ -25,5 +87,12 @@
25
87
  ],
26
88
  "preview": {
27
89
  "vectorSrc": "https://www.pptx.gallery/layout-previews/logic-tree.svg"
90
+ },
91
+ "composition": {
92
+ "mode": "column",
93
+ "weights": [
94
+ 1,
95
+ 3
96
+ ]
28
97
  }
29
98
  }
@@ -3,7 +3,7 @@
3
3
  "id": "market-size",
4
4
  "name": "Market_Size",
5
5
  "summary": "Nested TAM / SAM / SOM visualization showing total market, addressable segment, and obtainable share.",
6
- "description": "Nested TAM / SAM / SOM visualization showing total market, addressable segment, and obtainable share.",
6
+ "description": "Nested TAM / SAM / SOM visualization beside the three numbers stacked: total market, addressable segment, and obtainable share.",
7
7
  "design": {
8
8
  "titleAlignment": "left",
9
9
  "contentAlignment": "left",
@@ -15,7 +15,24 @@
15
15
  "type": "title"
16
16
  },
17
17
  {
18
- "type": "text"
18
+ "type": "image"
19
+ },
20
+ {
21
+ "type": "group",
22
+ "composition": {
23
+ "mode": "column"
24
+ },
25
+ "placeholders": [
26
+ {
27
+ "type": "metric"
28
+ },
29
+ {
30
+ "type": "metric"
31
+ },
32
+ {
33
+ "type": "metric"
34
+ }
35
+ ]
19
36
  }
20
37
  ],
21
38
  "tags": [
@@ -25,5 +42,12 @@
25
42
  ],
26
43
  "preview": {
27
44
  "vectorSrc": "https://www.pptx.gallery/layout-previews/market-size.svg"
45
+ },
46
+ "composition": {
47
+ "mode": "row",
48
+ "weights": [
49
+ 3,
50
+ 2
51
+ ]
28
52
  }
29
53
  }
@@ -7,7 +7,7 @@
7
7
  "design": {
8
8
  "titleAlignment": "left",
9
9
  "contentAlignment": "left",
10
- "contentBox": false,
10
+ "contentBox": true,
11
11
  "contentDirection": "horizontal"
12
12
  },
13
13
  "placeholders": [
@@ -15,10 +15,57 @@
15
15
  "type": "title"
16
16
  },
17
17
  {
18
- "type": "chart"
18
+ "type": "text"
19
19
  },
20
20
  {
21
- "type": "chart"
21
+ "type": "group",
22
+ "composition": {
23
+ "mode": "row"
24
+ },
25
+ "placeholders": [
26
+ {
27
+ "type": "group",
28
+ "composition": {
29
+ "mode": "column"
30
+ },
31
+ "placeholders": [
32
+ {
33
+ "type": "text"
34
+ },
35
+ {
36
+ "type": "text"
37
+ }
38
+ ]
39
+ },
40
+ {
41
+ "type": "group",
42
+ "composition": {
43
+ "mode": "column"
44
+ },
45
+ "placeholders": [
46
+ {
47
+ "type": "text"
48
+ },
49
+ {
50
+ "type": "text"
51
+ }
52
+ ]
53
+ },
54
+ {
55
+ "type": "group",
56
+ "composition": {
57
+ "mode": "column"
58
+ },
59
+ "placeholders": [
60
+ {
61
+ "type": "text"
62
+ },
63
+ {
64
+ "type": "text"
65
+ }
66
+ ]
67
+ }
68
+ ]
22
69
  }
23
70
  ],
24
71
  "tags": [
@@ -30,10 +77,10 @@
30
77
  "vectorSrc": "https://www.pptx.gallery/layout-previews/org-chart.svg"
31
78
  },
32
79
  "composition": {
33
- "mode": "row",
80
+ "mode": "column",
34
81
  "weights": [
35
- 2,
36
- 1
82
+ 1,
83
+ 3
37
84
  ]
38
85
  }
39
86
  }
@@ -4,7 +4,7 @@
4
4
  "publisher": "https://www.pptx.gallery",
5
5
  "source": {
6
6
  "repository": "https://github.com/Data-Advantage/pptx-gallery",
7
- "commit": "5645db8e4e9e09d0dd819c39538b1c783ee91aa1",
7
+ "commit": "db31c09e35d7e4c7a12072d6f95ece36336f5dfa",
8
8
  "path": "public"
9
9
  },
10
10
  "kinds": {
@@ -56,10 +56,10 @@
56
56
  "layouts": {
57
57
  "mode": "mirror",
58
58
  "records": 278,
59
- "contentSha256": "f9121c466032011762d58ee27cd3e50f43a388cc75b841219f87b8001f7632a3",
59
+ "contentSha256": "877c1cd335cbbb8258a5b93e78e112d740906c33c9910586c8b12c63482b5adb",
60
60
  "gallery": {
61
61
  "records": 278,
62
- "contentSha256": "f9121c466032011762d58ee27cd3e50f43a388cc75b841219f87b8001f7632a3"
62
+ "contentSha256": "877c1cd335cbbb8258a5b93e78e112d740906c33c9910586c8b12c63482b5adb"
63
63
  }
64
64
  },
65
65
  "narratives": {
@@ -57,8 +57,8 @@
57
57
  },
58
58
  "placeholders": {
59
59
  "type": "array",
60
- "items": { "$ref": "#/$defs/Placeholder" },
61
- "description": "Ordered regions the layout exposes. This is the single source of truth for what the layout holds: the content kind, the number of body regions and whether it has a title, subtitle or tag are derived from it (layoutContent in @openpresentation/opf), never stored separately. The engine fills 'title', 'subtitle' and 'tag' placeholders from Slide.title, Slide.subtitle and Slide.tag. The other placeholders are content-kind regions that composition uses to size the body and that pickers use to match layouts. Slide content itself lives either in root payload fields or promoted region keys on Slide. Chrome (slide number, footer, date) is not included here; it is owned by Design.header / Design.footer."
60
+ "items": { "$ref": "#/$defs/PlaceholderEntry" },
61
+ "description": "Ordered regions the layout exposes. This is the single source of truth for what the layout holds: the content kind, the number of body regions and whether it has a title, subtitle or tag are derived from it (layoutContent in @openpresentation/opf, which counts the leaves of placeholder groups), never stored separately. The engine fills 'title', 'subtitle' and 'tag' placeholders from Slide.title, Slide.subtitle and Slide.tag. The other placeholders are content-kind regions that composition uses to size the body and that pickers use to match layouts. An entry may instead be a placeholder group ({ \"type\": \"group\", \"composition\", \"placeholders\" }) that arranges its own regions inside one cell of this record's composition, so a record can say 'two stacked panels beside a chart' once; groups nest at most three levels. Slide content stays flat: its body payloads fill the leaf regions in reading order (depth first, in array order). Slide content itself lives either in root payload fields, blocks or promoted region keys on Slide. Chrome (slide number, footer, date) is not included here; it is owned by Design.header / Design.footer."
62
62
  },
63
63
  "tags": {
64
64
  "type": "array",
@@ -116,6 +116,173 @@
116
116
  }
117
117
  },
118
118
  "$defs": {
119
+ "PlaceholderEntry": {
120
+ "description": "One entry of a layout's placeholders: a region (Placeholder) or, when its type is 'group', a placeholder group (PlaceholderGroup).",
121
+ "if": {
122
+ "type": "object",
123
+ "required": [
124
+ "type"
125
+ ],
126
+ "properties": {
127
+ "type": {
128
+ "const": "group"
129
+ }
130
+ }
131
+ },
132
+ "then": {
133
+ "$ref": "#/$defs/PlaceholderGroup"
134
+ },
135
+ "else": {
136
+ "$ref": "#/$defs/Placeholder"
137
+ }
138
+ },
139
+ "PlaceholderGroup": {
140
+ "type": "object",
141
+ "additionalProperties": false,
142
+ "required": [
143
+ "type",
144
+ "placeholders"
145
+ ],
146
+ "description": "A placeholder group: regions arranged by their own composition inside one cell of the record's composition, the way a content group (a block with blocks) arranges its children. Slide content fills the group's leaf regions in reading order, as part of one flat sequence for the whole record. A group holds body regions and groups only (no title, subtitle or tag, and no placement), and groups nest at most three levels inside a record: this is the first. Groups draw nothing of their own and have no slide path; design.chartPrimary is shorthand for a record whose root holds the chart and one group of the other content.",
147
+ "properties": {
148
+ "type": {
149
+ "const": "group",
150
+ "description": "Marks the entry as a placeholder group."
151
+ },
152
+ "composition": {
153
+ "$ref": "#/$defs/Composition",
154
+ "description": "How the group arranges its regions, with the semantics of a content group's composition: only minFontSize and overflow inherit from the enclosing composition; padding defaults to 0 and gap is a fraction of the group's short edge. Omitted, the group arranges its regions automatically."
155
+ },
156
+ "placeholders": {
157
+ "type": "array",
158
+ "minItems": 1,
159
+ "items": {
160
+ "$ref": "#/$defs/PlaceholderGroupEntry2"
161
+ },
162
+ "description": "The group's regions and nested groups, in reading order."
163
+ }
164
+ }
165
+ },
166
+ "PlaceholderGroupEntry2": {
167
+ "description": "An entry of a first-level group: a region (GroupedPlaceholder) or a second-level group (PlaceholderGroup2).",
168
+ "if": {
169
+ "type": "object",
170
+ "required": [
171
+ "type"
172
+ ],
173
+ "properties": {
174
+ "type": {
175
+ "const": "group"
176
+ }
177
+ }
178
+ },
179
+ "then": {
180
+ "$ref": "#/$defs/PlaceholderGroup2"
181
+ },
182
+ "else": {
183
+ "$ref": "#/$defs/GroupedPlaceholder"
184
+ }
185
+ },
186
+ "PlaceholderGroup2": {
187
+ "type": "object",
188
+ "additionalProperties": false,
189
+ "required": [
190
+ "type",
191
+ "placeholders"
192
+ ],
193
+ "description": "A placeholder group nested in another (the second level). Same fields as PlaceholderGroup.",
194
+ "properties": {
195
+ "type": {
196
+ "const": "group",
197
+ "description": "Marks the entry as a placeholder group."
198
+ },
199
+ "composition": {
200
+ "$ref": "#/$defs/Composition",
201
+ "description": "How the group arranges its regions; see PlaceholderGroup.composition."
202
+ },
203
+ "placeholders": {
204
+ "type": "array",
205
+ "minItems": 1,
206
+ "items": {
207
+ "$ref": "#/$defs/PlaceholderGroupEntry3"
208
+ },
209
+ "description": "The group's regions and nested groups, in reading order."
210
+ }
211
+ }
212
+ },
213
+ "PlaceholderGroupEntry3": {
214
+ "description": "An entry of a second-level group: a region (GroupedPlaceholder) or a third-level group (PlaceholderGroup3).",
215
+ "if": {
216
+ "type": "object",
217
+ "required": [
218
+ "type"
219
+ ],
220
+ "properties": {
221
+ "type": {
222
+ "const": "group"
223
+ }
224
+ }
225
+ },
226
+ "then": {
227
+ "$ref": "#/$defs/PlaceholderGroup3"
228
+ },
229
+ "else": {
230
+ "$ref": "#/$defs/GroupedPlaceholder"
231
+ }
232
+ },
233
+ "PlaceholderGroup3": {
234
+ "type": "object",
235
+ "additionalProperties": false,
236
+ "required": [
237
+ "type",
238
+ "placeholders"
239
+ ],
240
+ "description": "The innermost placeholder group (the third level): it holds regions only, never another group.",
241
+ "properties": {
242
+ "type": {
243
+ "const": "group",
244
+ "description": "Marks the entry as a placeholder group."
245
+ },
246
+ "composition": {
247
+ "$ref": "#/$defs/Composition",
248
+ "description": "How the group arranges its regions; see PlaceholderGroup.composition."
249
+ },
250
+ "placeholders": {
251
+ "type": "array",
252
+ "minItems": 1,
253
+ "items": {
254
+ "$ref": "#/$defs/GroupedPlaceholder"
255
+ },
256
+ "description": "The group's regions, in reading order."
257
+ }
258
+ }
259
+ },
260
+ "GroupedPlaceholder": {
261
+ "type": "object",
262
+ "additionalProperties": false,
263
+ "required": [
264
+ "type"
265
+ ],
266
+ "description": "A region inside a placeholder group: a body content kind only. Headings ('title', 'subtitle', 'tag') stay at the record's top level, and only a top-level image placeholder may carry a placement.",
267
+ "properties": {
268
+ "type": {
269
+ "type": "string",
270
+ "enum": [
271
+ "text",
272
+ "list",
273
+ "image",
274
+ "video",
275
+ "chart",
276
+ "table",
277
+ "code",
278
+ "metric",
279
+ "quote",
280
+ "timeline"
281
+ ],
282
+ "description": "The content kind of the region, from the one OPF content-kind vocabulary (see Placeholder.type)."
283
+ }
284
+ }
285
+ },
119
286
  "Placeholder": {
120
287
  "type": "object",
121
288
  "required": [
@@ -156,7 +323,7 @@
156
323
  },
157
324
  "placement": {
158
325
  "$ref": "#/$defs/ImagePlacement",
159
- "description": "Image placeholders only. Bleeds the slide's image for this region to one slide edge, as an image block's placement does: the n-th image placeholder places the slide's n-th top-level image (Slide.image or an image block in blocks) unless that block sets its own placement. The headings and the other content compose in the rest of the slide."
326
+ "description": "Image placeholders only. Bleeds the slide's image for this region to one slide edge, as an image block's placement does: the n-th image placeholder (counting the image regions of placeholder groups too, in reading order) places the slide's n-th top-level image (Slide.image or an image block in blocks) unless that block sets its own placement. Only a top-level image placeholder may carry a placement; a region inside a placeholder group cannot bleed to a slide edge. The headings and the other content compose in the rest of the slide."
160
327
  }
161
328
  }
162
329
  },
@@ -234,7 +401,7 @@
234
401
  "left",
235
402
  "right"
236
403
  ],
237
- "description": "Where the primary chart sits relative to the other body content. Composition applies it below the slide's and the deck's design.chartPrimary, with the semantics described there."
404
+ "description": "Where the primary chart sits relative to the other body content. Composition applies it below the slide's and the deck's design.chartPrimary, with the semantics described there. It is shorthand for a placeholder group: a record can state the same structure explicitly as a root row or column of the chart and one PlaceholderGroup of the other regions, weighted 3:2."
238
405
  },
239
406
  "imageFit": {
240
407
  "type": "string",
@@ -258,7 +425,7 @@
258
425
  "Composition": {
259
426
  "type": "object",
260
427
  "additionalProperties": false,
261
- "description": "Portable dynamic composition. Slide fields override the resolved layout. Nested groups arrange their children independently, inheriting only minFontSize and overflow. Explicit promoted regions retain their positions.",
428
+ "description": "Portable dynamic composition. Slide fields override the resolved layout. Nested groups (placeholder groups here, content groups in a slide) arrange their children independently, inheriting only minFontSize and overflow. Explicit promoted regions retain their positions.",
262
429
  "properties": {
263
430
  "mode": {
264
431
  "type": "string",
@@ -750,7 +750,7 @@
750
750
  "chartPrimary": {
751
751
  "type": "string",
752
752
  "enum": ["none", "top", "bottom", "left", "right"],
753
- "description": "Where the primary chart sits relative to supporting content. Effective value: slide design, then deck design, then the layout record's design.chartPrimary. When the slide has no promoted regions and no composition.mode of its own, and its root nodes mix at least one chart with other content, the first chart becomes a primary track and the other nodes form one synthetic sub-grid: 'left'/'right' is a two-track row and 'top'/'bottom' a two-track column, weighted 3:2 in favor of the chart; explicit root columns and weights are ignored while it applies. 'none' (the default) keeps the ordinary automatic grid with equal weight."
753
+ "description": "Where the primary chart sits relative to supporting content. Effective value: slide design, then deck design, then the layout record's design.chartPrimary. When the slide has no promoted regions and no composition.mode of its own, and its root nodes mix at least one chart with other content, the first chart becomes a primary track and the other nodes form one synthetic sub-grid: 'left'/'right' is a two-track row and 'top'/'bottom' a two-track column, weighted 3:2 in favor of the chart; explicit root columns and weights are ignored while it applies. 'none' (the default) keeps the ordinary automatic grid with equal weight. It is shorthand for a placeholder group (layout.schema.json PlaceholderGroup): the slide composes exactly as on a layout record whose root composition is that weighted row or column and whose placeholders are the chart and one automatic group of the other content, and while it applies it replaces the layout record's own placeholder groups as well."
754
754
  },
755
755
  "imageFit": {
756
756
  "type": "string",
@@ -1969,12 +1969,12 @@
1969
1969
  "items": {
1970
1970
  "type": "array",
1971
1971
  "items": { "$ref": "#/$defs/ListItem" },
1972
- "description": "Full-slide generic list payload. Presence of this field infers type 'list'. At slide root, multiple content payload kinds with no explicit type, blocks, or regions are accepted as shorthand for layout-agnostic blocks."
1972
+ "description": "Full-slide structured list payload. Presence of this field infers type 'list'. Entries are strings, TextRun[] or objects with `text`, optional `description` (supporting detail under the entry), `level` and `start`. Use `items` when entries share a shape (features, steps, options, risks) or any entry needs a `description`; use `bullets` for plain talking points. Both draw the same marker, nesting and numbering; they differ in the inferred kind and in `description`, which only `items` accepts. At slide root, multiple content payload kinds with no explicit type, blocks, or regions are accepted as shorthand for layout-agnostic blocks, so `items` next to `text` or `bullets` composes as separate blocks side by side."
1973
1973
  },
1974
1974
  "bullets": {
1975
1975
  "type": "array",
1976
1976
  "items": { "$ref": "#/$defs/BulletItem" },
1977
- "description": "Full-slide text-style bullet payload. Presence of this field infers type 'text'."
1977
+ "description": "Full-slide prose bullet payload: short talking points, each standing alone. Presence of this field infers type 'text', so it may sit beside `text` in one payload. Entries are strings, TextRun[] or objects with `text`, `level` and `start`; there is no `description` (use `items` for entries with supporting detail)."
1978
1978
  },
1979
1979
  "numbering": {
1980
1980
  "$ref": "#/$defs/NumberingSpec",
@@ -2244,7 +2244,7 @@
2244
2244
  "items": {
2245
2245
  "type": "array",
2246
2246
  "items": { "$ref": "#/$defs/ListItem" },
2247
- "description": "Generic list payload. Each item is either a plain string, a TextRun[] rich text sequence, or a ListItem object. List nesting uses item.level rather than nested content payloads.",
2247
+ "description": "Structured list payload (type 'list'). Each item is either a plain string, a TextRun[] rich text sequence, or a ListItem object with optional `description`. List nesting uses item.level rather than nested content payloads. Use `items` when entries share a shape or any entry needs a `description`; use `bullets` for plain talking points. Both draw the same marker, nesting and numbering. A block or region holds `items` or `bullets`, never both, and `items` cannot sit beside `text`.",
2248
2248
  "examples": [[
2249
2249
  "Sub-second agent latency",
2250
2250
  ["Drop-in compatible with ", { "text": "OpenAI tool-calling", "bold": true }],
@@ -2257,7 +2257,7 @@
2257
2257
  "bullets": {
2258
2258
  "type": "array",
2259
2259
  "items": { "$ref": "#/$defs/BulletItem" },
2260
- "description": "Text-style bullet payload. Presence of this field infers type 'text'.",
2260
+ "description": "Prose bullet payload: short talking points, each standing alone. Presence of this field infers type 'text', so it may sit beside `text` in one payload. Entries have no `description`; use `items` for entries with supporting detail.",
2261
2261
  "examples": [["Sub-second agent latency", "Drop-in compatible with OpenAI tool-calling", "SOC 2 Type II"]]
2262
2262
  },
2263
2263
  "numbering": {
@@ -3313,6 +3313,11 @@
3313
3313
  "fields": {
3314
3314
  "$ref": "#/$defs/DatasetFields",
3315
3315
  "description": "Dataset tables only: the dataset columns to show, by name and in order. Absent shows every column. An unknown name is a 'dataset-field-unknown' error."
3316
+ },
3317
+ "alt": {
3318
+ "type": "string",
3319
+ "description": "Text alternative for the table: what it shows (the point and the key numbers), not 'a table'. The preview exposes it as the table's accessible name (role group with aria-label; the cells stay readable) and the PowerPoint export writes it as the table frame's alternative text (descr); import reads it back. An empty string hides a purely decorative table, with the same meaning as an empty Asset alt. The alt is a summary read before the cells, which stay readable, so it is most useful for a large or dense table; validate does not require one and does not report a missing one.",
3320
+ "examples": ["North America grew 46% to $18.1M in Q4, ahead of EMEA at 40%."]
3316
3321
  }
3317
3322
  }
3318
3323
  },
@@ -3849,7 +3854,7 @@
3849
3854
  "Composition": {
3850
3855
  "type": "object",
3851
3856
  "additionalProperties": false,
3852
- "description": "Portable dynamic composition. Slide fields override the resolved layout. Nested groups arrange their children independently, inheriting only minFontSize and overflow. Explicit promoted regions retain their positions.",
3857
+ "description": "Portable dynamic composition. Slide fields override the resolved layout. Nested groups (content groups here, placeholder groups in a layout record) arrange their children independently, inheriting only minFontSize and overflow. Explicit promoted regions retain their positions.",
3853
3858
  "properties": {
3854
3859
  "mode": {
3855
3860
  "type": "string",
package/dist/types.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export { P as Presentation } from './presentation-CDKQVkyI.js';
2
- export { C as CatalogKind } from './catalog-refs-BSfGELpt.js';
1
+ export { P as Presentation } from './presentation-COrFuj2g.js';
2
+ export { a as CatalogKind } from './catalog-refs-_anZs-Qz.js';
3
3
  export { SchemaName } from './schemas.js';
4
4
  export { a as Finding, d as FindingCategory, e as FindingFix, f as FindingFocus, b as FindingLocation, F as FindingReport, c as FindingSeverity, g as FindingSuggestion, J as JsonPatchOperation, V as ValidationIssue } from './finding-CT_f_vbD.js';
5
5
  import './json-BFSdESOE.js';
@@ -326,9 +326,9 @@ interface Layout {
326
326
  description?: string;
327
327
  design?: DesignHints;
328
328
  /**
329
- * Ordered regions the layout exposes. This is the single source of truth for what the layout holds: the content kind, the number of body regions and whether it has a title, subtitle or tag are derived from it (layoutContent in @openpresentation/opf), never stored separately. The engine fills 'title', 'subtitle' and 'tag' placeholders from Slide.title, Slide.subtitle and Slide.tag. The other placeholders are content-kind regions that composition uses to size the body and that pickers use to match layouts. Slide content itself lives either in root payload fields or promoted region keys on Slide. Chrome (slide number, footer, date) is not included here; it is owned by Design.header / Design.footer.
329
+ * Ordered regions the layout exposes. This is the single source of truth for what the layout holds: the content kind, the number of body regions and whether it has a title, subtitle or tag are derived from it (layoutContent in @openpresentation/opf, which counts the leaves of placeholder groups), never stored separately. The engine fills 'title', 'subtitle' and 'tag' placeholders from Slide.title, Slide.subtitle and Slide.tag. The other placeholders are content-kind regions that composition uses to size the body and that pickers use to match layouts. An entry may instead be a placeholder group ({ "type": "group", "composition", "placeholders" }) that arranges its own regions inside one cell of this record's composition, so a record can say 'two stacked panels beside a chart' once; groups nest at most three levels. Slide content stays flat: its body payloads fill the leaf regions in reading order (depth first, in array order). Slide content itself lives either in root payload fields, blocks or promoted region keys on Slide. Chrome (slide number, footer, date) is not included here; it is owned by Design.header / Design.footer.
330
330
  */
331
- placeholders?: Placeholder[];
331
+ placeholders?: PlaceholderEntry[];
332
332
  /**
333
333
  * Free-form labels for filtering and search.
334
334
  */
@@ -375,7 +375,7 @@ interface DesignHints {
375
375
  */
376
376
  contentDirection?: ("horizontal" | "vertical");
377
377
  /**
378
- * Where the primary chart sits relative to the other body content. Composition applies it below the slide's and the deck's design.chartPrimary, with the semantics described there.
378
+ * Where the primary chart sits relative to the other body content. Composition applies it below the slide's and the deck's design.chartPrimary, with the semantics described there. It is shorthand for a placeholder group: a record can state the same structure explicitly as a root row or column of the chart and one PlaceholderGroup of the other regions, weighted 3:2.
379
379
  */
380
380
  chartPrimary?: ("none" | "top" | "bottom" | "left" | "right");
381
381
  /**
@@ -388,38 +388,16 @@ interface DesignHints {
388
388
  listBullet?: ("character" | "image");
389
389
  }
390
390
  /**
391
- * A single region inside a slide layout. Title, subtitle, and tag placeholders bind to the corresponding Slide fields; every other placeholder describes the content kind that region holds. The array order in the surrounding 'placeholders' field preserves layout region order.
391
+ * One entry of a layout's placeholders: a region (Placeholder) or, when its type is 'group', a placeholder group (PlaceholderGroup).
392
392
  *
393
393
  * This interface was referenced by `Layout`'s JSON-Schema
394
- * via the `definition` "Placeholder".
394
+ * via the `definition` "PlaceholderEntry".
395
395
  */
396
- interface Placeholder {
397
- /**
398
- * The content kind of the region. This is the one OPF content-kind vocabulary: the same words name a slide's payload fields (text, items, image, video, chart, table, code, metric, quote, timeline). 'title', 'subtitle' and 'tag' are the heading kinds and bind to Slide.title, Slide.subtitle and Slide.tag. 'text' holds text and bullets; 'list' holds items. 'image' is filled by an image payload and 'video' by a video payload. 'metric', 'quote', 'timeline', 'chart', 'table' and 'code' are filled by the payload of the same name; a metric region shows the metric payload with its optional label, description, unit, delta, trend and sentiment.
399
- */
400
- type: ("title" | "subtitle" | "tag" | "text" | "list" | "image" | "video" | "chart" | "table" | "code" | "metric" | "quote" | "timeline");
401
- placement?: ImagePlacement;
396
+ interface PlaceholderEntry {
402
397
  [k: string]: unknown;
403
398
  }
404
399
  /**
405
- * Image placeholders only. Bleeds the slide's image for this region to one slide edge, as an image block's placement does: the n-th image placeholder places the slide's n-th top-level image (Slide.image or an image block in blocks) unless that block sets its own placement. The headings and the other content compose in the rest of the slide.
406
- */
407
- interface ImagePlacement {
408
- /**
409
- * The slide edge the image bleeds to. In a right-to-left deck 'left' is the start side, drawn at the right.
410
- */
411
- edge: ("left" | "right" | "top" | "bottom");
412
- /**
413
- * Share of the slide width (left, right) or height (top, bottom) given to the band. Default 0.5.
414
- */
415
- size?: number;
416
- /**
417
- * Draw the frame inside the slide padding on every side of the band instead of edge to edge. Default false.
418
- */
419
- inset?: boolean;
420
- }
421
- /**
422
- * Portable dynamic composition. Slide fields override the resolved layout. Nested groups arrange their children independently, inheriting only minFontSize and overflow. Explicit promoted regions retain their positions.
400
+ * Portable dynamic composition. Slide fields override the resolved layout. Nested groups (placeholder groups here, content groups in a slide) arrange their children independently, inheriting only minFontSize and overflow. Explicit promoted regions retain their positions.
423
401
  *
424
402
  * This interface was referenced by `Layout`'s JSON-Schema
425
403
  * via the `definition` "Composition".
@@ -1,5 +1,5 @@
1
- import { a as Catalog } from './catalog-refs-BSfGELpt.js';
2
- import { T as TextMeasurement } from './composition-D2tghM82.js';
1
+ import { C as Catalog } from './catalog-refs-_anZs-Qz.js';
2
+ import { T as TextMeasurement } from './composition-D4ADF5c-.js';
3
3
  import { c as FindingSeverity, F as FindingReport } from './finding-CT_f_vbD.js';
4
4
  import { J as JsonPrimitive } from './json-BFSdESOE.js';
5
5
 
@@ -1,12 +1,12 @@
1
- import { a as CatalogRecordKind } from './catalog-schemas-CinPh5WA.js';
1
+ import { a as CatalogRecordKind } from './catalog-schemas-BZCjgAxu.js';
2
2
  import { a as Finding } from './finding-CT_f_vbD.js';
3
- import { P as Presentation } from './presentation-CDKQVkyI.js';
4
- import { i as ValidationThresholds, h as ValidationRuleInfo, a as ValidationReport, V as ValidateOptions } from './validation-types-BOcY9GTs.js';
5
- export { C as Contract, d as ValidateFonts, e as ValidationCategory, f as ValidationChecks, g as ValidationRuleCost, z as validationCategories } from './validation-types-BOcY9GTs.js';
6
- import './catalog-refs-BSfGELpt.js';
3
+ import { P as Presentation } from './presentation-COrFuj2g.js';
4
+ import { i as ValidationThresholds, h as ValidationRuleInfo, a as ValidationReport, V as ValidateOptions } from './validation-types-HxIgJfKx.js';
5
+ export { C as Contract, d as ValidateFonts, e as ValidationCategory, f as ValidationChecks, g as ValidationRuleCost, z as validationCategories } from './validation-types-HxIgJfKx.js';
6
+ import './catalog-refs-_anZs-Qz.js';
7
7
  import './schemas.js';
8
8
  import './json-BFSdESOE.js';
9
- import './composition-D2tghM82.js';
9
+ import './composition-D4ADF5c-.js';
10
10
  import './chart-data-BnNqgnC-.js';
11
11
 
12
12
  /**
package/dist/validator.js CHANGED
@@ -1,5 +1,5 @@
1
- export { DEFAULT_CHART_PALETTE, DEFAULT_VALIDATION_THRESHOLDS, OPFValidationError, assertValid, assertValidCatalogRecord, findValidationRule, validate, validateCatalogRecord, validationCategories, validationRules } from './chunk-QDI75P2M.js';
2
- export { promotedRegionKeys } from './chunk-O744SXXA.js';
1
+ export { DEFAULT_CHART_PALETTE, DEFAULT_VALIDATION_THRESHOLDS, OPFValidationError, assertValid, assertValidCatalogRecord, findValidationRule, validate, validateCatalogRecord, validationCategories, validationRules } from './chunk-PX5AWL7Y.js';
2
+ export { promotedRegionKeys } from './chunk-5PDN7BN6.js';
3
3
  import './chunk-TRDXRRQK.js';
4
4
  import './chunk-SPFV27O5.js';
5
- import './chunk-2CJPC4HI.js';
5
+ import './chunk-WEDGVC5W.js';
package/dist/yaml.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { a as Catalog } from './catalog-refs-BSfGELpt.js';
2
- import { P as Presentation } from './presentation-CDKQVkyI.js';
3
- import { V as ValidateOptions, a as ValidationReport } from './validation-types-BOcY9GTs.js';
1
+ import { C as Catalog } from './catalog-refs-_anZs-Qz.js';
2
+ import { P as Presentation } from './presentation-COrFuj2g.js';
3
+ import { V as ValidateOptions, a as ValidationReport } from './validation-types-HxIgJfKx.js';
4
4
  import { a as Finding, b as FindingLocation } from './finding-CT_f_vbD.js';
5
- import './composition-D2tghM82.js';
5
+ import './composition-D4ADF5c-.js';
6
6
  import './chart-data-BnNqgnC-.js';
7
7
  import './json-BFSdESOE.js';
8
8