@bendyline/squisq 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (226) hide show
  1. package/dist/ContentContainer-DNx460y8.d.ts +88 -0
  2. package/dist/{Doc-1hmT1LZl.d.ts → Doc-Dwn5aHFC.d.ts} +115 -6
  3. package/dist/__tests__/dataTable.test.d.ts +2 -0
  4. package/dist/__tests__/dataTable.test.d.ts.map +1 -0
  5. package/dist/__tests__/dataTable.test.js +110 -0
  6. package/dist/__tests__/dataTable.test.js.map +1 -0
  7. package/dist/__tests__/markdownToDoc.test.js +75 -0
  8. package/dist/__tests__/markdownToDoc.test.js.map +1 -1
  9. package/dist/{chunk-6YJPI6VI.js → chunk-4X3JQXNM.js} +1 -1
  10. package/dist/chunk-DNJKBAI7.js +1 -0
  11. package/dist/chunk-DNJKBAI7.js.map +1 -0
  12. package/dist/{chunk-S4F2RY37.js → chunk-KEFWM2VC.js} +1 -1
  13. package/dist/chunk-KEFWM2VC.js.map +1 -0
  14. package/dist/{chunk-VP5SZTZ2.js → chunk-MIBRIRGJ.js} +2 -139
  15. package/dist/chunk-MIBRIRGJ.js.map +1 -0
  16. package/dist/{chunk-URU6QMLY.js → chunk-NJLL5XYC.js} +15 -8
  17. package/dist/chunk-NJLL5XYC.js.map +1 -0
  18. package/dist/chunk-QM5PKNPW.js +165 -0
  19. package/dist/chunk-QM5PKNPW.js.map +1 -0
  20. package/dist/{chunk-PJ7AODIM.js → chunk-T6WBC3ND.js} +459 -53
  21. package/dist/chunk-T6WBC3ND.js.map +1 -0
  22. package/dist/chunk-TSG2OSE6.js +145 -0
  23. package/dist/chunk-TSG2OSE6.js.map +1 -0
  24. package/dist/{chunk-O5HCIUAD.js → chunk-TVPKD76V.js} +81 -187
  25. package/dist/chunk-TVPKD76V.js.map +1 -0
  26. package/dist/contentExtractor-BNfVJV2U.d.ts +113 -0
  27. package/dist/doc/audioMapping.d.ts +36 -0
  28. package/dist/doc/audioMapping.d.ts.map +1 -0
  29. package/dist/doc/audioMapping.js +279 -0
  30. package/dist/doc/audioMapping.js.map +1 -0
  31. package/dist/doc/index.d.ts +1 -0
  32. package/dist/doc/index.d.ts.map +1 -1
  33. package/dist/doc/index.js +1 -0
  34. package/dist/doc/index.js.map +1 -1
  35. package/dist/doc/markdownToDoc.d.ts.map +1 -1
  36. package/dist/doc/markdownToDoc.js +126 -1
  37. package/dist/doc/markdownToDoc.js.map +1 -1
  38. package/dist/doc/templates/comparisonBar.d.ts.map +1 -1
  39. package/dist/doc/templates/comparisonBar.js +23 -5
  40. package/dist/doc/templates/comparisonBar.js.map +1 -1
  41. package/dist/doc/templates/coverBlock.d.ts.map +1 -1
  42. package/dist/doc/templates/coverBlock.js +3 -0
  43. package/dist/doc/templates/coverBlock.js.map +1 -1
  44. package/dist/doc/templates/dataTable.d.ts +14 -0
  45. package/dist/doc/templates/dataTable.d.ts.map +1 -0
  46. package/dist/doc/templates/dataTable.js +73 -0
  47. package/dist/doc/templates/dataTable.js.map +1 -0
  48. package/dist/doc/templates/dateEvent.d.ts.map +1 -1
  49. package/dist/doc/templates/dateEvent.js +4 -0
  50. package/dist/doc/templates/dateEvent.js.map +1 -1
  51. package/dist/doc/templates/definitionCard.d.ts.map +1 -1
  52. package/dist/doc/templates/definitionCard.js +4 -1
  53. package/dist/doc/templates/definitionCard.js.map +1 -1
  54. package/dist/doc/templates/factCard.d.ts.map +1 -1
  55. package/dist/doc/templates/factCard.js +4 -0
  56. package/dist/doc/templates/factCard.js.map +1 -1
  57. package/dist/doc/templates/fullBleedQuote.d.ts.map +1 -1
  58. package/dist/doc/templates/fullBleedQuote.js +2 -1
  59. package/dist/doc/templates/fullBleedQuote.js.map +1 -1
  60. package/dist/doc/templates/imageWithCaption.d.ts.map +1 -1
  61. package/dist/doc/templates/imageWithCaption.js +4 -0
  62. package/dist/doc/templates/imageWithCaption.js.map +1 -1
  63. package/dist/doc/templates/index.d.ts +1 -0
  64. package/dist/doc/templates/index.d.ts.map +1 -1
  65. package/dist/doc/templates/index.js +3 -0
  66. package/dist/doc/templates/index.js.map +1 -1
  67. package/dist/doc/templates/listBlock.d.ts.map +1 -1
  68. package/dist/doc/templates/listBlock.js +3 -0
  69. package/dist/doc/templates/listBlock.js.map +1 -1
  70. package/dist/doc/templates/mapBlock.d.ts.map +1 -1
  71. package/dist/doc/templates/mapBlock.js +3 -0
  72. package/dist/doc/templates/mapBlock.js.map +1 -1
  73. package/dist/doc/templates/photoGrid.d.ts.map +1 -1
  74. package/dist/doc/templates/photoGrid.js +3 -0
  75. package/dist/doc/templates/photoGrid.js.map +1 -1
  76. package/dist/doc/templates/pullQuote.d.ts.map +1 -1
  77. package/dist/doc/templates/pullQuote.js +4 -0
  78. package/dist/doc/templates/pullQuote.js.map +1 -1
  79. package/dist/doc/templates/quoteBlock.d.ts.map +1 -1
  80. package/dist/doc/templates/quoteBlock.js +4 -0
  81. package/dist/doc/templates/quoteBlock.js.map +1 -1
  82. package/dist/doc/templates/sectionHeader.d.ts.map +1 -1
  83. package/dist/doc/templates/sectionHeader.js +3 -2
  84. package/dist/doc/templates/sectionHeader.js.map +1 -1
  85. package/dist/doc/templates/statHighlight.d.ts.map +1 -1
  86. package/dist/doc/templates/statHighlight.js +4 -1
  87. package/dist/doc/templates/statHighlight.js.map +1 -1
  88. package/dist/doc/templates/titleBlock.d.ts.map +1 -1
  89. package/dist/doc/templates/titleBlock.js +3 -0
  90. package/dist/doc/templates/titleBlock.js.map +1 -1
  91. package/dist/doc/templates/twoColumn.d.ts.map +1 -1
  92. package/dist/doc/templates/twoColumn.js +7 -1
  93. package/dist/doc/templates/twoColumn.js.map +1 -1
  94. package/dist/doc/templates/videoPullQuote.d.ts.map +1 -1
  95. package/dist/doc/templates/videoPullQuote.js +4 -0
  96. package/dist/doc/templates/videoPullQuote.js.map +1 -1
  97. package/dist/doc/templates/videoWithCaption.d.ts.map +1 -1
  98. package/dist/doc/templates/videoWithCaption.js +3 -0
  99. package/dist/doc/templates/videoWithCaption.js.map +1 -1
  100. package/dist/doc/utils/themeUtils.d.ts +9 -0
  101. package/dist/doc/utils/themeUtils.d.ts.map +1 -1
  102. package/dist/doc/utils/themeUtils.js +26 -0
  103. package/dist/doc/utils/themeUtils.js.map +1 -1
  104. package/dist/markdown/convert.d.ts.map +1 -1
  105. package/dist/markdown/convert.js +16 -7
  106. package/dist/markdown/convert.js.map +1 -1
  107. package/dist/markdown/types.d.ts +4 -2
  108. package/dist/markdown/types.d.ts.map +1 -1
  109. package/dist/schemas/BlockTemplates.d.ts +20 -3
  110. package/dist/schemas/BlockTemplates.d.ts.map +1 -1
  111. package/dist/schemas/BlockTemplates.js +2 -2
  112. package/dist/schemas/BlockTemplates.js.map +1 -1
  113. package/dist/schemas/Doc.d.ts +93 -1
  114. package/dist/schemas/Doc.d.ts.map +1 -1
  115. package/dist/schemas/Doc.js.map +1 -1
  116. package/dist/schemas/themeLibrary.d.ts +2 -2
  117. package/dist/schemas/themeLibrary.d.ts.map +1 -1
  118. package/dist/schemas/themeLibrary.js +91 -26
  119. package/dist/schemas/themeLibrary.js.map +1 -1
  120. package/dist/story/index.d.ts +63 -5
  121. package/dist/story/index.js +17 -5
  122. package/dist/{themeLibrary-DR1VRo-8.d.ts → themeLibrary-DLJtGh8-.d.ts} +3 -3
  123. package/dist/transform/applyTransform.d.ts +22 -0
  124. package/dist/transform/applyTransform.d.ts.map +1 -0
  125. package/dist/transform/applyTransform.js +68 -0
  126. package/dist/transform/applyTransform.js.map +1 -0
  127. package/dist/transform/blockAnalyzer.d.ts +48 -0
  128. package/dist/transform/blockAnalyzer.d.ts.map +1 -0
  129. package/dist/transform/blockAnalyzer.js +135 -0
  130. package/dist/transform/blockAnalyzer.js.map +1 -0
  131. package/dist/transform/index.d.ts +6 -0
  132. package/dist/transform/index.d.ts.map +1 -0
  133. package/dist/transform/index.js +4 -0
  134. package/dist/transform/index.js.map +1 -0
  135. package/dist/transform/registry.d.ts +19 -0
  136. package/dist/transform/registry.d.ts.map +1 -0
  137. package/dist/transform/registry.js +41 -0
  138. package/dist/transform/registry.js.map +1 -0
  139. package/dist/transform/styles/dataDriven.d.ts +4 -0
  140. package/dist/transform/styles/dataDriven.d.ts.map +1 -0
  141. package/dist/transform/styles/dataDriven.js +15 -0
  142. package/dist/transform/styles/dataDriven.js.map +1 -0
  143. package/dist/transform/styles/documentary.d.ts +4 -0
  144. package/dist/transform/styles/documentary.d.ts.map +1 -0
  145. package/dist/transform/styles/documentary.js +15 -0
  146. package/dist/transform/styles/documentary.js.map +1 -0
  147. package/dist/transform/styles/index.d.ts +6 -0
  148. package/dist/transform/styles/index.d.ts.map +1 -0
  149. package/dist/transform/styles/index.js +6 -0
  150. package/dist/transform/styles/index.js.map +1 -0
  151. package/dist/transform/styles/magazine.d.ts +4 -0
  152. package/dist/transform/styles/magazine.d.ts.map +1 -0
  153. package/dist/transform/styles/magazine.js +15 -0
  154. package/dist/transform/styles/magazine.js.map +1 -0
  155. package/dist/transform/styles/minimal.d.ts +4 -0
  156. package/dist/transform/styles/minimal.d.ts.map +1 -0
  157. package/dist/transform/styles/minimal.js +15 -0
  158. package/dist/transform/styles/minimal.js.map +1 -0
  159. package/dist/transform/styles/narrative.d.ts +4 -0
  160. package/dist/transform/styles/narrative.d.ts.map +1 -0
  161. package/dist/transform/styles/narrative.js +15 -0
  162. package/dist/transform/styles/narrative.js.map +1 -0
  163. package/dist/transform/templateSelector.d.ts +30 -0
  164. package/dist/transform/templateSelector.d.ts.map +1 -0
  165. package/dist/transform/templateSelector.js +218 -0
  166. package/dist/transform/templateSelector.js.map +1 -0
  167. package/dist/transform/timingAllocator.d.ts +21 -0
  168. package/dist/transform/timingAllocator.d.ts.map +1 -0
  169. package/dist/transform/timingAllocator.js +111 -0
  170. package/dist/transform/timingAllocator.js.map +1 -0
  171. package/dist/transform/types.d.ts +86 -0
  172. package/dist/transform/types.d.ts.map +1 -0
  173. package/dist/transform/types.js +9 -0
  174. package/dist/transform/types.js.map +1 -0
  175. package/dist/{types-DHiv_Pnm.d.ts → types-DYAzisMG.d.ts} +4 -2
  176. package/package.json +6 -1
  177. package/src/__tests__/dataTable.test.ts +135 -0
  178. package/src/__tests__/markdownToDoc.test.ts +96 -0
  179. package/src/doc/audioMapping.ts +346 -0
  180. package/src/doc/index.ts +1 -0
  181. package/src/doc/markdownToDoc.ts +136 -2
  182. package/src/doc/templates/comparisonBar.ts +23 -5
  183. package/src/doc/templates/coverBlock.ts +3 -0
  184. package/src/doc/templates/dataTable.ts +84 -0
  185. package/src/doc/templates/dateEvent.ts +4 -0
  186. package/src/doc/templates/definitionCard.ts +4 -1
  187. package/src/doc/templates/factCard.ts +4 -0
  188. package/src/doc/templates/fullBleedQuote.ts +2 -1
  189. package/src/doc/templates/imageWithCaption.ts +4 -0
  190. package/src/doc/templates/index.ts +3 -0
  191. package/src/doc/templates/listBlock.ts +3 -0
  192. package/src/doc/templates/mapBlock.ts +3 -0
  193. package/src/doc/templates/photoGrid.ts +3 -0
  194. package/src/doc/templates/pullQuote.ts +4 -0
  195. package/src/doc/templates/quoteBlock.ts +4 -0
  196. package/src/doc/templates/sectionHeader.ts +3 -2
  197. package/src/doc/templates/statHighlight.ts +4 -1
  198. package/src/doc/templates/titleBlock.ts +3 -0
  199. package/src/doc/templates/twoColumn.ts +7 -1
  200. package/src/doc/templates/videoPullQuote.ts +4 -0
  201. package/src/doc/templates/videoWithCaption.ts +3 -0
  202. package/src/doc/utils/themeUtils.ts +29 -0
  203. package/src/markdown/convert.ts +17 -7
  204. package/src/markdown/types.ts +4 -2
  205. package/src/schemas/BlockTemplates.ts +22 -3
  206. package/src/schemas/Doc.ts +103 -1
  207. package/src/schemas/themeLibrary.ts +95 -26
  208. package/src/transform/applyTransform.ts +83 -0
  209. package/src/transform/blockAnalyzer.ts +181 -0
  210. package/src/transform/index.ts +20 -0
  211. package/src/transform/registry.ts +47 -0
  212. package/src/transform/styles/dataDriven.ts +16 -0
  213. package/src/transform/styles/documentary.ts +16 -0
  214. package/src/transform/styles/index.ts +5 -0
  215. package/src/transform/styles/magazine.ts +16 -0
  216. package/src/transform/styles/minimal.ts +16 -0
  217. package/src/transform/styles/narrative.ts +16 -0
  218. package/src/transform/templateSelector.ts +294 -0
  219. package/src/transform/timingAllocator.ts +126 -0
  220. package/src/transform/types.ts +105 -0
  221. package/dist/chunk-O5HCIUAD.js.map +0 -1
  222. package/dist/chunk-PJ7AODIM.js.map +0 -1
  223. package/dist/chunk-S4F2RY37.js.map +0 -1
  224. package/dist/chunk-URU6QMLY.js.map +0 -1
  225. package/dist/chunk-VP5SZTZ2.js.map +0 -1
  226. /package/dist/{chunk-6YJPI6VI.js.map → chunk-4X3JQXNM.js.map} +0 -0
@@ -0,0 +1,145 @@
1
+ import {
2
+ extractContent,
3
+ mapElementToBlock,
4
+ stripMarkdown
5
+ } from "./chunk-MIBRIRGJ.js";
6
+ import {
7
+ SeededRandom,
8
+ hashString
9
+ } from "./chunk-FVTQSNR7.js";
10
+ import {
11
+ estimateNarrationDuration
12
+ } from "./chunk-3E5F2XMR.js";
13
+
14
+ // src/generate/slideshowGenerator.ts
15
+ var DEFAULT_COLOR_SCHEMES = ["blue", "green", "purple", "orange", "red"];
16
+ var DEFAULT_AMBIENT_MOTIONS = [
17
+ "zoomIn",
18
+ "zoomOut",
19
+ "panLeft",
20
+ "panRight"
21
+ ];
22
+ var DEFAULT_ACCENT_POSITIONS = ["left-strip", "right-strip", "bottom-strip"];
23
+ function generateSlideshow(text, images = [], options = {}) {
24
+ const {
25
+ seed,
26
+ title,
27
+ subtitle,
28
+ duration: explicitDuration,
29
+ targetSlides,
30
+ colorSchemes = DEFAULT_COLOR_SCHEMES,
31
+ ambientMotions = DEFAULT_AMBIENT_MOTIONS,
32
+ accentPositions = DEFAULT_ACCENT_POSITIONS,
33
+ minSlideDuration = 4,
34
+ maxSlideDuration = 15,
35
+ themeId,
36
+ isMarkdown = false,
37
+ minConfidence = 0.3
38
+ } = options;
39
+ const plainText = isMarkdown ? stripMarkdown(text) : text;
40
+ const rng = new SeededRandom(seed ?? hashString(plainText));
41
+ const totalDuration = explicitDuration ?? estimateNarrationDuration(plainText);
42
+ const extraction = extractContent(plainText, { minConfidence });
43
+ const allElements = extraction.elements;
44
+ const slideBudget = targetSlides ?? computeSlideBudget(totalDuration, allElements.length);
45
+ const imageSlotCount = images.length > 0 ? Math.max(1, Math.round(slideBudget * 0.4)) : 0;
46
+ const contentSlotCount = Math.max(0, slideBudget - imageSlotCount - (title ? 1 : 0));
47
+ const sorted = [...allElements].sort((a, b) => b.confidence - a.confidence);
48
+ const selected = sorted.slice(0, contentSlotCount);
49
+ selected.sort((a, b) => a.sourcePosition - b.sourcePosition);
50
+ const blocks = [];
51
+ let slideIndex = 0;
52
+ let colorIdx = 0;
53
+ let accentIdx = 0;
54
+ const totalSlideCount = (title ? 1 : 0) + selected.length + Math.min(imageSlotCount, images.length);
55
+ const perSlide = totalSlideCount > 0 ? Math.min(maxSlideDuration, Math.max(minSlideDuration, totalDuration / totalSlideCount)) : minSlideDuration;
56
+ if (title) {
57
+ const titleBlock = {
58
+ id: `slide-${slideIndex++}`,
59
+ template: "titleBlock",
60
+ title,
61
+ subtitle,
62
+ duration: Math.min(perSlide, 6),
63
+ audioSegment: 0
64
+ };
65
+ blocks.push(titleBlock);
66
+ }
67
+ const standaloneImages = images.slice(0, Math.min(imageSlotCount, images.length));
68
+ const accentPool = images.length > standaloneImages.length ? images.slice(standaloneImages.length) : [...images];
69
+ const imageInterval = standaloneImages.length > 0 ? Math.max(1, Math.floor(selected.length / (standaloneImages.length + 1))) : Infinity;
70
+ let imgIdx = 0;
71
+ let sinceImage = 0;
72
+ for (let i = 0; i < selected.length; i++) {
73
+ if (sinceImage >= imageInterval && imgIdx < standaloneImages.length) {
74
+ blocks.push(
75
+ createImageSlide(standaloneImages[imgIdx], slideIndex++, perSlide, rng, ambientMotions)
76
+ );
77
+ imgIdx++;
78
+ sinceImage = 0;
79
+ }
80
+ const element = selected[i];
81
+ let accentImage;
82
+ if (accentPool.length > 0) {
83
+ const img = accentPool[i % accentPool.length];
84
+ accentImage = {
85
+ src: img.src,
86
+ alt: img.alt ?? "",
87
+ position: accentPositions[accentIdx % accentPositions.length],
88
+ ambientMotion: rng.pickRequired(ambientMotions),
89
+ credit: img.credit,
90
+ license: img.license
91
+ };
92
+ accentIdx++;
93
+ }
94
+ const block = mapElementToBlock(element, {
95
+ id: `slide-${slideIndex++}`,
96
+ duration: perSlide,
97
+ audioSegment: 0,
98
+ colorScheme: colorSchemes[colorIdx % colorSchemes.length],
99
+ accentImage
100
+ });
101
+ blocks.push(block);
102
+ colorIdx++;
103
+ sinceImage++;
104
+ }
105
+ while (imgIdx < standaloneImages.length) {
106
+ blocks.push(
107
+ createImageSlide(standaloneImages[imgIdx], slideIndex++, perSlide, rng, ambientMotions)
108
+ );
109
+ imgIdx++;
110
+ }
111
+ const doc = {
112
+ articleId: title ?? "slideshow",
113
+ duration: totalDuration,
114
+ blocks,
115
+ audio: {
116
+ segments: [{ src: "", name: "main", duration: totalDuration, startTime: 0 }]
117
+ },
118
+ themeId
119
+ };
120
+ return doc;
121
+ }
122
+ function computeSlideBudget(duration, elementCount) {
123
+ const byDuration = Math.round(duration / 60 * 5);
124
+ const budget = Math.min(byDuration, elementCount + 4);
125
+ return Math.max(3, Math.min(12, budget));
126
+ }
127
+ function createImageSlide(img, index, duration, rng, motions) {
128
+ return {
129
+ id: `slide-${index}`,
130
+ template: "imageWithCaption",
131
+ imageSrc: img.src,
132
+ imageAlt: img.alt ?? "",
133
+ caption: img.alt,
134
+ duration,
135
+ audioSegment: 0,
136
+ ambientMotion: rng.pickRequired(motions),
137
+ imageCredit: img.credit,
138
+ imageLicense: img.license
139
+ };
140
+ }
141
+
142
+ export {
143
+ generateSlideshow
144
+ };
145
+ //# sourceMappingURL=chunk-TSG2OSE6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/generate/slideshowGenerator.ts"],"sourcesContent":["/**\n * Slideshow Generator\n *\n * Turns plain text + optional images into a complete squisq `Doc`.\n *\n * Pipeline:\n * 1. Strip markdown (if needed)\n * 2. Extract compelling content (stats, dates, quotes, …)\n * 3. Estimate narration timing\n * 4. Map extractions → template blocks\n * 5. Interleave image slides\n * 6. Return a ready-to-render `Doc`\n */\n\nimport type { Doc } from '../schemas/Doc.js';\nimport type {\n TemplateBlock,\n ImageWithCaptionInput,\n TitleBlockInput,\n ColorScheme,\n AccentImage,\n AccentPosition,\n} from '../schemas/BlockTemplates.js';\nimport { extractContent, stripMarkdown } from './contentExtractor.js';\nimport { mapElementToBlock } from './templateMapper.js';\nimport { estimateNarrationDuration } from '../timing/narrationTiming.js';\nimport { SeededRandom, hashString } from '../random/SeededRandom.js';\n\n// ── Public types ───────────────────────────────────────────────────\n\n/** A Doc variant whose blocks are TemplateBlocks (no startTime required). */\nexport type SlideshowDoc = Omit<Doc, 'blocks'> & {\n blocks: TemplateBlock[];\n};\n\n/** Image metadata passed to the generator. */\nexport interface SlideshowImage {\n /** Image source path or URL. */\n src: string;\n /** Alt text for accessibility. */\n alt?: string;\n /** Photo credit. */\n credit?: string;\n /** License identifier. */\n license?: string;\n}\n\n/** Options for `generateSlideshow`. */\nexport interface SlideshowOptions {\n /** Deterministic seed (default: hash of the text). */\n seed?: number;\n /** Title slide text. Omit to skip the title slide. */\n title?: string;\n /** Subtitle for the title slide. */\n subtitle?: string;\n /** Explicit total duration in seconds. When omitted, estimated from text. */\n duration?: number;\n /** Target number of content slides (default: 5–8, auto-scaled). */\n targetSlides?: number;\n /** Color schemes to rotate (default: ['blue','green','purple','orange','red']). */\n colorSchemes?: ColorScheme[];\n /** Ambient motions to rotate on images. */\n ambientMotions?: Array<'zoomIn' | 'zoomOut' | 'panLeft' | 'panRight'>;\n /** Accent positions to rotate on text slides. */\n accentPositions?: AccentPosition[];\n /** Minimum slide duration in seconds (default: 4). */\n minSlideDuration?: number;\n /** Maximum slide duration in seconds (default: 15). */\n maxSlideDuration?: number;\n /** Theme identifier to embed in the Doc. */\n themeId?: string;\n /** Whether the input text is markdown (default: false). */\n isMarkdown?: boolean;\n /** Minimum extraction confidence (default: 0.3). */\n minConfidence?: number;\n}\n\nconst DEFAULT_COLOR_SCHEMES: ColorScheme[] = ['blue', 'green', 'purple', 'orange', 'red'];\nconst DEFAULT_AMBIENT_MOTIONS: Array<'zoomIn' | 'zoomOut' | 'panLeft' | 'panRight'> = [\n 'zoomIn',\n 'zoomOut',\n 'panLeft',\n 'panRight',\n];\nconst DEFAULT_ACCENT_POSITIONS: AccentPosition[] = ['left-strip', 'right-strip', 'bottom-strip'];\n\n// ── Main ───────────────────────────────────────────────────────────\n\n/**\n * Generate a slideshow `Doc` from text and optional images.\n *\n * ```ts\n * const doc = generateSlideshow(articleText, myImages, {\n * title: 'Mount Rainier',\n * themeId: 'documentary',\n * });\n * // doc is a complete Doc ready for DocPlayer / LinearDocView\n * ```\n */\nexport function generateSlideshow(\n text: string,\n images: SlideshowImage[] = [],\n options: SlideshowOptions = {},\n): SlideshowDoc {\n const {\n seed,\n title,\n subtitle,\n duration: explicitDuration,\n targetSlides,\n colorSchemes = DEFAULT_COLOR_SCHEMES,\n ambientMotions = DEFAULT_AMBIENT_MOTIONS,\n accentPositions = DEFAULT_ACCENT_POSITIONS,\n minSlideDuration = 4,\n maxSlideDuration = 15,\n themeId,\n isMarkdown = false,\n minConfidence = 0.3,\n } = options;\n\n const plainText = isMarkdown ? stripMarkdown(text) : text;\n const rng = new SeededRandom(seed ?? hashString(plainText));\n\n // 1. Estimate total duration\n const totalDuration = explicitDuration ?? estimateNarrationDuration(plainText);\n\n // 2. Extract compelling content\n const extraction = extractContent(plainText, { minConfidence });\n const allElements = extraction.elements;\n\n // 3. Decide slide budget\n const slideBudget = targetSlides ?? computeSlideBudget(totalDuration, allElements.length);\n\n // Allocate slots between content and images\n const imageSlotCount = images.length > 0 ? Math.max(1, Math.round(slideBudget * 0.4)) : 0;\n const contentSlotCount = Math.max(0, slideBudget - imageSlotCount - (title ? 1 : 0));\n\n // Select top elements by confidence, then restore source order\n const sorted = [...allElements].sort((a, b) => b.confidence - a.confidence);\n const selected = sorted.slice(0, contentSlotCount);\n selected.sort((a, b) => a.sourcePosition - b.sourcePosition);\n\n // 4. Build slides\n const blocks: TemplateBlock[] = [];\n let slideIndex = 0;\n let colorIdx = 0;\n let accentIdx = 0;\n\n // Determine per-slide duration\n const totalSlideCount =\n (title ? 1 : 0) + selected.length + Math.min(imageSlotCount, images.length);\n const perSlide =\n totalSlideCount > 0\n ? Math.min(maxSlideDuration, Math.max(minSlideDuration, totalDuration / totalSlideCount))\n : minSlideDuration;\n\n // Title slide\n if (title) {\n const titleBlock: TitleBlockInput = {\n id: `slide-${slideIndex++}`,\n template: 'titleBlock',\n title,\n subtitle,\n duration: Math.min(perSlide, 6),\n audioSegment: 0,\n };\n blocks.push(titleBlock);\n }\n\n // Prepare image pool for standalone + accent images\n const standaloneImages = images.slice(0, Math.min(imageSlotCount, images.length));\n const accentPool =\n images.length > standaloneImages.length ? images.slice(standaloneImages.length) : [...images]; // reuse if not enough\n\n // Interleave pattern: insert an image slide every N content slides\n const imageInterval =\n standaloneImages.length > 0\n ? Math.max(1, Math.floor(selected.length / (standaloneImages.length + 1)))\n : Infinity;\n let imgIdx = 0;\n let sinceImage = 0;\n\n for (let i = 0; i < selected.length; i++) {\n // Maybe insert a standalone image slide before this content slide\n if (sinceImage >= imageInterval && imgIdx < standaloneImages.length) {\n blocks.push(\n createImageSlide(standaloneImages[imgIdx], slideIndex++, perSlide, rng, ambientMotions),\n );\n imgIdx++;\n sinceImage = 0;\n }\n\n const element = selected[i];\n\n // Optional accent image\n let accentImage: AccentImage | undefined;\n if (accentPool.length > 0) {\n const img = accentPool[i % accentPool.length];\n accentImage = {\n src: img.src,\n alt: img.alt ?? '',\n position: accentPositions[accentIdx % accentPositions.length],\n ambientMotion: rng.pickRequired(ambientMotions),\n credit: img.credit,\n license: img.license,\n };\n accentIdx++;\n }\n\n const block = mapElementToBlock(element, {\n id: `slide-${slideIndex++}`,\n duration: perSlide,\n audioSegment: 0,\n colorScheme: colorSchemes[colorIdx % colorSchemes.length],\n accentImage,\n });\n blocks.push(block);\n colorIdx++;\n sinceImage++;\n }\n\n // Append any remaining standalone images\n while (imgIdx < standaloneImages.length) {\n blocks.push(\n createImageSlide(standaloneImages[imgIdx], slideIndex++, perSlide, rng, ambientMotions),\n );\n imgIdx++;\n }\n\n // 5. Assemble Doc\n const doc: SlideshowDoc = {\n articleId: title ?? 'slideshow',\n duration: totalDuration,\n blocks,\n audio: {\n segments: [{ src: '', name: 'main', duration: totalDuration, startTime: 0 }],\n },\n themeId,\n };\n\n return doc;\n}\n\n// ── Helpers ────────────────────────────────────────────────────────\n\nfunction computeSlideBudget(duration: number, elementCount: number): number {\n // Aim for ~5 slides per minute of content, clamped 3–12\n const byDuration = Math.round((duration / 60) * 5);\n // But don't exceed available elements + a few image slots\n const budget = Math.min(byDuration, elementCount + 4);\n return Math.max(3, Math.min(12, budget));\n}\n\nfunction createImageSlide(\n img: SlideshowImage,\n index: number,\n duration: number,\n rng: SeededRandom,\n motions: Array<'zoomIn' | 'zoomOut' | 'panLeft' | 'panRight'>,\n): ImageWithCaptionInput {\n return {\n id: `slide-${index}`,\n template: 'imageWithCaption',\n imageSrc: img.src,\n imageAlt: img.alt ?? '',\n caption: img.alt,\n duration,\n audioSegment: 0,\n ambientMotion: rng.pickRequired(motions),\n imageCredit: img.credit,\n imageLicense: img.license,\n };\n}\n"],"mappings":"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","names":[]}
@@ -1,156 +1,22 @@
1
- // src/schemas/Viewport.ts
2
- var VIEWPORT_PRESETS = {
3
- /** 16:9 landscape (default, 1080p) */
4
- landscape: { width: 1920, height: 1080, name: "16:9 Landscape" },
5
- /** 9:16 portrait (vertical video, stories) */
6
- portrait: { width: 1080, height: 1920, name: "9:16 Portrait" },
7
- /** 1:1 square (social media) */
8
- square: { width: 1080, height: 1080, name: "1:1 Square" },
9
- /** 4:3 standard (legacy) */
10
- standard: { width: 1440, height: 1080, name: "4:3 Standard" }
11
- };
12
- function getViewport(viewport) {
13
- if (typeof viewport === "string") {
14
- return VIEWPORT_PRESETS[viewport];
15
- }
16
- return viewport;
17
- }
18
- var REFERENCE_DIAGONAL = Math.sqrt(1920 * 1920 + 1080 * 1080);
19
- function calculateFontScale(viewport) {
20
- const currentDiagonal = Math.sqrt(
21
- viewport.width * viewport.width + viewport.height * viewport.height
22
- );
23
- return currentDiagonal / REFERENCE_DIAGONAL;
24
- }
25
- function getViewportOrientation(viewport) {
26
- const ratio = viewport.width / viewport.height;
27
- if (Math.abs(ratio - 1) < 0.05) return "square";
28
- return ratio > 1 ? "landscape" : "portrait";
29
- }
30
- function getAspectRatioString(viewport) {
31
- const gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
32
- const divisor = gcd(viewport.width, viewport.height);
33
- return `${viewport.width / divisor}:${viewport.height / divisor}`;
34
- }
35
-
36
- // src/schemas/LayoutStrategy.ts
37
- var LAYOUT_CONFIGS = {
38
- landscape: {
39
- primaryY: "35%",
40
- secondaryY: "55%",
41
- tertiaryY: "75%",
42
- titleScale: 1,
43
- bodyScale: 1,
44
- columnLeftX: "25%",
45
- columnRightX: "75%",
46
- columnTopY: "35%",
47
- columnBottomY: "65%",
48
- stackColumns: false,
49
- maxTextWidth: "80%",
50
- horizontalPadding: "10%",
51
- captionY: "85%",
52
- captionScale: 1
53
- },
54
- portrait: {
55
- // Content positioned higher for thumb-reach zone on mobile
56
- primaryY: "25%",
57
- secondaryY: "42%",
58
- tertiaryY: "58%",
59
- // Titles scale down for narrower width; body text scales up to fill vertical space
60
- titleScale: 0.7,
61
- bodyScale: 1.5,
62
- // Stacked columns instead of side-by-side
63
- columnLeftX: "50%",
64
- columnRightX: "50%",
65
- columnTopY: "30%",
66
- columnBottomY: "55%",
67
- stackColumns: true,
68
- // Wider relative to viewport to use available space
69
- maxTextWidth: "90%",
70
- horizontalPadding: "5%",
71
- captionY: "75%",
72
- captionScale: 0.85
73
- },
74
- square: {
75
- primaryY: "30%",
76
- secondaryY: "50%",
77
- tertiaryY: "70%",
78
- titleScale: 0.85,
79
- bodyScale: 0.9,
80
- columnLeftX: "25%",
81
- columnRightX: "75%",
82
- columnTopY: "35%",
83
- columnBottomY: "65%",
84
- stackColumns: false,
85
- maxTextWidth: "85%",
86
- horizontalPadding: "7.5%",
87
- captionY: "82%",
88
- captionScale: 0.9
89
- }
90
- };
91
- function getLayoutHints(orientation) {
92
- return LAYOUT_CONFIGS[orientation];
93
- }
94
- function scaledFontSize(basePx, viewport, orientation, isTitle = false) {
95
- const fontScale = calculateFontScale(viewport);
96
- const layout = getLayoutHints(orientation);
97
- const typeScale = isTitle ? layout.titleScale : layout.bodyScale;
98
- return Math.round(basePx * fontScale * typeScale);
99
- }
100
- function getTwoColumnPositions(orientation) {
101
- const layout = getLayoutHints(orientation);
102
- if (layout.stackColumns) {
103
- return {
104
- left: { x: "50%", y: layout.columnTopY },
105
- right: { x: "50%", y: layout.columnBottomY }
106
- };
107
- }
108
- return {
109
- left: { x: layout.columnLeftX, y: "50%" },
110
- right: { x: layout.columnRightX, y: "50%" }
111
- };
112
- }
113
- function getSafeTextBounds(orientation) {
114
- const layout = getLayoutHints(orientation);
115
- return {
116
- left: layout.horizontalPadding,
117
- right: layout.horizontalPadding,
118
- top: "10%",
119
- bottom: "10%"
120
- };
121
- }
122
-
123
- // src/schemas/BlockTemplates.ts
124
- var DEFAULT_DOC_FONT = '"PT Serif", Georgia, "Times New Roman", serif';
125
- var DEFAULT_TITLE_FONT = '"PT Serif", Georgia, "Times New Roman", serif';
126
- function isTemplateBlock(block) {
127
- return "template" in block && typeof block.template === "string";
128
- }
129
- function createTemplateContext(theme, blockIndex, totalBlocks, viewport = VIEWPORT_PRESETS.landscape) {
130
- const orientation = getViewportOrientation(viewport);
131
- return {
132
- theme,
133
- blockIndex,
134
- totalBlocks,
135
- viewport,
136
- fontScale: calculateFontScale(viewport),
137
- orientation,
138
- layout: getLayoutHints(orientation)
139
- };
140
- }
141
- function scaledFontSize2(basePx, context, isTitle = false) {
142
- return scaledFontSize(basePx, context.viewport, context.orientation, isTitle);
143
- }
144
- function isPersistentLayerTemplate(layer) {
145
- return "template" in layer && typeof layer.template === "string";
146
- }
147
-
148
1
  // src/schemas/themeLibrary.ts
149
- var SERIF = '"PT Serif", Georgia, "Times New Roman", serif';
150
- var SANS = '"Inter", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif';
151
- var MONO = '"JetBrains Mono", "Fira Code", "Consolas", monospace';
152
- var MERRIWEATHER = '"Merriweather", Georgia, "Times New Roman", serif';
153
- var GEORGIA = 'Georgia, "Times New Roman", serif';
2
+ var SYSTEM_SANS = 'system-ui, -apple-system, "Segoe UI", Roboto, sans-serif';
3
+ var SYSTEM_SERIF = 'Georgia, "Times New Roman", serif';
4
+ var SYSTEM_MONO = 'Consolas, "Courier New", monospace';
5
+ var PLAYFAIR = '"Playfair Display", Georgia, serif';
6
+ var SOURCE_SERIF = '"Source Serif 4", "PT Serif", Georgia, serif';
7
+ var INTER = '"Inter", "Segoe UI", Roboto, sans-serif';
8
+ var OSWALD = '"Oswald", Impact, "Arial Black", sans-serif';
9
+ var ROBOTO = '"Roboto", "Segoe UI", Arial, sans-serif';
10
+ var MERRIWEATHER = '"Merriweather", Georgia, serif';
11
+ var LORA = '"Lora", "Merriweather", Georgia, serif';
12
+ var JETBRAINS_MONO = '"JetBrains Mono", "Fira Code", Consolas, monospace';
13
+ var IBM_PLEX_SANS = '"IBM Plex Sans", "Segoe UI", Roboto, sans-serif';
14
+ var DM_SERIF = '"DM Serif Display", Georgia, serif';
15
+ var DM_SANS = '"DM Sans", "Segoe UI", Roboto, sans-serif';
16
+ var CORMORANT = '"Cormorant Garamond", Garamond, Georgia, serif';
17
+ var CRIMSON = '"Crimson Text", Georgia, serif';
18
+ var PT_SERIF = '"PT Serif", Georgia, serif';
19
+ var HANKEN_GROTESK = '"Hanken Grotesk", system-ui, sans-serif';
154
20
  var CLASSIC_COLOR_SCHEMES = {
155
21
  blue: { bg: "#1a365d", text: "#63b3ed", accent: "#90cdf4" },
156
22
  green: { bg: "#22543d", text: "#9ae6b4", accent: "#68d391" },
@@ -159,10 +25,52 @@ var CLASSIC_COLOR_SCHEMES = {
159
25
  orange: { bg: "#744210", text: "#fbd38d", accent: "#f6ad55" },
160
26
  teal: { bg: "#234e52", text: "#81e6d9", accent: "#4fd1c5" }
161
27
  };
28
+ var standard = {
29
+ id: "standard",
30
+ name: "Standard",
31
+ description: "Clean and safe. System fonts only \u2014 no external font dependencies.",
32
+ colors: {
33
+ primary: "#3182ce",
34
+ secondary: "#4a5568",
35
+ background: "#1a202c",
36
+ backgroundLight: "#2d3748",
37
+ text: "#f7fafc",
38
+ textMuted: "#a0aec0",
39
+ highlight: "#4299e1",
40
+ warning: "#fc8181"
41
+ },
42
+ typography: {
43
+ bodyFontFamily: SYSTEM_SANS,
44
+ titleFontFamily: SYSTEM_SERIF,
45
+ monoFontFamily: SYSTEM_MONO,
46
+ titleWeight: "bold"
47
+ },
48
+ style: {
49
+ textShadow: true,
50
+ overlayOpacity: 0.45,
51
+ animationSpeed: 1
52
+ },
53
+ renderStyle: {
54
+ name: "standard",
55
+ defaultTextAnimation: "fadeIn",
56
+ defaultImageAnimation: "slowZoom",
57
+ ambientMotion: true,
58
+ defaultTransition: { type: "fade", duration: 0.7 }
59
+ },
60
+ colorSchemes: CLASSIC_COLOR_SCHEMES,
61
+ persistentLayers: {
62
+ bottomLayers: [
63
+ {
64
+ template: "gradientBackground",
65
+ config: { type: "gradientBackground", preset: "dark-vignette" }
66
+ }
67
+ ]
68
+ }
69
+ };
162
70
  var documentary = {
163
71
  id: "documentary",
164
72
  name: "Documentary",
165
- description: "Classic dark cinematic look with serif typography. The original Squisq style.",
73
+ description: "Classic dark cinematic look with elegant serif typography.",
166
74
  colors: {
167
75
  primary: "#3d5a80",
168
76
  secondary: "#63b3ed",
@@ -174,8 +82,8 @@ var documentary = {
174
82
  warning: "#fc8181"
175
83
  },
176
84
  typography: {
177
- bodyFontFamily: SERIF,
178
- titleFontFamily: SERIF,
85
+ bodyFontFamily: SOURCE_SERIF,
86
+ titleFontFamily: PLAYFAIR,
179
87
  titleWeight: "bold"
180
88
  },
181
89
  style: {
@@ -215,8 +123,8 @@ var minimalist = {
215
123
  warning: "#e53e3e"
216
124
  },
217
125
  typography: {
218
- bodyFontFamily: SANS,
219
- titleFontFamily: SANS,
126
+ bodyFontFamily: INTER,
127
+ titleFontFamily: INTER,
220
128
  titleWeight: "bold",
221
129
  lineHeight: 1.6
222
130
  },
@@ -259,8 +167,8 @@ var bold = {
259
167
  warning: "#fc8181"
260
168
  },
261
169
  typography: {
262
- bodyFontFamily: SANS,
263
- titleFontFamily: SANS,
170
+ bodyFontFamily: ROBOTO,
171
+ titleFontFamily: OSWALD,
264
172
  titleWeight: "bold",
265
173
  titleScale: 1.15,
266
174
  bodyScale: 1,
@@ -306,7 +214,7 @@ var morningLight = {
306
214
  warning: "#c53030"
307
215
  },
308
216
  typography: {
309
- bodyFontFamily: MERRIWEATHER,
217
+ bodyFontFamily: LORA,
310
218
  titleFontFamily: MERRIWEATHER,
311
219
  titleWeight: "bold",
312
220
  lineHeight: 1.7
@@ -347,9 +255,9 @@ var techDark = {
347
255
  warning: "#ff5252"
348
256
  },
349
257
  typography: {
350
- bodyFontFamily: SANS,
351
- titleFontFamily: MONO,
352
- monoFontFamily: MONO,
258
+ bodyFontFamily: IBM_PLEX_SANS,
259
+ titleFontFamily: JETBRAINS_MONO,
260
+ monoFontFamily: JETBRAINS_MONO,
353
261
  titleWeight: "bold",
354
262
  titleScale: 0.9,
355
263
  lineHeight: 1.5
@@ -394,8 +302,8 @@ var magazine = {
394
302
  warning: "#fc8181"
395
303
  },
396
304
  typography: {
397
- bodyFontFamily: SANS,
398
- titleFontFamily: GEORGIA,
305
+ bodyFontFamily: DM_SANS,
306
+ titleFontFamily: DM_SERIF,
399
307
  titleWeight: "bold",
400
308
  titleScale: 1.05,
401
309
  lineHeight: 1.5
@@ -437,8 +345,8 @@ var cinematic = {
437
345
  warning: "#fc8181"
438
346
  },
439
347
  typography: {
440
- bodyFontFamily: SERIF,
441
- titleFontFamily: SERIF,
348
+ bodyFontFamily: CRIMSON,
349
+ titleFontFamily: CORMORANT,
442
350
  titleWeight: "bold",
443
351
  lineHeight: 1.5,
444
352
  titleLineHeight: 1.2
@@ -490,8 +398,8 @@ var warmEarth = {
490
398
  warning: "#e53e3e"
491
399
  },
492
400
  typography: {
493
- bodyFontFamily: GEORGIA,
494
- titleFontFamily: GEORGIA,
401
+ bodyFontFamily: HANKEN_GROTESK,
402
+ titleFontFamily: PT_SERIF,
495
403
  titleWeight: "bold",
496
404
  lineHeight: 1.6
497
405
  },
@@ -525,6 +433,7 @@ var warmEarth = {
525
433
  }
526
434
  };
527
435
  var THEMES = {
436
+ standard,
528
437
  documentary,
529
438
  minimalist,
530
439
  bold,
@@ -534,8 +443,8 @@ var THEMES = {
534
443
  cinematic,
535
444
  "warm-earth": warmEarth
536
445
  };
537
- var DEFAULT_THEME_ID = "documentary";
538
- var DEFAULT_THEME = documentary;
446
+ var DEFAULT_THEME_ID = "standard";
447
+ var DEFAULT_THEME = standard;
539
448
  function resolveTheme(id) {
540
449
  if (id && id in THEMES) return THEMES[id];
541
450
  return DEFAULT_THEME;
@@ -552,21 +461,6 @@ function getThemeSummaries() {
552
461
  }
553
462
 
554
463
  export {
555
- VIEWPORT_PRESETS,
556
- getViewport,
557
- calculateFontScale,
558
- getViewportOrientation,
559
- getAspectRatioString,
560
- getLayoutHints,
561
- scaledFontSize,
562
- getTwoColumnPositions,
563
- getSafeTextBounds,
564
- DEFAULT_DOC_FONT,
565
- DEFAULT_TITLE_FONT,
566
- isTemplateBlock,
567
- createTemplateContext,
568
- scaledFontSize2,
569
- isPersistentLayerTemplate,
570
464
  THEMES,
571
465
  DEFAULT_THEME_ID,
572
466
  DEFAULT_THEME,
@@ -574,4 +468,4 @@ export {
574
468
  getAvailableThemes,
575
469
  getThemeSummaries
576
470
  };
577
- //# sourceMappingURL=chunk-O5HCIUAD.js.map
471
+ //# sourceMappingURL=chunk-TVPKD76V.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/schemas/themeLibrary.ts"],"sourcesContent":["/**\n * Built-in Theme Library\n *\n * Ships 8 curated themes covering documentary, editorial, minimal, and\n * cinematic styles. Each theme is fully JSON-serializable.\n *\n * Usage:\n * ```ts\n * import { THEMES, resolveTheme } from '@bendyline/squisq/schemas';\n *\n * const theme = resolveTheme('minimalist'); // look up by id\n * const theme = THEMES.documentary; // direct access\n * ```\n */\n\nimport type { Theme, ThemeColorScheme } from './Theme.js';\n\n// ============================================\n// Shared constants\n// ============================================\n\n// ── Font stacks ──────────────────────────────────────────────────\n// Each stack lists the recommended Google Font first (works when the\n// wrapping site loads it), then degrades to safe system fonts.\n// Squisq itself does NOT load Google Fonts.\n\n/** System fonts only — no external dependencies. */\nconst SYSTEM_SANS = 'system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif';\nconst SYSTEM_SERIF = 'Georgia, \"Times New Roman\", serif';\nconst SYSTEM_MONO = 'Consolas, \"Courier New\", monospace';\n\n/** Theme-specific stacks with Google Font leads. */\nconst PLAYFAIR = '\"Playfair Display\", Georgia, serif';\nconst SOURCE_SERIF = '\"Source Serif 4\", \"PT Serif\", Georgia, serif';\nconst INTER = '\"Inter\", \"Segoe UI\", Roboto, sans-serif';\nconst OSWALD = '\"Oswald\", Impact, \"Arial Black\", sans-serif';\nconst ROBOTO = '\"Roboto\", \"Segoe UI\", Arial, sans-serif';\nconst MERRIWEATHER = '\"Merriweather\", Georgia, serif';\nconst LORA = '\"Lora\", \"Merriweather\", Georgia, serif';\nconst JETBRAINS_MONO = '\"JetBrains Mono\", \"Fira Code\", Consolas, monospace';\nconst IBM_PLEX_SANS = '\"IBM Plex Sans\", \"Segoe UI\", Roboto, sans-serif';\nconst DM_SERIF = '\"DM Serif Display\", Georgia, serif';\nconst DM_SANS = '\"DM Sans\", \"Segoe UI\", Roboto, sans-serif';\nconst CORMORANT = '\"Cormorant Garamond\", Garamond, Georgia, serif';\nconst CRIMSON = '\"Crimson Text\", Georgia, serif';\nconst PT_SERIF = '\"PT Serif\", Georgia, serif';\nconst HANKEN_GROTESK = '\"Hanken Grotesk\", system-ui, sans-serif';\n\n/** Standard 6-scheme set used by the documentary theme (migrated from old COLOR_SCHEMES). */\nconst CLASSIC_COLOR_SCHEMES: Record<string, ThemeColorScheme> = {\n blue: { bg: '#1a365d', text: '#63b3ed', accent: '#90cdf4' },\n green: { bg: '#22543d', text: '#9ae6b4', accent: '#68d391' },\n purple: { bg: '#44337a', text: '#d6bcfa', accent: '#b794f4' },\n red: { bg: '#742a2a', text: '#fc8181', accent: '#feb2b2' },\n orange: { bg: '#744210', text: '#fbd38d', accent: '#f6ad55' },\n teal: { bg: '#234e52', text: '#81e6d9', accent: '#4fd1c5' },\n};\n\n// ============================================\n// 1. Standard (default — safe system fonts, no external dependencies)\n// ============================================\n\nconst standard: Theme = {\n id: 'standard',\n name: 'Standard',\n description: 'Clean and safe. System fonts only — no external font dependencies.',\n colors: {\n primary: '#3182ce',\n secondary: '#4a5568',\n background: '#1a202c',\n backgroundLight: '#2d3748',\n text: '#f7fafc',\n textMuted: '#a0aec0',\n highlight: '#4299e1',\n warning: '#fc8181',\n },\n typography: {\n bodyFontFamily: SYSTEM_SANS,\n titleFontFamily: SYSTEM_SERIF,\n monoFontFamily: SYSTEM_MONO,\n titleWeight: 'bold',\n },\n style: {\n textShadow: true,\n overlayOpacity: 0.45,\n animationSpeed: 1.0,\n },\n renderStyle: {\n name: 'standard',\n defaultTextAnimation: 'fadeIn',\n defaultImageAnimation: 'slowZoom',\n ambientMotion: true,\n defaultTransition: { type: 'fade', duration: 0.7 },\n },\n colorSchemes: CLASSIC_COLOR_SCHEMES,\n persistentLayers: {\n bottomLayers: [\n {\n template: 'gradientBackground',\n config: { type: 'gradientBackground', preset: 'dark-vignette' },\n },\n ],\n },\n};\n\n// ============================================\n// 2. Documentary\n// ============================================\n\nconst documentary: Theme = {\n id: 'documentary',\n name: 'Documentary',\n description: 'Classic dark cinematic look with elegant serif typography.',\n colors: {\n primary: '#3d5a80',\n secondary: '#63b3ed',\n background: '#1a202c',\n backgroundLight: '#2d3748',\n text: '#ffffff',\n textMuted: '#a0aec0',\n highlight: '#63b3ed',\n warning: '#fc8181',\n },\n typography: {\n bodyFontFamily: SOURCE_SERIF,\n titleFontFamily: PLAYFAIR,\n titleWeight: 'bold',\n },\n style: {\n textShadow: true,\n overlayOpacity: 0.5,\n animationSpeed: 1.0,\n },\n renderStyle: {\n name: 'documentary',\n defaultTextAnimation: 'fadeIn',\n defaultImageAnimation: 'slowZoom',\n ambientMotion: true,\n defaultTransition: { type: 'fade', duration: 0.8 },\n },\n colorSchemes: CLASSIC_COLOR_SCHEMES,\n persistentLayers: {\n bottomLayers: [\n {\n template: 'gradientBackground',\n config: { type: 'gradientBackground', preset: 'dark-vignette' },\n },\n ],\n },\n};\n\n// ============================================\n// 2. Minimalist\n// ============================================\n\nconst minimalist: Theme = {\n id: 'minimalist',\n name: 'Minimalist',\n description: 'Clean near-white background with sans-serif type and minimal animation.',\n colors: {\n primary: '#2d3748',\n secondary: '#4a5568',\n background: '#f7fafc',\n backgroundLight: '#edf2f7',\n text: '#1a202c',\n textMuted: '#718096',\n highlight: '#3182ce',\n warning: '#e53e3e',\n },\n typography: {\n bodyFontFamily: INTER,\n titleFontFamily: INTER,\n titleWeight: 'bold',\n lineHeight: 1.6,\n },\n style: {\n textShadow: false,\n overlayOpacity: 0.3,\n animationSpeed: 1.2,\n borderRadius: 8,\n },\n renderStyle: {\n name: 'minimalist',\n defaultTextAnimation: 'fadeIn',\n ambientMotion: false,\n defaultTransition: { type: 'fade', duration: 0.6 },\n templateHints: {\n titleBlock: { showAccentLine: false },\n },\n },\n colorSchemes: {\n blue: { bg: '#ebf8ff', text: '#2b6cb0', accent: '#3182ce' },\n green: { bg: '#f0fff4', text: '#276749', accent: '#38a169' },\n purple: { bg: '#faf5ff', text: '#553c9a', accent: '#805ad5' },\n red: { bg: '#fff5f5', text: '#c53030', accent: '#e53e3e' },\n orange: { bg: '#fffaf0', text: '#c05621', accent: '#dd6b20' },\n teal: { bg: '#e6fffa', text: '#285e61', accent: '#319795' },\n },\n};\n\n// ============================================\n// 3. Bold\n// ============================================\n\nconst bold: Theme = {\n id: 'bold',\n name: 'Bold',\n description: 'High-contrast black with vivid accents and dramatic animations.',\n colors: {\n primary: '#e53e3e',\n secondary: '#ed8936',\n background: '#000000',\n backgroundLight: '#1a1a1a',\n text: '#ffffff',\n textMuted: '#cbd5e0',\n highlight: '#f6e05e',\n warning: '#fc8181',\n },\n typography: {\n bodyFontFamily: ROBOTO,\n titleFontFamily: OSWALD,\n titleWeight: 'bold',\n titleScale: 1.15,\n bodyScale: 1.0,\n titleLineHeight: 1.1,\n },\n style: {\n textShadow: true,\n overlayOpacity: 0.6,\n animationSpeed: 0.8,\n },\n renderStyle: {\n name: 'bold',\n defaultTextAnimation: 'zoomIn',\n defaultImageAnimation: 'slowZoom',\n ambientMotion: true,\n defaultTransition: { type: 'dissolve', duration: 0.5 },\n templateHints: {\n statHighlight: { entrance: 'dramatic' },\n fullBleedQuote: { entrance: 'dramatic' },\n },\n },\n colorSchemes: {\n blue: { bg: '#1a202c', text: '#63b3ed', accent: '#90cdf4' },\n green: { bg: '#1a202c', text: '#48bb78', accent: '#68d391' },\n purple: { bg: '#1a202c', text: '#b794f4', accent: '#d6bcfa' },\n red: { bg: '#1a202c', text: '#fc8181', accent: '#feb2b2' },\n orange: { bg: '#1a202c', text: '#f6ad55', accent: '#fbd38d' },\n teal: { bg: '#1a202c', text: '#4fd1c5', accent: '#81e6d9' },\n },\n};\n\n// ============================================\n// 4. Morning Light\n// ============================================\n\nconst morningLight: Theme = {\n id: 'morning-light',\n name: 'Morning Light',\n description: 'Warm light background with dark text and gentle serif typography.',\n colors: {\n primary: '#744210',\n secondary: '#975a16',\n background: '#faf8f5',\n backgroundLight: '#f5f0eb',\n text: '#2d3748',\n textMuted: '#718096',\n highlight: '#dd6b20',\n warning: '#c53030',\n },\n typography: {\n bodyFontFamily: LORA,\n titleFontFamily: MERRIWEATHER,\n titleWeight: 'bold',\n lineHeight: 1.7,\n },\n style: {\n textShadow: false,\n overlayOpacity: 0.35,\n animationSpeed: 1.1,\n borderRadius: 4,\n },\n renderStyle: {\n name: 'morning-light',\n defaultTextAnimation: 'fadeIn',\n ambientMotion: false,\n defaultTransition: { type: 'fade', duration: 1.0 },\n },\n colorSchemes: {\n blue: { bg: '#ebf8ff', text: '#2c5282', accent: '#4299e1' },\n green: { bg: '#f0fff4', text: '#22543d', accent: '#48bb78' },\n purple: { bg: '#faf5ff', text: '#44337a', accent: '#9f7aea' },\n red: { bg: '#fff5f5', text: '#9b2c2c', accent: '#fc8181' },\n orange: { bg: '#fffaf0', text: '#744210', accent: '#ed8936' },\n teal: { bg: '#e6fffa', text: '#234e52', accent: '#38b2ac' },\n },\n};\n\n// ============================================\n// 5. Tech Dark\n// ============================================\n\nconst techDark: Theme = {\n id: 'tech-dark',\n name: 'Tech Dark',\n description: 'True black with neon cyan/green accents and monospace titles.',\n colors: {\n primary: '#00e5ff',\n secondary: '#00e676',\n background: '#0a0a0a',\n backgroundLight: '#1a1a2e',\n text: '#e0e0e0',\n textMuted: '#9e9e9e',\n highlight: '#00e5ff',\n warning: '#ff5252',\n },\n typography: {\n bodyFontFamily: IBM_PLEX_SANS,\n titleFontFamily: JETBRAINS_MONO,\n monoFontFamily: JETBRAINS_MONO,\n titleWeight: 'bold',\n titleScale: 0.9,\n lineHeight: 1.5,\n },\n style: {\n textShadow: true,\n overlayOpacity: 0.55,\n animationSpeed: 0.9,\n borderRadius: 2,\n },\n renderStyle: {\n name: 'tech-dark',\n defaultTextAnimation: 'typewriter',\n defaultImageAnimation: 'slowZoom',\n ambientMotion: true,\n defaultTransition: { type: 'dissolve', duration: 0.4 },\n templateHints: {\n statHighlight: { entrance: 'dramatic' },\n },\n },\n colorSchemes: {\n blue: { bg: '#0d1b2a', text: '#00b0ff', accent: '#40c4ff' },\n green: { bg: '#0d1b0d', text: '#00e676', accent: '#69f0ae' },\n purple: { bg: '#1a0d2e', text: '#d500f9', accent: '#ea80fc' },\n red: { bg: '#2e0d0d', text: '#ff5252', accent: '#ff8a80' },\n orange: { bg: '#2e1a0d', text: '#ff9100', accent: '#ffab40' },\n teal: { bg: '#0d2e2e', text: '#1de9b6', accent: '#64ffda' },\n },\n};\n\n// ============================================\n// 6. Magazine\n// ============================================\n\nconst magazine: Theme = {\n id: 'magazine',\n name: 'Magazine',\n description: 'Rich editorial palette with mixed serif/sans typography and slide transitions.',\n colors: {\n primary: '#c53030',\n secondary: '#2b6cb0',\n background: '#1a202c',\n backgroundLight: '#2d3748',\n text: '#f7fafc',\n textMuted: '#cbd5e0',\n highlight: '#ed8936',\n warning: '#fc8181',\n },\n typography: {\n bodyFontFamily: DM_SANS,\n titleFontFamily: DM_SERIF,\n titleWeight: 'bold',\n titleScale: 1.05,\n lineHeight: 1.5,\n },\n style: {\n textShadow: true,\n overlayOpacity: 0.45,\n animationSpeed: 1.0,\n borderRadius: 6,\n },\n renderStyle: {\n name: 'magazine',\n defaultTextAnimation: 'fadeIn',\n defaultImageAnimation: 'slowZoom',\n ambientMotion: true,\n defaultTransition: { type: 'slideLeft', duration: 0.7 },\n },\n colorSchemes: {\n blue: { bg: '#1a365d', text: '#90cdf4', accent: '#63b3ed' },\n green: { bg: '#1c4532', text: '#9ae6b4', accent: '#68d391' },\n purple: { bg: '#322659', text: '#d6bcfa', accent: '#b794f4' },\n red: { bg: '#63171b', text: '#feb2b2', accent: '#fc8181' },\n orange: { bg: '#652b19', text: '#fbd38d', accent: '#f6ad55' },\n teal: { bg: '#1d4044', text: '#81e6d9', accent: '#4fd1c5' },\n },\n};\n\n// ============================================\n// 7. Cinematic\n// ============================================\n\nconst cinematic: Theme = {\n id: 'cinematic',\n name: 'Cinematic',\n description: 'Ultra-dark with moody gradients, gold accents, and slow dissolve transitions.',\n colors: {\n primary: '#d69e2e',\n secondary: '#b7791f',\n background: '#0a0f1a',\n backgroundLight: '#1a202c',\n text: '#f7fafc',\n textMuted: '#a0aec0',\n highlight: '#ecc94b',\n warning: '#fc8181',\n },\n typography: {\n bodyFontFamily: CRIMSON,\n titleFontFamily: CORMORANT,\n titleWeight: 'bold',\n lineHeight: 1.5,\n titleLineHeight: 1.2,\n },\n style: {\n textShadow: true,\n overlayOpacity: 0.55,\n animationSpeed: 1.2,\n },\n renderStyle: {\n name: 'cinematic',\n defaultTextAnimation: 'fadeIn',\n defaultImageAnimation: 'slowZoom',\n ambientMotion: true,\n defaultTransition: { type: 'dissolve', duration: 1.2 },\n templateHints: {\n titleBlock: { showAccentLine: true },\n },\n },\n colorSchemes: {\n blue: { bg: '#0d1b2a', text: '#90cdf4', accent: '#63b3ed' },\n green: { bg: '#0d1b14', text: '#9ae6b4', accent: '#68d391' },\n purple: { bg: '#1a0d2e', text: '#d6bcfa', accent: '#b794f4' },\n red: { bg: '#2a0d0d', text: '#fc8181', accent: '#feb2b2' },\n orange: { bg: '#2a1a0d', text: '#fbd38d', accent: '#f6ad55' },\n teal: { bg: '#0d2a2a', text: '#81e6d9', accent: '#4fd1c5' },\n },\n persistentLayers: {\n bottomLayers: [\n {\n template: 'gradientBackground',\n config: { type: 'gradientBackground', preset: 'radial-dark' },\n },\n ],\n },\n};\n\n// ============================================\n// 8. Warm Earth\n// ============================================\n\nconst warmEarth: Theme = {\n id: 'warm-earth',\n name: 'Warm Earth',\n description: 'Natural warm tones with earthy browns and terracotta accents.',\n colors: {\n primary: '#9c4221',\n secondary: '#c05621',\n background: '#1c1410',\n backgroundLight: '#2d241e',\n text: '#faf5f0',\n textMuted: '#c4a882',\n highlight: '#dd6b20',\n warning: '#e53e3e',\n },\n typography: {\n bodyFontFamily: HANKEN_GROTESK,\n titleFontFamily: PT_SERIF,\n titleWeight: 'bold',\n lineHeight: 1.6,\n },\n style: {\n textShadow: true,\n overlayOpacity: 0.5,\n animationSpeed: 1.1,\n },\n renderStyle: {\n name: 'warm-earth',\n defaultTextAnimation: 'fadeIn',\n defaultImageAnimation: 'panLeft',\n ambientMotion: true,\n defaultTransition: { type: 'fade', duration: 0.9 },\n },\n colorSchemes: {\n blue: { bg: '#2a1f14', text: '#90cdf4', accent: '#63b3ed' },\n green: { bg: '#1e2a14', text: '#9ae6b4', accent: '#68d391' },\n purple: { bg: '#2a142a', text: '#d6bcfa', accent: '#b794f4' },\n red: { bg: '#2a1414', text: '#fc8181', accent: '#feb2b2' },\n orange: { bg: '#2a1e0a', text: '#fbd38d', accent: '#f6ad55' },\n teal: { bg: '#142a28', text: '#81e6d9', accent: '#4fd1c5' },\n },\n persistentLayers: {\n bottomLayers: [\n {\n template: 'gradientBackground',\n config: { type: 'gradientBackground', preset: 'earth-tones' },\n },\n ],\n },\n};\n\n// ============================================\n// Theme Library\n// ============================================\n\n/**\n * All built-in themes, keyed by id.\n */\nexport const THEMES: Record<string, Theme> = {\n standard,\n documentary,\n minimalist,\n bold,\n 'morning-light': morningLight,\n 'tech-dark': techDark,\n magazine,\n cinematic,\n 'warm-earth': warmEarth,\n};\n\n/** The default theme id. */\nexport const DEFAULT_THEME_ID = 'standard';\n\n/** The default theme (standard — safe system fonts, no external dependencies). */\nexport const DEFAULT_THEME: Theme = standard;\n\n/**\n * Resolve a theme by id. Returns the default theme when `id` is\n * undefined or not found in the library.\n */\nexport function resolveTheme(id: string | undefined): Theme {\n if (id && id in THEMES) return THEMES[id];\n return DEFAULT_THEME;\n}\n\n/**\n * Get all available theme ids.\n */\nexport function getAvailableThemes(): string[] {\n return Object.keys(THEMES);\n}\n\n/**\n * Get a summary of all themes (id + name + description) for theme pickers.\n */\nexport function getThemeSummaries(): Array<{ id: string; name: string; description?: string }> {\n return Object.values(THEMES).map((t) => ({\n id: t.id,\n name: t.name,\n description: t.description,\n }));\n}\n"],"mappings":"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","names":[]}