@agent-native/core-corpus 0.213.1 → 0.216.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 (1108) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/actions/references/action-fields.md +1 -1
  3. package/corpus/templates/analytics/CHANGELOG.md +1 -0
  4. package/corpus/templates/analytics/changelog/2026-10-21-session-replay-quotas-count-the-compressed-size-analytics-st.md +6 -0
  5. package/corpus/templates/analytics/server/lib/session-replay.ts +40 -9
  6. package/corpus/templates/assets/.agents/skills/actions/references/action-fields.md +1 -1
  7. package/corpus/templates/brain/.agents/skills/actions/references/action-fields.md +1 -1
  8. package/corpus/templates/calendar/.agents/skills/actions/references/action-fields.md +1 -1
  9. package/corpus/templates/chat/.agents/skills/actions/references/action-fields.md +1 -1
  10. package/corpus/templates/clips/.agents/skills/actions/references/action-fields.md +1 -1
  11. package/corpus/templates/community/qr/package.json +1 -1
  12. package/corpus/templates/content/.agents/skills/actions/references/action-fields.md +1 -1
  13. package/corpus/templates/content/.agents/skills/content-product-development/references/verification.md +36 -0
  14. package/corpus/templates/content/.agents/skills/document-editing/SKILL.md +10 -0
  15. package/corpus/templates/content/.agents/skills/document-editing/references/databases.md +26 -1
  16. package/corpus/templates/content/.agents/skills/notion-integration/SKILL.md +4 -2
  17. package/corpus/templates/content/CHANGELOG.md +51 -0
  18. package/corpus/templates/content/acceptance/_writers.ts +604 -0
  19. package/corpus/templates/content/acceptance/generate-action-registry.ts +10 -0
  20. package/corpus/templates/content/acceptance/golden/gate-off-stored-bytes/create-document.json +75 -0
  21. package/corpus/templates/content/acceptance/golden/gate-off-stored-bytes/duplicate-page.json +75 -0
  22. package/corpus/templates/content/acceptance/golden/gate-off-stored-bytes/edit-document-find-and-replace-without-a-revision.json +75 -0
  23. package/corpus/templates/content/acceptance/golden/gate-off-stored-bytes/edit-document-find-and-replace.json +75 -0
  24. package/corpus/templates/content/acceptance/golden/gate-off-stored-bytes/edit-document-initializecontent.json +75 -0
  25. package/corpus/templates/content/acceptance/golden/gate-off-stored-bytes/import-content.json +75 -0
  26. package/corpus/templates/content/acceptance/golden/gate-off-stored-bytes/local-files-import-content-source-existing-page.json +75 -0
  27. package/corpus/templates/content/acceptance/golden/gate-off-stored-bytes/local-files-import-content-source-new-page.json +75 -0
  28. package/corpus/templates/content/acceptance/golden/gate-off-stored-bytes/local-files-sync-local-folder-source-changed-file.json +75 -0
  29. package/corpus/templates/content/acceptance/golden/gate-off-stored-bytes/local-files-sync-local-folder-source-new-file.json +75 -0
  30. package/corpus/templates/content/acceptance/golden/gate-off-stored-bytes/restore-document-version.json +75 -0
  31. package/corpus/templates/content/acceptance/golden/gate-off-stored-bytes/set-document-property-primary-blocks-field.json +75 -0
  32. package/corpus/templates/content/acceptance/golden/gate-off-stored-bytes/set-image-alt-text.json +75 -0
  33. package/corpus/templates/content/acceptance/golden/gate-off-stored-bytes/undo-content-import.json +75 -0
  34. package/corpus/templates/content/acceptance/golden/gate-off-stored-bytes/update-document-browser-full-rewrite.json +75 -0
  35. package/corpus/templates/content/acceptance/known-loss.ts +69 -0
  36. package/corpus/templates/content/acceptance/round-trip-corpus.ts +1397 -0
  37. package/corpus/templates/content/actions/_blocks-field-identity.ts +35 -1
  38. package/corpus/templates/content/actions/_content-database-lifecycle.ts +11 -11
  39. package/corpus/templates/content/actions/_content-database-personal-view.ts +2 -0
  40. package/corpus/templates/content/actions/_content-favorites.ts +37 -0
  41. package/corpus/templates/content/actions/_database-membership-lock.ts +39 -8
  42. package/corpus/templates/content/actions/_database-navigation.ts +19 -21
  43. package/corpus/templates/content/actions/_database-row-batch.ts +41 -18
  44. package/corpus/templates/content/actions/_database-row-mutation.ts +17 -28
  45. package/corpus/templates/content/actions/_database-source-utils.ts +18 -1
  46. package/corpus/templates/content/actions/_database-utils.ts +3 -0
  47. package/corpus/templates/content/actions/_database-view-setup.ts +321 -11
  48. package/corpus/templates/content/actions/_document-edit-mutation.ts +33 -32
  49. package/corpus/templates/content/actions/_document-flush.ts +593 -171
  50. package/corpus/templates/content/actions/_document-save-locks.ts +54 -0
  51. package/corpus/templates/content/actions/_document-save-row.ts +133 -0
  52. package/corpus/templates/content/actions/_github-source.ts +18 -8
  53. package/corpus/templates/content/actions/_move-page-to-space.ts +189 -25
  54. package/corpus/templates/content/actions/_nfm-syntax.ts +2 -0
  55. package/corpus/templates/content/actions/_property-utils.ts +3 -0
  56. package/corpus/templates/content/actions/_row-lock-order.ts +115 -0
  57. package/corpus/templates/content/actions/create-content-database.ts +11 -0
  58. package/corpus/templates/content/actions/create-document.ts +13 -1
  59. package/corpus/templates/content/actions/delete-content-database.ts +17 -14
  60. package/corpus/templates/content/actions/delete-document-property.ts +5 -0
  61. package/corpus/templates/content/actions/delete-document.ts +270 -97
  62. package/corpus/templates/content/actions/edit-document.ts +18 -5
  63. package/corpus/templates/content/actions/export-document.ts +3 -0
  64. package/corpus/templates/content/actions/get-blocks-field-word-count.ts +22 -5
  65. package/corpus/templates/content/actions/import-content-source.ts +170 -54
  66. package/corpus/templates/content/actions/move-document.ts +191 -73
  67. package/corpus/templates/content/actions/pull-document.ts +8 -2
  68. package/corpus/templates/content/actions/remove-database-items.ts +23 -4
  69. package/corpus/templates/content/actions/restore-content-database.ts +76 -55
  70. package/corpus/templates/content/actions/restore-document-version.ts +19 -35
  71. package/corpus/templates/content/actions/restore-document.ts +65 -53
  72. package/corpus/templates/content/actions/rollback-created-slash-document.ts +11 -16
  73. package/corpus/templates/content/actions/set-document-property.ts +15 -1
  74. package/corpus/templates/content/actions/share-local-file-document.ts +18 -14
  75. package/corpus/templates/content/actions/suggest-document-edit.ts +2 -3
  76. package/corpus/templates/content/actions/sync-local-folder-source.ts +35 -1
  77. package/corpus/templates/content/actions/undo-content-import.ts +16 -12
  78. package/corpus/templates/content/actions/update-content-database-view.ts +20 -2
  79. package/corpus/templates/content/actions/update-document.ts +19 -14
  80. package/corpus/templates/content/actions/view-screen.ts +12 -0
  81. package/corpus/templates/content/app/components/editor/BubbleToolbar.tsx +1 -6
  82. package/corpus/templates/content/app/components/editor/CommentsSidebar.tsx +49 -3
  83. package/corpus/templates/content/app/components/editor/ContentImportDialog.tsx +2 -0
  84. package/corpus/templates/content/app/components/editor/DocumentBlockFields.tsx +53 -11
  85. package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +608 -353
  86. package/corpus/templates/content/app/components/editor/StaticDocumentBody.tsx +765 -0
  87. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +233 -80
  88. package/corpus/templates/content/app/components/editor/blockFieldSaveController.ts +32 -3
  89. package/corpus/templates/content/app/components/editor/blockFieldSaveRegistry.ts +88 -23
  90. package/corpus/templates/content/app/components/editor/comment-anchors.ts +19 -0
  91. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +296 -87
  92. package/corpus/templates/content/app/components/editor/database/ListItemLayout.tsx +410 -0
  93. package/corpus/templates/content/app/components/editor/database/ListItemRow.tsx +426 -0
  94. package/corpus/templates/content/app/components/editor/database/ListView.tsx +136 -18
  95. package/corpus/templates/content/app/components/editor/database/navigation-state.ts +3 -0
  96. package/corpus/templates/content/app/components/editor/database/settings.tsx +3 -3
  97. package/corpus/templates/content/app/components/editor/database/view-config.ts +4 -0
  98. package/corpus/templates/content/app/components/editor/document-flush-participant.ts +253 -0
  99. package/corpus/templates/content/app/components/editor/editor-transaction-meta.ts +28 -0
  100. package/corpus/templates/content/app/components/editor/extensions/AudioBlock.tsx +2 -1
  101. package/corpus/templates/content/app/components/editor/extensions/ImageBlock.tsx +27 -6
  102. package/corpus/templates/content/app/components/editor/extensions/LocalMdxComponentNode.tsx +0 -1
  103. package/corpus/templates/content/app/components/editor/extensions/NotionExtensions.tsx +4 -4
  104. package/corpus/templates/content/app/components/editor/extensions/SuggestionHighlight.ts +24 -2
  105. package/corpus/templates/content/app/components/editor/extensions/VideoBlock.tsx +25 -6
  106. package/corpus/templates/content/app/components/editor/pending-document-persistence.ts +59 -1
  107. package/corpus/templates/content/app/components/editor/stored-body-images.ts +27 -0
  108. package/corpus/templates/content/app/components/editor/suggestions/presentation-rebase.ts +17 -0
  109. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +11 -4
  110. package/corpus/templates/content/app/components/trash/TrashBrowser.tsx +4 -1
  111. package/corpus/templates/content/app/global.css +34 -0
  112. package/corpus/templates/content/app/hooks/use-content-trash.ts +8 -0
  113. package/corpus/templates/content/app/i18n-data.ts +32 -0
  114. package/corpus/templates/content/app/import-messages.ts +25 -0
  115. package/corpus/templates/content/app/trash-messages.ts +16 -0
  116. package/corpus/templates/content/changelog/2026-10-16-a-page-open-in-a-tab-that-shows-it-s-in-the-trash-reopens-wi.md +6 -0
  117. package/corpus/templates/content/changelog/2026-10-16-a-page-restored-from-trash-returns-to-its-place-in-its-colle.md +6 -0
  118. package/corpus/templates/content/changelog/2026-10-16-agent-written-markdown-keeps-nested-lists-indented-with-spac.md +6 -0
  119. package/corpus/templates/content/changelog/2026-10-16-opening-a-page-you-can-edit-no-longer-rebuilds-its-editor-on.md +6 -0
  120. package/corpus/templates/content/changelog/2026-10-16-pages-moved-or-imported-at-the-same-time-can-no-longer-end-u.md +6 -0
  121. package/corpus/templates/content/changelog/2026-10-16-re-importing-a-markdown-export-of-a-page-no-longer-reports-t.md +6 -0
  122. package/corpus/templates/content/changelog/2026-10-16-saving-a-page-or-restoring-one-of-its-versions-no-longer-fai.md +6 -0
  123. package/corpus/templates/content/changelog/2026-10-17-agents-reading-a-page-you-have-open-no-longer-wait-or-fail-w.md +6 -0
  124. package/corpus/templates/content/changelog/2026-10-19-fresh-document-reads-require-confirmation-from-every-open-ed.md +6 -0
  125. package/corpus/templates/content/changelog/2026-10-19-list-rows-can-be-customized.md +6 -0
  126. package/corpus/templates/content/changelog/2026-10-19-list-views-fit-phone-screens.md +6 -0
  127. package/corpus/templates/content/changelog/2026-10-20-html-table-cells-preserve-a-trailing-backslash-when-opening-.md +6 -0
  128. package/corpus/templates/content/changelog/2026-10-20-preserve-empty-paragraph-colors-and-refuse-unsupported-inlin.md +6 -0
  129. package/corpus/templates/content/changelog/2026-10-20-the-advanced-filter-and-each-filter-group-inside-it-have-the.md +6 -0
  130. package/corpus/templates/content/changelog/2026-10-21-blocks-fields-keep-unconfirmed-saves-visible-and-agent-reads.md +6 -0
  131. package/corpus/templates/content/changelog/2026-10-21-preserve-compact-table-row-groups-and-report-invalid-block-colors.md +6 -0
  132. package/corpus/templates/content/changelog/2026-10-21-suggested-edits-show-an-agent-s-whole-reason-open-a-group-to.md +6 -0
  133. package/corpus/templates/content/changelog/2026-10-21-suggestions-keep-refusing-unmatched-emphasis-in-stored-markd.md +6 -0
  134. package/corpus/templates/content/changelog/2026-10-22-accept-remaining-and-reject-remaining-show-the-result-for-ev.md +6 -0
  135. package/corpus/templates/content/changelog/2026-10-22-accepting-a-group-of-suggested-edits-saves-faster-and-adds-o.md +6 -0
  136. package/corpus/templates/content/changelog/2026-10-22-agents-read-saved-page-text-after-failed-icon-change.md +6 -0
  137. package/corpus/templates/content/changelog/2026-10-22-changes-made-from-a-menu-or-popover-such-as-an-image-s-alt-t.md +6 -0
  138. package/corpus/templates/content/changelog/2026-10-22-text-an-agent-writes-inside-a-callout-column-or-synced-block.md +6 -0
  139. package/corpus/templates/content/e2e/auth-files.ts +28 -0
  140. package/corpus/templates/content/e2e/convergence-summary.ts +84 -29
  141. package/corpus/templates/content/e2e/gate-arm.ts +15 -0
  142. package/corpus/templates/content/e2e/global-setup.ts +43 -75
  143. package/corpus/templates/content/e2e/global-teardown.ts +34 -0
  144. package/corpus/templates/content/e2e/helpers.ts +598 -92
  145. package/corpus/templates/content/e2e/live-body-gate.ts +188 -0
  146. package/corpus/templates/content/e2e/playwright.config.ts +12 -3
  147. package/corpus/templates/content/e2e/server-identity.ts +47 -0
  148. package/corpus/templates/content/e2e/stored-form/collab-blocks.ts +123 -0
  149. package/corpus/templates/content/package.json +1 -1
  150. package/corpus/templates/content/scripts/_stored-form-census-kinds.ts +30 -2
  151. package/corpus/templates/content/scripts/historical-icon-apply.ts +9 -1
  152. package/corpus/templates/content/scripts/trace-startup.mjs +460 -133
  153. package/corpus/templates/content/server/db/exec.ts +58 -0
  154. package/corpus/templates/content/server/db/schema.ts +1 -0
  155. package/corpus/templates/content/server/lib/content-trash-purge.ts +208 -144
  156. package/corpus/templates/content/server/lib/document-metadata-updated-at.ts +43 -1
  157. package/corpus/templates/content/server/lib/document-revision.ts +23 -0
  158. package/corpus/templates/content/server/lib/live-body-writer.ts +199 -0
  159. package/corpus/templates/content/server/lib/notion-sync.ts +63 -29
  160. package/corpus/templates/content/server/lib/notion.ts +5 -5
  161. package/corpus/templates/content/server/lib/suggested-edits.ts +357 -230
  162. package/corpus/templates/content/server/plugins/db.ts +5 -0
  163. package/corpus/templates/content/server/routes/api/documents/[id]/move.patch.ts +50 -168
  164. package/corpus/templates/content/shared/api.ts +20 -0
  165. package/corpus/templates/content/shared/blocks-fields-manifest.ts +106 -0
  166. package/corpus/templates/content/shared/database-item-layout.ts +591 -0
  167. package/corpus/templates/content/shared/database-query.ts +192 -30
  168. package/corpus/templates/content/shared/document-export.ts +12 -14
  169. package/corpus/templates/content/shared/document-flush-protocol.ts +88 -0
  170. package/corpus/templates/content/shared/editor-save-state.ts +97 -0
  171. package/corpus/templates/content/shared/feature-flags.ts +10 -0
  172. package/corpus/templates/content/shared/import/markdown.ts +91 -7
  173. package/corpus/templates/content/shared/import/types.ts +2 -0
  174. package/corpus/templates/content/shared/inline-math.ts +6 -4
  175. package/corpus/templates/content/shared/nfm-fidelity.ts +247 -0
  176. package/corpus/templates/content/shared/nfm.ts +1933 -340
  177. package/corpus/templates/content/shared/suggestion-diff.ts +13 -0
  178. package/corpus/templates/content/shared/suggestion-formatting.ts +143 -20
  179. package/corpus/templates/content/shared/suggestion-text.ts +39 -0
  180. package/corpus/templates/content/vitest.config.ts +10 -0
  181. package/corpus/templates/crm/.agents/skills/actions/references/action-fields.md +1 -1
  182. package/corpus/templates/design/.agents/skills/actions/references/action-fields.md +1 -1
  183. package/corpus/templates/design/.agents/skills/native-effects/SKILL.md +9 -2
  184. package/corpus/templates/design/.generated/bridge/shader-fill-preview.generated.ts +3 -249
  185. package/corpus/templates/design/.generated/bridge/shader-runtime.generated.ts +5 -88
  186. package/corpus/templates/design/AGENTS.md +1 -3
  187. package/corpus/templates/design/CHANGELOG.md +32 -0
  188. package/corpus/templates/design/CODE_NATIVE_DESIGN_STUDIO_IMPLEMENTATION_PLAN.md +1 -6
  189. package/corpus/templates/design/DESIGN-STUDIO-PLAN.md +5 -7
  190. package/corpus/templates/design/actions/_native-local-export-server.ts +44 -31
  191. package/corpus/templates/design/actions/_native-render-contexts.ts +76 -21
  192. package/corpus/templates/design/actions/claim-native-local-export.ts +5 -0
  193. package/corpus/templates/design/actions/finish-native-local-export.ts +13 -2
  194. package/corpus/templates/design/actions/get-native-shader-approvals.ts +35 -0
  195. package/corpus/templates/design/actions/get-shader.ts +134 -219
  196. package/corpus/templates/design/actions/list-design-extensions.ts +3 -58
  197. package/corpus/templates/design/actions/request-native-local-export.ts +32 -6
  198. package/corpus/templates/design/actions/run-design-extension-action.ts +0 -29
  199. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +131 -108
  200. package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +0 -218
  201. package/corpus/templates/design/app/components/design/DesignThumbnail.tsx +59 -3
  202. package/corpus/templates/design/app/components/design/EditPanel.tsx +35 -47
  203. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +242 -62
  204. package/corpus/templates/design/app/components/design/NativePreviewErrorBoundary.tsx +53 -0
  205. package/corpus/templates/design/app/components/design/bridge/codegen.ts +18 -3
  206. package/corpus/templates/design/app/components/design/bridge/native-composition-clock.ts +5 -4
  207. package/corpus/templates/design/app/components/design/bridge/native-dom.ts +37 -0
  208. package/corpus/templates/design/app/components/design/bridge/native-intrinsic-image.ts +2 -1
  209. package/corpus/templates/design/app/components/design/bridge/native-mesh-grid.ts +90 -0
  210. package/corpus/templates/design/app/components/design/bridge/native-opaque-public-asset.ts +363 -0
  211. package/corpus/templates/design/app/components/design/bridge/native-opaque-worker-lease.ts +179 -0
  212. package/corpus/templates/design/app/components/design/bridge/native-preview-geometry.ts +132 -7
  213. package/corpus/templates/design/app/components/design/bridge/native-preview-policy.ts +4 -0
  214. package/corpus/templates/design/app/components/design/bridge/native-preview-viewport-transport.ts +378 -0
  215. package/corpus/templates/design/app/components/design/bridge/native-scene-body-transform.ts +62 -0
  216. package/corpus/templates/design/app/components/design/bridge/native-scene-presentation-element.ts +10 -0
  217. package/corpus/templates/design/app/components/design/bridge/native-shader-runtime.bridge.ts +646 -167
  218. package/corpus/templates/design/app/components/design/bridge/native-source-provider.ts +246 -192
  219. package/corpus/templates/design/app/components/design/bridge/native-stateful-resource.ts +2 -2
  220. package/corpus/templates/design/app/components/design/bridge/native-stateless-compute.ts +5 -2
  221. package/corpus/templates/design/app/components/design/bridge/native-svg-source.ts +11 -1
  222. package/corpus/templates/design/app/components/design/bridge/native-worker-broker.ts +6 -0
  223. package/corpus/templates/design/app/components/design/bridge/native-worker-entry.ts +761 -303
  224. package/corpus/templates/design/app/components/design/bridge/native-worker-fill.ts +16 -6
  225. package/corpus/templates/design/app/components/design/bridge/native-worker-gpu.ts +854 -91
  226. package/corpus/templates/design/app/components/design/bridge/native-worker-host.ts +15 -1
  227. package/corpus/templates/design/app/components/design/bridge/native-worker-input-assets.ts +200 -0
  228. package/corpus/templates/design/app/components/design/bridge/native-worker-protocol.ts +40 -1
  229. package/corpus/templates/design/app/components/design/bridge/native-worker-scene-host.ts +425 -126
  230. package/corpus/templates/design/app/components/design/bridge/native-worker-source-snapshot.ts +21 -0
  231. package/corpus/templates/design/app/components/design/bridge/shader-fill-preview.bridge.ts +5 -371
  232. package/corpus/templates/design/app/components/design/bridge/shader-runtime.bridge.ts +4 -146
  233. package/corpus/templates/design/app/components/design/design-canvas/interact-document.ts +5 -9
  234. package/corpus/templates/design/app/components/design/design-canvas/native-preview-surface.ts +150 -0
  235. package/corpus/templates/design/app/components/design/design-canvas/native-public-asset-preview.ts +409 -0
  236. package/corpus/templates/design/app/components/design/design-canvas/native-public-worker-preview.ts +1086 -0
  237. package/corpus/templates/design/app/components/design/design-canvas/private-replay-screenshot-preview.ts +2 -2
  238. package/corpus/templates/design/app/components/design/edit-panel/effects-properties.tsx +15 -26
  239. package/corpus/templates/design/app/components/design/edit-panel/fill-properties.tsx +74 -67
  240. package/corpus/templates/design/app/components/design/edit-panel/panel-primitives.tsx +7 -19
  241. package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +39 -30
  242. package/corpus/templates/design/app/components/design/inspector/GradientEditor.tsx +4 -0
  243. package/corpus/templates/design/app/components/design/inspector/NativeShaderColorControls.tsx +3 -7
  244. package/corpus/templates/design/app/components/design/inspector/NativeShaderPaintControls.tsx +12 -5
  245. package/corpus/templates/design/app/components/design/inspector/NativeShaderPanel.tsx +705 -190
  246. package/corpus/templates/design/app/components/design/inspector/fill-field-reading.ts +1 -2
  247. package/corpus/templates/design/app/components/design/inspector/index.ts +0 -6
  248. package/corpus/templates/design/app/components/design/inspector/native-catalog-display.ts +26 -5
  249. package/corpus/templates/design/app/components/design/inspector/native-shader-catalog-fixture.ts +42 -0
  250. package/corpus/templates/design/app/components/design/inspector/native-shader-catalog-preview.ts +51 -33
  251. package/corpus/templates/design/app/components/design/inspector/native-shader-paint.ts +1 -0
  252. package/corpus/templates/design/app/components/design/inspector/native-shader-property-draft.ts +89 -23
  253. package/corpus/templates/design/app/components/design/inspector/saved-glsl-shader.tsx +243 -0
  254. package/corpus/templates/design/app/components/design/multi-screen/board-surface-html.ts +54 -5
  255. package/corpus/templates/design/app/components/design/shader-source-coordination.ts +66 -0
  256. package/corpus/templates/design/app/components/design/use-native-shader-approvals.ts +36 -8
  257. package/corpus/templates/design/app/components/templates/TemplatePreview.tsx +60 -3
  258. package/corpus/templates/design/app/i18n/en-US.ts +78 -2
  259. package/corpus/templates/design/app/pages/Present.tsx +36 -1
  260. package/corpus/templates/design/app/pages/design-editor/commands/apply-file-content-update.ts +1 -1
  261. package/corpus/templates/design/app/pages/design-editor/commands/apply-local-content-update.ts +1 -1
  262. package/corpus/templates/design/app/pages/design-editor/commands/commit-visual-styles.ts +2 -3
  263. package/corpus/templates/design/app/pages/design-editor/commands/cross-screen-element-drop.ts +1 -1
  264. package/corpus/templates/design/app/pages/design-editor/commands/layer-move-to-screen.ts +1 -1
  265. package/corpus/templates/design/app/pages/design-editor/commands/paste-selection.ts +1 -1
  266. package/corpus/templates/design/app/pages/design-editor/commands/paste-svg-layer.ts +1 -1
  267. package/corpus/templates/design/app/pages/design-editor/commands/prepare-content-history-replay.ts +1 -1
  268. package/corpus/templates/design/app/pages/design-editor/commands/redo.ts +1 -1
  269. package/corpus/templates/design/app/pages/design-editor/commands/render-png-blob.ts +84 -41
  270. package/corpus/templates/design/app/pages/design-editor/commands/shader-source-edit.ts +1 -1
  271. package/corpus/templates/design/app/pages/design-editor/commands/undo.ts +1 -1
  272. package/corpus/templates/design/app/pages/design-editor/design-editor-view.tsx +0 -2
  273. package/corpus/templates/design/app/pages/design-editor/domains/use-editor-content-and-components.ts +4 -33
  274. package/corpus/templates/design/app/pages/design-editor/domains/use-editor-export-and-handoff.ts +2 -2
  275. package/corpus/templates/design/app/pages/design-editor/domains/use-editor-history.ts +0 -11
  276. package/corpus/templates/design/app/pages/design-editor/domains/use-editor-layer-models.ts +2 -55
  277. package/corpus/templates/design/app/pages/design-editor/domains/use-editor-screen-rendering.tsx +0 -3
  278. package/corpus/templates/design/app/pages/design-editor/domains/use-editor-selection-and-styles.ts +0 -24
  279. package/corpus/templates/design/app/pages/design-editor/text-edit-utils.ts +0 -16
  280. package/corpus/templates/design/app/pages/design-editor/use-native-local-export-requests.ts +70 -11
  281. package/corpus/templates/design/app/pages/design-editor/view/single-screen-canvas.tsx +0 -2
  282. package/corpus/templates/design/changelog/2026-10-20-folded-mesh-adds-an-animated-sculpted-fill-with-editable-col.md +6 -0
  283. package/corpus/templates/design/changelog/2026-10-20-read-only-design-views-render-native-shader-previews-in-nest.md +6 -0
  284. package/corpus/templates/design/changelog/2026-10-20-selected-screens-with-shader-effects-can-be-exported-togethe.md +6 -0
  285. package/corpus/templates/design/changelog/2026-10-20-shader-previews-reuse-validated-scene-data-while-panning-inc.md +6 -0
  286. package/corpus/templates/design/changelog/2026-10-20-shader-previews-stay-aligned-while-you-zoom.md +6 -0
  287. package/corpus/templates/design/changelog/2026-10-20-signed-out-sessions-no-longer-watch-for-private-png-export-r.md +6 -0
  288. package/corpus/templates/design/changelog/2026-10-21-effect-thumbnails-show-richer-previews.md +6 -0
  289. package/corpus/templates/design/changelog/2026-10-21-native-effects-render-across-previews.md +6 -0
  290. package/corpus/templates/design/changelog/2026-10-21-native-shader-previews-use-less-gpu-memory-when-many-mesh-ef.md +6 -0
  291. package/corpus/templates/design/changelog/2026-10-21-opening-design-no-longer-shows-png-export-errors-when-no-exp.md +6 -0
  292. package/corpus/templates/design/changelog/2026-10-21-pulsing-border-controls-grouped.md +6 -0
  293. package/corpus/templates/design/changelog/2026-10-21-pulsing-border-follows-element-outlines.md +6 -0
  294. package/corpus/templates/design/changelog/2026-10-21-remove-obsolete-shader-fills.md +6 -0
  295. package/corpus/templates/design/changelog/2026-10-21-shader-previews-recover-from-temporary-gpu-and-image-failure.md +6 -0
  296. package/corpus/templates/design/changelog/2026-10-22-shader-fills-and-effects-render-correctly-on-canvas-elements.md +6 -0
  297. package/corpus/templates/design/package.json +0 -1
  298. package/corpus/templates/design/playwright.config.ts +1 -1
  299. package/corpus/templates/design/scripts/runtime-budget-zoom.ts +9 -21
  300. package/corpus/templates/design/scripts/runtime-budget.ts +10 -24
  301. package/corpus/templates/design/server/plugins/agent-chat.ts +0 -2
  302. package/corpus/templates/design/shared/effect-graph.ts +46 -1
  303. package/corpus/templates/design/shared/generation-output-receipt.ts +0 -1
  304. package/corpus/templates/design/shared/native-effect-animation-capability.ts +6 -0
  305. package/corpus/templates/design/shared/native-effect-folded-mesh-v1.ts +268 -0
  306. package/corpus/templates/design/shared/native-effect-folded-mesh-v2.ts +310 -0
  307. package/corpus/templates/design/shared/native-effect-folded-mesh.ts +489 -0
  308. package/corpus/templates/design/shared/native-effect-gallery-additions.ts +2 -2
  309. package/corpus/templates/design/shared/native-effect-paint.ts +8 -0
  310. package/corpus/templates/design/shared/native-effect-parameter-constraints.ts +8 -1
  311. package/corpus/templates/design/shared/native-effect-presets.ts +18 -1
  312. package/corpus/templates/design/shared/native-effect-property-presentation.ts +81 -0
  313. package/corpus/templates/design/shared/native-effect-pulsing-border-v3.ts +281 -0
  314. package/corpus/templates/design/shared/native-effect-pulsing-border-v4.ts +284 -0
  315. package/corpus/templates/design/shared/native-effect-pulsing-border.ts +300 -0
  316. package/corpus/templates/design/shared/native-effect-trust.ts +6 -0
  317. package/corpus/templates/design/shared/native-effect-wgsl.ts +12 -0
  318. package/corpus/templates/design/shared/native-effects.ts +528 -15
  319. package/corpus/templates/design/shared/native-input-resources.ts +36 -0
  320. package/corpus/templates/design/shared/native-local-export.ts +14 -0
  321. package/corpus/templates/design/shared/native-parameter-animation.ts +1 -0
  322. package/corpus/templates/design/shared/native-pointer-input.ts +9 -11
  323. package/corpus/templates/design/shared/shader-fills.ts +0 -513
  324. package/corpus/templates/design/vitest.setup.ts +7 -1
  325. package/corpus/templates/dispatch/.agents/skills/actions/references/action-fields.md +1 -1
  326. package/corpus/templates/dispatch/.agents/skills/turn-into-app/SKILL.md +20 -18
  327. package/corpus/templates/factory/.agents/skills/actions/references/action-fields.md +1 -1
  328. package/corpus/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +36 -80
  329. package/corpus/templates/factory/.agents/skills/review-latest-feedback/references/channel-inventory.md +54 -16
  330. package/corpus/templates/factory/.agents/skills/review-latest-feedback/references/slack-reaction-replies.md +50 -73
  331. package/corpus/templates/factory/.agents/skills/turn-into-app/SKILL.md +20 -18
  332. package/corpus/templates/forms/.agents/skills/actions/references/action-fields.md +1 -1
  333. package/corpus/templates/mail/.agents/skills/actions/references/action-fields.md +1 -1
  334. package/corpus/templates/plan/.agents/skills/actions/references/action-fields.md +1 -1
  335. package/corpus/templates/slides/.agents/skills/actions/references/action-fields.md +1 -1
  336. package/corpus/templates/slides-2/.agents/skills/actions/SKILL.md +199 -0
  337. package/corpus/templates/slides-2/.agents/skills/actions/references/action-fields.md +145 -0
  338. package/corpus/templates/slides-2/.agents/skills/actions/references/examples.md +96 -0
  339. package/corpus/templates/slides-2/.agents/skills/actions/references/provider-apis.md +95 -0
  340. package/corpus/templates/slides-2/.agents/skills/adding-a-feature/SKILL.md +235 -0
  341. package/corpus/templates/slides-2/.agents/skills/agent-native-docs/SKILL.md +161 -0
  342. package/corpus/templates/slides-2/.agents/skills/agent-native-toolkit/SKILL.md +314 -0
  343. package/corpus/templates/slides-2/.agents/skills/analytics-data-for-decks/SKILL.md +44 -0
  344. package/corpus/templates/slides-2/.agents/skills/apply-slide-comments/SKILL.md +63 -0
  345. package/corpus/templates/slides-2/.agents/skills/client-side-routing/SKILL.md +87 -0
  346. package/corpus/templates/slides-2/.agents/skills/context-awareness/SKILL.md +282 -0
  347. package/corpus/templates/slides-2/.agents/skills/create-deck/SKILL.md +263 -0
  348. package/corpus/templates/slides-2/.agents/skills/create-deck/references/reference-inputs.md +72 -0
  349. package/corpus/templates/slides-2/.agents/skills/create-deck/references/slide-templates.md +93 -0
  350. package/corpus/templates/slides-2/.agents/skills/create-deck/references/source-material.md +16 -0
  351. package/corpus/templates/slides-2/.agents/skills/creative-context/SKILL.md +134 -0
  352. package/corpus/templates/slides-2/.agents/skills/customizing-agent-native/SKILL.md +219 -0
  353. package/corpus/templates/slides-2/.agents/skills/deck-management/SKILL.md +182 -0
  354. package/corpus/templates/slides-2/.agents/skills/delegate-to-agent/SKILL.md +62 -0
  355. package/corpus/templates/slides-2/.agents/skills/design-systems/SKILL.md +233 -0
  356. package/corpus/templates/slides-2/.agents/skills/external-agents/SKILL.md +549 -0
  357. package/corpus/templates/slides-2/.agents/skills/external-agents/references/mcp-apps-embedding.md +169 -0
  358. package/corpus/templates/slides-2/.agents/skills/frontend-design/SKILL.md +102 -0
  359. package/corpus/templates/slides-2/.agents/skills/frontend-design/references/visual-direction.md +102 -0
  360. package/corpus/templates/slides-2/.agents/skills/image-generation-via-a2a/SKILL.md +134 -0
  361. package/corpus/templates/slides-2/.agents/skills/performance/SKILL.md +79 -0
  362. package/corpus/templates/slides-2/.agents/skills/portability/SKILL.md +108 -0
  363. package/corpus/templates/slides-2/.agents/skills/real-time-sync/SKILL.md +146 -0
  364. package/corpus/templates/slides-2/.agents/skills/reliable-mutations/SKILL.md +72 -0
  365. package/corpus/templates/slides-2/.agents/skills/secrets/SKILL.md +82 -0
  366. package/corpus/templates/slides-2/.agents/skills/security/SKILL.md +80 -0
  367. package/corpus/templates/slides-2/.agents/skills/self-modifying-code/SKILL.md +123 -0
  368. package/corpus/templates/slides-2/.agents/skills/shadcn-ui/SKILL.md +71 -0
  369. package/corpus/templates/slides-2/.agents/skills/sharing/SKILL.md +286 -0
  370. package/corpus/templates/slides-2/.agents/skills/slide-design/SKILL.md +144 -0
  371. package/corpus/templates/slides-2/.agents/skills/slide-editing/SKILL.md +284 -0
  372. package/corpus/templates/slides-2/.agents/skills/slide-editing/references/animations.md +33 -0
  373. package/corpus/templates/slides-2/.agents/skills/slide-editing/references/freeform-objects.md +22 -0
  374. package/corpus/templates/slides-2/.agents/skills/slide-editing/references/restyling.md +69 -0
  375. package/corpus/templates/slides-2/.agents/skills/slide-editing/references/transitions.md +26 -0
  376. package/corpus/templates/slides-2/.agents/skills/slide-editing/references/video.md +45 -0
  377. package/corpus/templates/slides-2/.agents/skills/slide-images/SKILL.md +136 -0
  378. package/corpus/templates/slides-2/.agents/skills/storing-data/SKILL.md +234 -0
  379. package/corpus/templates/slides-2/.agents/skills/turn-into-skill/SKILL.md +112 -0
  380. package/corpus/templates/slides-2/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  381. package/corpus/templates/slides-2/.agents/skills/workspace-conventions/SKILL.md +103 -0
  382. package/corpus/templates/slides-2/.builder/rules/deploy-app.mdc +22 -0
  383. package/corpus/templates/slides-2/.builder/rules/organize-ui.mdc +9 -0
  384. package/corpus/templates/slides-2/.dockerignore +61 -0
  385. package/corpus/templates/slides-2/.env.example +23 -0
  386. package/corpus/templates/slides-2/.ignore +3 -0
  387. package/corpus/templates/slides-2/.mcp.json +8 -0
  388. package/corpus/templates/slides-2/.oxfmtrc.json +8 -0
  389. package/corpus/templates/slides-2/AGENTS.md +66 -0
  390. package/corpus/templates/slides-2/CHANGELOG.md +76 -0
  391. package/corpus/templates/slides-2/DEVELOPING.md +157 -0
  392. package/corpus/templates/slides-2/README.md +58 -0
  393. package/corpus/templates/slides-2/THIRD_PARTY_NOTICES.md +33 -0
  394. package/corpus/templates/slides-2/_gitignore +38 -0
  395. package/corpus/templates/slides-2/actions/_agent-presence.ts +29 -0
  396. package/corpus/templates/slides-2/actions/_app-url.ts +37 -0
  397. package/corpus/templates/slides-2/actions/_deck-app-scope.ts +30 -0
  398. package/corpus/templates/slides-2/actions/_deck-tracking.ts +260 -0
  399. package/corpus/templates/slides-2/actions/_deck-write.ts +206 -0
  400. package/corpus/templates/slides-2/actions/_imported-slide-source.ts +162 -0
  401. package/corpus/templates/slides-2/actions/_inline-image-storage.ts +1013 -0
  402. package/corpus/templates/slides-2/actions/_linked-design-system.ts +83 -0
  403. package/corpus/templates/slides-2/actions/_presenter-notes.ts +83 -0
  404. package/corpus/templates/slides-2/actions/_render-artifacts.ts +111 -0
  405. package/corpus/templates/slides-2/actions/_slide-source.ts +344 -0
  406. package/corpus/templates/slides-2/actions/_tab-state.ts +51 -0
  407. package/corpus/templates/slides-2/actions/_test-brandfetch.ts +31 -0
  408. package/corpus/templates/slides-2/actions/_uploaded-files.ts +114 -0
  409. package/corpus/templates/slides-2/actions/add-deck.ts +123 -0
  410. package/corpus/templates/slides-2/actions/add-slide-comment.ts +267 -0
  411. package/corpus/templates/slides-2/actions/add-slide.ts +888 -0
  412. package/corpus/templates/slides-2/actions/analyze-brand-assets.ts +66 -0
  413. package/corpus/templates/slides-2/actions/apply-design-system.ts +111 -0
  414. package/corpus/templates/slides-2/actions/approve-deck-access-request.ts +287 -0
  415. package/corpus/templates/slides-2/actions/audit-contrast.ts +143 -0
  416. package/corpus/templates/slides-2/actions/check-image-gen.ts +17 -0
  417. package/corpus/templates/slides-2/actions/clone-context-slide.ts +340 -0
  418. package/corpus/templates/slides-2/actions/clone-creative-context-deck.ts +143 -0
  419. package/corpus/templates/slides-2/actions/control-deck-history.ts +186 -0
  420. package/corpus/templates/slides-2/actions/control-presenter.ts +117 -0
  421. package/corpus/templates/slides-2/actions/control-slide-editor.ts +267 -0
  422. package/corpus/templates/slides-2/actions/create-deck-from-template.ts +274 -0
  423. package/corpus/templates/slides-2/actions/create-deck.ts +1243 -0
  424. package/corpus/templates/slides-2/actions/create-design-system.ts +131 -0
  425. package/corpus/templates/slides-2/actions/create-share-link.ts +127 -0
  426. package/corpus/templates/slides-2/actions/db-health.ts +22 -0
  427. package/corpus/templates/slides-2/actions/delete-asset.ts +154 -0
  428. package/corpus/templates/slides-2/actions/delete-deck.ts +427 -0
  429. package/corpus/templates/slides-2/actions/delete-design-system.ts +167 -0
  430. package/corpus/templates/slides-2/actions/delete-slide-comment.ts +143 -0
  431. package/corpus/templates/slides-2/actions/delete-staged-dataset.ts +30 -0
  432. package/corpus/templates/slides-2/actions/duplicate-deck.ts +299 -0
  433. package/corpus/templates/slides-2/actions/export-google-slides.ts +41 -0
  434. package/corpus/templates/slides-2/actions/export-html.ts +770 -0
  435. package/corpus/templates/slides-2/actions/export-pptx.ts +2203 -0
  436. package/corpus/templates/slides-2/actions/extract-pdf.ts +49 -0
  437. package/corpus/templates/slides-2/actions/generate-image-api.ts +671 -0
  438. package/corpus/templates/slides-2/actions/generate-image.ts +492 -0
  439. package/corpus/templates/slides-2/actions/get-agent-access-deck.ts +52 -0
  440. package/corpus/templates/slides-2/actions/get-deck-access-status.ts +130 -0
  441. package/corpus/templates/slides-2/actions/get-deck-design-tokens.ts +62 -0
  442. package/corpus/templates/slides-2/actions/get-deck-reference-context.ts +232 -0
  443. package/corpus/templates/slides-2/actions/get-deck-template.ts +38 -0
  444. package/corpus/templates/slides-2/actions/get-deck-version.ts +85 -0
  445. package/corpus/templates/slides-2/actions/get-deck.ts +562 -0
  446. package/corpus/templates/slides-2/actions/get-design-system-decode-job-status.ts +57 -0
  447. package/corpus/templates/slides-2/actions/get-design-system-tier-limit.ts +12 -0
  448. package/corpus/templates/slides-2/actions/get-design-system.ts +453 -0
  449. package/corpus/templates/slides-2/actions/get-google-docs-status.ts +106 -0
  450. package/corpus/templates/slides-2/actions/get-google-picker-token.ts +84 -0
  451. package/corpus/templates/slides-2/actions/get-home-suggestions.ts +52 -0
  452. package/corpus/templates/slides-2/actions/get-layout-overflows.ts +192 -0
  453. package/corpus/templates/slides-2/actions/get-slide-render.ts +125 -0
  454. package/corpus/templates/slides-2/actions/get-slide-source.ts +115 -0
  455. package/corpus/templates/slides-2/actions/get-slide-theme-preview.ts +64 -0
  456. package/corpus/templates/slides-2/actions/get-slide-theme.ts +44 -0
  457. package/corpus/templates/slides-2/actions/get-slides-2-upload-storage-status.ts +17 -0
  458. package/corpus/templates/slides-2/actions/get-slides-notification-prefs.ts +37 -0
  459. package/corpus/templates/slides-2/actions/get-workspace-defaults.ts +51 -0
  460. package/corpus/templates/slides-2/actions/image-gen-status.ts +35 -0
  461. package/corpus/templates/slides-2/actions/import-code.ts +26 -0
  462. package/corpus/templates/slides-2/actions/import-design-project.ts +49 -0
  463. package/corpus/templates/slides-2/actions/import-document.ts +125 -0
  464. package/corpus/templates/slides-2/actions/import-docx.ts +57 -0
  465. package/corpus/templates/slides-2/actions/import-file.ts +1273 -0
  466. package/corpus/templates/slides-2/actions/import-from-url.ts +25 -0
  467. package/corpus/templates/slides-2/actions/import-google-doc.ts +208 -0
  468. package/corpus/templates/slides-2/actions/import-google-font.ts +110 -0
  469. package/corpus/templates/slides-2/actions/import-google-slides-reference.ts +667 -0
  470. package/corpus/templates/slides-2/actions/import-pptx.ts +564 -0
  471. package/corpus/templates/slides-2/actions/import-svgl-logo.ts +115 -0
  472. package/corpus/templates/slides-2/actions/index-design-system-with-builder.ts +181 -0
  473. package/corpus/templates/slides-2/actions/index-uploaded-design-system-files.ts +77 -0
  474. package/corpus/templates/slides-2/actions/list-assets.ts +286 -0
  475. package/corpus/templates/slides-2/actions/list-deck-templates.ts +83 -0
  476. package/corpus/templates/slides-2/actions/list-deck-versions.ts +185 -0
  477. package/corpus/templates/slides-2/actions/list-decks.ts +591 -0
  478. package/corpus/templates/slides-2/actions/list-design-systems.ts +180 -0
  479. package/corpus/templates/slides-2/actions/list-slide-comments.ts +128 -0
  480. package/corpus/templates/slides-2/actions/list-slide-themes.ts +17 -0
  481. package/corpus/templates/slides-2/actions/list-staged-datasets.ts +14 -0
  482. package/corpus/templates/slides-2/actions/logo-config.ts +13 -0
  483. package/corpus/templates/slides-2/actions/navigate.ts +158 -0
  484. package/corpus/templates/slides-2/actions/patch-deck.ts +2378 -0
  485. package/corpus/templates/slides-2/actions/provider-api-catalog.ts +25 -0
  486. package/corpus/templates/slides-2/actions/provider-api-docs.ts +83 -0
  487. package/corpus/templates/slides-2/actions/provider-api-request.ts +222 -0
  488. package/corpus/templates/slides-2/actions/query-staged-dataset.ts +83 -0
  489. package/corpus/templates/slides-2/actions/read-composer-source.ts +108 -0
  490. package/corpus/templates/slides-2/actions/request-deck-access.ts +803 -0
  491. package/corpus/templates/slides-2/actions/restore-deck-version.ts +203 -0
  492. package/corpus/templates/slides-2/actions/run.ts +2 -0
  493. package/corpus/templates/slides-2/actions/save-deck.ts +313 -0
  494. package/corpus/templates/slides-2/actions/search-google-fonts.ts +61 -0
  495. package/corpus/templates/slides-2/actions/search-images.ts +30 -0
  496. package/corpus/templates/slides-2/actions/search-logos.ts +23 -0
  497. package/corpus/templates/slides-2/actions/search-svgl-logos.ts +42 -0
  498. package/corpus/templates/slides-2/actions/set-default-design-system.ts +88 -0
  499. package/corpus/templates/slides-2/actions/set-workspace-defaults.ts +61 -0
  500. package/corpus/templates/slides-2/actions/start-design-system-upload.ts +80 -0
  501. package/corpus/templates/slides-2/actions/sync-design-system-with-builder.ts +84 -0
  502. package/corpus/templates/slides-2/actions/toggle-slide-comment-reaction.ts +150 -0
  503. package/corpus/templates/slides-2/actions/transform-slide-objects.ts +1528 -0
  504. package/corpus/templates/slides-2/actions/update-asset.ts +499 -0
  505. package/corpus/templates/slides-2/actions/update-deck-aspect-ratio.ts +95 -0
  506. package/corpus/templates/slides-2/actions/update-deck-design-tokens.ts +175 -0
  507. package/corpus/templates/slides-2/actions/update-design-system.ts +95 -0
  508. package/corpus/templates/slides-2/actions/update-slide-comment.ts +213 -0
  509. package/corpus/templates/slides-2/actions/update-slide-source.ts +353 -0
  510. package/corpus/templates/slides-2/actions/update-slide.ts +850 -0
  511. package/corpus/templates/slides-2/actions/update-slides-notification-prefs.ts +55 -0
  512. package/corpus/templates/slides-2/actions/view-screen.ts +1098 -0
  513. package/corpus/templates/slides-2/agent-native.app-skill.json +165 -0
  514. package/corpus/templates/slides-2/agent-native.config.ts +20 -0
  515. package/corpus/templates/slides-2/agent-native.json +18 -0
  516. package/corpus/templates/slides-2/app/components/ThemeToggle.tsx +47 -0
  517. package/corpus/templates/slides-2/app/components/comments/SlideCommentPins.tsx +781 -0
  518. package/corpus/templates/slides-2/app/components/comments/SlideCommentsPanel.tsx +1075 -0
  519. package/corpus/templates/slides-2/app/components/deck/DeckCard.tsx +304 -0
  520. package/corpus/templates/slides-2/app/components/deck/DeckFilterMenu.tsx +83 -0
  521. package/corpus/templates/slides-2/app/components/deck/ExcalidrawSlide.tsx +183 -0
  522. package/corpus/templates/slides-2/app/components/deck/MermaidRenderer.tsx +126 -0
  523. package/corpus/templates/slides-2/app/components/deck/SlideRenderer.tsx +1553 -0
  524. package/corpus/templates/slides-2/app/components/design-system/DesignSystemCard.tsx +235 -0
  525. package/corpus/templates/slides-2/app/components/design-system/DesignSystemSetup.tsx +2021 -0
  526. package/corpus/templates/slides-2/app/components/design-system/builder-design-system-upload.ts +200 -0
  527. package/corpus/templates/slides-2/app/components/design-system/builder-index-response.ts +104 -0
  528. package/corpus/templates/slides-2/app/components/editor/AddSlidePopover.tsx +461 -0
  529. package/corpus/templates/slides-2/app/components/editor/AiEditingMarker.tsx +24 -0
  530. package/corpus/templates/slides-2/app/components/editor/AlignmentGuides.tsx +82 -0
  531. package/corpus/templates/slides-2/app/components/editor/AnimationsPanel.tsx +698 -0
  532. package/corpus/templates/slides-2/app/components/editor/AppMenu.tsx +356 -0
  533. package/corpus/templates/slides-2/app/components/editor/AssetLibraryPanel.tsx +508 -0
  534. package/corpus/templates/slides-2/app/components/editor/BlockBubbleMenu.tsx +548 -0
  535. package/corpus/templates/slides-2/app/components/editor/DeckAccessDeniedPage.tsx +173 -0
  536. package/corpus/templates/slides-2/app/components/editor/DeckEditorSkeleton.tsx +35 -0
  537. package/corpus/templates/slides-2/app/components/editor/DeferredPopoverFallback.tsx +148 -0
  538. package/corpus/templates/slides-2/app/components/editor/EditorActionCluster.tsx +217 -0
  539. package/corpus/templates/slides-2/app/components/editor/EditorSidebar.tsx +1047 -0
  540. package/corpus/templates/slides-2/app/components/editor/EditorToolbar.tsx +1285 -0
  541. package/corpus/templates/slides-2/app/components/editor/ExportMenu.tsx +579 -0
  542. package/corpus/templates/slides-2/app/components/editor/GeneratingOverlay.tsx +21 -0
  543. package/corpus/templates/slides-2/app/components/editor/GeneratingSlidePreview.tsx +73 -0
  544. package/corpus/templates/slides-2/app/components/editor/GoogleDocImportHint.tsx +378 -0
  545. package/corpus/templates/slides-2/app/components/editor/GoogleDriveConnectionCta.tsx +154 -0
  546. package/corpus/templates/slides-2/app/components/editor/GoogleSlidesReferenceImport.tsx +299 -0
  547. package/corpus/templates/slides-2/app/components/editor/HistoryPanel.tsx +354 -0
  548. package/corpus/templates/slides-2/app/components/editor/HomeQuickStartDialog.tsx +202 -0
  549. package/corpus/templates/slides-2/app/components/editor/ImageCropOverlay.tsx +820 -0
  550. package/corpus/templates/slides-2/app/components/editor/ImageDropPromptPopover.tsx +280 -0
  551. package/corpus/templates/slides-2/app/components/editor/ImageGenPanel.tsx +244 -0
  552. package/corpus/templates/slides-2/app/components/editor/ImageOverlay.tsx +280 -0
  553. package/corpus/templates/slides-2/app/components/editor/ImageSearchPanel.tsx +183 -0
  554. package/corpus/templates/slides-2/app/components/editor/ImportDeckButton.tsx +247 -0
  555. package/corpus/templates/slides-2/app/components/editor/LogoSearchPanel.tsx +366 -0
  556. package/corpus/templates/slides-2/app/components/editor/MermaidToExcalidrawPanel.tsx +99 -0
  557. package/corpus/templates/slides-2/app/components/editor/MissingDeckAccessPane.tsx +219 -0
  558. package/corpus/templates/slides-2/app/components/editor/NewDeckReferenceStep.tsx +812 -0
  559. package/corpus/templates/slides-2/app/components/editor/PromptDialog.tsx +963 -0
  560. package/corpus/templates/slides-2/app/components/editor/QuestionFlow.tsx +119 -0
  561. package/corpus/templates/slides-2/app/components/editor/RequestDeckAccessDialog.tsx +101 -0
  562. package/corpus/templates/slides-2/app/components/editor/ShareDialog.tsx +126 -0
  563. package/corpus/templates/slides-2/app/components/editor/SlideContextToolbar.tsx +1471 -0
  564. package/corpus/templates/slides-2/app/components/editor/SlideEditor.tsx +11183 -0
  565. package/corpus/templates/slides-2/app/components/editor/SlideOverflowWarning.tsx +82 -0
  566. package/corpus/templates/slides-2/app/components/editor/SlideScrollStack.tsx +307 -0
  567. package/corpus/templates/slides-2/app/components/editor/SlideSlashCommandMenu.tsx +692 -0
  568. package/corpus/templates/slides-2/app/components/editor/SlideThumbnailContextMenu.tsx +52 -0
  569. package/corpus/templates/slides-2/app/components/editor/SlideTransitionControl.tsx +184 -0
  570. package/corpus/templates/slides-2/app/components/editor/SlidesComposerContext.tsx +789 -0
  571. package/corpus/templates/slides-2/app/components/editor/SlidesComposerContextProvider.tsx +74 -0
  572. package/corpus/templates/slides-2/app/components/editor/SlidesLayersPanel.tsx +377 -0
  573. package/corpus/templates/slides-2/app/components/editor/SpeakerNotesPanel.tsx +119 -0
  574. package/corpus/templates/slides-2/app/components/editor/TweaksPanel.tsx +77 -0
  575. package/corpus/templates/slides-2/app/components/editor/UploadStorageGate.tsx +37 -0
  576. package/corpus/templates/slides-2/app/components/editor/bullet-editing.ts +880 -0
  577. package/corpus/templates/slides-2/app/components/editor/canvas-interactions/index.ts +12 -0
  578. package/corpus/templates/slides-2/app/components/editor/canvas-interactions/slides-canvas-adapter.ts +119 -0
  579. package/corpus/templates/slides-2/app/components/editor/commit-active-edit.ts +14 -0
  580. package/corpus/templates/slides-2/app/components/editor/editor-command-model.ts +35 -0
  581. package/corpus/templates/slides-2/app/components/editor/fit-text-object.ts +31 -0
  582. package/corpus/templates/slides-2/app/components/editor/in-place-text-session.browser-cases.json +983 -0
  583. package/corpus/templates/slides-2/app/components/editor/in-place-text-session.browser-host.ts +747 -0
  584. package/corpus/templates/slides-2/app/components/editor/in-place-text-session.ts +6891 -0
  585. package/corpus/templates/slides-2/app/components/editor/inline-edit-session.ts +26 -0
  586. package/corpus/templates/slides-2/app/components/editor/list-editing.ts +501 -0
  587. package/corpus/templates/slides-2/app/components/editor/rich-text-selection.ts +975 -0
  588. package/corpus/templates/slides-2/app/components/editor/rte-test-utils.ts +265 -0
  589. package/corpus/templates/slides-2/app/components/editor/selection-overlay-measurement.ts +191 -0
  590. package/corpus/templates/slides-2/app/components/editor/slide-escape-arbiter.ts +34 -0
  591. package/corpus/templates/slides-2/app/components/editor/slide-object-interactions.ts +6362 -0
  592. package/corpus/templates/slides-2/app/components/editor/slide-object-transform.browser-host.ts +19 -0
  593. package/corpus/templates/slides-2/app/components/editor/slide-pointer-target.ts +432 -0
  594. package/corpus/templates/slides-2/app/components/editor/slide-presence.ts +13 -0
  595. package/corpus/templates/slides-2/app/components/editor/slide-style.ts +243 -0
  596. package/corpus/templates/slides-2/app/components/editor/slide-text-targets.ts +540 -0
  597. package/corpus/templates/slides-2/app/components/editor/style-clipboard.ts +102 -0
  598. package/corpus/templates/slides-2/app/components/editor/use-prompt-import.ts +159 -0
  599. package/corpus/templates/slides-2/app/components/home/SlidesHomeLibrary.tsx +79 -0
  600. package/corpus/templates/slides-2/app/components/layout/AgentWorkIndicator.tsx +193 -0
  601. package/corpus/templates/slides-2/app/components/layout/Header.tsx +110 -0
  602. package/corpus/templates/slides-2/app/components/layout/Layout.tsx +492 -0
  603. package/corpus/templates/slides-2/app/components/layout/Sidebar.tsx +109 -0
  604. package/corpus/templates/slides-2/app/components/layout/layout-route-policy.ts +28 -0
  605. package/corpus/templates/slides-2/app/components/presentation/PresentationView.tsx +1116 -0
  606. package/corpus/templates/slides-2/app/components/presentation/PresenterView.tsx +526 -0
  607. package/corpus/templates/slides-2/app/components/presentation/SlideTransitionStage.tsx +297 -0
  608. package/corpus/templates/slides-2/app/components/presentation/present-channel.ts +31 -0
  609. package/corpus/templates/slides-2/app/components/presentation/slide-build-steps.ts +231 -0
  610. package/corpus/templates/slides-2/app/components/presentation/slide-navigation.ts +273 -0
  611. package/corpus/templates/slides-2/app/components/presentation/slide-transition-motion.ts +258 -0
  612. package/corpus/templates/slides-2/app/components/presentation/voice-navigation.ts +61 -0
  613. package/corpus/templates/slides-2/app/components/settings/notification-settings.tsx +93 -0
  614. package/corpus/templates/slides-2/app/components/slides-2-editor/Slides2AssetBrowser.tsx +726 -0
  615. package/corpus/templates/slides-2/app/components/slides-2-editor/Slides2CommandMenu.tsx +453 -0
  616. package/corpus/templates/slides-2/app/components/slides-2-editor/Slides2Comments.tsx +571 -0
  617. package/corpus/templates/slides-2/app/components/slides-2-editor/Slides2DesignTokens.tsx +345 -0
  618. package/corpus/templates/slides-2/app/components/slides-2-editor/Slides2Editor.tsx +4804 -0
  619. package/corpus/templates/slides-2/app/components/slides-2-editor/Slides2ExportMenu.tsx +671 -0
  620. package/corpus/templates/slides-2/app/components/slides-2-editor/Slides2FontBrowser.tsx +342 -0
  621. package/corpus/templates/slides-2/app/components/slides-2-editor/Slides2ImageCropControls.tsx +487 -0
  622. package/corpus/templates/slides-2/app/components/slides-2-editor/Slides2Inspector.tsx +950 -0
  623. package/corpus/templates/slides-2/app/components/slides-2-editor/Slides2SvglLogoSearchDialog.tsx +332 -0
  624. package/corpus/templates/slides-2/app/components/slides-2-editor/cross-slide-edit-history.ts +151 -0
  625. package/corpus/templates/slides-2/app/components/slides-2-editor/design-token-presets.ts +140 -0
  626. package/corpus/templates/slides-2/app/components/slides-2-editor/editor-action-errors.ts +47 -0
  627. package/corpus/templates/slides-2/app/components/slides-2-editor/editor-export-errors.ts +60 -0
  628. package/corpus/templates/slides-2/app/components/slides-2-editor/geometry.ts +275 -0
  629. package/corpus/templates/slides-2/app/components/slides-2-editor/image-crop-style.ts +82 -0
  630. package/corpus/templates/slides-2/app/components/slides-2-editor/inline-text-editor.tsx +631 -0
  631. package/corpus/templates/slides-2/app/components/slides-2-editor/keyboard-shortcuts.ts +104 -0
  632. package/corpus/templates/slides-2/app/components/slides-2-editor/object-insertion.ts +13 -0
  633. package/corpus/templates/slides-2/app/components/slides-2-editor/preview-patches.ts +54 -0
  634. package/corpus/templates/slides-2/app/components/slides-2-editor/sandbox-render-errors.ts +23 -0
  635. package/corpus/templates/slides-2/app/components/slides-2-editor/source-structure.ts +634 -0
  636. package/corpus/templates/slides-2/app/components/slides-2-editor/types.ts +85 -0
  637. package/corpus/templates/slides-2/app/components/slides-2-presenter/Slides2BlackoutOverlay.tsx +13 -0
  638. package/corpus/templates/slides-2/app/components/slides-2-presenter/Slides2ControlBar.tsx +285 -0
  639. package/corpus/templates/slides-2/app/components/slides-2-presenter/Slides2HelpDialog.tsx +72 -0
  640. package/corpus/templates/slides-2/app/components/slides-2-presenter/Slides2JumpInput.tsx +38 -0
  641. package/corpus/templates/slides-2/app/components/slides-2-presenter/Slides2LaserPointer.tsx +67 -0
  642. package/corpus/templates/slides-2/app/components/slides-2-presenter/Slides2Overview.tsx +161 -0
  643. package/corpus/templates/slides-2/app/components/slides-2-presenter/Slides2Player.tsx +839 -0
  644. package/corpus/templates/slides-2/app/components/slides-2-presenter/Slides2ProgressBar.tsx +23 -0
  645. package/corpus/templates/slides-2/app/components/slides-2-presenter/keyboard.ts +36 -0
  646. package/corpus/templates/slides-2/app/components/slides-2-presenter/presenter-channel.ts +131 -0
  647. package/corpus/templates/slides-2/app/components/slides-2-presenter/use-presenter-action-bridge.ts +296 -0
  648. package/corpus/templates/slides-2/app/components/slides-2-presenter/useSlides2TouchSwipe.ts +80 -0
  649. package/corpus/templates/slides-2/app/components/slides-2-runtime/SandboxedSlide.tsx +724 -0
  650. package/corpus/templates/slides-2/app/components/slides-2-runtime/SlideContentRenderer.tsx +137 -0
  651. package/corpus/templates/slides-2/app/components/slides-2-runtime/Slides2Canvas.tsx +99 -0
  652. package/corpus/templates/slides-2/app/components/slides-2-runtime/constants.ts +4 -0
  653. package/corpus/templates/slides-2/app/components/slides-2-runtime/protocol.ts +1400 -0
  654. package/corpus/templates/slides-2/app/components/slides-2-runtime/transition-frame.ts +439 -0
  655. package/corpus/templates/slides-2/app/components/templates/DeckTemplateLibrary.tsx +314 -0
  656. package/corpus/templates/slides-2/app/components/templates/DeckTemplatePreview.tsx +60 -0
  657. package/corpus/templates/slides-2/app/components/templates/DeckTemplateStage.tsx +45 -0
  658. package/corpus/templates/slides-2/app/components/ui/alert-dialog.tsx +1 -0
  659. package/corpus/templates/slides-2/app/components/ui/avatar.tsx +1 -0
  660. package/corpus/templates/slides-2/app/components/ui/button-group.tsx +1 -0
  661. package/corpus/templates/slides-2/app/components/ui/button.tsx +1 -0
  662. package/corpus/templates/slides-2/app/components/ui/card.tsx +1 -0
  663. package/corpus/templates/slides-2/app/components/ui/command.tsx +1 -0
  664. package/corpus/templates/slides-2/app/components/ui/context-menu.tsx +32 -0
  665. package/corpus/templates/slides-2/app/components/ui/dialog.tsx +1 -0
  666. package/corpus/templates/slides-2/app/components/ui/dropdown-menu.tsx +1 -0
  667. package/corpus/templates/slides-2/app/components/ui/filter-trigger.tsx +1 -0
  668. package/corpus/templates/slides-2/app/components/ui/input.tsx +1 -0
  669. package/corpus/templates/slides-2/app/components/ui/label.tsx +1 -0
  670. package/corpus/templates/slides-2/app/components/ui/popover.tsx +1 -0
  671. package/corpus/templates/slides-2/app/components/ui/progress.tsx +1 -0
  672. package/corpus/templates/slides-2/app/components/ui/scroll-area.tsx +1 -0
  673. package/corpus/templates/slides-2/app/components/ui/select.tsx +1 -0
  674. package/corpus/templates/slides-2/app/components/ui/separator.tsx +1 -0
  675. package/corpus/templates/slides-2/app/components/ui/sheet.tsx +1 -0
  676. package/corpus/templates/slides-2/app/components/ui/skeleton.tsx +1 -0
  677. package/corpus/templates/slides-2/app/components/ui/slider.tsx +1 -0
  678. package/corpus/templates/slides-2/app/components/ui/spinner.tsx +1 -0
  679. package/corpus/templates/slides-2/app/components/ui/switch.tsx +1 -0
  680. package/corpus/templates/slides-2/app/components/ui/tabs.tsx +59 -0
  681. package/corpus/templates/slides-2/app/components/ui/textarea.tsx +1 -0
  682. package/corpus/templates/slides-2/app/components/ui/toggle-group.tsx +1 -0
  683. package/corpus/templates/slides-2/app/components/ui/toolkit-provider.tsx +17 -0
  684. package/corpus/templates/slides-2/app/components/ui/tooltip.tsx +1 -0
  685. package/corpus/templates/slides-2/app/components/visual-editor/CanvasCommentPins.tsx +46 -0
  686. package/corpus/templates/slides-2/app/components/visual-editor/DrawOverlay.tsx +27 -0
  687. package/corpus/templates/slides-2/app/components/visual-editor/MultiSelectChip.tsx +97 -0
  688. package/corpus/templates/slides-2/app/components/visual-editor/SaveStatusIndicator.tsx +273 -0
  689. package/corpus/templates/slides-2/app/components/visual-editor/index.ts +4 -0
  690. package/corpus/templates/slides-2/app/context/DeckContext.tsx +7486 -0
  691. package/corpus/templates/slides-2/app/design-system.ts +3 -0
  692. package/corpus/templates/slides-2/app/entry.client.tsx +10 -0
  693. package/corpus/templates/slides-2/app/entry.server.tsx +10 -0
  694. package/corpus/templates/slides-2/app/global.css +1626 -0
  695. package/corpus/templates/slides-2/app/hooks/use-agent-generating.ts +517 -0
  696. package/corpus/templates/slides-2/app/hooks/use-compact-editor-layout.ts +26 -0
  697. package/corpus/templates/slides-2/app/hooks/use-contrast-audit-bridge.ts +49 -0
  698. package/corpus/templates/slides-2/app/hooks/use-deck-access-reload.ts +70 -0
  699. package/corpus/templates/slides-2/app/hooks/use-deck-access.ts +50 -0
  700. package/corpus/templates/slides-2/app/hooks/use-deck-design-system.ts +146 -0
  701. package/corpus/templates/slides-2/app/hooks/use-deck-history-action-bridge.ts +266 -0
  702. package/corpus/templates/slides-2/app/hooks/use-deck-presence.ts +89 -0
  703. package/corpus/templates/slides-2/app/hooks/use-deck-role.ts +46 -0
  704. package/corpus/templates/slides-2/app/hooks/use-deck-versions.ts +43 -0
  705. package/corpus/templates/slides-2/app/hooks/use-design-system-workflows.ts +11 -0
  706. package/corpus/templates/slides-2/app/hooks/use-design-systems.ts +31 -0
  707. package/corpus/templates/slides-2/app/hooks/use-generating-slide-preview.ts +115 -0
  708. package/corpus/templates/slides-2/app/hooks/use-navigation-state.ts +229 -0
  709. package/corpus/templates/slides-2/app/hooks/use-new-deck-generation-signal.ts +46 -0
  710. package/corpus/templates/slides-2/app/hooks/use-new-deck-generation.ts +710 -0
  711. package/corpus/templates/slides-2/app/hooks/use-sidebar-collapsed.ts +95 -0
  712. package/corpus/templates/slides-2/app/hooks/use-slide-comments.ts +202 -0
  713. package/corpus/templates/slides-2/app/hooks/use-slide-file-storage-status.ts +55 -0
  714. package/corpus/templates/slides-2/app/hooks/use-undo-selection.ts +66 -0
  715. package/corpus/templates/slides-2/app/hooks/use-workspace-defaults.ts +31 -0
  716. package/corpus/templates/slides-2/app/i18n/en-US.ts +1507 -0
  717. package/corpus/templates/slides-2/app/i18n/index.ts +19 -0
  718. package/corpus/templates/slides-2/app/lib/agent-visible-message.ts +21 -0
  719. package/corpus/templates/slides-2/app/lib/aspect-ratios.ts +7 -0
  720. package/corpus/templates/slides-2/app/lib/asset-error-copy.ts +59 -0
  721. package/corpus/templates/slides-2/app/lib/canvas-zoom.ts +47 -0
  722. package/corpus/templates/slides-2/app/lib/composer-context.ts +152 -0
  723. package/corpus/templates/slides-2/app/lib/composer-draft.ts +34 -0
  724. package/corpus/templates/slides-2/app/lib/contrast-audit.ts +390 -0
  725. package/corpus/templates/slides-2/app/lib/contrast-resolve.ts +240 -0
  726. package/corpus/templates/slides-2/app/lib/create-deck-generation.ts +938 -0
  727. package/corpus/templates/slides-2/app/lib/deck-access-lost.ts +4 -0
  728. package/corpus/templates/slides-2/app/lib/deck-backup.ts +186 -0
  729. package/corpus/templates/slides-2/app/lib/deck-editor-loading.ts +91 -0
  730. package/corpus/templates/slides-2/app/lib/deck-export-file-client.ts +77 -0
  731. package/corpus/templates/slides-2/app/lib/deck-filter.ts +52 -0
  732. package/corpus/templates/slides-2/app/lib/deck-list-loading.ts +16 -0
  733. package/corpus/templates/slides-2/app/lib/deck-preview-frame.ts +15 -0
  734. package/corpus/templates/slides-2/app/lib/deck-share-links.ts +9 -0
  735. package/corpus/templates/slides-2/app/lib/deck-sorting.ts +19 -0
  736. package/corpus/templates/slides-2/app/lib/deferred-editor-surfaces.ts +24 -0
  737. package/corpus/templates/slides-2/app/lib/design-system-selection.ts +11 -0
  738. package/corpus/templates/slides-2/app/lib/design-systems.ts +231 -0
  739. package/corpus/templates/slides-2/app/lib/dynamic-import.ts +50 -0
  740. package/corpus/templates/slides-2/app/lib/editor-agent-handoff.ts +92 -0
  741. package/corpus/templates/slides-2/app/lib/editor-shortcuts.ts +153 -0
  742. package/corpus/templates/slides-2/app/lib/export-google-slides-client.ts +168 -0
  743. package/corpus/templates/slides-2/app/lib/export-pdf-client.ts +684 -0
  744. package/corpus/templates/slides-2/app/lib/export-pptx-client.ts +2420 -0
  745. package/corpus/templates/slides-2/app/lib/generation-lifecycle.ts +24 -0
  746. package/corpus/templates/slides-2/app/lib/generation-state.ts +247 -0
  747. package/corpus/templates/slides-2/app/lib/google-docs-client.ts +110 -0
  748. package/corpus/templates/slides-2/app/lib/google-slides-export-availability-client.ts +53 -0
  749. package/corpus/templates/slides-2/app/lib/google-slides-reference-source.ts +18 -0
  750. package/corpus/templates/slides-2/app/lib/image-download.ts +85 -0
  751. package/corpus/templates/slides-2/app/lib/image-drop-to-agent.ts +210 -0
  752. package/corpus/templates/slides-2/app/lib/import-uploaded-deck.ts +132 -0
  753. package/corpus/templates/slides-2/app/lib/inline-edit-remote.ts +55 -0
  754. package/corpus/templates/slides-2/app/lib/localize-slides-changelog.ts +47 -0
  755. package/corpus/templates/slides-2/app/lib/mermaid-blocks.ts +18 -0
  756. package/corpus/templates/slides-2/app/lib/new-deck-reference-selection.ts +174 -0
  757. package/corpus/templates/slides-2/app/lib/normalize-slide-padding.ts +74 -0
  758. package/corpus/templates/slides-2/app/lib/pending-deck-changes.ts +33 -0
  759. package/corpus/templates/slides-2/app/lib/portaled-layer.ts +7 -0
  760. package/corpus/templates/slides-2/app/lib/pptx-google-slides.ts +204 -0
  761. package/corpus/templates/slides-2/app/lib/prompt-attachment-adapter.ts +37 -0
  762. package/corpus/templates/slides-2/app/lib/prompt-file-uploads.ts +557 -0
  763. package/corpus/templates/slides-2/app/lib/recent-references.ts +106 -0
  764. package/corpus/templates/slides-2/app/lib/reference-document-hydration.ts +406 -0
  765. package/corpus/templates/slides-2/app/lib/register-chat-renderers.tsx +645 -0
  766. package/corpus/templates/slides-2/app/lib/reveal-after-delete.ts +55 -0
  767. package/corpus/templates/slides-2/app/lib/sanitize-slide-html.ts +752 -0
  768. package/corpus/templates/slides-2/app/lib/slide-agent-context.ts +148 -0
  769. package/corpus/templates/slides-2/app/lib/slide-animation-elements.ts +900 -0
  770. package/corpus/templates/slides-2/app/lib/slide-clipboard.ts +534 -0
  771. package/corpus/templates/slides-2/app/lib/slide-comment-anchor.ts +286 -0
  772. package/corpus/templates/slides-2/app/lib/slide-content-merge.ts +295 -0
  773. package/corpus/templates/slides-2/app/lib/slide-image-replacement.ts +1919 -0
  774. package/corpus/templates/slides-2/app/lib/slide-live-remote.ts +215 -0
  775. package/corpus/templates/slides-2/app/lib/slide-scroll.ts +56 -0
  776. package/corpus/templates/slides-2/app/lib/slide-source-map.ts +1099 -0
  777. package/corpus/templates/slides-2/app/lib/slide-video.ts +390 -0
  778. package/corpus/templates/slides-2/app/lib/slides-relay-tracking.ts +114 -0
  779. package/corpus/templates/slides-2/app/lib/streaming-slide-html.ts +77 -0
  780. package/corpus/templates/slides-2/app/lib/tab-id.ts +3 -0
  781. package/corpus/templates/slides-2/app/lib/template-navigation.ts +15 -0
  782. package/corpus/templates/slides-2/app/lib/text-tool-shortcut.ts +75 -0
  783. package/corpus/templates/slides-2/app/lib/undo-reveal.ts +332 -0
  784. package/corpus/templates/slides-2/app/lib/upload-response.ts +107 -0
  785. package/corpus/templates/slides-2/app/lib/utils.ts +38 -0
  786. package/corpus/templates/slides-2/app/lib/validate-native-slide-html.ts +177 -0
  787. package/corpus/templates/slides-2/app/lib/video-upload.ts +354 -0
  788. package/corpus/templates/slides-2/app/pages/DeckEditor.tsx +6158 -0
  789. package/corpus/templates/slides-2/app/pages/DesignSystems.tsx +363 -0
  790. package/corpus/templates/slides-2/app/pages/Index.tsx +3254 -0
  791. package/corpus/templates/slides-2/app/pages/NotFound.tsx +33 -0
  792. package/corpus/templates/slides-2/app/pages/Presentation.tsx +120 -0
  793. package/corpus/templates/slides-2/app/pages/SharedPresentation.tsx +174 -0
  794. package/corpus/templates/slides-2/app/pages/SlideThemeDetail.tsx +227 -0
  795. package/corpus/templates/slides-2/app/pages/SlideThemes.tsx +155 -0
  796. package/corpus/templates/slides-2/app/pages/Slides2EditorPage.tsx +1618 -0
  797. package/corpus/templates/slides-2/app/pages/Slides2PresenterConsolePage.tsx +937 -0
  798. package/corpus/templates/slides-2/app/pages/Slides2PresenterPage.tsx +979 -0
  799. package/corpus/templates/slides-2/app/pages/Templates.tsx +32 -0
  800. package/corpus/templates/slides-2/app/root.tsx +391 -0
  801. package/corpus/templates/slides-2/app/routes/$.tsx +10 -0
  802. package/corpus/templates/slides-2/app/routes/_index.tsx +1 -0
  803. package/corpus/templates/slides-2/app/routes/access-request.approve.tsx +276 -0
  804. package/corpus/templates/slides-2/app/routes/agent.tsx +19 -0
  805. package/corpus/templates/slides-2/app/routes/chat.$threadId.tsx +1 -0
  806. package/corpus/templates/slides-2/app/routes/chat.tsx +190 -0
  807. package/corpus/templates/slides-2/app/routes/deck.$id.tsx +10 -0
  808. package/corpus/templates/slides-2/app/routes/deck.$id_.present.tsx +10 -0
  809. package/corpus/templates/slides-2/app/routes/design-systems.tsx +10 -0
  810. package/corpus/templates/slides-2/app/routes/extensions.$id.$slug.tsx +2 -0
  811. package/corpus/templates/slides-2/app/routes/extensions.$id.tsx +5 -0
  812. package/corpus/templates/slides-2/app/routes/extensions._index.tsx +5 -0
  813. package/corpus/templates/slides-2/app/routes/extensions.tsx +5 -0
  814. package/corpus/templates/slides-2/app/routes/home-layout.tsx +31 -0
  815. package/corpus/templates/slides-2/app/routes/home.tsx +22 -0
  816. package/corpus/templates/slides-2/app/routes/p.$id.tsx +195 -0
  817. package/corpus/templates/slides-2/app/routes/settings.$.tsx +1 -0
  818. package/corpus/templates/slides-2/app/routes/settings.tsx +131 -0
  819. package/corpus/templates/slides-2/app/routes/share.$token.tsx +137 -0
  820. package/corpus/templates/slides-2/app/routes/slide.tsx +209 -0
  821. package/corpus/templates/slides-2/app/routes/team.tsx +11 -0
  822. package/corpus/templates/slides-2/app/routes/templates.tsx +1 -0
  823. package/corpus/templates/slides-2/app/routes/themes.$id.tsx +1 -0
  824. package/corpus/templates/slides-2/app/routes/themes.tsx +1 -0
  825. package/corpus/templates/slides-2/app/routes.ts +24 -0
  826. package/corpus/templates/slides-2/app/vite-env.d.ts +24 -0
  827. package/corpus/templates/slides-2/changelog/2026-10-17-find-and-switch-decks-from-the-presenter-console.md +6 -0
  828. package/corpus/templates/slides-2/changelog/2026-10-17-meet-slides-2-create-and-refine-editable-slide-decks-with-an.md +6 -0
  829. package/corpus/templates/slides-2/changelog/2026-10-17-pptx-image-export.md +6 -0
  830. package/corpus/templates/slides-2/changelog/2026-10-17-visual-editor.md +6 -0
  831. package/corpus/templates/slides-2/changelog/2026-10-18-apply-an-accessible-design-system-to-an-existing-deck-before.md +6 -0
  832. package/corpus/templates/slides-2/changelog/2026-10-18-choose-a-template-or-start-a-new-presentation-from-the-slide.md +6 -0
  833. package/corpus/templates/slides-2/changelog/2026-10-18-generate-decks-from-a-prompt-then-edit-slide-elements-direct.md +6 -0
  834. package/corpus/templates/slides-2/changelog/2026-10-18-generate-presentation-decks-from-a-prompt-and-edit-every-sli.md +6 -0
  835. package/corpus/templates/slides-2/changelog/2026-10-18-new-presentation-drafts-save-before-generation-starts-so-you.md +6 -0
  836. package/corpus/templates/slides-2/changelog/2026-10-18-the-assistant-can-undo-redo-and-save-pending-edits-in-the-vi.md +6 -0
  837. package/corpus/templates/slides-2/changelog/2026-10-19-agents-can-insert-duplicate-and-delete-canvas-objects-in-sou.md +6 -0
  838. package/corpus/templates/slides-2/changelog/2026-10-19-browse-slide-themes.md +6 -0
  839. package/corpus/templates/slides-2/changelog/2026-10-19-clicking-a-slide-preview-in-overview-selects-that-slide.md +6 -0
  840. package/corpus/templates/slides-2/changelog/2026-10-19-create-decks-from-a-prompt-and-edit-slides-directly-on-the-c.md +6 -0
  841. package/corpus/templates/slides-2/changelog/2026-10-19-creating-and-editing-decks-now-starts-with-the-tools-most-re.md +6 -0
  842. package/corpus/templates/slides-2/changelog/2026-10-19-deleting-decks-revokes-public-links.md +7 -0
  843. package/corpus/templates/slides-2/changelog/2026-10-19-escape-cancels-an-in-progress-slide-drag-without-losing-earl.md +6 -0
  844. package/corpus/templates/slides-2/changelog/2026-10-19-import-failures-now-show-clear-localized-descriptions-instea.md +6 -0
  845. package/corpus/templates/slides-2/changelog/2026-10-19-presenter-controls-stay-responsive-when-moving-over-the-slid.md +6 -0
  846. package/corpus/templates/slides-2/changelog/2026-10-19-presenter-notes-stay-private-from-viewers-and-commenters.md +6 -0
  847. package/corpus/templates/slides-2/changelog/2026-10-19-preview-generated-slides-in-chat.md +6 -0
  848. package/corpus/templates/slides-2/changelog/2026-10-19-remote-image-previews-accept-supported-raster-formats.md +6 -0
  849. package/corpus/templates/slides-2/changelog/2026-10-19-search-the-svgl-catalog-and-add-svg-logos-to-a-deck-or-the-g.md +6 -0
  850. package/corpus/templates/slides-2/changelog/2026-10-19-slide-generation-explains-when-react-effect-hooks-cannot-run.md +6 -0
  851. package/corpus/templates/slides-2/changelog/2026-10-19-the-editor-highlights-hovered-objects-and-keeps-image-replac.md +6 -0
  852. package/corpus/templates/slides-2/changelog/2026-10-19-the-slide-editor-uses-the-shared-agent-native-controls.md +6 -0
  853. package/corpus/templates/slides-2/changelog/2026-10-20-deck-editing-controls-match-the-workspace.md +6 -0
  854. package/corpus/templates/slides-2/changelog/2026-10-20-google-slides-imports-now-report-missing-image-data-instead-.md +6 -0
  855. package/corpus/templates/slides-2/changelog/2026-10-20-imports-and-previews-handle-large-content-safely.md +6 -0
  856. package/corpus/templates/slides-2/changelog/2026-10-20-public-deck-pages-can-export-source-backed-slides-to-pdf.md +6 -0
  857. package/corpus/templates/slides-2/changelog/2026-10-20-saved-slide-images-stay-available.md +6 -0
  858. package/corpus/templates/slides-2/changelog/2026-10-20-scope-global-media-picks-to-assets-the-current-deck-can-reso.md +6 -0
  859. package/corpus/templates/slides-2/components.json +20 -0
  860. package/corpus/templates/slides-2/drizzle.config.ts +3 -0
  861. package/corpus/templates/slides-2/learnings.defaults.md +5 -0
  862. package/corpus/templates/slides-2/netlify.toml +24 -0
  863. package/corpus/templates/slides-2/package.json +147 -0
  864. package/corpus/templates/slides-2/public/agent-native-icon-dark.svg +10 -0
  865. package/corpus/templates/slides-2/public/agent-native-icon-light.svg +10 -0
  866. package/corpus/templates/slides-2/public/agent-native-logo-dark.svg +21 -0
  867. package/corpus/templates/slides-2/public/agent-native-logo-light.svg +21 -0
  868. package/corpus/templates/slides-2/public/assets/builder-logo-white.svg +15 -0
  869. package/corpus/templates/slides-2/public/assets/generated/preview.html +61 -0
  870. package/corpus/templates/slides-2/public/assets/intuit-logo-white.svg +6 -0
  871. package/corpus/templates/slides-2/public/assets/walmart-logo-white.svg +6 -0
  872. package/corpus/templates/slides-2/public/chatgpt-plugin-icon.svg +7 -0
  873. package/corpus/templates/slides-2/public/favicon.svg +1 -0
  874. package/corpus/templates/slides-2/public/icon-180.svg +1 -0
  875. package/corpus/templates/slides-2/public/icon-192.svg +1 -0
  876. package/corpus/templates/slides-2/public/icon-512.svg +1 -0
  877. package/corpus/templates/slides-2/public/manifest.json +20 -0
  878. package/corpus/templates/slides-2/public/placeholder.svg +1 -0
  879. package/corpus/templates/slides-2/public/robots.txt +14 -0
  880. package/corpus/templates/slides-2/public/visual-edit-structure-proof.html +99 -0
  881. package/corpus/templates/slides-2/react-router.config.ts +7 -0
  882. package/corpus/templates/slides-2/scripts/edit-fidelity/README.md +499 -0
  883. package/corpus/templates/slides-2/scripts/edit-fidelity/authoring-fuzz.ts +9517 -0
  884. package/corpus/templates/slides-2/scripts/edit-fidelity/baseline.json +16427 -0
  885. package/corpus/templates/slides-2/scripts/edit-fidelity/dev-server-url.ts +10 -0
  886. package/corpus/templates/slides-2/scripts/edit-fidelity/lib/in-page.ts +1975 -0
  887. package/corpus/templates/slides-2/scripts/edit-fidelity/lib/metrics.ts +1401 -0
  888. package/corpus/templates/slides-2/scripts/edit-fidelity/retry-infra.ts +7 -0
  889. package/corpus/templates/slides-2/scripts/edit-fidelity/run-options.ts +21 -0
  890. package/corpus/templates/slides-2/scripts/edit-fidelity/run-outcomes.ts +127 -0
  891. package/corpus/templates/slides-2/scripts/edit-fidelity/run.ts +8451 -0
  892. package/corpus/templates/slides-2/scripts/export-fidelity/README.md +116 -0
  893. package/corpus/templates/slides-2/scripts/export-fidelity/compare-layout-lib.ts +241 -0
  894. package/corpus/templates/slides-2/scripts/export-fidelity/compare-layout.ts +30 -0
  895. package/corpus/templates/slides-2/scripts/export-fidelity/diff.ts +222 -0
  896. package/corpus/templates/slides-2/scripts/export-fidelity/export.ts +765 -0
  897. package/corpus/templates/slides-2/scripts/export-fidelity/fixtures/agent-dark-deck.json +48 -0
  898. package/corpus/templates/slides-2/scripts/export-fidelity/generate-calibration.ts +765 -0
  899. package/corpus/templates/slides-2/scripts/export-fidelity/google-export.ts +137 -0
  900. package/corpus/templates/slides-2/scripts/export-fidelity/google-layout.ts +82 -0
  901. package/corpus/templates/slides-2/scripts/export-fidelity/resolve-pkg.ts +29 -0
  902. package/corpus/templates/slides-2/scripts/migrate-production.ts +22 -0
  903. package/corpus/templates/slides-2/server/db/index.ts +73 -0
  904. package/corpus/templates/slides-2/server/db/schema.ts +189 -0
  905. package/corpus/templates/slides-2/server/handlers/assets-url.ts +13 -0
  906. package/corpus/templates/slides-2/server/handlers/assets.ts +3217 -0
  907. package/corpus/templates/slides-2/server/handlers/decks.ts +185 -0
  908. package/corpus/templates/slides-2/server/handlers/demo.ts +9 -0
  909. package/corpus/templates/slides-2/server/handlers/design-systems.ts +219 -0
  910. package/corpus/templates/slides-2/server/handlers/google-docs-auth.ts +165 -0
  911. package/corpus/templates/slides-2/server/handlers/image-gen.ts +153 -0
  912. package/corpus/templates/slides-2/server/handlers/image-providers/gemini.ts +209 -0
  913. package/corpus/templates/slides-2/server/handlers/image-providers/index.ts +61 -0
  914. package/corpus/templates/slides-2/server/handlers/image-providers/openai.ts +288 -0
  915. package/corpus/templates/slides-2/server/handlers/image-providers/types.ts +35 -0
  916. package/corpus/templates/slides-2/server/handlers/import/docx-parser.ts +31 -0
  917. package/corpus/templates/slides-2/server/handlers/import/html-converter.ts +1534 -0
  918. package/corpus/templates/slides-2/server/handlers/import/pdf-fidelity-parser.ts +1039 -0
  919. package/corpus/templates/slides-2/server/handlers/import/pdf-sidecar-reader.ts +81 -0
  920. package/corpus/templates/slides-2/server/handlers/import/pdf-style-digest.ts +187 -0
  921. package/corpus/templates/slides-2/server/handlers/import/pptx-assets.ts +155 -0
  922. package/corpus/templates/slides-2/server/handlers/import/pptx-parser.ts +57 -0
  923. package/corpus/templates/slides-2/server/handlers/request-auth-context.ts +108 -0
  924. package/corpus/templates/slides-2/server/handlers/share.ts +52 -0
  925. package/corpus/templates/slides-2/server/handlers/uploads-chunked.ts +1066 -0
  926. package/corpus/templates/slides-2/server/handlers/uploads.ts +457 -0
  927. package/corpus/templates/slides-2/server/lib/access-request-email.ts +66 -0
  928. package/corpus/templates/slides-2/server/lib/assets-image-delegation.ts +331 -0
  929. package/corpus/templates/slides-2/server/lib/bounded-multipart.ts +49 -0
  930. package/corpus/templates/slides-2/server/lib/builder-design-system-proxy.ts +122 -0
  931. package/corpus/templates/slides-2/server/lib/chat-attachments.ts +425 -0
  932. package/corpus/templates/slides-2/server/lib/chatgpt-directory-tools.ts +246 -0
  933. package/corpus/templates/slides-2/server/lib/chunked-upload-session.ts +195 -0
  934. package/corpus/templates/slides-2/server/lib/comment-notifications.ts +184 -0
  935. package/corpus/templates/slides-2/server/lib/deck-access-requests.ts +102 -0
  936. package/corpus/templates/slides-2/server/lib/deck-asset-scope.ts +150 -0
  937. package/corpus/templates/slides-2/server/lib/deck-export-tracking.ts +119 -0
  938. package/corpus/templates/slides-2/server/lib/deck-templates/a-case-study.ts +154 -0
  939. package/corpus/templates/slides-2/server/lib/deck-templates/a-company.ts +160 -0
  940. package/corpus/templates/slides-2/server/lib/deck-templates/a-pitch.ts +151 -0
  941. package/corpus/templates/slides-2/server/lib/deck-templates/a-quarterly.ts +264 -0
  942. package/corpus/templates/slides-2/server/lib/deck-templates/a-shared.ts +35 -0
  943. package/corpus/templates/slides-2/server/lib/deck-templates/a-update.ts +188 -0
  944. package/corpus/templates/slides-2/server/lib/deck-templates/a-workshop.ts +196 -0
  945. package/corpus/templates/slides-2/server/lib/deck-templates/b-keynote.ts +131 -0
  946. package/corpus/templates/slides-2/server/lib/deck-templates/b-lesson.ts +209 -0
  947. package/corpus/templates/slides-2/server/lib/deck-templates/b-manifesto.ts +149 -0
  948. package/corpus/templates/slides-2/server/lib/deck-templates/b-portfolio.ts +144 -0
  949. package/corpus/templates/slides-2/server/lib/deck-templates/b-research.ts +221 -0
  950. package/corpus/templates/slides-2/server/lib/deck-templates/b-roadmap.ts +264 -0
  951. package/corpus/templates/slides-2/server/lib/deck-templates/b-shared.ts +44 -0
  952. package/corpus/templates/slides-2/server/lib/deck-templates/group-a.ts +16 -0
  953. package/corpus/templates/slides-2/server/lib/deck-templates/group-b.ts +16 -0
  954. package/corpus/templates/slides-2/server/lib/deck-templates/legacy.ts +567 -0
  955. package/corpus/templates/slides-2/server/lib/deck-templates.ts +60 -0
  956. package/corpus/templates/slides-2/server/lib/deck-versions.ts +233 -0
  957. package/corpus/templates/slides-2/server/lib/design-system-workflows.ts +22 -0
  958. package/corpus/templates/slides-2/server/lib/emails.ts +84 -0
  959. package/corpus/templates/slides-2/server/lib/env-config.ts +15 -0
  960. package/corpus/templates/slides-2/server/lib/fetch-remote-image.ts +245 -0
  961. package/corpus/templates/slides-2/server/lib/generation-completion.ts +278 -0
  962. package/corpus/templates/slides-2/server/lib/google-docs-access.ts +51 -0
  963. package/corpus/templates/slides-2/server/lib/google-docs-error.ts +54 -0
  964. package/corpus/templates/slides-2/server/lib/google-docs-oauth.ts +422 -0
  965. package/corpus/templates/slides-2/server/lib/google-fonts.ts +509 -0
  966. package/corpus/templates/slides-2/server/lib/google-oauth-preflight.ts +119 -0
  967. package/corpus/templates/slides-2/server/lib/google-slides-export-availability.ts +55 -0
  968. package/corpus/templates/slides-2/server/lib/image-proxy-response.ts +16 -0
  969. package/corpus/templates/slides-2/server/lib/image-proxy-url.ts +155 -0
  970. package/corpus/templates/slides-2/server/lib/import-asset-storage.ts +214 -0
  971. package/corpus/templates/slides-2/server/lib/imported-asset-batch.ts +218 -0
  972. package/corpus/templates/slides-2/server/lib/legacy-slide-source.ts +692 -0
  973. package/corpus/templates/slides-2/server/lib/media-search-providers.ts +216 -0
  974. package/corpus/templates/slides-2/server/lib/native-creative-context.ts +295 -0
  975. package/corpus/templates/slides-2/server/lib/pdf-parse-setup.ts +115 -0
  976. package/corpus/templates/slides-2/server/lib/provider-api.ts +57 -0
  977. package/corpus/templates/slides-2/server/lib/request-wait-until.ts +30 -0
  978. package/corpus/templates/slides-2/server/lib/shared-deck.ts +29 -0
  979. package/corpus/templates/slides-2/server/lib/slide-asset-references.ts +309 -0
  980. package/corpus/templates/slides-2/server/lib/slide-content-patch.ts +1004 -0
  981. package/corpus/templates/slides-2/server/lib/slide-hygiene.ts +731 -0
  982. package/corpus/templates/slides-2/server/lib/slide-image-insertion.ts +136 -0
  983. package/corpus/templates/slides-2/server/lib/slide-reveal-issues.ts +41 -0
  984. package/corpus/templates/slides-2/server/lib/slide-source-editing/babel-walk.ts +117 -0
  985. package/corpus/templates/slides-2/server/lib/slide-source-editing/batch-edit.ts +152 -0
  986. package/corpus/templates/slides-2/server/lib/slide-source-editing/edit-ops.ts +1478 -0
  987. package/corpus/templates/slides-2/server/lib/slide-source-editing/image-target.ts +128 -0
  988. package/corpus/templates/slides-2/server/lib/slide-source-editing/text-diff.ts +23 -0
  989. package/corpus/templates/slides-2/server/lib/slide-source-limits.ts +9 -0
  990. package/corpus/templates/slides-2/server/lib/slide-source.ts +1786 -0
  991. package/corpus/templates/slides-2/server/lib/slide-theme-demo-sources.ts +2106 -0
  992. package/corpus/templates/slides-2/server/lib/slide-themes.ts +2174 -0
  993. package/corpus/templates/slides-2/server/lib/slide-worker-runtime.ts +1995 -0
  994. package/corpus/templates/slides-2/server/lib/slides-tracking.ts +73 -0
  995. package/corpus/templates/slides-2/server/lib/source-import.ts +213 -0
  996. package/corpus/templates/slides-2/server/lib/svgl.ts +364 -0
  997. package/corpus/templates/slides-2/server/lib/tenant-files.ts +179 -0
  998. package/corpus/templates/slides-2/server/lib/upload-storage-status.ts +9 -0
  999. package/corpus/templates/slides-2/server/lib/uploaded-asset-cleanup-outbox.ts +521 -0
  1000. package/corpus/templates/slides-2/server/lib/uploaded-asset-object-lifecycle.ts +404 -0
  1001. package/corpus/templates/slides-2/server/lib/uploaded-fonts.ts +696 -0
  1002. package/corpus/templates/slides-2/server/lib/uploaded-reference-storage.ts +77 -0
  1003. package/corpus/templates/slides-2/server/lib/validate-slide-animations.ts +341 -0
  1004. package/corpus/templates/slides-2/server/middleware/auth.ts +6 -0
  1005. package/corpus/templates/slides-2/server/plugins/_dev-upload-stub.ts +6 -0
  1006. package/corpus/templates/slides-2/server/plugins/agent-chat.ts +402 -0
  1007. package/corpus/templates/slides-2/server/plugins/auth.ts +31 -0
  1008. package/corpus/templates/slides-2/server/plugins/collab.ts +30 -0
  1009. package/corpus/templates/slides-2/server/plugins/config.ts +6 -0
  1010. package/corpus/templates/slides-2/server/plugins/core-routes.ts +30 -0
  1011. package/corpus/templates/slides-2/server/plugins/creative-context.ts +187 -0
  1012. package/corpus/templates/slides-2/server/plugins/db.ts +462 -0
  1013. package/corpus/templates/slides-2/server/plugins/feature-flags.ts +5 -0
  1014. package/corpus/templates/slides-2/server/plugins/labs.ts +8 -0
  1015. package/corpus/templates/slides-2/server/plugins/orphaned-asset-cleanup.ts +17 -0
  1016. package/corpus/templates/slides-2/server/plugins/otel.ts +6 -0
  1017. package/corpus/templates/slides-2/server/plugins/transactional-emails.ts +5 -0
  1018. package/corpus/templates/slides-2/server/register-secrets.ts +209 -0
  1019. package/corpus/templates/slides-2/server/routes/[...page].get.ts +5 -0
  1020. package/corpus/templates/slides-2/server/routes/[...page].head.ts +1 -0
  1021. package/corpus/templates/slides-2/server/routes/[base]/_agent-native/google-docs/auth-url.get.ts +1 -0
  1022. package/corpus/templates/slides-2/server/routes/[base]/_agent-native/google-docs/callback.get.ts +1 -0
  1023. package/corpus/templates/slides-2/server/routes/_agent-native/google-docs/auth-url.get.ts +1 -0
  1024. package/corpus/templates/slides-2/server/routes/_agent-native/google-docs/callback.get.ts +1 -0
  1025. package/corpus/templates/slides-2/server/routes/api/assets/upload-video.post.ts +1 -0
  1026. package/corpus/templates/slides-2/server/routes/api/assets/upload.post.ts +1 -0
  1027. package/corpus/templates/slides-2/server/routes/api/assets/video-uploads.delete.ts +1 -0
  1028. package/corpus/templates/slides-2/server/routes/api/deck-agent-context.json.get.ts +105 -0
  1029. package/corpus/templates/slides-2/server/routes/api/decks/events.get.ts +1 -0
  1030. package/corpus/templates/slides-2/server/routes/api/demo.get.ts +1 -0
  1031. package/corpus/templates/slides-2/server/routes/api/exports/[filename].get.ts +221 -0
  1032. package/corpus/templates/slides-2/server/routes/api/exports/google-slides.post.ts +240 -0
  1033. package/corpus/templates/slides-2/server/routes/api/exports/html.post.ts +67 -0
  1034. package/corpus/templates/slides-2/server/routes/api/exports/pptx.post.ts +100 -0
  1035. package/corpus/templates/slides-2/server/routes/api/gen-preview/[...].get.ts +24 -0
  1036. package/corpus/templates/slides-2/server/routes/api/generated/[...].get.ts +24 -0
  1037. package/corpus/templates/slides-2/server/routes/api/image-proxy.get.ts +518 -0
  1038. package/corpus/templates/slides-2/server/routes/api/import-assets/[token].get.ts +70 -0
  1039. package/corpus/templates/slides-2/server/routes/api/preview-images.get.ts +20 -0
  1040. package/corpus/templates/slides-2/server/routes/api/share/[token].get.ts +1 -0
  1041. package/corpus/templates/slides-2/server/routes/api/uploads-chunked/[sessionId]/chunk.post.ts +1 -0
  1042. package/corpus/templates/slides-2/server/routes/api/uploads-chunked/[sessionId]/status.get.ts +1 -0
  1043. package/corpus/templates/slides-2/server/routes/api/uploads-chunked/[sessionId].delete.ts +1 -0
  1044. package/corpus/templates/slides-2/server/routes/api/uploads-chunked/start.post.ts +1 -0
  1045. package/corpus/templates/slides-2/server/routes/api/uploads.delete.ts +1 -0
  1046. package/corpus/templates/slides-2/server/routes/api/uploads.post.ts +1 -0
  1047. package/corpus/templates/slides-2/server/workspace-defaults.ts +196 -0
  1048. package/corpus/templates/slides-2/shared/action-ui.ts +147 -0
  1049. package/corpus/templates/slides-2/shared/agent-readable.ts +2 -0
  1050. package/corpus/templates/slides-2/shared/api.ts +406 -0
  1051. package/corpus/templates/slides-2/shared/app-state-tabs.ts +30 -0
  1052. package/corpus/templates/slides-2/shared/app-storage.ts +9 -0
  1053. package/corpus/templates/slides-2/shared/aspect-ratios.ts +49 -0
  1054. package/corpus/templates/slides-2/shared/blank-slide.ts +179 -0
  1055. package/corpus/templates/slides-2/shared/client-compatibility.ts +2 -0
  1056. package/corpus/templates/slides-2/shared/contrast-audit.ts +255 -0
  1057. package/corpus/templates/slides-2/shared/deck-access.ts +26 -0
  1058. package/corpus/templates/slides-2/shared/deck-app-scope.ts +14 -0
  1059. package/corpus/templates/slides-2/shared/deck-content.ts +37 -0
  1060. package/corpus/templates/slides-2/shared/deck-history-control.ts +79 -0
  1061. package/corpus/templates/slides-2/shared/deck-scope.ts +5 -0
  1062. package/corpus/templates/slides-2/shared/deck-title.ts +199 -0
  1063. package/corpus/templates/slides-2/shared/deck-write.ts +61 -0
  1064. package/corpus/templates/slides-2/shared/design-flags.ts +7 -0
  1065. package/corpus/templates/slides-2/shared/design-system-validation.ts +88 -0
  1066. package/corpus/templates/slides-2/shared/editor-control.ts +120 -0
  1067. package/corpus/templates/slides-2/shared/generation-timing.ts +19 -0
  1068. package/corpus/templates/slides-2/shared/google-docs.ts +69 -0
  1069. package/corpus/templates/slides-2/shared/labs.ts +10 -0
  1070. package/corpus/templates/slides-2/shared/overview-navigation.ts +34 -0
  1071. package/corpus/templates/slides-2/shared/ownership.ts +6 -0
  1072. package/corpus/templates/slides-2/shared/pdf-sidecar.ts +130 -0
  1073. package/corpus/templates/slides-2/shared/presenter-control.ts +111 -0
  1074. package/corpus/templates/slides-2/shared/representative-slide.ts +89 -0
  1075. package/corpus/templates/slides-2/shared/slide-background.ts +30 -0
  1076. package/corpus/templates/slides-2/shared/slide-comment-anchor.ts +117 -0
  1077. package/corpus/templates/slides-2/shared/slide-comment-reactions.ts +47 -0
  1078. package/corpus/templates/slides-2/shared/slide-design-tokens.ts +92 -0
  1079. package/corpus/templates/slides-2/shared/slide-fit.ts +78 -0
  1080. package/corpus/templates/slides-2/shared/slide-ids.ts +133 -0
  1081. package/corpus/templates/slides-2/shared/slide-number.ts +124 -0
  1082. package/corpus/templates/slides-2/shared/slide-object-structure.ts +790 -0
  1083. package/corpus/templates/slides-2/shared/slide-text-range-selection.ts +50 -0
  1084. package/corpus/templates/slides-2/shared/slide-transitions.ts +70 -0
  1085. package/corpus/templates/slides-2/shared/slides-2-transition.ts +194 -0
  1086. package/corpus/templates/slides-2/shared/slides-user-prefs.ts +22 -0
  1087. package/corpus/templates/slides-2/shared/source-import-errors.ts +12 -0
  1088. package/corpus/templates/slides-2/shared/source-runtime-export.ts +76 -0
  1089. package/corpus/templates/slides-2/shared/upload-types.ts +41 -0
  1090. package/corpus/templates/slides-2/ssr-entry.ts +11 -0
  1091. package/corpus/templates/slides-2/tsconfig.json +27 -0
  1092. package/corpus/templates/slides-2/vite.config.ts +77 -0
  1093. package/corpus/templates/slides-2/vitest.config.ts +28 -0
  1094. package/corpus/templates/tasks/.agents/skills/actions/references/action-fields.md +1 -1
  1095. package/package.json +1 -1
  1096. package/corpus/templates/design/.agents/skills/shader-fills/SKILL.md +0 -182
  1097. package/corpus/templates/design/actions/apply-shader-fill.ts +0 -450
  1098. package/corpus/templates/design/actions/apply-shader.ts +0 -257
  1099. package/corpus/templates/design/actions/preview-shader-fill.ts +0 -157
  1100. package/corpus/templates/design/app/components/design/inspector/GlslShaderPanel.tsx +0 -1144
  1101. package/corpus/templates/design/app/components/design/inspector/SHADER_INTEGRATION.md +0 -450
  1102. package/corpus/templates/design/app/components/design/inspector/ShaderControls.stories.tsx +0 -71
  1103. package/corpus/templates/design/app/components/design/inspector/ShaderControls.tsx +0 -555
  1104. package/corpus/templates/design/app/components/design/inspector/ShaderEffectRow.tsx +0 -105
  1105. package/corpus/templates/design/app/components/design/inspector/ShaderFillsPanel.tsx +0 -433
  1106. package/corpus/templates/design/app/components/design/inspector/color-picker-shader-pane.tsx +0 -648
  1107. package/corpus/templates/design/shared/shader-fill.ts +0 -174
  1108. package/corpus/templates/design/shared/shader-presets.ts +0 -1523
@@ -0,0 +1,1995 @@
1
+ import { fileURLToPath } from "node:url";
2
+
3
+ import * as t from "@babel/types";
4
+ import postcss from "postcss";
5
+
6
+ import {
7
+ SlideTransitionSchema,
8
+ type SlideTransition,
9
+ } from "../../shared/slides-2-transition.js";
10
+ import { parseSource, walkAll } from "./slide-source-editing/babel-walk.js";
11
+ import {
12
+ isSlideSourceWithinByteLimit,
13
+ MAX_SLIDE_SOURCE_BYTES,
14
+ SLIDE_SOURCE_BYTE_LIMIT_MESSAGE,
15
+ } from "./slide-source-limits.js";
16
+ import { findStaticLocalPageArray, SlideSourceError } from "./slide-source.js";
17
+
18
+ export const MAX_REACT_SLIDE_SOURCE_BYTES = MAX_SLIDE_SOURCE_BYTES;
19
+ export const MAX_REACT_SLIDE_AST_NODES = 50_000;
20
+ export const MAX_REACT_SLIDE_WORKER_SOURCE_LENGTH = 4 * 1024 * 1024;
21
+ export const REACT_SLIDE_WORKER_TIMEOUT_MS = 2_500;
22
+
23
+ export type Slides2Design = {
24
+ palette: { bg: string; text: string; accent: string };
25
+ fonts: { display: string; body: string };
26
+ typeScale: { hero: number; body: number };
27
+ radius: number;
28
+ };
29
+
30
+ export type Slides2Meta = {
31
+ title?: string;
32
+ theme?: string;
33
+ createdAt?: string;
34
+ };
35
+
36
+ export type SlideWorkerRuntime = {
37
+ kind: "open-slide-react-worker-v1";
38
+ workerSource: string;
39
+ page: { current: number; total: number };
40
+ assetUrls: Record<string, string>;
41
+ styles: string[];
42
+ design?: Slides2Design;
43
+ meta?: Slides2Meta;
44
+ transition?: SlideTransition;
45
+ timeoutMs: typeof REACT_SLIDE_WORKER_TIMEOUT_MS;
46
+ };
47
+
48
+ type PreparedModule = {
49
+ source: string;
50
+ design?: Slides2Design;
51
+ meta?: Slides2Meta;
52
+ transition?: SlideTransition;
53
+ styles: string[];
54
+ };
55
+
56
+ const MAX_STYLE_LENGTH = 64 * 1024;
57
+ const MAX_TOTAL_STYLE_LENGTH = 128 * 1024;
58
+ const MAX_STATIC_VALUE_DEPTH = 16;
59
+ const MAX_STATIC_VALUE_NODES = 5_000;
60
+ const REDUCED_MOTION_STEPS_CSS =
61
+ "@media (prefers-reduced-motion: reduce) { [data-slides2-step] { transition-duration: 0ms !important; } }";
62
+ const SAFE_CSS_FUNCTIONS = new Set([
63
+ "calc",
64
+ "clamp",
65
+ "color",
66
+ "color-mix",
67
+ "conic-gradient",
68
+ "hsl",
69
+ "hsla",
70
+ "hwb",
71
+ "lab",
72
+ "lch",
73
+ "linear-gradient",
74
+ "max",
75
+ "min",
76
+ "oklab",
77
+ "oklch",
78
+ "polygon",
79
+ "radial-gradient",
80
+ "repeating-conic-gradient",
81
+ "repeating-linear-gradient",
82
+ "repeating-radial-gradient",
83
+ "rgb",
84
+ "rgba",
85
+ "rotate",
86
+ "rotatex",
87
+ "rotatey",
88
+ "rotatez",
89
+ "scale",
90
+ "scalex",
91
+ "scaley",
92
+ "scalez",
93
+ "skew",
94
+ "skewx",
95
+ "skewy",
96
+ "translate",
97
+ "translatex",
98
+ "translatey",
99
+ "translatez",
100
+ "var",
101
+ ]);
102
+ const BLOCKED_CSS_PROPERTIES = new Set(["-moz-binding", "behavior", "src"]);
103
+ const BLOCKED_GLOBALS = new Set([
104
+ "BroadcastChannel",
105
+ "Buffer",
106
+ "Deno",
107
+ "EventSource",
108
+ "FormData",
109
+ "Function",
110
+ "Headers",
111
+ "MessageChannel",
112
+ "Proxy",
113
+ "Reflect",
114
+ "Request",
115
+ "Response",
116
+ "SharedArrayBuffer",
117
+ "SharedWorker",
118
+ "URL",
119
+ "URLSearchParams",
120
+ "WebSocket",
121
+ "Worker",
122
+ "XMLHttpRequest",
123
+ "Atomics",
124
+ "Blob",
125
+ "Bun",
126
+ "BunFile",
127
+ "CacheStorage",
128
+ "EventTarget",
129
+ "WebAssembly",
130
+ "caches",
131
+ "close",
132
+ "crypto",
133
+ "document",
134
+ "eval",
135
+ "fetch",
136
+ "global",
137
+ "globalThis",
138
+ "indexedDB",
139
+ "importScripts",
140
+ "localStorage",
141
+ "location",
142
+ "module",
143
+ "navigator",
144
+ "onmessage",
145
+ "postMessage",
146
+ "process",
147
+ "queueMicrotask",
148
+ "require",
149
+ "self",
150
+ "sessionStorage",
151
+ "setInterval",
152
+ "setTimeout",
153
+ "window",
154
+ "WebTransport",
155
+ "console",
156
+ ]);
157
+ const BLOCKED_PROPERTIES = new Set([
158
+ "__defineGetter__",
159
+ "__defineSetter__",
160
+ "__lookupGetter__",
161
+ "__lookupSetter__",
162
+ "__proto__",
163
+ "callee",
164
+ "caller",
165
+ "constructor",
166
+ "eval",
167
+ "prototype",
168
+ "repeat",
169
+ "flat",
170
+ "flatMap",
171
+ "concat",
172
+ "fill",
173
+ "copyWithin",
174
+ "sort",
175
+ "reverse",
176
+ "splice",
177
+ "unshift",
178
+ "shift",
179
+ "pop",
180
+ "slice",
181
+ "call",
182
+ "apply",
183
+ "bind",
184
+ ]);
185
+ const BOUNDED_MEMBER_METHODS = new Set([
186
+ "map",
187
+ "push",
188
+ "join",
189
+ "padStart",
190
+ "replace",
191
+ ]);
192
+ const SAFE_MATH_METHODS = new Set([
193
+ "abs",
194
+ "atan2",
195
+ "cos",
196
+ "hypot",
197
+ "max",
198
+ "min",
199
+ "sin",
200
+ ]);
201
+ const SAFE_VALUE_METHODS = new Set(["includes", "toFixed", "X", "Y"]);
202
+ const SAFE_OBJECT_METHODS = new Set([
203
+ "entries",
204
+ "fromEntries",
205
+ "hasOwn",
206
+ "is",
207
+ "keys",
208
+ "values",
209
+ ]);
210
+ const SAFE_ARRAY_METHODS = new Set(["isArray"]);
211
+ const SAFE_REACT_MEMBERS = new Set([
212
+ "Children",
213
+ "Fragment",
214
+ "cloneElement",
215
+ "createContext",
216
+ "createElement",
217
+ "forwardRef",
218
+ "isValidElement",
219
+ "memo",
220
+ "useCallback",
221
+ "useContext",
222
+ "useId",
223
+ "useMemo",
224
+ "useState",
225
+ ]);
226
+ const UNSUPPORTED_REACT_EFFECT_HOOKS = new Set([
227
+ "useEffect",
228
+ "useLayoutEffect",
229
+ ]);
230
+ const SAFE_HTML_TAGS = new Set([
231
+ "a",
232
+ "article",
233
+ "aside",
234
+ "b",
235
+ "blockquote",
236
+ "br",
237
+ "caption",
238
+ "cite",
239
+ "code",
240
+ "dd",
241
+ "del",
242
+ "details",
243
+ "div",
244
+ "dl",
245
+ "dt",
246
+ "em",
247
+ "figcaption",
248
+ "figure",
249
+ "footer",
250
+ "h1",
251
+ "h2",
252
+ "h3",
253
+ "h4",
254
+ "h5",
255
+ "h6",
256
+ "header",
257
+ "hr",
258
+ "i",
259
+ "img",
260
+ "ins",
261
+ "kbd",
262
+ "li",
263
+ "main",
264
+ "mark",
265
+ "nav",
266
+ "ol",
267
+ "p",
268
+ "q",
269
+ "s",
270
+ "section",
271
+ "small",
272
+ "source",
273
+ "span",
274
+ "strong",
275
+ "sub",
276
+ "sup",
277
+ "table",
278
+ "tbody",
279
+ "td",
280
+ "tfoot",
281
+ "th",
282
+ "thead",
283
+ "tr",
284
+ "u",
285
+ "ul",
286
+ "video",
287
+ "svg",
288
+ "g",
289
+ "path",
290
+ "circle",
291
+ "ellipse",
292
+ "line",
293
+ "polygon",
294
+ "polyline",
295
+ "rect",
296
+ "text",
297
+ "tspan",
298
+ "defs",
299
+ "lineargradient",
300
+ "radialgradient",
301
+ "stop",
302
+ "clippath",
303
+ "mask",
304
+ "pattern",
305
+ "marker",
306
+ "symbol",
307
+ "use",
308
+ ]);
309
+ const SAFE_HTML_ATTRIBUTES = new Set([
310
+ "alt",
311
+ "align",
312
+ "autoplay",
313
+ "aria-label",
314
+ "aria-hidden",
315
+ "aria-roledescription",
316
+ "class",
317
+ "colspan",
318
+ "controls",
319
+ "cx",
320
+ "cy",
321
+ "d",
322
+ "decoding",
323
+ "dir",
324
+ "draggable",
325
+ "fill",
326
+ "fill-opacity",
327
+ "fill-rule",
328
+ "focusable",
329
+ "font-family",
330
+ "font-size",
331
+ "font-weight",
332
+ "height",
333
+ "hidden",
334
+ "href",
335
+ "id",
336
+ "lang",
337
+ "loading",
338
+ "marker-end",
339
+ "marker-mid",
340
+ "marker-start",
341
+ "offset",
342
+ "opacity",
343
+ "points",
344
+ "poster",
345
+ "preload",
346
+ "preserveaspectratio",
347
+ "r",
348
+ "rx",
349
+ "rel",
350
+ "role",
351
+ "rowspan",
352
+ "scope",
353
+ "shape-rendering",
354
+ "src",
355
+ "loop",
356
+ "muted",
357
+ "playsinline",
358
+ "type",
359
+ "stop-color",
360
+ "stop-opacity",
361
+ "stroke",
362
+ "stroke-dasharray",
363
+ "stroke-dashoffset",
364
+ "stroke-linecap",
365
+ "stroke-linejoin",
366
+ "stroke-opacity",
367
+ "stroke-width",
368
+ "style",
369
+ "tabindex",
370
+ "text-anchor",
371
+ "title",
372
+ "transform",
373
+ "vector-effect",
374
+ "viewbox",
375
+ "width",
376
+ "x",
377
+ "x1",
378
+ "x2",
379
+ "xmlns",
380
+ "y",
381
+ "y1",
382
+ "y2",
383
+ "data-slide-loc",
384
+ "data-slides2-step",
385
+ ]);
386
+
387
+ const WORKER_ENTRY = String.raw`
388
+ import React, { Children, cloneElement, createContext, isValidElement, useContext } from "react";
389
+ import { renderToStaticMarkup } from "react-dom/server.browser";
390
+ import { parseFragment, serialize } from "parse5";
391
+ import postcss from "postcss";
392
+ import SlidePage from "virtual:slide-page";
393
+ import * as Slides2Core from "virtual:slide-page-shim";
394
+
395
+ const RenderContext = createContext(null);
396
+ const LIMITS = { values: 0, bytes: 0, stepCount: 0, remainingSteps: Infinity };
397
+ const MAX_VALUES = 50_000;
398
+ const MAX_BYTES = 16 * 1024 * 1024;
399
+ const MAX_HTML = 1024 * 1024;
400
+ const MAX_NODES = 20_000;
401
+ const MAX_DEPTH = 64;
402
+ const blockedCssFunctions = new Set(["url", "expression", "image", "image-set", "cross-fade", "paint", "element"]);
403
+ const safeCssFunctions = new Set(${JSON.stringify([...SAFE_CSS_FUNCTIONS])});
404
+ const blockedCssProperties = new Set(${JSON.stringify([...BLOCKED_CSS_PROPERTIES])});
405
+ const safeTags = new Set(${JSON.stringify([...SAFE_HTML_TAGS])});
406
+ const safeAttributes = new Set(${JSON.stringify([...SAFE_HTML_ATTRIBUTES])});
407
+ const localSvgReferenceProperties = new Set(["fill", "stroke", "marker-end", "marker-mid", "marker-start"]);
408
+
409
+ function fail(message) { throw new Error(message); }
410
+ function reserve(values, bytes = 0) {
411
+ if (!Number.isSafeInteger(values) || values < 0 || LIMITS.values + values > MAX_VALUES) fail("Slide render exceeded its value budget.");
412
+ if (!Number.isSafeInteger(bytes) || bytes < 0 || LIMITS.bytes + bytes > MAX_BYTES) fail("Slide render exceeded its memory estimate.");
413
+ LIMITS.values += values;
414
+ LIMITS.bytes += bytes;
415
+ }
416
+ function estimate(value, depth = 0, seen = new Set()) {
417
+ if (depth > 16) fail("Slide data is nested too deeply.");
418
+ if (typeof value === "string") { reserve(1, value.length * 2); return; }
419
+ if (value == null || typeof value === "boolean" || typeof value === "number") { reserve(1, 16); return; }
420
+ if (typeof value === "function") { reserve(1, 64); return; }
421
+ if (typeof value !== "object" || seen.has(value)) { reserve(1, 32); return; }
422
+ seen.add(value);
423
+ reserve(1, 64);
424
+ if (Array.isArray(value)) {
425
+ if (value.length > MAX_VALUES) fail("Slide data array is too large.");
426
+ for (const child of value) estimate(child, depth + 1, seen);
427
+ return;
428
+ }
429
+ const keys = Object.keys(value);
430
+ if (keys.length > 256) fail("Slide data object is too large.");
431
+ for (const key of keys) estimate(value[key], depth + 1, seen);
432
+ }
433
+ export function __slideRuntimeMap(array, callback, thisArg) {
434
+ if (!Array.isArray(array) || typeof callback !== "function") fail("Only static arrays can be mapped in slide source.");
435
+ if (array.length > MAX_VALUES) fail("Slide render exceeded its map budget.");
436
+ reserve(array.length, array.length * 8);
437
+ const result = new Array(array.length);
438
+ for (let index = 0; index < array.length; index++) {
439
+ if (!(index in array)) continue;
440
+ const value = callback.call(thisArg, array[index], index, array);
441
+ estimate(value);
442
+ result[index] = value;
443
+ }
444
+ return result;
445
+ }
446
+ export function __slideRuntimePush(array, ...values) {
447
+ if (!Array.isArray(array) || values.some((value) => value === undefined)) fail("Only explicit values can be appended in slide source.");
448
+ if (array.length + values.length > MAX_VALUES) fail("Slide render exceeded its array budget.");
449
+ for (const value of values) estimate(value);
450
+ for (const value of values) array[array.length] = value;
451
+ return array.length;
452
+ }
453
+ export function __slideRuntimeJoin(array, separator = ",") {
454
+ if (!Array.isArray(array) || array.length > MAX_VALUES || !isPrimitive(separator)) fail("Only bounded primitive arrays can be joined in slide source.");
455
+ reserve(array.length, 0);
456
+ if (!array.every(isPrimitive)) fail("Only bounded primitive arrays can be joined in slide source.");
457
+ const joiner = String(separator);
458
+ let length = Math.max(0, array.length - 1) * joiner.length;
459
+ for (const value of array) length += value == null ? 0 : String(value).length;
460
+ if (length > MAX_HTML) fail("Slide render string is too large.");
461
+ reserve(1, length * 2);
462
+ return array.join(joiner);
463
+ }
464
+ export function __slideRuntimePadStart(value, length, padding) {
465
+ if (!isPrimitive(value) || (padding !== undefined && !isPrimitive(padding))) fail("Slide padding accepts primitive text only.");
466
+ const text = String(value);
467
+ const requested = Number(length);
468
+ if (!Number.isFinite(requested) || requested > MAX_HTML || requested < 0) fail("Slide padding is out of bounds.");
469
+ const outputLength = Math.max(text.length, Math.trunc(requested));
470
+ if (outputLength > MAX_HTML) fail("Slide padding is out of bounds.");
471
+ reserve(1, outputLength * 2);
472
+ const result = text.padStart(requested, padding === undefined ? " " : String(padding));
473
+ return result;
474
+ }
475
+ export function __slideRuntimeReplace(value, pattern, replacement) {
476
+ if (!isPrimitive(value) || typeof replacement !== "string" || replacement.includes("$") || (typeof pattern !== "string" && !(pattern instanceof RegExp))) fail("Slide replacement must use primitive text and a literal replacement string.");
477
+ const text = String(value);
478
+ const matches = [];
479
+ if (pattern instanceof RegExp) {
480
+ const regex = new RegExp(pattern.source, pattern.flags);
481
+ let match;
482
+ while ((match = regex.exec(text))) {
483
+ reserve(1, 24);
484
+ matches.push({ index: match.index, length: match[0].length });
485
+ if (!regex.global) break;
486
+ if (match[0].length === 0) regex.lastIndex++;
487
+ if (matches.length > MAX_VALUES) fail("Slide replacement has too many matches.");
488
+ }
489
+ } else {
490
+ const search = String(pattern);
491
+ let cursor = 0;
492
+ if (!search) { reserve(1, 24); matches.push({ index: 0, length: 0 }); }
493
+ else while ((cursor = text.indexOf(search, cursor)) !== -1) {
494
+ reserve(1, 24);
495
+ matches.push({ index: cursor, length: search.length });
496
+ cursor += search.length;
497
+ if (matches.length > MAX_VALUES) fail("Slide replacement has too many matches.");
498
+ }
499
+ }
500
+ const outputLength = text.length + matches.length * replacement.length - matches.reduce((size, match) => size + match.length, 0);
501
+ if (outputLength > MAX_HTML) fail("Slide render string is too large.");
502
+ reserve(matches.length * 2 + 1, outputLength * 2);
503
+ const parts = new Array(matches.length * 2 + 1);
504
+ let cursor = 0;
505
+ let part = 0;
506
+ for (const match of matches) {
507
+ parts[part++] = text.slice(cursor, match.index);
508
+ parts[part++] = replacement;
509
+ cursor = match.index + match.length;
510
+ }
511
+ parts[part] = text.slice(cursor);
512
+ return parts.join("");
513
+ }
514
+ function isPrimitive(value) { return value == null || ["string", "number", "boolean"].includes(typeof value); }
515
+
516
+ export function SlideRuntimeProvider({ value, children }) {
517
+ return React.createElement(RenderContext.Provider, { value }, children);
518
+ }
519
+ export function useSlidePageNumber() {
520
+ const context = useContext(RenderContext);
521
+ if (!context) fail("useSlidePageNumber must be called from a rendered slide page.");
522
+ return { current: context.page.current, total: context.page.total };
523
+ }
524
+ export function useIsActivePage() {
525
+ return useContext(RenderContext)?.isActivePage ?? false;
526
+ }
527
+ export function Step({ children, duration = 180, _revealed }) {
528
+ const revealed = _revealed ?? true;
529
+ return React.createElement("div", {
530
+ "data-slides2-step": revealed ? "revealed" : "pending",
531
+ style: {
532
+ opacity: revealed ? 1 : 0,
533
+ visibility: revealed ? "visible" : "hidden",
534
+ transition: "opacity " + duration + "ms cubic-bezier(0, 0, 0.2, 1)",
535
+ },
536
+ }, children);
537
+ }
538
+ export function Steps({ children }) {
539
+ const context = useContext(RenderContext);
540
+ const childrenArray = Children.toArray(children);
541
+ let count = 0;
542
+ for (const child of childrenArray) if (isValidElement(child) && child.type === Step) count++;
543
+ LIMITS.stepCount += count;
544
+ const revealed = Math.min(count, LIMITS.remainingSteps);
545
+ LIMITS.remainingSteps = Math.max(0, LIMITS.remainingSteps - revealed);
546
+ let index = 0;
547
+ return React.createElement(React.Fragment, null, ...childrenArray.map((child, key) => {
548
+ if (isValidElement(child) && child.type === Step) {
549
+ const stepIndex = index++;
550
+ return cloneElement(child, { key: child.key ?? key, _revealed: stepIndex < revealed });
551
+ }
552
+ return child;
553
+ }));
554
+ }
555
+ export function ImagePlaceholder({ label = "Image placeholder", children, ...props }) {
556
+ return React.createElement("div", {
557
+ "data-slide-loc": props["data-slide-loc"],
558
+ "data-slide-placeholder": true,
559
+ "aria-label": label,
560
+ style: { border: "2px dashed currentColor", display: "flex", alignItems: "center", justifyContent: "center" },
561
+ }, children ?? label);
562
+ }
563
+ export function MorphElement({ id, children, as = "div", ...props }) {
564
+ return React.createElement(as, { ...props, "data-slides2-morph": id }, children);
565
+ }
566
+
567
+ function safeStyle(value) {
568
+ let root;
569
+ try { root = postcss.parse("x{" + value + "}", { from: undefined }); } catch {
570
+ // coercion-ok: Invalid imported declarations are discarded at the SVG sanitization boundary.
571
+ return "";
572
+ }
573
+ const rule = root.nodes[0];
574
+ if (!rule || rule.type !== "rule") return "";
575
+ for (const child of [...(rule.nodes || [])]) {
576
+ if (child.type !== "decl") { child.remove(); continue; }
577
+ const property = child.prop.toLowerCase();
578
+ const text = child.value;
579
+ if (!/^(?:--[a-z0-9_-]+|[a-z][a-z0-9-]*)$/.test(property) || blockedCssProperties.has(property) || /[\\\u0000-\u001f\u007f{}<>@]|\/\*|\*\/|javascript:/i.test(text)) { child.remove(); continue; }
580
+ if (/\b(?:url|expression|image-set|cross-fade|paint|element)\s*\(/i.test(text)) {
581
+ const local = localSvgReferenceProperties.has(property) && /^url\(\s*#[a-z][a-z0-9_.:-]*\s*\)$/i.test(text.trim());
582
+ if (!local) { child.remove(); continue; }
583
+ }
584
+ const variables = [...text.matchAll(/var\(\s*(--[a-z0-9_-]+)/gi)];
585
+ if (/\bvar\s*\(/i.test(text.replace(/var\(\s*--[a-z0-9_-]+\s*(?:,\s*[^()]*)?\)/gi, ""))) { child.remove(); continue; }
586
+ if (variables.some((match) => !/^(?:--deck-|--ds-|--slides2-|--d$)/i.test(match[1]))) { child.remove(); continue; }
587
+ let unsafeFunction = false;
588
+ for (const match of text.matchAll(/([a-z][a-z0-9-]*)\s*\(/gi)) {
589
+ const name = match[1].toLowerCase();
590
+ if (blockedCssFunctions.has(name) || !safeCssFunctions.has(name)) unsafeFunction = true;
591
+ }
592
+ if (unsafeFunction) child.remove();
593
+ }
594
+ return (rule.nodes || []).map((node) => node.toString()).join(";");
595
+ }
596
+
597
+ function sanitizeHtml(html) {
598
+ if (typeof html !== "string" || html.length > MAX_HTML) fail("Slide HTML is too large.");
599
+ const fragment = parseFragment(html);
600
+ const topLevelChildren = fragment.childNodes || [];
601
+ for (let index = topLevelChildren.length - 1; index >= 0; index--) {
602
+ const node = topLevelChildren[index];
603
+ if (node.tagName?.toLowerCase() !== "link") continue;
604
+ const attributes = new Map(
605
+ (node.attrs || []).map((attribute) => [
606
+ attribute.name.toLowerCase(),
607
+ attribute.value,
608
+ ]),
609
+ );
610
+ // React's server renderer prepends this hint; the host resolves the handle on the image itself.
611
+ if (
612
+ attributes.get("rel")?.toLowerCase() === "preload" &&
613
+ attributes.get("as")?.toLowerCase() === "image" &&
614
+ /^asset:\/\/[A-Za-z0-9_-]{1,200}$/.test(
615
+ attributes.get("href") || "",
616
+ )
617
+ ) {
618
+ topLevelChildren.splice(index, 1);
619
+ }
620
+ }
621
+ const stack = [...(fragment.childNodes || [])].map((node) => ({ node, depth: 1, parent: null }));
622
+ const videos = [];
623
+ let count = 0;
624
+ while (stack.length) {
625
+ const { node, depth, parent } = stack.pop();
626
+ if (++count > MAX_NODES || depth > MAX_DEPTH) fail("Slide HTML is too complex.");
627
+ if (node.nodeName === "#text" || node.nodeName === "#comment") continue;
628
+ if (!node.tagName || !safeTags.has(node.tagName.toLowerCase())) fail("Slide contains an unsupported HTML element.");
629
+ const tagName = node.tagName.toLowerCase();
630
+ if (tagName === "video") videos.push(node);
631
+ if (tagName === "source" && parent?.tagName?.toLowerCase() !== "video") fail("Slide sources must be direct children of a video.");
632
+ for (const attribute of [...(node.attrs || [])]) {
633
+ const name = attribute.name.toLowerCase();
634
+ const value = attribute.value;
635
+ if (/^on/i.test(name) || name === "srcdoc" || name === "dangerouslysetinnerhtml" || !safeAttributes.has(name) && !/^(?:aria-[a-z0-9-]+|data-[a-z0-9-]+)$/.test(name)) {
636
+ node.attrs.splice(node.attrs.indexOf(attribute), 1);
637
+ continue;
638
+ }
639
+ if (name === "style") {
640
+ const safe = safeStyle(value);
641
+ if (safe) attribute.value = safe;
642
+ else node.attrs.splice(node.attrs.indexOf(attribute), 1);
643
+ continue;
644
+ }
645
+ if (name === "src") {
646
+ if (!["img", "video", "source"].includes(tagName) || !/^asset:\/\/[A-Za-z0-9_-]{1,200}$/.test(value)) fail("Media references must use uploaded asset handles.");
647
+ }
648
+ if (name === "poster" && (tagName !== "video" || !/^asset:\/\/[A-Za-z0-9_-]{1,200}$/.test(value))) fail("Video posters must use uploaded asset handles.");
649
+ if (name === "preload" && !["none", "metadata", "auto"].includes(value.toLowerCase())) fail("Video preload must be none, metadata, or auto.");
650
+ if (name === "href" && !/^#[A-Za-z_][A-Za-z0-9_.:-]{0,200}$/.test(value)) {
651
+ node.attrs.splice(node.attrs.indexOf(attribute), 1);
652
+ continue;
653
+ }
654
+ if (name === "id" && !/^[A-Za-z_][A-Za-z0-9_.:-]{0,200}$/.test(value)) node.attrs.splice(node.attrs.indexOf(attribute), 1);
655
+ if (name === "data-slide-loc" && !/^\d{1,6}:\d{1,6}$/.test(value)) node.attrs.splice(node.attrs.indexOf(attribute), 1);
656
+ }
657
+ if (tagName === "source" && !(node.attrs || []).some((attribute) => attribute.name.toLowerCase() === "src")) fail("Video sources need an uploaded asset handle.");
658
+ for (const child of node.childNodes || []) stack.push({ node: child, depth: depth + 1, parent: node });
659
+ }
660
+ for (const video of videos) {
661
+ const hasSource = (video.attrs || []).some((attribute) => attribute.name.toLowerCase() === "src") || (video.childNodes || []).some((child) => child.tagName?.toLowerCase() === "source" && (child.attrs || []).some((attribute) => attribute.name.toLowerCase() === "src"));
662
+ if (!hasSource) fail("Video elements need an uploaded asset source.");
663
+ }
664
+ const safe = serialize(fragment);
665
+ if (safe.length > MAX_HTML) fail("Sanitized slide HTML is too large.");
666
+ return safe;
667
+ }
668
+
669
+ function handleMessage(event) {
670
+ const request = event.data;
671
+ const requestId = request && typeof request.requestId === "string" ? request.requestId.slice(0, 80) : "";
672
+ try {
673
+ if (!request || request.type !== "render" || !requestId || !request.page || !Number.isSafeInteger(request.page.current) || !Number.isSafeInteger(request.page.total) || request.page.current < 1 || request.page.total < request.page.current || (request.revealedSteps !== null && (!Number.isInteger(request.revealedSteps) || request.revealedSteps < 0 || request.revealedSteps > 500)) || typeof request.isActivePage !== "boolean") fail("Slide render request is invalid.");
674
+ Slides2Core.__slideRuntimeReset(request.revealedSteps);
675
+ const context = { page: request.page, isActivePage: request.isActivePage, revealedSteps: request.revealedSteps };
676
+ const markup = renderToStaticMarkup(React.createElement(Slides2Core.SlideRuntimeProvider, { value: context }, React.createElement(SlidePage)));
677
+ const html = sanitizeHtml(markup);
678
+ postMessage({ type: "rendered", requestId, html, stepCount: Math.min(500, Slides2Core.__slideRuntimeStepCount()) });
679
+ } catch (error) {
680
+ postMessage({ type: "error", requestId, message: error instanceof Error ? error.message.slice(0, 300) : "Slide rendering failed." });
681
+ }
682
+ }
683
+ self.onmessage = handleMessage;
684
+ `;
685
+
686
+ export function prepareReactSlideSource(sourceTsx: string): PreparedModule {
687
+ if (!sourceTsx.trim() || !isSlideSourceWithinByteLimit(sourceTsx)) {
688
+ throw new SlideSourceError(SLIDE_SOURCE_BYTE_LIMIT_MESSAGE);
689
+ }
690
+ const original = parseModule(sourceTsx);
691
+ const staticBindings = collectStaticBindings(original);
692
+ const exportValues = readModuleMetadata(original, staticBindings);
693
+ const extractedStyles = collectModuleStyles(original, staticBindings);
694
+ const styles = sanitizeStyles(extractedStyles);
695
+ const reducedMotionStepStyle = sanitizeStyles([REDUCED_MOTION_STEPS_CSS])[0];
696
+ if (styles.length === 0) {
697
+ if (reducedMotionStepStyle) styles.push(reducedMotionStepStyle);
698
+ } else if (reducedMotionStepStyle) {
699
+ const lastStyleIndex = styles.length - 1;
700
+ styles[lastStyleIndex] =
701
+ `${styles[lastStyleIndex] ?? ""}\n${reducedMotionStepStyle}`;
702
+ }
703
+ const guardedRanges = findDocumentGuards(original, sourceTsx);
704
+ let safeSource = replaceRangesWithSpaces(sourceTsx, guardedRanges);
705
+ const ast = parseModule(safeSource);
706
+ validateReactModule(ast);
707
+ safeSource = addSourceLocations(safeSource, ast);
708
+ const locatedAst = parseModule(safeSource);
709
+ safeSource = instrumentBoundedCollectionCalls(safeSource, locatedAst);
710
+ safeSource = `import { __slideRuntimeGet, __slideRuntimeJoin, __slideRuntimeMap, __slideRuntimePadStart, __slideRuntimePush, __slideRuntimeReplace } from "@open-slide/core";\n${safeSource}`;
711
+ return {
712
+ source: safeSource,
713
+ ...exportValues,
714
+ styles,
715
+ };
716
+ }
717
+
718
+ export async function buildReactSlideRuntime(
719
+ sourceTsx: string,
720
+ options: {
721
+ current: number;
722
+ total: number;
723
+ assetUrls: ReadonlyMap<string, string>;
724
+ },
725
+ ): Promise<SlideWorkerRuntime> {
726
+ const prepared = prepareReactSlideSource(sourceTsx);
727
+ let workerSource: string | undefined;
728
+ try {
729
+ const { build } = await import("esbuild");
730
+ const templateRoot = fileURLToPath(new URL("../../", import.meta.url));
731
+ const result = await build({
732
+ stdin: {
733
+ contents: WORKER_ENTRY,
734
+ resolveDir: templateRoot,
735
+ sourcefile: "slide-worker-entry.tsx",
736
+ loader: "tsx",
737
+ },
738
+ absWorkingDir: templateRoot,
739
+ bundle: true,
740
+ format: "iife",
741
+ platform: "browser",
742
+ target: "es2022",
743
+ jsx: "automatic",
744
+ legalComments: "none",
745
+ minify: true,
746
+ sourcemap: false,
747
+ write: false,
748
+ treeShaking: true,
749
+ plugins: [
750
+ {
751
+ name: "slides-2-react-source",
752
+ setup(builder) {
753
+ builder.onResolve({ filter: /^virtual:slide-page$/ }, () => ({
754
+ path: "slide-page",
755
+ namespace: "slides-2-worker",
756
+ }));
757
+ builder.onLoad(
758
+ { filter: /^slide-page$/, namespace: "slides-2-worker" },
759
+ () => ({
760
+ contents: prepared.source,
761
+ loader: "tsx",
762
+ resolveDir: templateRoot,
763
+ }),
764
+ );
765
+ builder.onResolve(
766
+ {
767
+ filter:
768
+ /^(?:@open-slide\/core|@Slides 2\/core|virtual:slide-page-shim)$/,
769
+ },
770
+ () => ({
771
+ path: "slide-page-shim",
772
+ namespace: "slides-2-worker",
773
+ }),
774
+ );
775
+ builder.onLoad(
776
+ { filter: /^slide-page-shim$/, namespace: "slides-2-worker" },
777
+ () => ({
778
+ contents: slidePageShim,
779
+ loader: "tsx",
780
+ resolveDir: templateRoot,
781
+ }),
782
+ );
783
+ },
784
+ },
785
+ ],
786
+ });
787
+ workerSource = result.outputFiles[0]?.text;
788
+ } catch (error) {
789
+ const message =
790
+ error instanceof Error ? error.message : "Compilation failed.";
791
+ throw new SlideSourceError(
792
+ `Slide Worker bundle could not be compiled: ${message.slice(0, 500)}`,
793
+ );
794
+ }
795
+ if (
796
+ !workerSource ||
797
+ workerSource.length > MAX_REACT_SLIDE_WORKER_SOURCE_LENGTH
798
+ ) {
799
+ throw new SlideSourceError(
800
+ "Slide Worker bundle is empty or exceeds 4 MiB.",
801
+ );
802
+ }
803
+ return {
804
+ kind: "open-slide-react-worker-v1",
805
+ workerSource,
806
+ page: {
807
+ current: clampPage(options.current, options.total),
808
+ total: clampPageTotal(options.total),
809
+ },
810
+ assetUrls: Object.fromEntries(options.assetUrls),
811
+ styles: prepared.styles,
812
+ ...(prepared.design ? { design: prepared.design } : {}),
813
+ ...(prepared.meta ? { meta: prepared.meta } : {}),
814
+ ...(prepared.transition ? { transition: prepared.transition } : {}),
815
+ timeoutMs: REACT_SLIDE_WORKER_TIMEOUT_MS,
816
+ };
817
+ }
818
+
819
+ function parseModule(source: string): t.File {
820
+ const ast = parseSource(source);
821
+ if (!ast) throw new SlideSourceError("Slide source has a syntax error.");
822
+ let nodeCount = 0;
823
+ walkAll(ast, () => {
824
+ nodeCount += 1;
825
+ if (nodeCount > MAX_REACT_SLIDE_AST_NODES) {
826
+ throw new SlideSourceError(
827
+ "Slide source is too complex for the React runtime.",
828
+ );
829
+ }
830
+ });
831
+ return ast;
832
+ }
833
+
834
+ function collectStaticBindings(ast: t.File): Map<string, t.Node> {
835
+ const bindings = new Map<string, t.Node>();
836
+ for (const statement of ast.program.body) {
837
+ const declaration = t.isExportNamedDeclaration(statement)
838
+ ? statement.declaration
839
+ : statement;
840
+ if (t.isVariableDeclaration(declaration) && declaration.kind === "const") {
841
+ for (const item of declaration.declarations) {
842
+ if (t.isIdentifier(item.id) && item.init)
843
+ bindings.set(item.id.name, item.init);
844
+ }
845
+ }
846
+ }
847
+ return bindings;
848
+ }
849
+
850
+ function readModuleMetadata(
851
+ ast: t.File,
852
+ bindings: Map<string, t.Node>,
853
+ ): Pick<PreparedModule, "design" | "meta" | "transition"> {
854
+ const exports = new Map<string, t.Node>();
855
+ for (const statement of ast.program.body) {
856
+ if (
857
+ !t.isExportNamedDeclaration(statement) ||
858
+ !t.isVariableDeclaration(statement.declaration)
859
+ )
860
+ continue;
861
+ for (const item of statement.declaration.declarations) {
862
+ if (t.isIdentifier(item.id) && item.init)
863
+ exports.set(item.id.name, item.init);
864
+ }
865
+ }
866
+ const designValue = exports.has("design")
867
+ ? evaluateStatic(exports.get("design")!, bindings)
868
+ : undefined;
869
+ const metaValue = exports.has("meta")
870
+ ? evaluateStatic(exports.get("meta")!, bindings)
871
+ : undefined;
872
+ const exportedTransitionValue = exports.has("transition")
873
+ ? validateTransition(evaluateStatic(exports.get("transition")!, bindings))
874
+ : undefined;
875
+ const pageTransitionValue = readDefaultPageTransition(ast, bindings);
876
+ const transitionValue = pageTransitionValue ?? exportedTransitionValue;
877
+ return {
878
+ ...(designValue === undefined
879
+ ? {}
880
+ : { design: validateDesign(designValue) }),
881
+ ...(metaValue === undefined ? {} : { meta: validateMeta(metaValue) }),
882
+ ...(transitionValue === undefined ? {} : { transition: transitionValue }),
883
+ };
884
+ }
885
+
886
+ function readDefaultPageTransition(
887
+ ast: t.File,
888
+ bindings: Map<string, t.Node>,
889
+ ): SlideTransition | undefined {
890
+ const componentName = defaultComponentName(ast);
891
+ if (!componentName) return undefined;
892
+
893
+ const assignments = ast.program.body.flatMap((statement) => {
894
+ const assignment = defaultPageTransitionAssignment(
895
+ statement,
896
+ componentName,
897
+ );
898
+ return assignment ? [assignment] : [];
899
+ });
900
+ if (assignments.length > 1) {
901
+ throw new SlideSourceError(
902
+ "A page may only declare one transition override.",
903
+ );
904
+ }
905
+ const assignment = assignments[0];
906
+ if (!assignment) return undefined;
907
+ return validateTransition(evaluateStatic(assignment.right, bindings));
908
+ }
909
+
910
+ function defaultComponentName(ast: t.File): string | null {
911
+ const declaration = ast.program.body.find(
912
+ t.isExportDefaultDeclaration,
913
+ )?.declaration;
914
+ if (t.isIdentifier(declaration)) return declaration.name;
915
+ if (
916
+ (t.isFunctionDeclaration(declaration) ||
917
+ t.isFunctionExpression(declaration)) &&
918
+ declaration.id
919
+ ) {
920
+ return declaration.id.name;
921
+ }
922
+ return null;
923
+ }
924
+
925
+ function defaultPageTransitionAssignment(
926
+ statement: t.Statement,
927
+ componentName: string,
928
+ ): t.AssignmentExpression | null {
929
+ if (
930
+ !t.isExpressionStatement(statement) ||
931
+ !t.isAssignmentExpression(statement.expression)
932
+ ) {
933
+ return null;
934
+ }
935
+ const assignment = statement.expression;
936
+ const left = assignment.left;
937
+ if (
938
+ assignment.operator !== "=" ||
939
+ !t.isMemberExpression(left) ||
940
+ left.computed ||
941
+ !t.isIdentifier(left.object, { name: componentName }) ||
942
+ !t.isIdentifier(left.property, { name: "transition" })
943
+ ) {
944
+ return null;
945
+ }
946
+ return assignment;
947
+ }
948
+
949
+ function evaluateStatic(
950
+ node: t.Node,
951
+ bindings: Map<string, t.Node>,
952
+ active = new Set<string>(),
953
+ depth = 0,
954
+ budget = { nodes: 0 },
955
+ ): unknown {
956
+ if (
957
+ depth > MAX_STATIC_VALUE_DEPTH ||
958
+ ++budget.nodes > MAX_STATIC_VALUE_NODES
959
+ ) {
960
+ throw new SlideSourceError("Slide module metadata is too complex.");
961
+ }
962
+ while (
963
+ t.isTSAsExpression(node) ||
964
+ t.isTSSatisfiesExpression(node) ||
965
+ t.isTSTypeAssertion(node) ||
966
+ t.isTSNonNullExpression(node)
967
+ )
968
+ node = node.expression;
969
+ if (
970
+ t.isStringLiteral(node) ||
971
+ t.isNumericLiteral(node) ||
972
+ t.isBooleanLiteral(node)
973
+ )
974
+ return node.value;
975
+ if (t.isNullLiteral(node)) return null;
976
+ if (t.isIdentifier(node)) {
977
+ if (node.name === "undefined") return undefined;
978
+ const reference = bindings.get(node.name);
979
+ if (!reference || active.has(node.name))
980
+ throw new SlideSourceError(
981
+ `Metadata references a non-static value: ${node.name}.`,
982
+ );
983
+ active.add(node.name);
984
+ const value = evaluateStatic(
985
+ reference,
986
+ bindings,
987
+ active,
988
+ depth + 1,
989
+ budget,
990
+ );
991
+ active.delete(node.name);
992
+ return value;
993
+ }
994
+ if (
995
+ t.isUnaryExpression(node) &&
996
+ node.operator === "-" &&
997
+ t.isNumericLiteral(node.argument)
998
+ )
999
+ return -node.argument.value;
1000
+ if (t.isTemplateLiteral(node) && node.expressions.length === 0)
1001
+ return node.quasis[0]?.value.cooked ?? "";
1002
+ if (t.isArrayExpression(node)) {
1003
+ if (node.elements.length > 500)
1004
+ throw new SlideSourceError("Slide module metadata arrays are too large.");
1005
+ return node.elements.map((element) =>
1006
+ element
1007
+ ? evaluateStatic(element, bindings, active, depth + 1, budget)
1008
+ : null,
1009
+ );
1010
+ }
1011
+ if (t.isObjectExpression(node)) {
1012
+ const value: Record<string, unknown> = Object.create(null);
1013
+ if (node.properties.length > 500)
1014
+ throw new SlideSourceError(
1015
+ "Slide module metadata objects are too large.",
1016
+ );
1017
+ for (const property of node.properties) {
1018
+ if (
1019
+ !t.isObjectProperty(property) ||
1020
+ property.computed ||
1021
+ property.shorthand
1022
+ ) {
1023
+ throw new SlideSourceError(
1024
+ "Slide module metadata must use static object properties.",
1025
+ );
1026
+ }
1027
+ const key = t.isIdentifier(property.key)
1028
+ ? property.key.name
1029
+ : t.isStringLiteral(property.key)
1030
+ ? property.key.value
1031
+ : null;
1032
+ if (!key || BLOCKED_PROPERTIES.has(key))
1033
+ throw new SlideSourceError("Slide module metadata has an invalid key.");
1034
+ value[key] = evaluateStatic(
1035
+ property.value,
1036
+ bindings,
1037
+ active,
1038
+ depth + 1,
1039
+ budget,
1040
+ );
1041
+ }
1042
+ return value;
1043
+ }
1044
+ throw new SlideSourceError("Slide module metadata must be a static object.");
1045
+ }
1046
+
1047
+ function validateDesign(value: unknown): Slides2Design {
1048
+ if (!isRecord(value))
1049
+ throw new SlideSourceError("The design export must be a static object.");
1050
+ const palette = value.palette;
1051
+ const fonts = value.fonts;
1052
+ const typeScale = value.typeScale;
1053
+ if (!isRecord(palette) || !isRecord(fonts) || !isRecord(typeScale))
1054
+ throw new SlideSourceError(
1055
+ "Design must include palette, fonts, and typeScale objects.",
1056
+ );
1057
+ const design: Slides2Design = {
1058
+ palette: {
1059
+ bg: validateCssScalar(palette.bg, "design.palette.bg"),
1060
+ text: validateCssScalar(palette.text, "design.palette.text"),
1061
+ accent: validateCssScalar(palette.accent, "design.palette.accent"),
1062
+ },
1063
+ fonts: {
1064
+ display: validateFontStack(fonts.display, "design.fonts.display"),
1065
+ body: validateFontStack(fonts.body, "design.fonts.body"),
1066
+ },
1067
+ typeScale: {
1068
+ hero: validateSize(typeScale.hero, "design.typeScale.hero"),
1069
+ body: validateSize(typeScale.body, "design.typeScale.body"),
1070
+ },
1071
+ radius: validateRadius(value.radius),
1072
+ };
1073
+ return design;
1074
+ }
1075
+
1076
+ function validateMeta(value: unknown): Slides2Meta {
1077
+ if (!isRecord(value))
1078
+ throw new SlideSourceError("The meta export must be a static object.");
1079
+ const meta: Slides2Meta = {};
1080
+ for (const key of ["title", "theme", "createdAt"] as const) {
1081
+ const candidate = value[key];
1082
+ if (candidate === undefined) continue;
1083
+ if (
1084
+ typeof candidate !== "string" ||
1085
+ candidate.length > 300 ||
1086
+ /[\u0000-\u001f]/.test(candidate)
1087
+ ) {
1088
+ throw new SlideSourceError(`Meta field ${key} must be a short string.`);
1089
+ }
1090
+ meta[key] = candidate;
1091
+ }
1092
+ return meta;
1093
+ }
1094
+
1095
+ function validateTransition(value: unknown): SlideTransition {
1096
+ const parsed = SlideTransitionSchema.safeParse(value);
1097
+ if (!parsed.success) {
1098
+ throw new SlideSourceError(
1099
+ `The transition export is invalid: ${parsed.error.issues[0]?.message ?? "check the transition fields"}.`,
1100
+ );
1101
+ }
1102
+ if (JSON.stringify(parsed.data).length > 16 * 1024) {
1103
+ throw new SlideSourceError("The transition export is too large.");
1104
+ }
1105
+ return parsed.data as SlideTransition;
1106
+ }
1107
+
1108
+ function validateCssScalar(value: unknown, name: string): string {
1109
+ if (
1110
+ typeof value !== "string" ||
1111
+ value.length > 160 ||
1112
+ /[\\\u0000-\u001f\u007f;{}<>@]|\/\*|\*\/|url\s*\(/i.test(value)
1113
+ ) {
1114
+ throw new SlideSourceError(`${name} must be a safe CSS value.`);
1115
+ }
1116
+ return value;
1117
+ }
1118
+
1119
+ function validateFontStack(value: unknown, name: string): string {
1120
+ const font = validateCssScalar(value, name);
1121
+ if (!/^[A-Za-z0-9\s"',._-]+$/.test(font))
1122
+ throw new SlideSourceError(`${name} must be a static font stack.`);
1123
+ return font;
1124
+ }
1125
+
1126
+ function validateSize(value: unknown, name: string): number {
1127
+ if (
1128
+ typeof value !== "number" ||
1129
+ !Number.isFinite(value) ||
1130
+ value <= 0 ||
1131
+ value > 320
1132
+ ) {
1133
+ throw new SlideSourceError(`${name} must be between 0 and 320 pixels.`);
1134
+ }
1135
+ return value;
1136
+ }
1137
+
1138
+ function validateRadius(value: unknown): number {
1139
+ if (
1140
+ typeof value !== "number" ||
1141
+ !Number.isFinite(value) ||
1142
+ value < 0 ||
1143
+ value > 128
1144
+ ) {
1145
+ throw new SlideSourceError(
1146
+ "design.radius must be between 0 and 128 pixels.",
1147
+ );
1148
+ }
1149
+ return value;
1150
+ }
1151
+
1152
+ function collectModuleStyles(
1153
+ ast: t.File,
1154
+ bindings: Map<string, t.Node>,
1155
+ ): string[] {
1156
+ const styles = new Set<string>();
1157
+ for (const statement of ast.program.body) {
1158
+ const declaration = t.isExportNamedDeclaration(statement)
1159
+ ? statement.declaration
1160
+ : statement;
1161
+ if (!t.isVariableDeclaration(declaration) || declaration.kind !== "const")
1162
+ continue;
1163
+ for (const item of declaration.declarations) {
1164
+ if (
1165
+ !t.isIdentifier(item.id) ||
1166
+ !item.init ||
1167
+ !/style|css|keyframe/i.test(item.id.name)
1168
+ )
1169
+ continue;
1170
+ const value = evaluateStatic(item.init, bindings);
1171
+ if (typeof value !== "string" || !value.includes("{")) continue;
1172
+ if (value.length > MAX_STYLE_LENGTH)
1173
+ throw new SlideSourceError("A slide CSS block exceeds 64 KiB.");
1174
+ styles.add(value);
1175
+ }
1176
+ }
1177
+ if (
1178
+ [...styles].reduce((size, style) => size + style.length, 0) >
1179
+ MAX_TOTAL_STYLE_LENGTH
1180
+ ) {
1181
+ throw new SlideSourceError("Slide CSS exceeds 128 KiB.");
1182
+ }
1183
+ return [...styles];
1184
+ }
1185
+
1186
+ function sanitizeStyles(styles: string[]): string[] {
1187
+ const sanitized: string[] = [];
1188
+ for (const source of styles) {
1189
+ let root: postcss.Root;
1190
+ try {
1191
+ root = postcss.parse(source, { from: undefined });
1192
+ } catch {
1193
+ throw new SlideSourceError("A static CSS block has invalid syntax.");
1194
+ }
1195
+ root.walkAtRules((rule) => {
1196
+ const name = rule.name.toLowerCase();
1197
+ if (
1198
+ name === "import" ||
1199
+ name === "font-face" ||
1200
+ name === "namespace" ||
1201
+ name === "charset" ||
1202
+ name === "document" ||
1203
+ name === "supports"
1204
+ ) {
1205
+ rule.remove();
1206
+ return;
1207
+ }
1208
+ if (
1209
+ name === "media" &&
1210
+ !/^\s*\(\s*prefers-reduced-motion\s*:\s*reduce\s*\)\s*$/i.test(
1211
+ rule.params,
1212
+ )
1213
+ ) {
1214
+ rule.remove();
1215
+ return;
1216
+ }
1217
+ if (
1218
+ name !== "keyframes" &&
1219
+ name !== "-webkit-keyframes" &&
1220
+ name !== "media"
1221
+ )
1222
+ rule.remove();
1223
+ });
1224
+ root.walkComments((comment) => {
1225
+ comment.remove();
1226
+ });
1227
+ root.walkDecls((decl) => {
1228
+ const value = decl.value;
1229
+ if (
1230
+ BLOCKED_CSS_PROPERTIES.has(decl.prop.toLowerCase()) ||
1231
+ /[\\\u0000-\u001f\u007f{}<>@]|\/\*|\*\/|url\s*\(|javascript:/i.test(
1232
+ value,
1233
+ )
1234
+ ) {
1235
+ decl.remove();
1236
+ return;
1237
+ }
1238
+ for (const match of value.matchAll(/([a-z][a-z0-9-]*)\s*\(/gi)) {
1239
+ if (!SAFE_CSS_FUNCTIONS.has(match[1]!.toLowerCase())) {
1240
+ decl.remove();
1241
+ return;
1242
+ }
1243
+ }
1244
+ });
1245
+ root.walkRules((rule) => {
1246
+ if (rule.parent?.type === "atrule" && /keyframes$/.test(rule.parent.name))
1247
+ return;
1248
+ if (/[\\\u0000-\u001f\u007f{}<>@]|\/\*|\*\//.test(rule.selector)) {
1249
+ rule.remove();
1250
+ return;
1251
+ }
1252
+ rule.selector = `#slide-root :is(${rule.selector})`;
1253
+ });
1254
+ const css = root.toString();
1255
+ if (css) sanitized.push(css);
1256
+ }
1257
+ return sanitized;
1258
+ }
1259
+
1260
+ function validateReactModule(ast: t.File): void {
1261
+ const defaultExport = ast.program.body.filter(t.isExportDefaultDeclaration);
1262
+ if (defaultExport.length !== 1)
1263
+ throw new SlideSourceError(
1264
+ "Slide source must have one default page component.",
1265
+ );
1266
+ const declaration = defaultExport[0]!.declaration;
1267
+ if (findStaticLocalPageArray(ast, declaration)) {
1268
+ throw new SlideSourceError(
1269
+ "The default export must be a React page component.",
1270
+ );
1271
+ }
1272
+ if (
1273
+ !t.isIdentifier(declaration) &&
1274
+ !t.isFunctionDeclaration(declaration) &&
1275
+ !t.isArrowFunctionExpression(declaration) &&
1276
+ !t.isFunctionExpression(declaration)
1277
+ ) {
1278
+ throw new SlideSourceError(
1279
+ "The default export must be a React page component.",
1280
+ );
1281
+ }
1282
+ const pageComponentName = defaultComponentName(ast);
1283
+ for (const statement of ast.program.body) {
1284
+ if (t.isImportDeclaration(statement)) {
1285
+ validateImport(statement);
1286
+ continue;
1287
+ }
1288
+ if (
1289
+ t.isExportDefaultDeclaration(statement) ||
1290
+ t.isTSInterfaceDeclaration(statement) ||
1291
+ t.isTSTypeAliasDeclaration(statement) ||
1292
+ t.isEmptyStatement(statement) ||
1293
+ t.isFunctionDeclaration(statement)
1294
+ )
1295
+ continue;
1296
+ if (
1297
+ pageComponentName &&
1298
+ defaultPageTransitionAssignment(statement, pageComponentName)
1299
+ )
1300
+ continue;
1301
+ if (t.isVariableDeclaration(statement) && statement.kind === "const")
1302
+ continue;
1303
+ if (
1304
+ t.isExportNamedDeclaration(statement) &&
1305
+ t.isVariableDeclaration(statement.declaration) &&
1306
+ statement.declaration.kind === "const"
1307
+ ) {
1308
+ for (const declaration of statement.declaration.declarations) {
1309
+ if (
1310
+ !t.isIdentifier(declaration.id) ||
1311
+ !["design", "meta", "notes", "transition"].includes(
1312
+ declaration.id.name,
1313
+ )
1314
+ ) {
1315
+ throw new SlideSourceError(
1316
+ "Named exports are limited to design, meta, notes, and transition.",
1317
+ );
1318
+ }
1319
+ }
1320
+ continue;
1321
+ }
1322
+ throw new SlideSourceError(
1323
+ `Top-level ${statement.type} code is not supported in slide modules.`,
1324
+ );
1325
+ }
1326
+ const allowedObjectIdentifiers = new WeakSet<t.Identifier>();
1327
+ const allowedArrayIdentifiers = new WeakSet<t.Identifier>();
1328
+ const boundedCallMembers = new WeakSet<t.MemberExpression>();
1329
+ walkAll(ast, (node) => {
1330
+ if (
1331
+ (t.isCallExpression(node) &&
1332
+ t.isIdentifier(node.callee) &&
1333
+ UNSUPPORTED_REACT_EFFECT_HOOKS.has(node.callee.name)) ||
1334
+ (t.isCallExpression(node) &&
1335
+ t.isMemberExpression(node.callee) &&
1336
+ UNSUPPORTED_REACT_EFFECT_HOOKS.has(
1337
+ staticMemberProperty(node.callee) ?? "",
1338
+ )) ||
1339
+ (t.isMemberExpression(node) &&
1340
+ UNSUPPORTED_REACT_EFFECT_HOOKS.has(staticMemberProperty(node) ?? "")) ||
1341
+ (t.isObjectPattern(node) &&
1342
+ node.properties.some(
1343
+ (property) =>
1344
+ t.isObjectProperty(property) &&
1345
+ UNSUPPORTED_REACT_EFFECT_HOOKS.has(
1346
+ t.isIdentifier(property.key)
1347
+ ? property.key.name
1348
+ : t.isStringLiteral(property.key)
1349
+ ? property.key.value
1350
+ : "",
1351
+ ),
1352
+ ))
1353
+ ) {
1354
+ throw new SlideSourceError(
1355
+ "React effect hooks do not run during static slide rendering; render visual states directly or use CSS motion.",
1356
+ );
1357
+ }
1358
+ if (
1359
+ t.isOptionalMemberExpression(node) ||
1360
+ t.isOptionalCallExpression(node)
1361
+ ) {
1362
+ throw new SlideSourceError(
1363
+ "Optional access and calls are not supported in slide source.",
1364
+ );
1365
+ }
1366
+ if (t.isCallExpression(node) && t.isMemberExpression(node.callee)) {
1367
+ const callee = node.callee;
1368
+ const method = staticMemberProperty(callee);
1369
+ if (!method) {
1370
+ throw new SlideSourceError(
1371
+ "Member calls must use an approved static method.",
1372
+ );
1373
+ }
1374
+ const root = memberRootIdentifier(callee);
1375
+ if (BOUNDED_MEMBER_METHODS.has(method)) {
1376
+ boundedCallMembers.add(callee);
1377
+ } else if (root?.name === "Object" && SAFE_OBJECT_METHODS.has(method)) {
1378
+ // Object collection calls below are restricted to this small static allowlist.
1379
+ } else if (root?.name === "Array" && SAFE_ARRAY_METHODS.has(method)) {
1380
+ // Array.isArray is the only permitted Array constructor access.
1381
+ } else if (root?.name === "React" && SAFE_REACT_MEMBERS.has(method)) {
1382
+ // React calls are limited to the imported component/hook surface.
1383
+ } else if (root?.name === "Math" && SAFE_MATH_METHODS.has(method)) {
1384
+ // These scalar math functions do not allocate collections or access browser state.
1385
+ } else if (SAFE_VALUE_METHODS.has(method)) {
1386
+ // Used by generated geometry helpers and primitive formatting.
1387
+ } else {
1388
+ throw new SlideSourceError(
1389
+ `Member call ${method} is not supported in slide source.`,
1390
+ );
1391
+ }
1392
+ }
1393
+ if (!t.isMemberExpression(node)) return;
1394
+ const property = staticMemberProperty(node);
1395
+ const root = memberRootIdentifier(node);
1396
+ if (
1397
+ property &&
1398
+ BOUNDED_MEMBER_METHODS.has(property) &&
1399
+ !boundedCallMembers.has(node)
1400
+ ) {
1401
+ throw new SlideSourceError(
1402
+ `Method ${property} must be called directly so its bounds can be enforced.`,
1403
+ );
1404
+ }
1405
+ if (root?.name === "Object") {
1406
+ if (!property || !SAFE_OBJECT_METHODS.has(property)) {
1407
+ throw new SlideSourceError(
1408
+ "Object access is limited to safe static collection methods.",
1409
+ );
1410
+ }
1411
+ if (t.isIdentifier(node.object, { name: "Object" })) {
1412
+ allowedObjectIdentifiers.add(node.object);
1413
+ }
1414
+ }
1415
+ if (root?.name === "Array") {
1416
+ if (!property || !SAFE_ARRAY_METHODS.has(property)) {
1417
+ throw new SlideSourceError("Array access is limited to Array.isArray.");
1418
+ }
1419
+ if (t.isIdentifier(node.object, { name: "Array" })) {
1420
+ allowedArrayIdentifiers.add(node.object);
1421
+ }
1422
+ }
1423
+ if (root?.name === "React") {
1424
+ if (!property || !SAFE_REACT_MEMBERS.has(property)) {
1425
+ throw new SlideSourceError(
1426
+ "React access must use an approved static member.",
1427
+ );
1428
+ }
1429
+ }
1430
+ });
1431
+ walkAll(ast, (node) => {
1432
+ if (t.isIdentifier(node) && BLOCKED_GLOBALS.has(node.name)) {
1433
+ throw new SlideSourceError(`Slide source cannot access ${node.name}.`);
1434
+ }
1435
+ if (
1436
+ t.isIdentifier(node, { name: "Object" }) &&
1437
+ !allowedObjectIdentifiers.has(node)
1438
+ ) {
1439
+ throw new SlideSourceError(
1440
+ "Object may only be used with an approved static collection method.",
1441
+ );
1442
+ }
1443
+ if (
1444
+ t.isIdentifier(node, { name: "Array" }) &&
1445
+ !allowedArrayIdentifiers.has(node)
1446
+ ) {
1447
+ throw new SlideSourceError("Array may only be used with Array.isArray.");
1448
+ }
1449
+ if (t.isIdentifier(node) && node.name.startsWith("__slideRuntime")) {
1450
+ throw new SlideSourceError(
1451
+ "Slide source uses a reserved runtime identifier.",
1452
+ );
1453
+ }
1454
+ if (
1455
+ t.isNewExpression(node) ||
1456
+ t.isImportExpression(node) ||
1457
+ t.isWithStatement(node)
1458
+ ) {
1459
+ throw new SlideSourceError(
1460
+ `${node.type} is not supported in slide source.`,
1461
+ );
1462
+ }
1463
+ if (t.isMemberExpression(node)) {
1464
+ const property = staticMemberProperty(node);
1465
+ if (property && BLOCKED_PROPERTIES.has(property))
1466
+ throw new SlideSourceError(
1467
+ "Prototype access is not allowed in slide source.",
1468
+ );
1469
+ }
1470
+ if (t.isCallExpression(node)) {
1471
+ const callee = node.callee;
1472
+ if (
1473
+ t.isIdentifier(callee) &&
1474
+ ["Array", "Function", "eval", "require"].includes(callee.name)
1475
+ ) {
1476
+ throw new SlideSourceError(
1477
+ `Call to ${callee.name} is not supported in slide source.`,
1478
+ );
1479
+ }
1480
+ if (
1481
+ t.isMemberExpression(callee) &&
1482
+ t.isIdentifier(callee.object, { name: "Array" }) &&
1483
+ !t.isIdentifier(callee.property, { name: "isArray" })
1484
+ ) {
1485
+ throw new SlideSourceError(
1486
+ "Array constructors and generators are not supported in slide source.",
1487
+ );
1488
+ }
1489
+ }
1490
+ if (t.isJSXElement(node)) {
1491
+ const name = t.isJSXIdentifier(node.openingElement.name)
1492
+ ? node.openingElement.name.name
1493
+ : null;
1494
+ if (!name)
1495
+ throw new SlideSourceError(
1496
+ "Namespaced and member JSX tags are not supported.",
1497
+ );
1498
+ if (
1499
+ /^(?:script|style|iframe|frame|object|embed|link|meta|base|form|input|audio|portal|canvas|foreignObject)$/i.test(
1500
+ name,
1501
+ )
1502
+ ) {
1503
+ throw new SlideSourceError(`JSX element <${name}> is not allowed.`);
1504
+ }
1505
+ for (const attribute of node.openingElement.attributes) {
1506
+ if (!t.isJSXAttribute(attribute) || !t.isJSXIdentifier(attribute.name))
1507
+ continue;
1508
+ const attributeName = attribute.name.name;
1509
+ if (attributeName === "data-slide-loc") {
1510
+ throw new SlideSourceError(
1511
+ "data-slide-loc is reserved for source mapping.",
1512
+ );
1513
+ }
1514
+ if (/^on/i.test(attributeName)) {
1515
+ throw new SlideSourceError(
1516
+ "Event handlers are not allowed in slide source.",
1517
+ );
1518
+ }
1519
+ }
1520
+ }
1521
+ });
1522
+ }
1523
+
1524
+ function staticMemberProperty(
1525
+ node: t.MemberExpression | t.OptionalMemberExpression,
1526
+ ): string | null {
1527
+ if (!node.computed && t.isIdentifier(node.property))
1528
+ return node.property.name;
1529
+ if (node.computed && t.isStringLiteral(node.property))
1530
+ return node.property.value;
1531
+ if (node.computed && t.isNumericLiteral(node.property))
1532
+ return String(node.property.value);
1533
+ return null;
1534
+ }
1535
+
1536
+ function memberRootIdentifier(
1537
+ node: t.MemberExpression | t.OptionalMemberExpression,
1538
+ ): t.Identifier | null {
1539
+ let current: t.Expression | t.Super = node;
1540
+ while (
1541
+ t.isMemberExpression(current) ||
1542
+ t.isOptionalMemberExpression(current)
1543
+ ) {
1544
+ current = current.object;
1545
+ }
1546
+ return t.isIdentifier(current) ? current : null;
1547
+ }
1548
+
1549
+ function validateImport(declaration: t.ImportDeclaration): void {
1550
+ const moduleName = declaration.source.value;
1551
+ if (moduleName !== "react" && moduleName !== "@open-slide/core") {
1552
+ throw new SlideSourceError(
1553
+ `Import from ${moduleName} is not supported; use React and the supported @open-slide/core exports only.`,
1554
+ );
1555
+ }
1556
+ if (declaration.importKind === "type") return;
1557
+ const reactImports = new Set([
1558
+ "useId",
1559
+ "useState",
1560
+ "useMemo",
1561
+ "useCallback",
1562
+ "useContext",
1563
+ "createContext",
1564
+ "Fragment",
1565
+ "Children",
1566
+ "cloneElement",
1567
+ "isValidElement",
1568
+ "memo",
1569
+ "forwardRef",
1570
+ ]);
1571
+ const coreImports = new Set([
1572
+ "CANVAS_HEIGHT",
1573
+ "CANVAS_WIDTH",
1574
+ "Step",
1575
+ "Steps",
1576
+ "cssVarsToString",
1577
+ "defaultDesign",
1578
+ "designToCssVars",
1579
+ "useSlidePageNumber",
1580
+ "useIsActivePage",
1581
+ "ImagePlaceholder",
1582
+ "MorphElement",
1583
+ ]);
1584
+ for (const specifier of declaration.specifiers) {
1585
+ if (t.isImportNamespaceSpecifier(specifier))
1586
+ throw new SlideSourceError(
1587
+ "Namespace imports are not supported in slide modules.",
1588
+ );
1589
+ if (t.isImportDefaultSpecifier(specifier)) {
1590
+ if (moduleName !== "react")
1591
+ throw new SlideSourceError("Only React may be default-imported.");
1592
+ continue;
1593
+ }
1594
+ if (t.isImportSpecifier(specifier) && specifier.importKind !== "type") {
1595
+ const imported = t.isIdentifier(specifier.imported)
1596
+ ? specifier.imported.name
1597
+ : specifier.imported.value;
1598
+ if (
1599
+ moduleName === "react" &&
1600
+ UNSUPPORTED_REACT_EFFECT_HOOKS.has(imported)
1601
+ ) {
1602
+ throw new SlideSourceError(
1603
+ "React effect hooks do not run during static slide rendering; render visual states directly or use CSS motion.",
1604
+ );
1605
+ }
1606
+ const allowed = moduleName === "react" ? reactImports : coreImports;
1607
+ if (!allowed.has(imported))
1608
+ throw new SlideSourceError(
1609
+ `Import ${imported} from ${moduleName} is not supported.`,
1610
+ );
1611
+ }
1612
+ }
1613
+ }
1614
+
1615
+ function findDocumentGuards(
1616
+ ast: t.File,
1617
+ source: string,
1618
+ ): Array<{ start: number; end: number }> {
1619
+ const ranges: Array<{ start: number; end: number }> = [];
1620
+ for (const statement of ast.program.body) {
1621
+ if (
1622
+ !t.isIfStatement(statement) ||
1623
+ statement.alternate ||
1624
+ !containsDocumentTypeof(statement.test)
1625
+ )
1626
+ continue;
1627
+ if (statement.start == null || statement.end == null)
1628
+ throw new SlideSourceError("Document guard has no source location.");
1629
+ ranges.push({ start: statement.start, end: statement.end });
1630
+ }
1631
+ if (ranges.length) return ranges;
1632
+ return [];
1633
+ }
1634
+
1635
+ function containsDocumentTypeof(node: t.Node): boolean {
1636
+ let found = false;
1637
+ walkAll(node, (child) => {
1638
+ if (
1639
+ t.isUnaryExpression(child, { operator: "typeof" }) &&
1640
+ t.isIdentifier(child.argument, { name: "document" })
1641
+ )
1642
+ found = true;
1643
+ });
1644
+ return found;
1645
+ }
1646
+
1647
+ function replaceRangesWithSpaces(
1648
+ source: string,
1649
+ ranges: Array<{ start: number; end: number }>,
1650
+ ): string {
1651
+ let result = source;
1652
+ for (const range of ranges.sort((a, b) => b.start - a.start)) {
1653
+ const blank = source.slice(range.start, range.end).replace(/[^\r\n]/g, " ");
1654
+ result = result.slice(0, range.start) + blank + result.slice(range.end);
1655
+ }
1656
+ return result;
1657
+ }
1658
+
1659
+ function addSourceLocations(source: string, ast: t.File): string {
1660
+ const edits: Array<{ at: number; value: string }> = [];
1661
+ walkAll(ast, (node) => {
1662
+ if (!t.isJSXOpeningElement(node) || node.end == null || !node.loc) return;
1663
+ const beforeClose = node.selfClosing ? node.end - 2 : node.end - 1;
1664
+ edits.push({
1665
+ at: beforeClose,
1666
+ value: ` data-slide-loc="${node.loc.start.line}:${node.loc.start.column}"`,
1667
+ });
1668
+ });
1669
+ let result = source;
1670
+ for (const edit of edits.sort((a, b) => b.at - a.at))
1671
+ result = result.slice(0, edit.at) + edit.value + result.slice(edit.at);
1672
+ return result;
1673
+ }
1674
+
1675
+ function instrumentBoundedCollectionCalls(source: string, ast: t.File): string {
1676
+ type Target = {
1677
+ node: t.CallExpression | t.MemberExpression;
1678
+ start: number;
1679
+ end: number;
1680
+ kind: "call" | "computed";
1681
+ method?: string;
1682
+ children: Target[];
1683
+ };
1684
+ const targets: Target[] = [];
1685
+ walkAll(ast, (node) => {
1686
+ if (t.isCallExpression(node) && t.isMemberExpression(node.callee)) {
1687
+ const method = staticMemberProperty(node.callee);
1688
+ if (
1689
+ method &&
1690
+ BOUNDED_MEMBER_METHODS.has(method) &&
1691
+ node.start != null &&
1692
+ node.end != null
1693
+ ) {
1694
+ targets.push({
1695
+ node,
1696
+ start: node.start,
1697
+ end: node.end,
1698
+ kind: "call",
1699
+ method,
1700
+ children: [],
1701
+ });
1702
+ }
1703
+ return;
1704
+ }
1705
+ if (
1706
+ t.isMemberExpression(node) &&
1707
+ node.computed &&
1708
+ !t.isStringLiteral(node.property) &&
1709
+ !t.isNumericLiteral(node.property) &&
1710
+ node.start != null &&
1711
+ node.end != null
1712
+ ) {
1713
+ targets.push({
1714
+ node,
1715
+ start: node.start,
1716
+ end: node.end,
1717
+ kind: "computed",
1718
+ children: [],
1719
+ });
1720
+ }
1721
+ });
1722
+ targets.sort(
1723
+ (left, right) => left.start - right.start || right.end - left.end,
1724
+ );
1725
+ const roots: Target[] = [];
1726
+ const stack: Target[] = [];
1727
+ for (const target of targets) {
1728
+ while (stack.length) {
1729
+ const parent = stack[stack.length - 1]!;
1730
+ if (target.start >= parent.start && target.end <= parent.end) break;
1731
+ stack.pop();
1732
+ }
1733
+ if (stack.length) stack[stack.length - 1]!.children.push(target);
1734
+ else roots.push(target);
1735
+ stack.push(target);
1736
+ }
1737
+
1738
+ function transformRange(
1739
+ start: number,
1740
+ end: number,
1741
+ children: Target[],
1742
+ ): string {
1743
+ let cursor = start;
1744
+ let result = "";
1745
+ for (const child of children) {
1746
+ if (child.start < cursor || child.start < start || child.end > end)
1747
+ continue;
1748
+ result += source.slice(cursor, child.start) + transformTarget(child);
1749
+ cursor = child.end;
1750
+ }
1751
+ return result + source.slice(cursor, end);
1752
+ }
1753
+
1754
+ function transformTarget(target: Target): string {
1755
+ if (target.kind === "computed") {
1756
+ const member = target.node as t.MemberExpression;
1757
+ if (
1758
+ member.object.start == null ||
1759
+ member.object.end == null ||
1760
+ member.property.start == null ||
1761
+ member.property.end == null
1762
+ ) {
1763
+ throw new SlideSourceError(
1764
+ "Computed slide access has no source location.",
1765
+ );
1766
+ }
1767
+ return `__slideRuntimeGet(${transformRange(member.object.start, member.object.end, target.children)}, ${transformRange(member.property.start, member.property.end, target.children)})`;
1768
+ }
1769
+ const call = target.node as t.CallExpression;
1770
+ const callee = call.callee;
1771
+ if (
1772
+ !t.isMemberExpression(callee) ||
1773
+ callee.object.start == null ||
1774
+ callee.object.end == null
1775
+ ) {
1776
+ throw new SlideSourceError(
1777
+ "Bounded slide method has no source location.",
1778
+ );
1779
+ }
1780
+ const receiver = transformRange(
1781
+ callee.object.start,
1782
+ callee.object.end,
1783
+ target.children,
1784
+ );
1785
+ const args = call.arguments.map((argument) => {
1786
+ if (
1787
+ t.isSpreadElement(argument) ||
1788
+ t.isArgumentPlaceholder(argument) ||
1789
+ argument.start == null ||
1790
+ argument.end == null
1791
+ ) {
1792
+ throw new SlideSourceError(
1793
+ "Spread and partial method calls are not supported in slide source.",
1794
+ );
1795
+ }
1796
+ return transformRange(argument.start, argument.end, target.children);
1797
+ });
1798
+ const name = {
1799
+ map: "__slideRuntimeMap",
1800
+ push: "__slideRuntimePush",
1801
+ join: "__slideRuntimeJoin",
1802
+ padStart: "__slideRuntimePadStart",
1803
+ replace: "__slideRuntimeReplace",
1804
+ }[target.method!]!;
1805
+ return `${name}(${receiver}${args.length ? `, ${args.join(", ")}` : ""})`;
1806
+ }
1807
+
1808
+ return transformRange(0, source.length, roots);
1809
+ }
1810
+
1811
+ function isRecord(value: unknown): value is Record<string, unknown> {
1812
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
1813
+ }
1814
+
1815
+ function clampPage(current: number, total: number): number {
1816
+ const safeTotal = clampPageTotal(total);
1817
+ const safeCurrent = Number.isFinite(current) ? Math.trunc(current) : 1;
1818
+ return Math.max(1, Math.min(safeTotal, safeCurrent));
1819
+ }
1820
+
1821
+ function clampPageTotal(total: number): number {
1822
+ const safeTotal = Number.isFinite(total) ? Math.trunc(total) : 1;
1823
+ return Math.max(1, Math.min(Number.MAX_SAFE_INTEGER, safeTotal));
1824
+ }
1825
+
1826
+ const slidePageShim = String.raw`
1827
+ import React, { Children, cloneElement, createContext, isValidElement, useContext } from "react";
1828
+ const Context = createContext(null);
1829
+ const Budget = { values: 0, bytes: 0, stepCount: 0, remainingSteps: Infinity };
1830
+ const MAX_VALUES = 50_000;
1831
+ const MAX_BYTES = 16 * 1024 * 1024;
1832
+ function fail(message) { throw new Error(message); }
1833
+ function reserve(values, bytes = 0) { if (!Number.isSafeInteger(values) || values < 0 || Budget.values + values > MAX_VALUES) fail("Slide render exceeded its value budget."); if (!Number.isSafeInteger(bytes) || bytes < 0 || Budget.bytes + bytes > MAX_BYTES) fail("Slide render exceeded its memory estimate."); Budget.values += values; Budget.bytes += bytes; }
1834
+ function estimate(value, depth = 0, seen = new Set()) { if (depth > 16) fail("Slide data is nested too deeply."); if (typeof value === "string") { reserve(1, value.length * 2); return; } if (value == null || typeof value === "boolean" || typeof value === "number") { reserve(1, 16); return; } if (typeof value === "function") { reserve(1, 64); return; } if (typeof value !== "object" || seen.has(value)) { reserve(1, 32); return; } seen.add(value); reserve(1, 64); if (Array.isArray(value)) { if (value.length > MAX_VALUES) fail("Slide data array is too large."); for (const child of value) estimate(child, depth + 1, seen); return; } const keys = Object.keys(value); if (keys.length > 256) fail("Slide data object is too large."); for (const key of keys) estimate(value[key], depth + 1, seen); }
1835
+ export function __slideRuntimeReset(revealedSteps) { Budget.values = 0; Budget.bytes = 0; Budget.stepCount = 0; Budget.remainingSteps = revealedSteps == null ? Infinity : revealedSteps; }
1836
+ export function __slideRuntimeStepCount() { return Budget.stepCount; }
1837
+ export function __slideRuntimeGet(target, key) { if (typeof key === "string" && /^(?:0|[1-9][0-9]{0,5})$/.test(key)) key = Number(key); if (!Number.isSafeInteger(key) || key < 0 || key > MAX_VALUES) fail("Computed slide access must use a bounded array index."); if (Array.isArray(target) && key < target.length) return target[key]; if (typeof target === "string" && key < target.length) return target[key]; return undefined; }
1838
+ export function __slideRuntimeMap(array, callback, thisArg) { if (!Array.isArray(array) || typeof callback !== "function") fail("Only static arrays can be mapped in slide source."); if (array.length > MAX_VALUES) fail("Slide render exceeded its map budget."); reserve(array.length, array.length * 8); const result = new Array(array.length); for (let index = 0; index < array.length; index++) { if (!(index in array)) continue; const value = callback.call(thisArg, array[index], index, array); estimate(value); result[index] = value; } return result; }
1839
+ export function __slideRuntimePush(array, ...values) { if (!Array.isArray(array) || values.some((value) => value === undefined)) fail("Only explicit values can be appended in slide source."); if (array.length + values.length > MAX_VALUES) fail("Slide render exceeded its array budget."); for (const value of values) estimate(value); for (const value of values) array[array.length] = value; return array.length; }
1840
+ export function __slideRuntimeJoin(array, separator = ",") { if (!Array.isArray(array) || array.length > MAX_VALUES || !isPrimitive(separator)) fail("Only bounded primitive arrays can be joined in slide source."); reserve(array.length, 0); if (!array.every(isPrimitive)) fail("Only bounded primitive arrays can be joined in slide source."); const joiner = String(separator); let length = Math.max(0, array.length - 1) * joiner.length; for (const value of array) length += value == null ? 0 : String(value).length; if (length > 1024 * 1024) fail("Slide render string is too large."); reserve(1, length * 2); return array.join(joiner); }
1841
+ export function __slideRuntimePadStart(value, length, padding) { if (!isPrimitive(value) || (padding !== undefined && !isPrimitive(padding))) fail("Slide padding accepts primitive text only."); const text = String(value); const requested = Number(length); if (!Number.isFinite(requested) || requested > 1024 * 1024 || requested < 0) fail("Slide padding is out of bounds."); const outputLength = Math.max(text.length, Math.trunc(requested)); if (outputLength > 1024 * 1024) fail("Slide padding is out of bounds."); reserve(1, outputLength * 2); return text.padStart(requested, padding === undefined ? " " : String(padding)); }
1842
+ export function __slideRuntimeReplace(value, pattern, replacement) { if (!isPrimitive(value) || typeof replacement !== "string" || replacement.includes("$") || (typeof pattern !== "string" && !(pattern instanceof RegExp))) fail("Slide replacement must use primitive text and a literal replacement string."); const text = String(value); const matches = []; if (pattern instanceof RegExp) { const regex = new RegExp(pattern.source, pattern.flags); let match; while ((match = regex.exec(text))) { reserve(1, 24); matches.push({ index: match.index, length: match[0].length }); if (!regex.global) break; if (match[0].length === 0) regex.lastIndex++; if (matches.length > MAX_VALUES) fail("Slide replacement has too many matches."); } } else { const search = String(pattern); let cursor = 0; if (!search) { reserve(1, 24); matches.push({ index: 0, length: 0 }); } else while ((cursor = text.indexOf(search, cursor)) !== -1) { reserve(1, 24); matches.push({ index: cursor, length: search.length }); cursor += search.length; if (matches.length > MAX_VALUES) fail("Slide replacement has too many matches."); } } const outputLength = text.length + matches.length * replacement.length - matches.reduce((size, match) => size + match.length, 0); if (outputLength > 1024 * 1024) fail("Slide render string is too large."); reserve(matches.length * 2 + 1, outputLength * 2); const parts = new Array(matches.length * 2 + 1); let cursor = 0; let part = 0; for (const match of matches) { parts[part++] = text.slice(cursor, match.index); parts[part++] = replacement; cursor = match.index + match.length; } parts[part] = text.slice(cursor); return parts.join(""); }
1843
+ function isPrimitive(value) { return value == null || ["string", "number", "boolean"].includes(typeof value); }
1844
+ export const CANVAS_WIDTH = 1920;
1845
+ export const CANVAS_HEIGHT = 1080;
1846
+ export const defaultDesign = Object.freeze({
1847
+ palette: Object.freeze({ bg: "#f7f5f0", text: "#1a1814", accent: "#6d4cff" }), // guard:allow-raw-color — default generated slide palette, not app chrome.
1848
+ fonts: Object.freeze({
1849
+ display: 'Georgia, "Times New Roman", serif',
1850
+ body: '-apple-system, BlinkMacSystemFont, "Inter", system-ui, sans-serif',
1851
+ }),
1852
+ typeScale: Object.freeze({ hero: 168, body: 36 }),
1853
+ radius: 12,
1854
+ });
1855
+ export function designToCssVars(design) {
1856
+ return {
1857
+ "--slides2-bg": design.palette.bg,
1858
+ "--slides2-text": design.palette.text,
1859
+ "--slides2-accent": design.palette.accent,
1860
+ "--slides2-font-display": design.fonts.display,
1861
+ "--slides2-font-body": design.fonts.body,
1862
+ "--slides2-size-hero": design.typeScale.hero + "px",
1863
+ "--slides2-size-body": design.typeScale.body + "px",
1864
+ "--slides2-radius": design.radius + "px",
1865
+ };
1866
+ }
1867
+ export function cssVarsToString(vars) {
1868
+ if (!vars || typeof vars !== "object" || Array.isArray(vars)) fail("CSS variables must be a map.");
1869
+ const keys = Object.keys(vars);
1870
+ if (keys.length > 64) fail("CSS variable map exceeds 64 entries.");
1871
+ let outputLength = Math.max(0, keys.length - 1);
1872
+ for (const key of keys) {
1873
+ const value = vars[key];
1874
+ if (!/^--[A-Za-z_][A-Za-z0-9_-]{0,125}$/.test(key)) fail("CSS variable names must be bounded custom properties.");
1875
+ if (typeof value !== "string" || value.length > 160 || /[\\\u0000-\u001f\u007f;{}<>@]|\/\*|\*\/|url\s*\(/i.test(value)) fail("CSS variable values must be safe scalar text.");
1876
+ outputLength += key.length + value.length + 5;
1877
+ if (outputLength > 64 * 1024) fail("CSS variable text is too large.");
1878
+ }
1879
+ return keys.map((key) => " " + key + ": " + vars[key] + ";").join("\n");
1880
+ }
1881
+ export function SlideRuntimeProvider({ value, children }) { __slideRuntimeReset(value.revealedSteps); return React.createElement(Context.Provider, { value }, children); }
1882
+ export function useSlidePageNumber() { const context = useContext(Context); if (!context) fail("useSlidePageNumber must be called from a rendered slide page."); return { current: context.page.current, total: context.page.total }; }
1883
+ export function useIsActivePage() { return useContext(Context)?.isActivePage ?? false; }
1884
+ export function Step({ children, duration = 180, _revealed }) { const revealed = _revealed ?? true; return React.createElement("div", { "data-slides2-step": revealed ? "revealed" : "pending", style: { opacity: revealed ? 1 : 0, visibility: revealed ? "visible" : "hidden", transition: "opacity " + duration + "ms cubic-bezier(0, 0, 0.2, 1)" } }, children); }
1885
+ export function Steps({ children }) { const childrenArray = Children.toArray(children); let count = 0; for (const child of childrenArray) if (isValidElement(child) && child.type === Step) count++; Budget.stepCount += count; const revealed = Math.min(count, Budget.remainingSteps); Budget.remainingSteps = Math.max(0, Budget.remainingSteps - revealed); let index = 0; return React.createElement(React.Fragment, null, ...childrenArray.map((child, key) => { if (isValidElement(child) && child.type === Step) { const stepIndex = index++; return cloneElement(child, { key: child.key ?? key, _revealed: stepIndex < revealed }); } return child; })); }
1886
+ export function ImagePlaceholder({ hint, label, width, height, style, className, ...props }) {
1887
+ const description =
1888
+ typeof hint === "string"
1889
+ ? hint
1890
+ : typeof label === "string"
1891
+ ? label
1892
+ : "Image placeholder";
1893
+ const dimensions = width && height ? width + " × " + height : null;
1894
+ const icon = React.createElement("svg", {
1895
+ width: 32,
1896
+ height: 32,
1897
+ viewBox: "0 0 32 32",
1898
+ fill: "none",
1899
+ stroke: "currentColor",
1900
+ strokeWidth: 1.5,
1901
+ strokeLinecap: "round",
1902
+ strokeLinejoin: "round",
1903
+ style: { opacity: 0.55 },
1904
+ role: "img",
1905
+ "aria-label": "image placeholder",
1906
+ },
1907
+ React.createElement("rect", { x: 4, y: 6, width: 24, height: 20, rx: 2.5 }),
1908
+ React.createElement("circle", { cx: 11, cy: 13, r: 2 }),
1909
+ React.createElement("path", { d: "M4 22l7-7 6 6 4-4 7 7" }),
1910
+ );
1911
+ const detail = React.createElement("div", {
1912
+ style: {
1913
+ display: "flex",
1914
+ flexDirection: "column",
1915
+ alignItems: "center",
1916
+ gap: 6,
1917
+ maxWidth: "85%",
1918
+ },
1919
+ },
1920
+ React.createElement("span", {
1921
+ style: {
1922
+ fontSize: 11,
1923
+ fontWeight: 600,
1924
+ letterSpacing: "0.14em",
1925
+ textTransform: "uppercase",
1926
+ opacity: 0.55,
1927
+ },
1928
+ }, "Image"),
1929
+ React.createElement("span", {
1930
+ style: {
1931
+ fontSize: 16,
1932
+ fontWeight: 500,
1933
+ lineHeight: 1.4,
1934
+ color:
1935
+ "color-mix(in srgb, var(--slides2-text, currentColor) 85%, transparent)",
1936
+ },
1937
+ }, description),
1938
+ dimensions && React.createElement("span", {
1939
+ style: {
1940
+ fontSize: 11,
1941
+ fontVariantNumeric: "tabular-nums",
1942
+ fontFamily: 'ui-monospace, "SF Mono", Menlo, Consolas, monospace',
1943
+ opacity: 0.5,
1944
+ marginTop: 2,
1945
+ },
1946
+ }, dimensions),
1947
+ );
1948
+ return React.createElement("div", {
1949
+ ...props,
1950
+ "data-slide-loc": props["data-slide-loc"],
1951
+ "data-slide-placeholder": description,
1952
+ "data-placeholder-w": width,
1953
+ "data-placeholder-h": height,
1954
+ role: "img",
1955
+ "aria-label": description,
1956
+ className,
1957
+ style: {
1958
+ position: "relative",
1959
+ width: width ?? "100%",
1960
+ height: height ?? "100%",
1961
+ display: "flex",
1962
+ alignItems: "center",
1963
+ justifyContent: "center",
1964
+ flexDirection: "column",
1965
+ gap: 14,
1966
+ border:
1967
+ "1px dashed color-mix(in srgb, var(--slides2-text, currentColor) 35%, transparent)",
1968
+ borderRadius: 12,
1969
+ background:
1970
+ "linear-gradient(135deg, color-mix(in srgb, var(--slides2-text, currentColor) 6%, transparent) 0%, color-mix(in srgb, var(--slides2-text, currentColor) 2%, transparent) 50%, color-mix(in srgb, var(--slides2-text, currentColor) 6%, transparent) 100%)",
1971
+ color:
1972
+ "color-mix(in srgb, var(--slides2-text, currentColor) 70%, transparent)",
1973
+ fontFamily:
1974
+ '-apple-system, BlinkMacSystemFont, "Inter", "Segoe UI", system-ui, sans-serif',
1975
+ textAlign: "center",
1976
+ padding: 24,
1977
+ boxSizing: "border-box",
1978
+ overflow: "hidden",
1979
+ ...(style && typeof style === "object" ? style : {}),
1980
+ },
1981
+ }, icon, detail);
1982
+ }
1983
+ export function MorphElement({ id, children, as = "div", className, style, ...props }) {
1984
+ const child = Children.toArray(children)[0] ?? null;
1985
+ if (Children.count(children) === 1 && isValidElement(child) && typeof child.type === "string") {
1986
+ return cloneElement(child, {
1987
+ ...props,
1988
+ "data-slides2-morph": id,
1989
+ className: [child.props.className, className].filter(Boolean).join(" ") || undefined,
1990
+ style: style ? { ...child.props.style, ...style } : child.props.style,
1991
+ });
1992
+ }
1993
+ return React.createElement(as, { ...props, className, style, "data-slides2-morph": id }, children);
1994
+ }
1995
+ `;