@ryanyahya/opendoc 0.4.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 (789) hide show
  1. package/.agents/skills/opendoc-apply-comments/SKILL.md +30 -0
  2. package/.agents/skills/opendoc-apply-comments/agents/openai.yaml +4 -0
  3. package/.agents/skills/opendoc-create/SKILL.md +63 -0
  4. package/.agents/skills/opendoc-create/agents/openai.yaml +6 -0
  5. package/.agents/skills/opendoc-create-template/SKILL.md +50 -0
  6. package/.agents/skills/opendoc-create-template/agents/openai.yaml +4 -0
  7. package/.agents/skills/opendoc-create-template/references/structured-reports.md +11 -0
  8. package/.agents/skills/opendoc-create-theme/SKILL.md +40 -0
  9. package/.agents/skills/opendoc-create-theme/agents/openai.yaml +4 -0
  10. package/.agents/skills/opendoc-current-document/SKILL.md +32 -0
  11. package/.agents/skills/opendoc-current-document/agents/openai.yaml +4 -0
  12. package/.agents/skills/opendoc-current-document/references/context-fields.md +20 -0
  13. package/.agents/skills/opendoc-review-document/SKILL.md +60 -0
  14. package/.agents/skills/opendoc-review-document/agents/openai.yaml +4 -0
  15. package/AGENTS.md +69 -0
  16. package/CONTRIBUTING.md +38 -0
  17. package/LICENSE +21 -0
  18. package/README.md +179 -0
  19. package/SECURITY.md +9 -0
  20. package/THIRD_PARTY.md +49 -0
  21. package/VALIDATION.md +99 -0
  22. package/bin/opendoc.mjs +6 -0
  23. package/dist/assets/Markdown-sNZyjJi7.js +29 -0
  24. package/dist/assets/OpenDocSerif-Regular-D3OXs9A9.ttf +0 -0
  25. package/dist/assets/OpenDocSerif-Semibold-CjL9oDRo.ttf +0 -0
  26. package/dist/assets/geist-latin-ext-wght-italic-XgKbg5n7.woff2 +0 -0
  27. package/dist/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
  28. package/dist/assets/geist-latin-wght-italic-dTnRTFFJ.woff2 +0 -0
  29. package/dist/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
  30. package/dist/assets/index-DdrZ6ozO.css +1 -0
  31. package/dist/assets/index-DgNBz7mL.js +39 -0
  32. package/dist/assets/pdf-B7Emtyld.js +54 -0
  33. package/dist/assets/pdf.worker.min-Dswkl-cV.mjs +29 -0
  34. package/dist/assets/wordmark-DsqLlZpb.png +0 -0
  35. package/dist/index.html +17 -0
  36. package/docs/APPEARANCE.md +21 -0
  37. package/docs/ASSETS.md +176 -0
  38. package/docs/AUTHORING.md +178 -0
  39. package/docs/HEADLESS.md +120 -0
  40. package/docs/MEDIA.md +112 -0
  41. package/docs/PROJECTS.md +55 -0
  42. package/docs/PROSE.md +15 -0
  43. package/docs/SELECTION.md +59 -0
  44. package/docs/TEMPLATES.md +55 -0
  45. package/docs/THEMES.md +106 -0
  46. package/node_modules/@formepdf/core/LICENSE +21 -0
  47. package/node_modules/@formepdf/core/README.md +53 -0
  48. package/node_modules/@formepdf/core/dist/attachments.d.ts +55 -0
  49. package/node_modules/@formepdf/core/dist/attachments.js +59 -0
  50. package/node_modules/@formepdf/core/dist/extract.d.ts +8 -0
  51. package/node_modules/@formepdf/core/dist/extract.js +56 -0
  52. package/node_modules/@formepdf/core/dist/index.d.ts +311 -0
  53. package/node_modules/@formepdf/core/dist/index.js +167 -0
  54. package/node_modules/@formepdf/core/dist/layout.d.ts +132 -0
  55. package/node_modules/@formepdf/core/dist/layout.js +240 -0
  56. package/node_modules/@formepdf/core/dist/shared/browserHelpers.d.ts +19 -0
  57. package/node_modules/@formepdf/core/dist/shared/browserHelpers.js +128 -0
  58. package/node_modules/@formepdf/core/package.json +35 -0
  59. package/node_modules/@formepdf/core/pkg-node/LICENSE +21 -0
  60. package/node_modules/@formepdf/core/pkg-node/README.md +84 -0
  61. package/node_modules/@formepdf/core/pkg-node/forme.d.ts +39 -0
  62. package/node_modules/@formepdf/core/pkg-node/forme.js +394 -0
  63. package/node_modules/@formepdf/core/pkg-node/forme_bg.wasm +0 -0
  64. package/node_modules/@formepdf/core/pkg-node/forme_bg.wasm.d.ts +21 -0
  65. package/node_modules/@formepdf/core/pkg-node/package.json +25 -0
  66. package/node_modules/@formepdf/react/README.md +70 -0
  67. package/node_modules/@formepdf/react/dist/charts.d.ts +72 -0
  68. package/node_modules/@formepdf/react/dist/charts.js +338 -0
  69. package/node_modules/@formepdf/react/dist/components.d.ts +533 -0
  70. package/node_modules/@formepdf/react/dist/components.js +608 -0
  71. package/node_modules/@formepdf/react/dist/expr.d.ts +20 -0
  72. package/node_modules/@formepdf/react/dist/expr.js +39 -0
  73. package/node_modules/@formepdf/react/dist/font.d.ts +2 -0
  74. package/node_modules/@formepdf/react/dist/font.js +1 -0
  75. package/node_modules/@formepdf/react/dist/index.d.ts +11 -0
  76. package/node_modules/@formepdf/react/dist/index.js +15 -0
  77. package/node_modules/@formepdf/react/dist/render.d.ts +12 -0
  78. package/node_modules/@formepdf/react/dist/render.js +15 -0
  79. package/node_modules/@formepdf/react/dist/serialize.d.ts +12 -0
  80. package/node_modules/@formepdf/react/dist/serialize.js +1470 -0
  81. package/node_modules/@formepdf/react/dist/stylesheet.d.ts +4 -0
  82. package/node_modules/@formepdf/react/dist/stylesheet.js +5 -0
  83. package/node_modules/@formepdf/react/dist/template-proxy.d.ts +38 -0
  84. package/node_modules/@formepdf/react/dist/template-proxy.js +100 -0
  85. package/node_modules/@formepdf/react/dist/types.d.ts +287 -0
  86. package/node_modules/@formepdf/react/dist/types.js +1 -0
  87. package/node_modules/@formepdf/react/package.json +41 -0
  88. package/node_modules/@formepdf/shared/README.md +7 -0
  89. package/node_modules/@formepdf/shared/dist/canvas.d.ts +6 -0
  90. package/node_modules/@formepdf/shared/dist/canvas.js +43 -0
  91. package/node_modules/@formepdf/shared/dist/charts.d.ts +100 -0
  92. package/node_modules/@formepdf/shared/dist/charts.js +98 -0
  93. package/node_modules/@formepdf/shared/dist/encode.d.ts +27 -0
  94. package/node_modules/@formepdf/shared/dist/encode.js +93 -0
  95. package/node_modules/@formepdf/shared/dist/font.d.ts +13 -0
  96. package/node_modules/@formepdf/shared/dist/font.js +52 -0
  97. package/node_modules/@formepdf/shared/dist/index.d.ts +10 -0
  98. package/node_modules/@formepdf/shared/dist/index.js +15 -0
  99. package/node_modules/@formepdf/shared/dist/parser.d.ts +30 -0
  100. package/node_modules/@formepdf/shared/dist/parser.js +756 -0
  101. package/node_modules/@formepdf/shared/dist/semantics.d.ts +15 -0
  102. package/node_modules/@formepdf/shared/dist/semantics.js +44 -0
  103. package/node_modules/@formepdf/shared/dist/style.d.ts +7 -0
  104. package/node_modules/@formepdf/shared/dist/style.js +1024 -0
  105. package/node_modules/@formepdf/shared/dist/types.d.ts +743 -0
  106. package/node_modules/@formepdf/shared/dist/types.js +2 -0
  107. package/node_modules/@formepdf/shared/package.json +35 -0
  108. package/node_modules/@types/node/LICENSE +21 -0
  109. package/node_modules/@types/node/README.md +15 -0
  110. package/node_modules/@types/node/assert/strict.d.ts +111 -0
  111. package/node_modules/@types/node/assert.d.ts +1078 -0
  112. package/node_modules/@types/node/async_hooks.d.ts +603 -0
  113. package/node_modules/@types/node/buffer.buffer.d.ts +472 -0
  114. package/node_modules/@types/node/buffer.d.ts +1934 -0
  115. package/node_modules/@types/node/child_process.d.ts +1476 -0
  116. package/node_modules/@types/node/cluster.d.ts +578 -0
  117. package/node_modules/@types/node/compatibility/disposable.d.ts +14 -0
  118. package/node_modules/@types/node/compatibility/index.d.ts +9 -0
  119. package/node_modules/@types/node/compatibility/indexable.d.ts +20 -0
  120. package/node_modules/@types/node/compatibility/iterators.d.ts +20 -0
  121. package/node_modules/@types/node/console.d.ts +452 -0
  122. package/node_modules/@types/node/constants.d.ts +21 -0
  123. package/node_modules/@types/node/crypto.d.ts +4545 -0
  124. package/node_modules/@types/node/dgram.d.ts +600 -0
  125. package/node_modules/@types/node/diagnostics_channel.d.ts +576 -0
  126. package/node_modules/@types/node/dns/promises.d.ts +503 -0
  127. package/node_modules/@types/node/dns.d.ts +923 -0
  128. package/node_modules/@types/node/domain.d.ts +170 -0
  129. package/node_modules/@types/node/events.d.ts +976 -0
  130. package/node_modules/@types/node/fs/promises.d.ts +1306 -0
  131. package/node_modules/@types/node/fs.d.ts +4463 -0
  132. package/node_modules/@types/node/globals.d.ts +172 -0
  133. package/node_modules/@types/node/globals.typedarray.d.ts +38 -0
  134. package/node_modules/@types/node/http.d.ts +2097 -0
  135. package/node_modules/@types/node/http2.d.ts +2843 -0
  136. package/node_modules/@types/node/https.d.ts +579 -0
  137. package/node_modules/@types/node/index.d.ts +98 -0
  138. package/node_modules/@types/node/inspector.d.ts +253 -0
  139. package/node_modules/@types/node/inspector.generated.d.ts +4052 -0
  140. package/node_modules/@types/node/module.d.ts +891 -0
  141. package/node_modules/@types/node/net.d.ts +1076 -0
  142. package/node_modules/@types/node/os.d.ts +506 -0
  143. package/node_modules/@types/node/package.json +145 -0
  144. package/node_modules/@types/node/path.d.ts +200 -0
  145. package/node_modules/@types/node/perf_hooks.d.ts +968 -0
  146. package/node_modules/@types/node/process.d.ts +2084 -0
  147. package/node_modules/@types/node/punycode.d.ts +117 -0
  148. package/node_modules/@types/node/querystring.d.ts +152 -0
  149. package/node_modules/@types/node/readline/promises.d.ts +161 -0
  150. package/node_modules/@types/node/readline.d.ts +594 -0
  151. package/node_modules/@types/node/repl.d.ts +428 -0
  152. package/node_modules/@types/node/sea.d.ts +162 -0
  153. package/node_modules/@types/node/sqlite.d.ts +722 -0
  154. package/node_modules/@types/node/stream/consumers.d.ts +38 -0
  155. package/node_modules/@types/node/stream/promises.d.ts +90 -0
  156. package/node_modules/@types/node/stream/web.d.ts +573 -0
  157. package/node_modules/@types/node/stream.d.ts +1694 -0
  158. package/node_modules/@types/node/string_decoder.d.ts +67 -0
  159. package/node_modules/@types/node/test.d.ts +2265 -0
  160. package/node_modules/@types/node/timers/promises.d.ts +108 -0
  161. package/node_modules/@types/node/timers.d.ts +287 -0
  162. package/node_modules/@types/node/tls.d.ts +1319 -0
  163. package/node_modules/@types/node/trace_events.d.ts +197 -0
  164. package/node_modules/@types/node/ts5.6/buffer.buffer.d.ts +468 -0
  165. package/node_modules/@types/node/ts5.6/globals.typedarray.d.ts +34 -0
  166. package/node_modules/@types/node/ts5.6/index.d.ts +98 -0
  167. package/node_modules/@types/node/tty.d.ts +208 -0
  168. package/node_modules/@types/node/url.d.ts +984 -0
  169. package/node_modules/@types/node/util.d.ts +2606 -0
  170. package/node_modules/@types/node/v8.d.ts +920 -0
  171. package/node_modules/@types/node/vm.d.ts +1053 -0
  172. package/node_modules/@types/node/wasi.d.ts +181 -0
  173. package/node_modules/@types/node/web-globals/abortcontroller.d.ts +34 -0
  174. package/node_modules/@types/node/web-globals/domexception.d.ts +68 -0
  175. package/node_modules/@types/node/web-globals/events.d.ts +97 -0
  176. package/node_modules/@types/node/web-globals/fetch.d.ts +55 -0
  177. package/node_modules/@types/node/web-globals/navigator.d.ts +22 -0
  178. package/node_modules/@types/node/web-globals/storage.d.ts +24 -0
  179. package/node_modules/@types/node/web-globals/streams.d.ts +22 -0
  180. package/node_modules/@types/node/worker_threads.d.ts +819 -0
  181. package/node_modules/@types/node/zlib.d.ts +747 -0
  182. package/node_modules/@types/react/LICENSE +21 -0
  183. package/node_modules/@types/react/README.md +15 -0
  184. package/node_modules/@types/react/canary.d.ts +129 -0
  185. package/node_modules/@types/react/compiler-runtime.d.ts +4 -0
  186. package/node_modules/@types/react/experimental.d.ts +184 -0
  187. package/node_modules/@types/react/global.d.ts +166 -0
  188. package/node_modules/@types/react/index.d.ts +4378 -0
  189. package/node_modules/@types/react/jsx-dev-runtime.d.ts +33 -0
  190. package/node_modules/@types/react/jsx-runtime.d.ts +24 -0
  191. package/node_modules/@types/react/package.json +210 -0
  192. package/node_modules/@types/react/ts5.0/canary.d.ts +129 -0
  193. package/node_modules/@types/react/ts5.0/experimental.d.ts +184 -0
  194. package/node_modules/@types/react/ts5.0/global.d.ts +166 -0
  195. package/node_modules/@types/react/ts5.0/index.d.ts +4365 -0
  196. package/node_modules/@types/react/ts5.0/jsx-dev-runtime.d.ts +33 -0
  197. package/node_modules/@types/react/ts5.0/jsx-runtime.d.ts +24 -0
  198. package/node_modules/csstype/LICENSE +19 -0
  199. package/node_modules/csstype/README.md +291 -0
  200. package/node_modules/csstype/index.d.ts +22569 -0
  201. package/node_modules/csstype/index.js.flow +6863 -0
  202. package/node_modules/csstype/package.json +70 -0
  203. package/node_modules/entities/LICENSE +11 -0
  204. package/node_modules/entities/decode.d.ts +1 -0
  205. package/node_modules/entities/decode.js +3 -0
  206. package/node_modules/entities/dist/commonjs/decode-codepoint.d.ts +19 -0
  207. package/node_modules/entities/dist/commonjs/decode-codepoint.d.ts.map +1 -0
  208. package/node_modules/entities/dist/commonjs/decode-codepoint.js +77 -0
  209. package/node_modules/entities/dist/commonjs/decode-codepoint.js.map +1 -0
  210. package/node_modules/entities/dist/commonjs/decode.d.ts +209 -0
  211. package/node_modules/entities/dist/commonjs/decode.d.ts.map +1 -0
  212. package/node_modules/entities/dist/commonjs/decode.js +511 -0
  213. package/node_modules/entities/dist/commonjs/decode.js.map +1 -0
  214. package/node_modules/entities/dist/commonjs/encode.d.ts +22 -0
  215. package/node_modules/entities/dist/commonjs/encode.d.ts.map +1 -0
  216. package/node_modules/entities/dist/commonjs/encode.js +73 -0
  217. package/node_modules/entities/dist/commonjs/encode.js.map +1 -0
  218. package/node_modules/entities/dist/commonjs/escape.d.ts +43 -0
  219. package/node_modules/entities/dist/commonjs/escape.d.ts.map +1 -0
  220. package/node_modules/entities/dist/commonjs/escape.js +121 -0
  221. package/node_modules/entities/dist/commonjs/escape.js.map +1 -0
  222. package/node_modules/entities/dist/commonjs/generated/decode-data-html.d.ts +2 -0
  223. package/node_modules/entities/dist/commonjs/generated/decode-data-html.d.ts.map +1 -0
  224. package/node_modules/entities/dist/commonjs/generated/decode-data-html.js +10 -0
  225. package/node_modules/entities/dist/commonjs/generated/decode-data-html.js.map +1 -0
  226. package/node_modules/entities/dist/commonjs/generated/decode-data-xml.d.ts +2 -0
  227. package/node_modules/entities/dist/commonjs/generated/decode-data-xml.d.ts.map +1 -0
  228. package/node_modules/entities/dist/commonjs/generated/decode-data-xml.js +10 -0
  229. package/node_modules/entities/dist/commonjs/generated/decode-data-xml.js.map +1 -0
  230. package/node_modules/entities/dist/commonjs/generated/encode-html.d.ts +8 -0
  231. package/node_modules/entities/dist/commonjs/generated/encode-html.d.ts.map +1 -0
  232. package/node_modules/entities/dist/commonjs/generated/encode-html.js +13 -0
  233. package/node_modules/entities/dist/commonjs/generated/encode-html.js.map +1 -0
  234. package/node_modules/entities/dist/commonjs/index.d.ts +96 -0
  235. package/node_modules/entities/dist/commonjs/index.d.ts.map +1 -0
  236. package/node_modules/entities/dist/commonjs/index.js +131 -0
  237. package/node_modules/entities/dist/commonjs/index.js.map +1 -0
  238. package/node_modules/entities/dist/commonjs/package.json +3 -0
  239. package/node_modules/entities/dist/esm/decode-codepoint.d.ts +19 -0
  240. package/node_modules/entities/dist/esm/decode-codepoint.d.ts.map +1 -0
  241. package/node_modules/entities/dist/esm/decode-codepoint.js +72 -0
  242. package/node_modules/entities/dist/esm/decode-codepoint.js.map +1 -0
  243. package/node_modules/entities/dist/esm/decode.d.ts +209 -0
  244. package/node_modules/entities/dist/esm/decode.d.ts.map +1 -0
  245. package/node_modules/entities/dist/esm/decode.js +497 -0
  246. package/node_modules/entities/dist/esm/decode.js.map +1 -0
  247. package/node_modules/entities/dist/esm/encode.d.ts +22 -0
  248. package/node_modules/entities/dist/esm/encode.d.ts.map +1 -0
  249. package/node_modules/entities/dist/esm/encode.js +69 -0
  250. package/node_modules/entities/dist/esm/encode.js.map +1 -0
  251. package/node_modules/entities/dist/esm/escape.d.ts +43 -0
  252. package/node_modules/entities/dist/esm/escape.d.ts.map +1 -0
  253. package/node_modules/entities/dist/esm/escape.js +117 -0
  254. package/node_modules/entities/dist/esm/escape.js.map +1 -0
  255. package/node_modules/entities/dist/esm/generated/decode-data-html.d.ts +2 -0
  256. package/node_modules/entities/dist/esm/generated/decode-data-html.d.ts.map +1 -0
  257. package/node_modules/entities/dist/esm/generated/decode-data-html.js +7 -0
  258. package/node_modules/entities/dist/esm/generated/decode-data-html.js.map +1 -0
  259. package/node_modules/entities/dist/esm/generated/decode-data-xml.d.ts +2 -0
  260. package/node_modules/entities/dist/esm/generated/decode-data-xml.d.ts.map +1 -0
  261. package/node_modules/entities/dist/esm/generated/decode-data-xml.js +7 -0
  262. package/node_modules/entities/dist/esm/generated/decode-data-xml.js.map +1 -0
  263. package/node_modules/entities/dist/esm/generated/encode-html.d.ts +8 -0
  264. package/node_modules/entities/dist/esm/generated/encode-html.d.ts.map +1 -0
  265. package/node_modules/entities/dist/esm/generated/encode-html.js +10 -0
  266. package/node_modules/entities/dist/esm/generated/encode-html.js.map +1 -0
  267. package/node_modules/entities/dist/esm/index.d.ts +96 -0
  268. package/node_modules/entities/dist/esm/index.d.ts.map +1 -0
  269. package/node_modules/entities/dist/esm/index.js +107 -0
  270. package/node_modules/entities/dist/esm/index.js.map +1 -0
  271. package/node_modules/entities/dist/esm/package.json +3 -0
  272. package/node_modules/entities/escape.d.ts +1 -0
  273. package/node_modules/entities/escape.js +3 -0
  274. package/node_modules/entities/package.json +118 -0
  275. package/node_modules/entities/readme.md +122 -0
  276. package/node_modules/entities/src/decode-codepoint.ts +81 -0
  277. package/node_modules/entities/src/decode.spec.ts +320 -0
  278. package/node_modules/entities/src/decode.ts +620 -0
  279. package/node_modules/entities/src/encode.spec.ts +78 -0
  280. package/node_modules/entities/src/encode.ts +77 -0
  281. package/node_modules/entities/src/escape.spec.ts +14 -0
  282. package/node_modules/entities/src/escape.ts +148 -0
  283. package/node_modules/entities/src/generated/.eslintrc.json +10 -0
  284. package/node_modules/entities/src/generated/decode-data-html.ts +8 -0
  285. package/node_modules/entities/src/generated/decode-data-xml.ts +8 -0
  286. package/node_modules/entities/src/generated/encode-html.ts +17 -0
  287. package/node_modules/entities/src/index.spec.ts +125 -0
  288. package/node_modules/entities/src/index.ts +188 -0
  289. package/node_modules/parse5/LICENSE +19 -0
  290. package/node_modules/parse5/README.md +38 -0
  291. package/node_modules/parse5/dist/cjs/common/doctype.d.ts +4 -0
  292. package/node_modules/parse5/dist/cjs/common/doctype.js +118 -0
  293. package/node_modules/parse5/dist/cjs/common/error-codes.d.ts +67 -0
  294. package/node_modules/parse5/dist/cjs/common/error-codes.js +66 -0
  295. package/node_modules/parse5/dist/cjs/common/foreign-content.d.ts +9 -0
  296. package/node_modules/parse5/dist/cjs/common/foreign-content.js +237 -0
  297. package/node_modules/parse5/dist/cjs/common/html.d.ts +289 -0
  298. package/node_modules/parse5/dist/cjs/common/html.js +528 -0
  299. package/node_modules/parse5/dist/cjs/common/token.d.ts +84 -0
  300. package/node_modules/parse5/dist/cjs/common/token.js +24 -0
  301. package/node_modules/parse5/dist/cjs/common/unicode.d.ts +42 -0
  302. package/node_modules/parse5/dist/cjs/common/unicode.js +70 -0
  303. package/node_modules/parse5/dist/cjs/index.d.ts +71 -0
  304. package/node_modules/parse5/dist/cjs/index.js +54 -0
  305. package/node_modules/parse5/dist/cjs/package.json +1 -0
  306. package/node_modules/parse5/dist/cjs/parser/formatting-element-list.d.ts +36 -0
  307. package/node_modules/parse5/dist/cjs/parser/formatting-element-list.js +114 -0
  308. package/node_modules/parse5/dist/cjs/parser/index.d.ts +221 -0
  309. package/node_modules/parse5/dist/cjs/parser/index.js +3240 -0
  310. package/node_modules/parse5/dist/cjs/parser/open-element-stack.d.ts +53 -0
  311. package/node_modules/parse5/dist/cjs/parser/open-element-stack.js +328 -0
  312. package/node_modules/parse5/dist/cjs/serializer/index.d.ts +60 -0
  313. package/node_modules/parse5/dist/cjs/serializer/index.js +172 -0
  314. package/node_modules/parse5/dist/cjs/tokenizer/index.d.ts +247 -0
  315. package/node_modules/parse5/dist/cjs/tokenizer/index.js +2714 -0
  316. package/node_modules/parse5/dist/cjs/tokenizer/preprocessor.d.ts +36 -0
  317. package/node_modules/parse5/dist/cjs/tokenizer/preprocessor.js +200 -0
  318. package/node_modules/parse5/dist/cjs/tree-adapters/default.d.ts +84 -0
  319. package/node_modules/parse5/dist/cjs/tree-adapters/default.js +176 -0
  320. package/node_modules/parse5/dist/cjs/tree-adapters/interface.d.ts +255 -0
  321. package/node_modules/parse5/dist/cjs/tree-adapters/interface.js +2 -0
  322. package/node_modules/parse5/dist/common/doctype.d.ts +4 -0
  323. package/node_modules/parse5/dist/common/doctype.js +114 -0
  324. package/node_modules/parse5/dist/common/error-codes.d.ts +67 -0
  325. package/node_modules/parse5/dist/common/error-codes.js +63 -0
  326. package/node_modules/parse5/dist/common/foreign-content.d.ts +9 -0
  327. package/node_modules/parse5/dist/common/foreign-content.js +228 -0
  328. package/node_modules/parse5/dist/common/html.d.ts +289 -0
  329. package/node_modules/parse5/dist/common/html.js +523 -0
  330. package/node_modules/parse5/dist/common/token.d.ts +84 -0
  331. package/node_modules/parse5/dist/common/token.js +20 -0
  332. package/node_modules/parse5/dist/common/unicode.d.ts +42 -0
  333. package/node_modules/parse5/dist/common/unicode.js +62 -0
  334. package/node_modules/parse5/dist/index.d.ts +71 -0
  335. package/node_modules/parse5/dist/index.js +42 -0
  336. package/node_modules/parse5/dist/parser/formatting-element-list.d.ts +36 -0
  337. package/node_modules/parse5/dist/parser/formatting-element-list.js +110 -0
  338. package/node_modules/parse5/dist/parser/index.d.ts +221 -0
  339. package/node_modules/parse5/dist/parser/index.js +3245 -0
  340. package/node_modules/parse5/dist/parser/open-element-stack.d.ts +53 -0
  341. package/node_modules/parse5/dist/parser/open-element-stack.js +324 -0
  342. package/node_modules/parse5/dist/serializer/index.d.ts +60 -0
  343. package/node_modules/parse5/dist/serializer/index.js +168 -0
  344. package/node_modules/parse5/dist/tokenizer/index.d.ts +247 -0
  345. package/node_modules/parse5/dist/tokenizer/index.js +2710 -0
  346. package/node_modules/parse5/dist/tokenizer/preprocessor.d.ts +36 -0
  347. package/node_modules/parse5/dist/tokenizer/preprocessor.js +196 -0
  348. package/node_modules/parse5/dist/tree-adapters/default.d.ts +84 -0
  349. package/node_modules/parse5/dist/tree-adapters/default.js +173 -0
  350. package/node_modules/parse5/dist/tree-adapters/interface.d.ts +255 -0
  351. package/node_modules/parse5/dist/tree-adapters/interface.js +1 -0
  352. package/node_modules/parse5/package.json +50 -0
  353. package/node_modules/undici-types/LICENSE +21 -0
  354. package/node_modules/undici-types/README.md +6 -0
  355. package/node_modules/undici-types/agent.d.ts +31 -0
  356. package/node_modules/undici-types/api.d.ts +43 -0
  357. package/node_modules/undici-types/balanced-pool.d.ts +29 -0
  358. package/node_modules/undici-types/cache.d.ts +36 -0
  359. package/node_modules/undici-types/client.d.ts +108 -0
  360. package/node_modules/undici-types/connector.d.ts +34 -0
  361. package/node_modules/undici-types/content-type.d.ts +21 -0
  362. package/node_modules/undici-types/cookies.d.ts +28 -0
  363. package/node_modules/undici-types/diagnostics-channel.d.ts +66 -0
  364. package/node_modules/undici-types/dispatcher.d.ts +256 -0
  365. package/node_modules/undici-types/env-http-proxy-agent.d.ts +21 -0
  366. package/node_modules/undici-types/errors.d.ts +149 -0
  367. package/node_modules/undici-types/eventsource.d.ts +61 -0
  368. package/node_modules/undici-types/fetch.d.ts +209 -0
  369. package/node_modules/undici-types/file.d.ts +39 -0
  370. package/node_modules/undici-types/filereader.d.ts +54 -0
  371. package/node_modules/undici-types/formdata.d.ts +108 -0
  372. package/node_modules/undici-types/global-dispatcher.d.ts +9 -0
  373. package/node_modules/undici-types/global-origin.d.ts +7 -0
  374. package/node_modules/undici-types/handlers.d.ts +15 -0
  375. package/node_modules/undici-types/header.d.ts +4 -0
  376. package/node_modules/undici-types/index.d.ts +71 -0
  377. package/node_modules/undici-types/interceptors.d.ts +17 -0
  378. package/node_modules/undici-types/mock-agent.d.ts +50 -0
  379. package/node_modules/undici-types/mock-client.d.ts +25 -0
  380. package/node_modules/undici-types/mock-errors.d.ts +12 -0
  381. package/node_modules/undici-types/mock-interceptor.d.ts +93 -0
  382. package/node_modules/undici-types/mock-pool.d.ts +25 -0
  383. package/node_modules/undici-types/package.json +55 -0
  384. package/node_modules/undici-types/patch.d.ts +33 -0
  385. package/node_modules/undici-types/pool-stats.d.ts +19 -0
  386. package/node_modules/undici-types/pool.d.ts +39 -0
  387. package/node_modules/undici-types/proxy-agent.d.ts +28 -0
  388. package/node_modules/undici-types/readable.d.ts +65 -0
  389. package/node_modules/undici-types/retry-agent.d.ts +8 -0
  390. package/node_modules/undici-types/retry-handler.d.ts +116 -0
  391. package/node_modules/undici-types/util.d.ts +18 -0
  392. package/node_modules/undici-types/webidl.d.ts +228 -0
  393. package/node_modules/undici-types/websocket.d.ts +150 -0
  394. package/package.json +80 -0
  395. package/scripts/rebuild-forme.mjs +61 -0
  396. package/src/app/AppearanceControl.tsx +44 -0
  397. package/src/app/AssetThemeDefaults.tsx +87 -0
  398. package/src/app/AssetsBrowser.tsx +273 -0
  399. package/src/app/CommentDock.tsx +108 -0
  400. package/src/app/CreateDocumentDialog.tsx +51 -0
  401. package/src/app/DocumentActions.tsx +69 -0
  402. package/src/app/DocumentCard.tsx +50 -0
  403. package/src/app/DocumentViewControl.tsx +31 -0
  404. package/src/app/DocumentsBrowser.tsx +70 -0
  405. package/src/app/ExportHistoryDialog.tsx +86 -0
  406. package/src/app/ExportMenu.tsx +127 -0
  407. package/src/app/GuideDialog.tsx +80 -0
  408. package/src/app/InspectionLayer.tsx +77 -0
  409. package/src/app/LogoUploadDialog.tsx +92 -0
  410. package/src/app/Markdown.tsx +34 -0
  411. package/src/app/MaterialsBrowser.tsx +149 -0
  412. package/src/app/PageNumberInput.tsx +56 -0
  413. package/src/app/Pdf.tsx +561 -0
  414. package/src/app/ProjectDialogs.tsx +100 -0
  415. package/src/app/Reader.tsx +769 -0
  416. package/src/app/SearchField.tsx +13 -0
  417. package/src/app/Sidebar.tsx +86 -0
  418. package/src/app/SkillIndex.tsx +30 -0
  419. package/src/app/TemplatesBrowser.tsx +149 -0
  420. package/src/app/ThemesBrowser.tsx +159 -0
  421. package/src/app/api.ts +47 -0
  422. package/src/app/appearance.ts +35 -0
  423. package/src/app/assets.css +139 -0
  424. package/src/app/catalogPreview.ts +20 -0
  425. package/src/app/colors.css +167 -0
  426. package/src/app/comment-dock.css +53 -0
  427. package/src/app/commentDrafts.ts +67 -0
  428. package/src/app/componentCorrection.ts +17 -0
  429. package/src/app/edit-workbench.css +87 -0
  430. package/src/app/editSession.ts +238 -0
  431. package/src/app/editorRecovery.ts +25 -0
  432. package/src/app/export-history.css +31 -0
  433. package/src/app/export.css +17 -0
  434. package/src/app/guideLinks.ts +21 -0
  435. package/src/app/guides.css +40 -0
  436. package/src/app/main.tsx +221 -0
  437. package/src/app/materials.css +53 -0
  438. package/src/app/pdfLoading.ts +12 -0
  439. package/src/app/pdfSelection.ts +112 -0
  440. package/src/app/projects.css +63 -0
  441. package/src/app/reader-toolbar.css +65 -0
  442. package/src/app/selection.css +150 -0
  443. package/src/app/sidebar.css +60 -0
  444. package/src/app/skills.css +7 -0
  445. package/src/app/style.css +1061 -0
  446. package/src/app/templates.css +49 -0
  447. package/src/app/themes.css +80 -0
  448. package/src/app/ui/Icon.tsx +92 -0
  449. package/src/app/ui/README.md +27 -0
  450. package/src/app/ui/fonts.css +36 -0
  451. package/src/app/ui/index.tsx +223 -0
  452. package/src/app/ui/ui.css +388 -0
  453. package/src/app/useReaderPreview.ts +19 -0
  454. package/src/app/useTextEditing.ts +155 -0
  455. package/src/assets/adapter.ts +122 -0
  456. package/src/assets/files.ts +378 -0
  457. package/src/assets/import-worker.ts +294 -0
  458. package/src/assets/imports.ts +124 -0
  459. package/src/assets/index.ts +60 -0
  460. package/src/assets/store.ts +798 -0
  461. package/src/assets/usage.ts +118 -0
  462. package/src/cli/check.ts +25 -0
  463. package/src/cli/init.ts +119 -0
  464. package/src/cli/lock.ts +34 -0
  465. package/src/cli/main.ts +118 -0
  466. package/src/cli/process.ts +19 -0
  467. package/src/cli/start.ts +96 -0
  468. package/src/cli/update.ts +348 -0
  469. package/src/cli/workspace.ts +94 -0
  470. package/src/document/index.tsx +641 -0
  471. package/src/document/page.tsx +53 -0
  472. package/src/document/text-targets.tsx +162 -0
  473. package/src/media/files.ts +124 -0
  474. package/src/media/render.ts +63 -0
  475. package/src/rendering/resolve-sources.ts +84 -0
  476. package/src/runtime/jsx-dev-runtime.ts +2 -0
  477. package/src/runtime/jsx-runtime.ts +2 -0
  478. package/src/runtime/paths.ts +12 -0
  479. package/src/server/assets-cli.ts +162 -0
  480. package/src/server/assets-http.ts +100 -0
  481. package/src/server/client.ts +50 -0
  482. package/src/server/clipboard.ts +22 -0
  483. package/src/server/comments-cli.ts +64 -0
  484. package/src/server/comments.ts +130 -0
  485. package/src/server/create-cli.ts +33 -0
  486. package/src/server/create.ts +228 -0
  487. package/src/server/dependencies.ts +91 -0
  488. package/src/server/documents.ts +143 -0
  489. package/src/server/edits.ts +249 -0
  490. package/src/server/export-batch.ts +105 -0
  491. package/src/server/export-errors.ts +2 -0
  492. package/src/server/export-file.ts +57 -0
  493. package/src/server/export-inputs.ts +66 -0
  494. package/src/server/export-preview.ts +69 -0
  495. package/src/server/export.ts +32 -0
  496. package/src/server/exports.ts +283 -0
  497. package/src/server/files.ts +21 -0
  498. package/src/server/guides.ts +71 -0
  499. package/src/server/index.ts +432 -0
  500. package/src/server/materials.ts +39 -0
  501. package/src/server/media-cli.ts +73 -0
  502. package/src/server/media-mutations.ts +168 -0
  503. package/src/server/pptx.ts +160 -0
  504. package/src/server/preflight.ts +129 -0
  505. package/src/server/projects-cli.ts +29 -0
  506. package/src/server/projects.ts +187 -0
  507. package/src/server/render-error.ts +9 -0
  508. package/src/server/render-source.ts +24 -0
  509. package/src/server/render.ts +48 -0
  510. package/src/server/review-cli.ts +40 -0
  511. package/src/server/review.ts +161 -0
  512. package/src/server/selection.ts +23 -0
  513. package/src/server/source-overrides.ts +97 -0
  514. package/src/server/templates-cli.ts +51 -0
  515. package/src/server/templates.ts +186 -0
  516. package/src/server/text-layout.ts +41 -0
  517. package/src/server/text-source.ts +307 -0
  518. package/src/server/themes-cli.ts +59 -0
  519. package/src/server/themes.ts +215 -0
  520. package/src/server/ttf2eot.d.ts +3 -0
  521. package/src/server/worker.ts +166 -0
  522. package/src/server/workspace.ts +242 -0
  523. package/src/shared/anchors.ts +69 -0
  524. package/src/shared/assets.ts +154 -0
  525. package/src/shared/export.ts +34 -0
  526. package/src/shared/media.ts +33 -0
  527. package/src/shared/projects.ts +19 -0
  528. package/src/shared/selection.ts +94 -0
  529. package/src/shared/skill-index.ts +14 -0
  530. package/src/shared/starters.ts +19 -0
  531. package/src/shared/templates.ts +18 -0
  532. package/src/shared/themes.ts +24 -0
  533. package/src/shared/types.ts +39 -0
  534. package/src/template/index.ts +27 -0
  535. package/src/themes/index.ts +3 -0
  536. package/src/themes/neutral.ts +20 -0
  537. package/src/themes/types.ts +110 -0
  538. package/starter/assets/brand/wordmark.png +0 -0
  539. package/starter/assets/fonts/InterUI-LICENSE.txt +93 -0
  540. package/starter/assets/fonts/InterUI-Medium.ttf +0 -0
  541. package/starter/assets/fonts/InterUI-Regular.ttf +0 -0
  542. package/starter/assets/fonts/InterUI-source.json +19 -0
  543. package/starter/assets/fonts/OpenDocMono-Regular.ttf +0 -0
  544. package/starter/assets/fonts/OpenDocSans-Italic.ttf +0 -0
  545. package/starter/assets/fonts/OpenDocSans-Regular.ttf +0 -0
  546. package/starter/assets/fonts/OpenDocSans-Semibold.ttf +0 -0
  547. package/starter/assets/fonts/OpenDocSans-SemiboldItalic.ttf +0 -0
  548. package/starter/assets/fonts/OpenDocSerif-Italic.ttf +0 -0
  549. package/starter/assets/fonts/OpenDocSerif-Regular.ttf +0 -0
  550. package/starter/assets/fonts/OpenDocSerif-Semibold.ttf +0 -0
  551. package/starter/assets/fonts/OpenDocSerif-SemiboldItalic.ttf +0 -0
  552. package/starter/assets/fonts/SourceCode-LICENSE.md +93 -0
  553. package/starter/assets/fonts/SourceSans-LICENSE.md +93 -0
  554. package/starter/assets/fonts/SourceSerif-LICENSE.md +93 -0
  555. package/starter/assets/fonts/geist/OFL.txt +93 -0
  556. package/starter/assets/fonts/geist/asset.json +7 -0
  557. package/starter/assets/fonts/geist/files/1a9874b3be0fc168692a3d2327bccb4d28835653d3b91537a755296a467a83e3.ttf +0 -0
  558. package/starter/assets/fonts/geist/files/a8eefb873ba9c9020665f8a98302697ce1f3b79ab2deef6ee508c0ca6a82e876.ttf +0 -0
  559. package/starter/assets/fonts/geist/files/ccce59465ae5c61930ada5453834f60500fbd95084d85db63e0e65fad0125455.ttf +0 -0
  560. package/starter/assets/fonts/geist/files/f5e95110d70593672515080bee9148463ada0a7f77b89ed65a3d43cb2b0ff83a.pdf +0 -0
  561. package/starter/assets/fonts/geist/revisions/9a2bc12fb2f23cb27bc227087e63e1407bb804ee0586480bd6b7966ec69fb474.json +60 -0
  562. package/starter/assets/fonts/inter/OFL.txt +93 -0
  563. package/starter/assets/fonts/inter/asset.json +7 -0
  564. package/starter/assets/fonts/inter/files/1b08e7fc267a5c7e1d614100f604b83e7e8a0be241f0f288faa2b3ac93a683ba.ttf +0 -0
  565. package/starter/assets/fonts/inter/files/5b6f0c6f26e5c554a64cdcc3a9b5d802b7f9aec6206f1dbcfcdcad7b5860a2a9.ttf +0 -0
  566. package/starter/assets/fonts/inter/files/957db8560d510a198a7d0333fae7b6b444b00c20801581126273978d778eb3c3.pdf +0 -0
  567. package/starter/assets/fonts/inter/files/b37284b5701b6b168dfc770aa1a4ac492106422fd3ba76bc7641e37434e8019c.ttf +0 -0
  568. package/starter/assets/fonts/inter/files/c1811d32ac0f6eed1bbf57529f2ecdfc6c717d48a969dd864942436315a1b198.ttf +0 -0
  569. package/starter/assets/fonts/inter/files/e7a1aaf7eda9f2fad4131725fa556265ec75ca7b2d756260173a040363e8d4f7.ttf +0 -0
  570. package/starter/assets/fonts/inter/files/ef8f755d933b9310804cc9152f1f18cb2ac460d6b05054ec913d889c9f11f79e.ttf +0 -0
  571. package/starter/assets/fonts/inter/revisions/600391517c413963b71e278a57c26c40366c81fa3939a6b9755f446206766d12.json +99 -0
  572. package/starter/assets/fonts/inter/source.json +57 -0
  573. package/starter/assets/fonts/lato/OFL.txt +93 -0
  574. package/starter/assets/fonts/lato/asset.json +7 -0
  575. package/starter/assets/fonts/lato/files/4a6b566dbb28adb473a8789ce5169306f42f0c8a070ac92bae93636f36348b0d.pdf +0 -0
  576. package/starter/assets/fonts/lato/files/5adeb6b334d8fb99ef053bc052b952773d544315e0e1d668a12c0ce8bd51375c.ttf +0 -0
  577. package/starter/assets/fonts/lato/files/62c1b7f0d2e74b45960154c3520efc337b553db0961bfdc950d5618334596cc8.ttf +0 -0
  578. package/starter/assets/fonts/lato/files/71b8b7decbe75a881ed267be539d402bd1e9420b799658aada4e0d1bd5af803c.ttf +0 -0
  579. package/starter/assets/fonts/lato/files/8a0aace75d33794eece4b28187bfc1df0bbd2888b5d8a56e01788c8d65d16be1.ttf +0 -0
  580. package/starter/assets/fonts/lato/files/d636e4683231f931eda222d588e944d082bfd3bdba02f928bee461c0f185b251.ttf +0 -0
  581. package/starter/assets/fonts/lato/files/e399c44efe1387100531d26c7e4800c5d12251b890d6654a3098c7c679cb1786.ttf +0 -0
  582. package/starter/assets/fonts/lato/revisions/49ccb93400a9d466fab7d9843b1ecf8916ec6d47a475dd79a597a22eb39616bc.json +99 -0
  583. package/starter/assets/fonts/lato/source.json +57 -0
  584. package/starter/assets/fonts/merriweather/OFL.txt +93 -0
  585. package/starter/assets/fonts/merriweather/asset.json +7 -0
  586. package/starter/assets/fonts/merriweather/files/1c54f91b910454251c4c2b7bd4e472e1abf265fba7ca3c0ef2eee2f41324099e.ttf +0 -0
  587. package/starter/assets/fonts/merriweather/files/8bde8da2bb7f0265e27ba0481f70bb48d0f98a976c145f2f239c648ddd6532e0.pdf +0 -0
  588. package/starter/assets/fonts/merriweather/files/90b7db4460fcd1a5ca49575c2668a793f3cd6447664d312a068d690e1c01e6bc.ttf +0 -0
  589. package/starter/assets/fonts/merriweather/files/afff81272b7653417bb6f8bef57add055b1f9fda36f27eba5f32b40752bd08da.ttf +0 -0
  590. package/starter/assets/fonts/merriweather/files/e029d3b71e5bae3877c73f4f2b15af28db16593d49b0aed2a328d37ff7075846.ttf +0 -0
  591. package/starter/assets/fonts/merriweather/files/e9864a6790bf712a04e20f3662b206a1535186ed3e877fd859dd5fb9682335df.ttf +0 -0
  592. package/starter/assets/fonts/merriweather/files/fa71baebdd20a7d0de2e5e445a5922530fe9e1d740efbe791f113b682d3cb093.ttf +0 -0
  593. package/starter/assets/fonts/merriweather/revisions/1888e390b3e4f38a3d7cd2dc1bb805aeb6ce13f986a97656f0265fd436bc91d2.json +99 -0
  594. package/starter/assets/fonts/merriweather/source.json +57 -0
  595. package/starter/assets/fonts/open-sans/OFL.txt +92 -0
  596. package/starter/assets/fonts/open-sans/asset.json +7 -0
  597. package/starter/assets/fonts/open-sans/files/1bc0594a83762b2c25d38915a34464b7fec6088298ca22d151757bf98d6700ec.ttf +0 -0
  598. package/starter/assets/fonts/open-sans/files/47ed1cfaa7ffca04a04ab850b2938fd52c09d1b44cfa3e2980878e166b0cbd87.ttf +0 -0
  599. package/starter/assets/fonts/open-sans/files/574939af301f07df8e21cfff279465c5981dd9d9cf62086f7515897df951c6f5.pdf +0 -0
  600. package/starter/assets/fonts/open-sans/files/6d3884d0d57c1b67e9c50c54eca7b69c535c114e76bd7a9cfda0258588185553.ttf +0 -0
  601. package/starter/assets/fonts/open-sans/files/733eb93b167e6d45de09aa768f6c0355647c2c26f5416dbc7407a08ed41e81c6.ttf +0 -0
  602. package/starter/assets/fonts/open-sans/files/75367e6da7d914eaed87883ba51b2a2b5816b5cdbb39f96ec5c81a5b032bfd5a.ttf +0 -0
  603. package/starter/assets/fonts/open-sans/files/ff4fdc11204e0edd14e9a0bb6c374b847a9093b0ec2c16702e03afca79ac4ef7.ttf +0 -0
  604. package/starter/assets/fonts/open-sans/revisions/bbbe3a4915b9bccbc883c0decb4097511c43b6bd09ae22a1516aff128c219bc5.json +99 -0
  605. package/starter/assets/fonts/open-sans/source.json +57 -0
  606. package/starter/assets/fonts/roboto/OFL.txt +93 -0
  607. package/starter/assets/fonts/roboto/asset.json +7 -0
  608. package/starter/assets/fonts/roboto/files/22d45d989248a624252b8382067ac56550212fa675dcdbaf12f03d297dd87a58.pdf +0 -0
  609. package/starter/assets/fonts/roboto/files/35757eaa996b3359022f47f164a67ee9eac04971af24c5b8fbd4b89e844ff190.ttf +0 -0
  610. package/starter/assets/fonts/roboto/files/4d3035883c531846bd1ce2dc89f36d932e72dc114f56062c7e3a9cdd74f3d3ea.ttf +0 -0
  611. package/starter/assets/fonts/roboto/files/be7639306a4fc4a02ce2ae2ff59eb1335e4db4a7379dd0a384ed7cc053817789.ttf +0 -0
  612. package/starter/assets/fonts/roboto/files/d2920cbb1b60a3fd11fbf22049286e43a6baf522d37fdf1e7c89562319bcfea5.ttf +0 -0
  613. package/starter/assets/fonts/roboto/files/dece7c71bbe61710787f0839c722c65e87355dd2eb4a823e6b5488121ff81e4b.ttf +0 -0
  614. package/starter/assets/fonts/roboto/files/f478ba88b0292e685e487901dfbb1401457d32d6ebee4030cdfd5698235bffa8.ttf +0 -0
  615. package/starter/assets/fonts/roboto/revisions/bda5e2d84c17313373dd2dbf3e64fe0dd450c7e1b59e6929e69557e122fe976e.json +99 -0
  616. package/starter/assets/fonts/roboto/source.json +57 -0
  617. package/starter/assets/logos/opendoc/asset.json +6 -0
  618. package/starter/assets/logos/opendoc/files/831d5ccd9eb6709cc8439ea257c03d81452e81a28a3d1eedbd6a3b7daff687b6.png +0 -0
  619. package/starter/assets/logos/opendoc/revisions/834dde8926ddb81de687254195a168bb13bfb77803307f1257de1f2228be63b2.json +33 -0
  620. package/starter/assets/ui-fonts/geist/OFL.txt +93 -0
  621. package/starter/assets/ui-fonts/geist/geist-latin-ext-wght-italic.woff2 +0 -0
  622. package/starter/assets/ui-fonts/geist/geist-latin-ext-wght-normal.woff2 +0 -0
  623. package/starter/assets/ui-fonts/geist/geist-latin-wght-italic.woff2 +0 -0
  624. package/starter/assets/ui-fonts/geist/geist-latin-wght-normal.woff2 +0 -0
  625. package/starter/assets/ui-fonts/geist/source.json +26 -0
  626. package/starter/documents/welcome/assets.json +7 -0
  627. package/starter/documents/welcome/index.tsx +160 -0
  628. package/starter/documents/welcome/media/.gitkeep +0 -0
  629. package/starter/documents/welcome/media/paper-architecture/image.png +0 -0
  630. package/starter/documents/welcome/media/paper-architecture/meta.json +9 -0
  631. package/starter/documents/welcome/media/paper-architecture/prompt.txt +1 -0
  632. package/starter/documents/welcome/media/studio-rhythm/chart.svg +2343 -0
  633. package/starter/documents/welcome/media/studio-rhythm/data.json +234 -0
  634. package/starter/documents/welcome/media/studio-rhythm/generation.json +9 -0
  635. package/starter/documents/welcome/media/studio-rhythm/image.png +0 -0
  636. package/starter/documents/welcome/media/studio-rhythm/meta.json +11 -0
  637. package/starter/documents/welcome/media/studio-rhythm/recipe.py +79 -0
  638. package/starter/documents/welcome/theme.tsx +5 -0
  639. package/starter/documents/welcome-presentation/assets.json +7 -0
  640. package/starter/documents/welcome-presentation/index.tsx +166 -0
  641. package/starter/documents/welcome-presentation/media/.gitkeep +0 -0
  642. package/starter/documents/welcome-presentation/media/paper-architecture/image.png +0 -0
  643. package/starter/documents/welcome-presentation/media/paper-architecture/meta.json +9 -0
  644. package/starter/documents/welcome-presentation/media/paper-architecture/prompt.txt +1 -0
  645. package/starter/documents/welcome-presentation/media/studio-rhythm/chart.svg +1336 -0
  646. package/starter/documents/welcome-presentation/media/studio-rhythm/data.json +234 -0
  647. package/starter/documents/welcome-presentation/media/studio-rhythm/generation.json +9 -0
  648. package/starter/documents/welcome-presentation/media/studio-rhythm/image.png +0 -0
  649. package/starter/documents/welcome-presentation/media/studio-rhythm/meta.json +13 -0
  650. package/starter/documents/welcome-presentation/media/studio-rhythm/recipe.py +49 -0
  651. package/starter/documents/welcome-presentation/theme.tsx +5 -0
  652. package/starter/projects.json +17 -0
  653. package/starter/templates/AGENTS.md +9 -0
  654. package/starter/templates/_shared/BusinessLogo.tsx +14 -0
  655. package/starter/templates/_shared/Pricing.tsx +40 -0
  656. package/starter/templates/_shared/commerce.ts +93 -0
  657. package/starter/templates/brand-guidelines/AGENTS.md +32 -0
  658. package/starter/templates/brand-guidelines/index.tsx +62 -0
  659. package/starter/templates/brand-guidelines/preview.tsx +181 -0
  660. package/starter/templates/brand-guidelines/starter.tsx +179 -0
  661. package/starter/templates/brand-guidelines/template.json +15 -0
  662. package/starter/templates/business-proposal/AGENTS.md +13 -0
  663. package/starter/templates/business-proposal/README.md +36 -0
  664. package/starter/templates/business-proposal/data.json +37 -0
  665. package/starter/templates/business-proposal/examples/long.json +142 -0
  666. package/starter/templates/business-proposal/examples/sparse.json +17 -0
  667. package/starter/templates/business-proposal/examples/typical.json +37 -0
  668. package/starter/templates/business-proposal/index.tsx +59 -0
  669. package/starter/templates/business-proposal/preview.tsx +47 -0
  670. package/starter/templates/business-proposal/schema.ts +14 -0
  671. package/starter/templates/business-proposal/starter.tsx +18 -0
  672. package/starter/templates/business-proposal/template.json +11 -0
  673. package/starter/templates/company-profile/AGENTS.md +48 -0
  674. package/starter/templates/company-profile/index.tsx +69 -0
  675. package/starter/templates/company-profile/preview.tsx +185 -0
  676. package/starter/templates/company-profile/starter.tsx +186 -0
  677. package/starter/templates/company-profile/template.json +15 -0
  678. package/starter/templates/consulting-report/AGENTS.md +11 -0
  679. package/starter/templates/consulting-report/README.md +13 -0
  680. package/starter/templates/consulting-report/RESEARCH.md +10 -0
  681. package/starter/templates/consulting-report/index.tsx +44 -0
  682. package/starter/templates/consulting-report/preview.tsx +39 -0
  683. package/starter/templates/consulting-report/starter.tsx +15 -0
  684. package/starter/templates/consulting-report/template.json +11 -0
  685. package/starter/templates/editorial-essay/AGENTS.md +11 -0
  686. package/starter/templates/editorial-essay/README.md +11 -0
  687. package/starter/templates/editorial-essay/index.tsx +30 -0
  688. package/starter/templates/editorial-essay/preview.tsx +26 -0
  689. package/starter/templates/editorial-essay/starter.tsx +15 -0
  690. package/starter/templates/editorial-essay/template.json +11 -0
  691. package/starter/templates/executive-brief/AGENTS.md +9 -0
  692. package/starter/templates/executive-brief/README.md +11 -0
  693. package/starter/templates/executive-brief/index.tsx +33 -0
  694. package/starter/templates/executive-brief/preview.tsx +37 -0
  695. package/starter/templates/executive-brief/starter.tsx +11 -0
  696. package/starter/templates/executive-brief/template.json +11 -0
  697. package/starter/templates/image-story/AGENTS.md +37 -0
  698. package/starter/templates/image-story/index.tsx +106 -0
  699. package/starter/templates/image-story/preview.tsx +33 -0
  700. package/starter/templates/image-story/starter.tsx +24 -0
  701. package/starter/templates/image-story/template.json +13 -0
  702. package/starter/templates/invoice/AGENTS.md +13 -0
  703. package/starter/templates/invoice/README.md +40 -0
  704. package/starter/templates/invoice/data.json +61 -0
  705. package/starter/templates/invoice/examples/long.json +241 -0
  706. package/starter/templates/invoice/examples/sparse.json +33 -0
  707. package/starter/templates/invoice/examples/typical.json +61 -0
  708. package/starter/templates/invoice/index.tsx +57 -0
  709. package/starter/templates/invoice/preview.tsx +12 -0
  710. package/starter/templates/invoice/schema.ts +45 -0
  711. package/starter/templates/invoice/starter.tsx +12 -0
  712. package/starter/templates/invoice/template.json +11 -0
  713. package/starter/templates/literary-text/AGENTS.md +9 -0
  714. package/starter/templates/literary-text/README.md +11 -0
  715. package/starter/templates/literary-text/index.tsx +31 -0
  716. package/starter/templates/literary-text/preview.tsx +20 -0
  717. package/starter/templates/literary-text/starter.tsx +11 -0
  718. package/starter/templates/literary-text/template.json +11 -0
  719. package/starter/templates/magazine-feature/AGENTS.md +11 -0
  720. package/starter/templates/magazine-feature/README.md +13 -0
  721. package/starter/templates/magazine-feature/index.tsx +41 -0
  722. package/starter/templates/magazine-feature/preview.tsx +34 -0
  723. package/starter/templates/magazine-feature/starter.tsx +15 -0
  724. package/starter/templates/magazine-feature/template.json +11 -0
  725. package/starter/templates/monthly-report/AGENTS.md +11 -0
  726. package/starter/templates/monthly-report/README.md +24 -0
  727. package/starter/templates/monthly-report/data.json +131 -0
  728. package/starter/templates/monthly-report/examples/long.json +519 -0
  729. package/starter/templates/monthly-report/examples/sparse.json +20 -0
  730. package/starter/templates/monthly-report/examples/typical.json +37 -0
  731. package/starter/templates/monthly-report/index.tsx +92 -0
  732. package/starter/templates/monthly-report/preview.tsx +14 -0
  733. package/starter/templates/monthly-report/schema.ts +127 -0
  734. package/starter/templates/monthly-report/starter.tsx +13 -0
  735. package/starter/templates/monthly-report/template.json +11 -0
  736. package/starter/templates/pitch-deck/AGENTS.md +32 -0
  737. package/starter/templates/pitch-deck/index.tsx +46 -0
  738. package/starter/templates/pitch-deck/preview.tsx +142 -0
  739. package/starter/templates/pitch-deck/starter.tsx +140 -0
  740. package/starter/templates/pitch-deck/template.json +15 -0
  741. package/starter/templates/proposal-deck/AGENTS.md +25 -0
  742. package/starter/templates/proposal-deck/index.tsx +52 -0
  743. package/starter/templates/proposal-deck/preview.tsx +172 -0
  744. package/starter/templates/proposal-deck/starter.tsx +168 -0
  745. package/starter/templates/proposal-deck/template.json +7 -0
  746. package/starter/templates/quotation/AGENTS.md +13 -0
  747. package/starter/templates/quotation/README.md +42 -0
  748. package/starter/templates/quotation/data.json +64 -0
  749. package/starter/templates/quotation/examples/long.json +272 -0
  750. package/starter/templates/quotation/examples/sparse.json +31 -0
  751. package/starter/templates/quotation/examples/typical.json +64 -0
  752. package/starter/templates/quotation/index.tsx +51 -0
  753. package/starter/templates/quotation/preview.tsx +12 -0
  754. package/starter/templates/quotation/schema.ts +27 -0
  755. package/starter/templates/quotation/starter.tsx +12 -0
  756. package/starter/templates/quotation/template.json +11 -0
  757. package/starter/templates/scientific-paper/AGENTS.md +11 -0
  758. package/starter/templates/scientific-paper/README.md +13 -0
  759. package/starter/templates/scientific-paper/index.tsx +47 -0
  760. package/starter/templates/scientific-paper/preview.tsx +43 -0
  761. package/starter/templates/scientific-paper/starter.tsx +15 -0
  762. package/starter/templates/scientific-paper/template.json +11 -0
  763. package/starter/themes/Specimen.tsx +54 -0
  764. package/starter/themes/civic-spectrum/components.tsx +92 -0
  765. package/starter/themes/civic-spectrum/design.md +70 -0
  766. package/starter/themes/civic-spectrum/index.ts +57 -0
  767. package/starter/themes/civic-spectrum/preview.tsx +66 -0
  768. package/starter/themes/field-manual/components.tsx +106 -0
  769. package/starter/themes/field-manual/design.md +72 -0
  770. package/starter/themes/field-manual/index.ts +57 -0
  771. package/starter/themes/field-manual/preview.tsx +82 -0
  772. package/starter/themes/index.ts +3 -0
  773. package/starter/themes/mckinsey-consulting/components.tsx +69 -0
  774. package/starter/themes/mckinsey-consulting/design.md +68 -0
  775. package/starter/themes/mckinsey-consulting/index.ts +60 -0
  776. package/starter/themes/mckinsey-consulting/preview.tsx +53 -0
  777. package/starter/themes/neutral/design.md +35 -0
  778. package/starter/themes/neutral/index.ts +21 -0
  779. package/starter/themes/neutral/preview.tsx +4 -0
  780. package/starter/themes/opendoc-neutral/components.tsx +77 -0
  781. package/starter/themes/opendoc-neutral/design.md +70 -0
  782. package/starter/themes/opendoc-neutral/index.ts +54 -0
  783. package/starter/themes/opendoc-neutral/preview.tsx +43 -0
  784. package/starter/themes/types.ts +3 -0
  785. package/tsconfig.workspace.json +24 -0
  786. package/vendor/formepdf/LICENSE +21 -0
  787. package/vendor/formepdf/README.md +97 -0
  788. package/vendor/formepdf/font-subset.patch +228 -0
  789. package/vendor/formepdf/text-writer.patch +507 -0
@@ -0,0 +1,64 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "title": "Website content package",
4
+ "number": "SAMPLE-Q-001",
5
+ "issuedOn": "2026-09-08",
6
+ "validUntil": "2026-09-22",
7
+ "seller": {
8
+ "name": "Example Studio",
9
+ "details": "Studio address placeholder\nContact details placeholder"
10
+ },
11
+ "client": {
12
+ "name": "Example Client",
13
+ "details": "Client address placeholder\nAttention: project contact"
14
+ },
15
+ "synthetic": true,
16
+ "introduction": "A sample scope and pricing schedule. Replace the illustrative details with the work and commercial terms actually agreed with the client.",
17
+ "pricing": {
18
+ "currency": {
19
+ "code": "USD",
20
+ "decimals": 2
21
+ },
22
+ "items": [
23
+ {
24
+ "id": "planning",
25
+ "description": "Content planning workshop",
26
+ "quantity": "2.5",
27
+ "unit": "hours",
28
+ "unitPrice": "160.00"
29
+ },
30
+ {
31
+ "id": "writing",
32
+ "description": "Website copy package: supplied scope and agreed deliverables",
33
+ "quantity": "1",
34
+ "unit": "package",
35
+ "unitPrice": "600.00"
36
+ },
37
+ {
38
+ "id": "review",
39
+ "description": "Review and revision sessions",
40
+ "quantity": "3",
41
+ "unit": "hours",
42
+ "unitPrice": "75.00"
43
+ }
44
+ ],
45
+ "discount": "25.00",
46
+ "tax": {
47
+ "label": "Illustrative tax",
48
+ "ratePercent": "10"
49
+ }
50
+ },
51
+ "terms": [
52
+ {
53
+ "id": "delivery",
54
+ "title": "Delivery",
55
+ "text": "Illustrative schedule placeholder. Supply the milestones, dependencies, and delivery dates that apply to the actual work."
56
+ },
57
+ {
58
+ "id": "payment",
59
+ "title": "Payment",
60
+ "text": "Illustrative payment placeholder. Supply the agreed payment schedule and any relevant reference details."
61
+ }
62
+ ],
63
+ "acceptance": "Optional acceptance wording placeholder. Replace with the agreed process, or omit this area when acceptance is recorded elsewhere."
64
+ }
@@ -0,0 +1,51 @@
1
+ import type { ReactNode } from 'react';
2
+ import * as F from '@formepdf/react';
3
+ import { TextSlot, Block, Document, Heading, Paragraph, Strong, Page } from 'opendoc';
4
+ import { defineTemplate } from 'opendoc/template';
5
+ import { themePage, type DocTheme } from 'opendoc/themes';
6
+ import { BusinessLogo } from '../_shared/BusinessLogo';
7
+ import { Pricing } from '../_shared/Pricing';
8
+ import { parseQuotation, type QuotationData } from './schema';
9
+ export { parseQuotation } from './schema';
10
+ export type { QuotationData } from './schema';
11
+
12
+ export function Quotation({ data, theme, titleStyle, logo }: { data: QuotationData; theme: DocTheme; titleStyle?: F.Style; logo?: ReactNode }) {
13
+ const layoutTheme = theme.design ? theme : { ...theme, fontSize: 10.5, lineHeight: 1.4, paragraphGap: 8 };
14
+ return <Document title={data.title} author={data.seller.name} theme={layoutTheme}>
15
+ <Page {...themePage(theme, { top: 48, bottom: 52, left: 48, right: 48 })} style={{ lineBreaking: 'greedy', ...theme.design?.page?.style }}>
16
+ {(!theme.design || theme.runningFooter) && <F.Fixed position="footer"><F.Text style={{ fontFamily: theme.design ? theme.body : undefined, fontSize: 8, color: theme.muted, textAlign: 'right', ...theme.design?.furniture?.text, ...theme.design?.furniture?.footer }}>{data.synthetic ? 'Illustrative quotation · ' : ''}{theme.design?.furniture?.pageNumber === 'total' ? '{{pageNumber}} / {{totalPages}}' : '{{pageNumber}}'}</F.Text></F.Fixed>}
17
+ <F.View style={theme.design?.title?.block}>
18
+ <F.View wrap={false} style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8 }}>
19
+ <Paragraph id="quote-label" role="label" baseStyle={{ fontSize: 9, letterSpacing: 0.8, color: theme.muted, marginBottom: 0 }} style={theme.design?.title?.eyebrow}>QUOTATION</Paragraph>
20
+ <BusinessLogo id="quote-logo" theme={theme}>{logo}</BusinessLogo>
21
+ </F.View>
22
+ <Heading id="quote-title" level={1} baseStyle={{ fontSize: 28, lineHeight: 1.15, marginBottom: 12 }} style={{ ...theme.design?.title?.heading, ...titleStyle }}><TextSlot slot="title" field={['title']}>{data.title}</TextSlot></Heading>
23
+ <Paragraph id="quote-reference" role="small" baseStyle={{ fontSize: 9, marginBottom: 20 }} style={theme.design?.title?.byline}>No. <TextSlot slot="number" field={['number']}>{data.number}</TextSlot> · Issued <TextSlot slot="issuedOn" field={['issuedOn']}>{data.issuedOn}</TextSlot>{data.validUntil ? <> · Valid through <TextSlot slot="validUntil" field={['validUntil']}>{data.validUntil}</TextSlot></> : ''}</Paragraph>
24
+ </F.View>
25
+ <Block id="quote-parties"><F.View wrap={false} style={{ flexDirection: 'row', gap: 28, marginBottom: 16 }}>
26
+ {([['From', data.seller, 'seller'], ['Prepared for', data.client, 'client']] as const).map(([label, details, partyField]) => {
27
+ return <F.View key={label} style={{ flex: 1 }}>
28
+ <F.Text style={{ fontSize: 8.5, color: theme.muted, marginBottom: 5, ...theme.design?.typography?.small }}>{label}</F.Text>
29
+ <F.Text style={{ fontWeight: 600, marginBottom: 5 }}><TextSlot slot={`${partyField}-name`} field={[partyField, 'name']}>{details.name}</TextSlot></F.Text>
30
+ {details.details && <F.Text style={{ fontSize: 9.5, color: theme.muted, ...theme.design?.typography?.small }}><TextSlot slot={`${partyField}-details`} field={[partyField, 'details']}>{details.details}</TextSlot></F.Text>}
31
+ </F.View>;
32
+ })}
33
+ </F.View></Block>
34
+ {data.synthetic && <Paragraph id="quote-sample-notice" role="small" baseStyle={{ fontSize: 9, color: theme.muted }}>Illustrative quotation. All parties, prices, dates, and terms are synthetic. This is not a commercial offer.</Paragraph>}
35
+ {data.introduction && <Paragraph id="quote-introduction"><TextSlot slot="introduction" field={['introduction']}>{data.introduction}</TextSlot></Paragraph>}
36
+ <Pricing data={data.pricing} theme={theme} totalLabel="Quoted total" />
37
+ {data.terms.map(term => <Paragraph key={term.id} id={`quote-term-${term.id.length}-${term.id}`} role="small" baseStyle={{ fontSize: 9.5, marginBottom: 10 }}><Strong><TextSlot slot="title" field={['terms', { id: term.id }, 'title']}>{term.title}</TextSlot>. </Strong><TextSlot slot="text" field={['terms', { id: term.id }, 'text']}>{term.text}</TextSlot></Paragraph>)}
38
+ {data.acceptance && <F.View wrap={data.acceptance.length > 420}>
39
+ <Paragraph id="quote-acceptance" role="small" baseStyle={{ fontSize: 9.5, marginTop: 10 }}><Strong>Acceptance. </Strong><TextSlot slot="acceptance" field={['acceptance']}>{data.acceptance}</TextSlot></Paragraph>
40
+ <Block id="quote-signature-fields"><F.View wrap={false} style={{ flexDirection: 'row', gap: 22, marginTop: 12 }}>
41
+ {['Name', 'Signature', 'Date'].map(label => <F.View key={label} style={{ flex: 1 }}><F.View style={{ height: 22, borderBottomWidth: 0.6, borderColor: theme.line }} /><F.Text style={{ fontSize: 8, color: theme.muted, marginTop: 5, ...theme.design?.typography?.small }}>{label}</F.Text></F.View>)}
42
+ </F.View></Block>
43
+ </F.View>}
44
+ </Page>
45
+ </Document>;
46
+ }
47
+ export const quotationTemplate = (theme: DocTheme, { logo }: { logo?: ReactNode } = {}) => defineTemplate<QuotationData>({
48
+ parse: parseQuotation,
49
+ meta: data => ({ title: data.title, description: `Quotation ${data.number} for ${data.client.name}.`, kind: 'report', theme: theme.id, author: data.seller.name }),
50
+ render: data => <Quotation data={data} theme={theme} logo={logo} />,
51
+ });
@@ -0,0 +1,12 @@
1
+ import { neutral } from '../../themes';
2
+ import { type DocTheme } from 'opendoc/themes';
3
+ import { parseQuotation, quotationTemplate } from './index';
4
+ import typical from './examples/typical.json';
5
+ import sparse from './examples/sparse.json';
6
+ import long from './examples/long.json';
7
+ export const meta = quotationTemplate(neutral).meta(parseQuotation(typical));
8
+ export function Specimen({ length = 'typical', theme = neutral }: { length?: 'sparse' | 'typical' | 'long'; theme?: DocTheme } = {}) {
9
+ const template = quotationTemplate(theme);
10
+ return template.render(template.parse({ sparse, typical, long }[length]));
11
+ }
12
+ export default Specimen;
@@ -0,0 +1,27 @@
1
+ import { date, object, optionalText, parsePricing, text, type PricingData } from '../_shared/commerce';
2
+ export interface QuotationData {
3
+ schemaVersion: 1; title: string; number: string; issuedOn: string; validUntil?: string;
4
+ seller: { name: string; details?: string }; client: { name: string; details?: string };
5
+ synthetic: boolean; introduction?: string; pricing: PricingData;
6
+ terms: { id: string; title: string; text: string }[]; acceptance?: string;
7
+ }
8
+ export function parseQuotation(input: unknown): QuotationData {
9
+ const data = object(input, ['schemaVersion', 'title', 'number', 'issuedOn', 'validUntil', 'seller', 'client', 'synthetic', 'introduction', 'pricing', 'terms', 'acceptance'], 'quotation');
10
+ if (data.schemaVersion !== 1) throw new Error('quotation.schemaVersion: expected 1.');
11
+ if (typeof data.synthetic !== 'boolean') throw new Error('quotation.synthetic: explicitly supply true or false.');
12
+ const party = (input: unknown, path: string) => { const value = object(input, ['name', 'details'], path); return { name: text(value.name, `${path}.name`, 180, 1), details: optionalText(value.details, `${path}.details`, 700, 8) }; };
13
+ const issuedOn = date(data.issuedOn, 'quotation.issuedOn');
14
+ const validUntil = data.validUntil === undefined || data.validUntil === null ? undefined : date(data.validUntil, 'quotation.validUntil');
15
+ if (validUntil && validUntil < issuedOn) throw new Error('quotation.validUntil: must be on or after issuedOn.');
16
+ if (data.terms !== undefined && !Array.isArray(data.terms)) throw new Error('quotation.terms: expected an array.');
17
+ const seen = new Set<string>();
18
+ const terms = ((data.terms ?? []) as unknown[]).map((raw, i) => {
19
+ const path = `quotation.terms[${i}]`, term = object(raw, ['id', 'title', 'text'], path), id = text(term.id, `${path}.id`, 100);
20
+ if (!/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(id) || seen.has(id)) throw new Error(`${path}.id: supply a unique stable ID.`);
21
+ seen.add(id);
22
+ return { id, title: text(term.title, `${path}.title`, 120), text: text(term.text, `${path}.text`) };
23
+ });
24
+ return { schemaVersion: 1, title: text(data.title, 'quotation.title', 300), number: text(data.number, 'quotation.number', 80), issuedOn, validUntil,
25
+ seller: party(data.seller, 'quotation.seller'), client: party(data.client, 'quotation.client'), synthetic: data.synthetic,
26
+ introduction: optionalText(data.introduction, 'quotation.introduction'), pricing: parsePricing(data.pricing), terms, acceptance: optionalText(data.acceptance, 'quotation.acceptance') };
27
+ }
@@ -0,0 +1,12 @@
1
+ import { bindTemplate } from 'opendoc/template';
2
+ import { quotationTemplate } from '../../templates/quotation';
3
+ // @ts-ignore The selected local theme module is inserted when this starter becomes a document.
4
+ import { theme } from "__OPENDOC_THEME_MODULE__";
5
+ import data from './data.json';
6
+ const documentId = "__OPENDOC_DOCUMENT_ID__";
7
+ const themeId = "__OPENDOC_THEME__";
8
+ // Bind a shared logo, pass <Logo slot="primary" /> through the logo option, or pass null to omit it.
9
+ const bound = bindTemplate(quotationTemplate(theme), data);
10
+ export const meta = { ...bound.meta, theme: themeId };
11
+ export const provenance = { template: 'templates/quotation/index.tsx', dataFile: `documents/${documentId}/data.json` };
12
+ export default bound.Document;
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "Quotation",
3
+ "description": "Business and client details, a clear pricing schedule, calculated totals, and optional terms and acceptance. For service and product quotations.",
4
+ "format": "A4 \u00b7 Business quotation",
5
+ "structure": [
6
+ "A compact quotation heading, reference, issue date, and optional validity date introduce the same page as the pricing. An optional logo slot sits at the upper right.",
7
+ "Seller and client details sit side by side, followed by an optional scope introduction.",
8
+ "Line items flow in a table with repeating headers. Calculated totals align to the right beneath it.",
9
+ "Optional terms and acceptance follow the pricing. Each document owns its data; themes change the appearance and the layout stays adaptable."
10
+ ]
11
+ }
@@ -0,0 +1,11 @@
1
+ # Scientific paper
2
+
3
+ Treat this template as a soft foundation for a manuscript, with room for variation and creativity. Its starting character is compact, legible, and focused on the research: a modest title and author block, a distinct abstract, and continuous single-column reading. The dimensions are defaults, not fixed rules. Reduce a long title through `titleStyle`, adapt the abstract or heading treatment, and adjust spacing or exhibit proportions to serve the material. Follow an actual journal's supplied instructions when relevant; this template does not itself claim journal compliance.
4
+
5
+ Let the writer and research determine the section order. An abstract, keywords, affiliations, and correspondence line are optional. Omit unused elements rather than filling them with invented information. Use `PaperHeading` for compact heading defaults, or ordinary Heading with native styles. Give a short heading and lead a native unbreakable View only when they need to stay together; leave longer passages breakable. Do not impose a mandatory methods/results/discussion outline on every type of paper.
6
+
7
+ Figures, tables, labels, units, uncertainty, captions, and reference text should remain readable. Adapt a dense exhibit rather than simply shrinking everything. Use the existing Figure, DataTable, Cite, and CrossReference blocks so numbering and references stay consistent. Numeric and author-date citations are existing workspace formats, not promises of a particular publisher's bibliography style. Only cite real supplied or verified sources in authored manuscripts; specimens must clearly identify illustrative records and data.
8
+
9
+ Keep layout native to Forme: Page, Fixed, View, Text, Image, and Table through the existing OpenDoc blocks. No Prose indentation shim, custom text fitting, manual line splitting, simulated two-column pagination, or renderer patches. For charts, use the established local Media workflow and native image placement. Preserve stable IDs and source provenance. Keep document-specific variations local or expose small options that preserve shared defaults.
10
+
11
+ Use Neutral for the catalog preview. Review each adapted PDF; shared changes also need sparse and long specimens, a second theme, a long abstract, reference extraction, and a working starter. Preserve unrelated templates and documents.
@@ -0,0 +1,13 @@
1
+ # Scientific paper
2
+
3
+ A flexible, single-column manuscript layout using native Forme flow. Defaults are A4 portrait, 72-point side and 58-point top/bottom margins, a 22-point centered title, 11/16.5-point body typography, and 9-point paragraph gaps. The abstract is inset 24 points on each side and uses 10/14.5-point text. The body width is approximately 451 points; the abstract width is approximately 403 points. Page numbers sit centrally below the text.
4
+
5
+ `ScientificPaper` takes `title`, `theme`, and ordinary OpenDoc blocks as `children`. Optional `authors`, `affiliations`, and `correspondence` form the opening. `abstract` accepts inline content, including Strong, Em, or Cite; `keywords` is an optional string. Both remain breakable, and an abstract's label is part of the same paragraph so it cannot be stranded by itself. Omitted fields leave no reserved panels. For a structured abstract, use inline labels and content or make a local variant with ordinary Paragraph blocks.
6
+
7
+ `titleStyle` accepts native Forme text styles for adjustments such as a smaller long title or left alignment. `PaperHeading` supplies compact level-2 and level-3 defaults, with an optional `style` override. There is no required section order. Keep a heading with a short lead using a native `View wrap={false}` where needed; do not wrap whole sections in an unbreakable group.
8
+
9
+ Pass verified `references` and use `Cite` for citations. `citationStyle` accepts the workspace's existing `numeric` (default) or `author-date` formats. These are not full implementations of named journal bibliography styles. References follow the body. Use existing Figure, DataTable, and CrossReference blocks for numbered evidence and native table continuation. Native charts have the workspace's known font-encoding limitation; the established [Media workflow](../../docs/MEDIA.md) supplies chart assets rendered as native images. Size a complete Figure and caption to fit a page.
10
+
11
+ The caller's theme supplies visual hierarchy, rhythm, and component treatments. The default catalog proof uses Neutral; `Specimen` in `preview.tsx` accepts sparse, typical, and long variants plus a theme for review. Its prose, visual areas, and table values are expressly illustrative. `starter.tsx` creates an ordinary linked document. Preserve stable authored IDs; the specimen's sequence IDs are only for its fixed proof.
12
+
13
+ This is a starting manuscript design, not a journal submission specification. Adapt it to the actual document and any supplied publisher instructions, following [AGENTS.md](AGENTS.md). No custom typography engine, floating-column logic, or automatic fitting is involved.
@@ -0,0 +1,47 @@
1
+ import type { ReactNode } from 'react';
2
+ import * as F from '@formepdf/react';
3
+ import { TextSlot, Document, Heading, Paragraph, References, Strong, Page } from 'opendoc';
4
+ import { themePage, type DocTheme } from 'opendoc/themes';
5
+
6
+ export interface ScientificPaperProps {
7
+ title: string;
8
+ theme: DocTheme;
9
+ authors?: string;
10
+ affiliations?: ReactNode;
11
+ correspondence?: string;
12
+ abstract?: ReactNode;
13
+ keywords?: string;
14
+ titleStyle?: F.Style;
15
+ citationStyle?: Parameters<typeof Document>[0]['citationStyle'];
16
+ references?: Parameters<typeof Document>[0]['references'];
17
+ children: ReactNode;
18
+ }
19
+
20
+ /** A manuscript opening and one continuous column, entirely in native Forme flow. */
21
+ export function ScientificPaper({ title, theme, authors, affiliations, correspondence, abstract, keywords, titleStyle, citationStyle, references, children }: ScientificPaperProps) {
22
+ const layoutTheme: DocTheme = theme.design ? theme : { ...theme, fontSize: 11, lineHeight: 1.5, paragraphGap: 9 };
23
+ return <Document title={title} author={authors} theme={layoutTheme} references={references} citationStyle={citationStyle}>
24
+ <Page {...themePage(theme, { top: 58, bottom: 58, left: 72, right: 72 })} style={{ lineBreaking: 'greedy', ...theme.design?.page?.style }}>
25
+ {(!theme.design || theme.runningFooter) && <F.Fixed position="footer"><F.Text style={{ fontFamily: theme.body, fontSize: 8, color: theme.muted, textAlign: 'center', ...theme.design?.furniture?.text, ...theme.design?.furniture?.footer }}>{theme.design?.furniture?.pageNumber === 'total' ? '{{pageNumber}} / {{totalPages}}' : '{{pageNumber}}'}</F.Text></F.Fixed>}
26
+ <F.View style={theme.design?.title?.block}>
27
+ <Heading id="paper-title" level={1} baseStyle={{ fontSize: 22, lineHeight: 1.18, textAlign: 'center', marginBottom: 14 }} style={{ ...theme.design?.title?.heading, ...titleStyle }}><TextSlot slot="title" from="title">{title}</TextSlot></Heading>
28
+ {authors && <Paragraph id="paper-authors" role="small" baseStyle={{ fontSize: 11, textAlign: 'center', marginBottom: 6 }} style={theme.design?.title?.byline}><TextSlot slot="authors" from="authors">{authors}</TextSlot></Paragraph>}
29
+ {affiliations && <Paragraph id="paper-affiliations" role="small" baseStyle={{ fontSize: 9.5, textAlign: 'center', color: theme.muted, marginBottom: 6 }} style={theme.design?.title?.byline}><TextSlot slot="affiliations" from="affiliations">{affiliations}</TextSlot></Paragraph>}
30
+ {correspondence && <Paragraph id="paper-correspondence" role="small" baseStyle={{ fontSize: 8.5, textAlign: 'center', color: theme.muted, marginBottom: 6 }} style={theme.design?.title?.byline}><TextSlot slot="correspondence" from="correspondence">{correspondence}</TextSlot></Paragraph>}
31
+ </F.View>
32
+ {(abstract || keywords) && <F.View style={{ marginLeft: 24, marginRight: 24, marginTop: 18, marginBottom: 20 }}>
33
+ {abstract && <Paragraph id="paper-abstract" role="small" baseStyle={{ fontSize: 10, lineHeight: 1.45, marginBottom: keywords ? 10 : 0 }}><Strong>Abstract. </Strong><TextSlot slot="abstract" from="abstract">{abstract}</TextSlot></Paragraph>}
34
+ {keywords && <Paragraph id="paper-keywords" role="small" baseStyle={{ fontSize: 9, lineHeight: 1.4, marginBottom: 0 }}><Strong>Keywords: </Strong><TextSlot slot="keywords" from="keywords">{keywords}</TextSlot></Paragraph>}
35
+ </F.View>}
36
+ <F.View style={{ marginTop: abstract || keywords ? 0 : 18 }}>
37
+ {children}
38
+ <References headingBaseStyle={{ fontSize: 14, marginTop: 20, marginBottom: 8 }} />
39
+ </F.View>
40
+ </Page>
41
+ </Document>;
42
+ }
43
+
44
+ /** Compact heading defaults; authors may override native styles for their manuscript. */
45
+ export function PaperHeading({ id, level = 2, style, children }: { id: string; level?: 2 | 3; style?: F.Style; children: ReactNode }) {
46
+ return <Heading id={id} level={level} baseStyle={{ fontSize: level === 2 ? 14 : 11.5, marginTop: 16, marginBottom: 7 }} style={style}><TextSlot slot="children" from="children">{children}</TextSlot></Heading>;
47
+ }
@@ -0,0 +1,43 @@
1
+ import * as F from '@formepdf/react';
2
+ import { DataTable, Figure, Paragraph } from 'opendoc';
3
+ import { neutral } from '../../themes';
4
+ import { type DocTheme } from 'opendoc/themes';
5
+ import { PaperHeading, ScientificPaper } from './index';
6
+
7
+ export const meta = { title: 'Scientific paper', description: 'A Neutral manuscript specimen with illustrative placeholders only.', kind: 'research' as const, theme: 'neutral' };
8
+ const paragraph = 'This is placeholder text for the manuscript. It demonstrates the length of a line, the space between paragraphs, and the relationship between headings and continuous prose. No study was conducted and no findings are reported. In an authored paper, the research question, methods, and evidence would determine the organization and the level of detail needed by the reader.';
9
+
10
+ export function Specimen({ length = 'typical', theme = neutral }: { length?: 'sparse' | 'typical' | 'long'; theme?: DocTheme } = {}) {
11
+ const sparse = length === 'sparse';
12
+ return <ScientificPaper title={meta.title} theme={theme}
13
+ authors={sparse ? undefined : 'Author name · Coauthor name'}
14
+ affiliations={sparse ? undefined : 'Department and institution · Affiliation placeholder'}
15
+ correspondence={sparse ? undefined : 'Correspondence details, when needed'}
16
+ abstract={sparse ? undefined : 'This abstract is a layout specimen. It shows a compact summary set apart from the main reading column. The text describes no real research, data, or conclusions. Its length and structure can be adapted to the paper and any applicable publisher instructions.'}
17
+ keywords={sparse ? undefined : 'manuscript; formatting; illustrative specimen'}>
18
+ <F.View wrap={false}>
19
+ <PaperHeading id="specimen-opening-heading">A manuscript section</PaperHeading>
20
+ <Paragraph id="specimen-opening-lead">A short opening stays with its heading. Section names and their order belong to the writer.</Paragraph>
21
+ </F.View>
22
+ <Paragraph id="specimen-opening">{paragraph}</Paragraph>
23
+ {!sparse && <>
24
+ {Array.from({ length: length === 'long' ? 12 : 1 }, (_, index) => <Paragraph key={index} id={`specimen-body-${index + 1}`}>{paragraph}</Paragraph>)}
25
+ <Figure id="specimen-figure" caption="Illustrative figure position. Captions identify the visual; labels and units belong where they can be read." sourceNote="Placeholder only. No measured data or source is claimed.">
26
+ <F.View style={{ height: 135, backgroundColor: theme.paper, borderWidth: 0.6, borderColor: theme.line, justifyContent: 'center', alignItems: 'center' }}>
27
+ <F.Text style={{ fontSize: 10, color: theme.muted }}>Figure area · Illustrative placeholder</F.Text>
28
+ </F.View>
29
+ </Figure>
30
+ <F.View wrap={false}>
31
+ <PaperHeading id="specimen-subheading" level={3}>A subordinate heading</PaperHeading>
32
+ <Paragraph id="specimen-detail">The smaller heading marks a change within the passage. This text demonstrates hierarchy without prescribing a research outline.</Paragraph>
33
+ </F.View>
34
+ <DataTable id="specimen-table" caption="Synthetic values for layout review" columns={[{ label: 'Sample', width: 1.5 }, { label: 'Value (a.u.)', width: 1, align: 'right' }, { label: 'Status', width: 1.4 }]}
35
+ rows={Array.from({ length: length === 'long' ? 25 : 4 }, (_, index) => [`Example ${index + 1}`, 10 + index, 'Illustrative only'])}
36
+ sourceNote="All values are synthetic; a.u. means arbitrary units. No research finding is claimed." />
37
+ <Paragraph id="specimen-closing">This closing passage follows the table in normal flow. The manuscript can continue with any sections the material requires.</Paragraph>
38
+ <PaperHeading id="specimen-reference-heading">References</PaperHeading>
39
+ <Paragraph id="specimen-reference" style={{ fontSize: 9.5, color: theme.muted }}>Reference placement specimen. Real references appear here only when cited; no source is being claimed.</Paragraph>
40
+ </>}
41
+ </ScientificPaper>;
42
+ }
43
+ export default Specimen;
@@ -0,0 +1,15 @@
1
+ import { ScientificPaper } from '../../templates/scientific-paper';
2
+ import { Paragraph } from 'opendoc';
3
+ // @ts-ignore The selected local theme module is inserted when this starter becomes a document.
4
+ import { theme } from "__OPENDOC_THEME_MODULE__";
5
+
6
+ const title = "__OPENDOC_TITLE__";
7
+ const themeId = "__OPENDOC_THEME__";
8
+ export const meta = { title, description: 'A scientific manuscript, ready for your material.', kind: 'research' as const, theme: themeId };
9
+ export const provenance = { template: 'templates/scientific-paper/index.tsx' };
10
+
11
+ export default function Paper() {
12
+ return <ScientificPaper title={title} theme={theme} authors="Author name" abstract="Replace this placeholder with a summary of your manuscript.">
13
+ <Paragraph id="paper-opening">Your manuscript begins here. Replace this placeholder with your own material and choose the sections that fit the research and intended reader.</Paragraph>
14
+ </ScientificPaper>;
15
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "Scientific paper",
3
+ "description": "A compact manuscript opening, a distinct abstract, and a continuous reading column with clear figures, tables, and references. For research manuscripts, preprints, and scholarly notes.",
4
+ "format": "A4 · Single-column manuscript",
5
+ "structure": [
6
+ "A centered title, author line, and optional affiliations share the first page with the manuscript.",
7
+ "An optional inset abstract and keywords separate the summary from the main text without a cover page.",
8
+ "Compact heading levels organize a continuous single column. Figures and tables sit in the author's chosen reading order.",
9
+ "Cited references follow the body and page numbers sit centrally below. The layout is adaptable and does not prescribe a journal style or section outline."
10
+ ]
11
+ }
@@ -0,0 +1,54 @@
1
+ import {
2
+ Callout, Cite, CrossReference, DataTable, Document, Em, Figure, Heading, List,
3
+ PageBreak, Pages, Paragraph, References, Section, Strong, Text, TitleBlock, View,
4
+ type DocTheme,
5
+ } from 'opendoc';
6
+
7
+ /** One shared proof: themes and authored documents use the same PDF primitives. */
8
+ export function ThemeSpecimen({ theme }: { theme: DocTheme }) {
9
+ return <Document title={`${theme.name} — A page with purpose`} theme={theme}
10
+ references={{ design: { title: `${theme.name} design guide — themes/${theme.id}/design.md`, author: 'OpenDoc' } }}>
11
+ <Pages title={`${theme.name} / Design specimen`} footer={`${theme.name} / Illustrative specimen`}>
12
+ <TitleBlock id="specimen-opening" eyebrow="A page with purpose" title={theme.name}
13
+ subtitle={theme.description} byline="Typography, composition, and the details that hold a document together." />
14
+ <Section id="specimen-reading" title="Make room for the thought"
15
+ lead="A page begins with a relationship: a heading invites us in, a paragraph gives us a place to settle, and the space around both sets the pace.">
16
+ <Paragraph id="specimen-prose">Good document design makes different kinds of information easy to recognize. A title can be confident without crowding the opening. Body text can be comfortable without losing momentum. A <Strong>short phrase</Strong> can carry the central thought; <Em>an italic aside</Em> can change the voice. Here, the same words appear in every theme so the differences in hierarchy, rhythm, and emphasis are visible.</Paragraph>
17
+ </Section>
18
+ <Heading id="specimen-details" level={3}>The small decisions matter</Heading>
19
+ <List id="specimen-principles" items={[
20
+ { id: 'alignment', children: 'Shared edges connect the different elements of a page.' },
21
+ { id: 'rhythm', children: 'A consistent rhythm holds related passages together.' },
22
+ { id: 'contrast', children: 'Contrast gives the reader a clear place to begin.' },
23
+ ]} />
24
+ <Callout id="specimen-aside" title="One useful interruption">
25
+ An aside should earn its place. Use this treatment for a decision, a qualification, or a detail the reader needs to notice before continuing.
26
+ </Callout>
27
+ <PageBreak />
28
+ <Section id="specimen-evidence" title="Give evidence a clear place"
29
+ lead="A visual and a table should belong to the same publication as the prose. Their labels, rules, captions, and spacing carry the theme at a smaller scale." />
30
+ <Figure id="specimen-figure" caption="An illustrative comparison, with each value placed beside its mark."
31
+ sourceNote="Synthetic values in arbitrary units. No measurements are claimed.">
32
+ <View style={{ paddingTop: 8, paddingBottom: 8 }}>
33
+ {[{ label: 'First', value: 18 }, { label: 'Second', value: 31 }, { label: 'Third', value: 46 }].map((item, index) =>
34
+ <View key={item.label} style={{ flexDirection: 'row', alignItems: 'center', gap: 12, marginBottom: 12 }}>
35
+ <Text style={{ width: 48, fontFamily: theme.body, fontSize: 9, color: theme.muted }}>{item.label}</Text>
36
+ <View style={{ flex: 1, height: 18, justifyContent: 'center' }}>
37
+ <View style={{ width: `${item.value * 2}%`, height: 18, backgroundColor: index === 2 ? theme.accent : theme.line }} />
38
+ </View>
39
+ <Text style={{ width: 25, fontFamily: theme.body, fontSize: 9, color: theme.ink, textAlign: 'right' }}>{item.value}</Text>
40
+ </View>)}
41
+ </View>
42
+ </Figure>
43
+ <DataTable id="specimen-table" caption="The same illustrative values, available as selectable text."
44
+ columns={[{ label: 'Example', width: 1.1 }, { label: 'Treatment', width: 2.2 }, { label: 'Value', width: 0.7 }]}
45
+ rows={[
46
+ ['First', 'Supporting comparison', 18],
47
+ ['Second', 'Supporting comparison', 31],
48
+ ['Third', 'Single point of emphasis', 46],
49
+ ]} sourceNote="Synthetic values, in arbitrary units." />
50
+ <Paragraph id="specimen-closing"><CrossReference target="specimen-figure" /> and <CrossReference target="specimen-table" /> show the same comparison. The local design guide describes this theme’s composition and usage. <Cite source="design" /></Paragraph>
51
+ <References title="Design reference" />
52
+ </Pages>
53
+ </Document>;
54
+ }
@@ -0,0 +1,92 @@
1
+ import type { ReactNode } from 'react';
2
+ import * as F from '@formepdf/react';
3
+ import { Block, Heading, Page, Paragraph } from 'opendoc';
4
+ import { colors, metrics, theme } from './index';
5
+
6
+ const spectrum = [colors.blue, colors.sky, colors.leaf, colors.sun, colors.flame, colors.violet];
7
+
8
+ /** The unequal lengths are an identity device, never a quantitative chart. */
9
+ export function SpectrumRail({ height = metrics.railHeight }: { height?: number }) {
10
+ return <F.View style={{ flexDirection: 'row', height, width: '100%' }}>
11
+ {spectrum.map((color, index) => <F.View key={color} style={{ flex: metrics.railWeights[index], height, backgroundColor: color }} />)}
12
+ </F.View>;
13
+ }
14
+
15
+ /** Flowing publication pages: the asymmetric compositions inside remain content-driven. */
16
+ export function CivicPages({ children, title, section = 'CS', footer = 'Civic Spectrum', rail = false }: {
17
+ children: ReactNode; title: string; section?: string; footer?: string; rail?: boolean;
18
+ }) {
19
+ return <Page size="A4" margin={{ top: metrics.margin, right: metrics.margin, bottom: metrics.bottomMargin, left: metrics.margin }} style={{ backgroundColor: colors.stock }}>
20
+ <F.Fixed position="header"><F.View style={{ flexDirection: 'row', justifyContent: 'space-between', paddingBottom: 16 }}>
21
+ <F.Text style={{ fontSize: 8, color: colors.muted }}>{title}</F.Text>
22
+ <F.Text style={{ fontSize: 8, fontWeight: 600, color: colors.ink }}>{section}</F.Text>
23
+ </F.View></F.Fixed>
24
+ <F.Fixed position="footer"><F.View style={{ borderTopWidth: 0.75, borderColor: colors.rule, paddingTop: 12, flexDirection: 'row', justifyContent: 'space-between' }}>
25
+ <F.Text style={{ fontSize: 8, fontWeight: 600, color: colors.ink }}>{footer}</F.Text>
26
+ <F.Text style={{ fontSize: 8, fontWeight: 600, color: colors.ink }}>{'{{pageNumber}}'}</F.Text>
27
+ </F.View></F.Fixed>
28
+ {rail && <F.View style={{ marginBottom: 24 }}><SpectrumRail /></F.View>}
29
+ {children}
30
+ </Page>;
31
+ }
32
+
33
+ export function SquareSignal({ id, label, color = colors.blue }: { id: string; label: string; color?: string }) {
34
+ return <Block id={id} style={{ flexDirection: 'row', alignItems: 'center', gap: 8 }}>
35
+ <F.View style={{ width: metrics.signalSize, height: metrics.signalSize, backgroundColor: color, flexShrink: 0 }} />
36
+ <F.Text style={{ fontSize: 8, fontWeight: 600, letterSpacing: 1, color: colors.ink }}>{label.toUpperCase()}</F.Text>
37
+ </Block>;
38
+ }
39
+
40
+ export function CivicBadge({ id, value, label, color = colors.blue, filled = false }: {
41
+ id: string; value: string; label: string; color?: string; filled?: boolean;
42
+ }) {
43
+ return <Block id={id}>
44
+ <F.View style={{ width: metrics.badgeSize, height: metrics.badgeSize, borderWidth: 0.75, borderColor: color, backgroundColor: filled ? color : colors.stock, justifyContent: 'center', alignItems: 'center' }}>
45
+ <F.Text style={{ fontSize: value.length > 2 ? 44 : 60, lineHeight: 1, fontWeight: 600, letterSpacing: -1.5, color: filled ? colors.ink : color }}>{value}</F.Text>
46
+ </F.View>
47
+ <F.Text style={{ width: metrics.badgeSize, fontSize: 8, lineHeight: 1.35, color: colors.muted, marginTop: 12 }}>{label}</F.Text>
48
+ </Block>;
49
+ }
50
+
51
+ export function CivicSplit({ id, main, aside }: { id: string; main: ReactNode; aside: ReactNode }) {
52
+ return <Block id={id} style={{ flexDirection: 'row', gap: metrics.gutter, alignItems: 'flex-start' }}>
53
+ <F.View style={{ width: metrics.mainWidth }}>{main}</F.View>
54
+ <F.View style={{ flex: 1, minWidth: 0 }}>{aside}</F.View>
55
+ </Block>;
56
+ }
57
+
58
+ export function CivicOpening({ id, kicker, title, subtitle, color = colors.blue }: {
59
+ id: string; kicker: string; title: string; subtitle?: string; color?: string;
60
+ }) {
61
+ return <F.View wrap={false} style={{ marginBottom: 24 }}>
62
+ <SquareSignal id={`${id}-signal`} label={kicker} color={color} />
63
+ <Heading id={`${id}-title`} level={1} style={{ marginTop: 20 }}>{title}</Heading>
64
+ {subtitle && <Paragraph id={`${id}-subtitle`} role="lead" style={{ marginBottom: 0 }}>{subtitle}</Paragraph>}
65
+ </F.View>;
66
+ }
67
+
68
+ /** A category module. Keep each color's meaning consistent throughout a document. */
69
+ export function SignalBlock({ id, code, title, children, color = colors.blue }: {
70
+ id: string; code: string; title: string; children: ReactNode; color?: string;
71
+ }) {
72
+ return <Block id={id} style={{ borderTopWidth: 4, borderColor: color, paddingTop: 12, marginBottom: 24 }}>
73
+ <F.View style={{ flexDirection: 'row', justifyContent: 'space-between', gap: 8, marginBottom: 8 }}>
74
+ <F.Text style={{ fontSize: 14, lineHeight: 1.1, fontWeight: 600, color: colors.ink }}>{title}</F.Text>
75
+ <F.Text style={{ fontSize: 8, color: colors.muted }}>{code}</F.Text>
76
+ </F.View>
77
+ <F.Text style={{ fontSize: 10, lineHeight: 1.4, color: colors.muted }}>{children}</F.Text>
78
+ </Block>;
79
+ }
80
+
81
+ /** Palette is shown as a real legend, with accessible text labels and exact values. */
82
+ export function SpectrumLegend({ id }: { id: string }) {
83
+ const entries = theme.palette!.slice(0, 6);
84
+ return <Block id={id}>
85
+ {[entries.slice(0, 3), entries.slice(3)].map((row, index) => <F.View key={index} style={{ flexDirection: 'row', gap: 12, marginBottom: 16 }}>
86
+ {row.map(entry => <F.View key={entry.name} style={{ flex: 1, flexDirection: 'row', gap: 8 }}>
87
+ <F.View style={{ width: 28, height: 28, flexShrink: 0, backgroundColor: entry.value }} />
88
+ <F.View style={{ flex: 1 }}><F.Text style={{ fontSize: 9, fontWeight: 600 }}>{entry.name}</F.Text><F.Text style={{ fontFamily: 'OpenDoc Mono', fontSize: 8, color: colors.muted, marginTop: 3 }}>{entry.value}</F.Text></F.View>
89
+ </F.View>)}
90
+ </F.View>)}
91
+ </Block>;
92
+ }
@@ -0,0 +1,70 @@
1
+ # Civic Spectrum
2
+
3
+ Warm civic modernism: lucid public information, compact grotesk type, square signals, and generous asymmetric space. Its signature is the **unequal six-color rail**, not a collection of interchangeable accent colors. Use it for community and cultural reports, public-information pages, and editorial explainers.
4
+
5
+ ## Palette and meaning
6
+
7
+ | Role | Hex | Use |
8
+ | --- | --- | --- |
9
+ | Signal blue | `#2F7EA5` | Orientation, primary emphasis, arrival |
10
+ | Sky | `#7ABED0` | Supporting information and shared activity |
11
+ | Leaf | `#5F9D7A` | Participation, progress, positive movement |
12
+ | Sun | `#E3C84F` | Attention and selected evidence; use dark text |
13
+ | Flame | `#E27D47` | Action, urgent emphasis, a next step |
14
+ | Violet | `#7D6FA6` | Context and reflection |
15
+ | Stock | `#FFFFFF` | White page background |
16
+ | Ink | `#17232B` | Primary text and optional inverse surface |
17
+ | Muted | `#68747A` | Secondary text and annotations |
18
+ | Rule | `#C9CEC7` | Quiet boundaries and alignment marks |
19
+ | Inverse text | `#F8F5EC` | Text on the ink surface |
20
+ | Inverse notes | `#B9C2C3` | Secondary text on dark |
21
+ | Inverse rule | `#516068` | Boundaries on dark |
22
+
23
+ Use one dominant signal in a passage. The entire spectrum belongs on an identity rail or in an explicit palette legend. On an applied page, two or three colors are acceptable only when they identify distinct categories. Preserve those assignments throughout a document. Sun is a good note surface; it is not a universal highlight pen. Use Ink text on the light signal fields. White text is reserved for sufficiently dark fields such as Signal blue or Ink.
24
+
25
+ ## Page geometry and shapes
26
+
27
+ The print grid is A4 portrait, **48 pt top/side margins and 56 pt bottom margin**. The approximately 499 pt field has six columns separated by **12 pt gutters**. `CivicSplit` assigns **328 pt** to the main reading field and the remaining approximately 159 pt to supporting material, with a 12 pt gap. This creates a four-column reading field and a two-column supporting field.
28
+
29
+ Work from a **4 pt baseline** and prefer 8, 12, 16, 24, and 32 pt spacing. The unequal rail is **12 pt high** with the invariant proportion **2 : 1 : 3 : 1.5 : 2 : 1**, in blue, sky, leaf, sun, flame, violet order. Its lengths are an identity device, never quantitative data. An 8 pt rail is available for a secondary signature.
30
+
31
+ Wayfinding markers are **8 × 8 pt squares**. Badges are **132 × 132 pt squares**, outlined with a 0.75 pt rule or filled with a meaningful color. Category modules start with a **4 pt top rule** and 12 pt inset. Corners are square. Do not introduce shadows, gradients, rounded cards, glass surfaces, or ornamental circles. Large empty areas are deliberate: keep one side of a reading spread quieter rather than filling every cell.
32
+
33
+ ## Typography
34
+
35
+ The local print family is **OpenDoc Sans**, the bundled Source Sans 3 derivative. It substitutes for the slide theme's Archivo. Use the real 600 face for emphasis and display; body is 400. The substitution preserves a clear grotesk voice but does not claim identical Archivo letterforms. OpenDoc Mono is used only for exact hexadecimal labels in the specimen.
36
+
37
+ | Role | Size / line height | Notes |
38
+ | --- | --- | --- |
39
+ | Cover display | 52 pt / 1.02 | Tight, confident; identity specimen uses 54 pt / 0.98 |
40
+ | Main title | 42 pt / 1.04 | Tracking −0.8 pt; flush left |
41
+ | Section | 23 pt / 1.10 | Tracking −0.35 pt; 24 pt before, 12 after |
42
+ | Subheading | 14 pt / 1.20 | 20 pt before, 8 after |
43
+ | Lead | 16 pt / 1.40 | Muted, short measure |
44
+ | Body | 11 pt / 1.50 | 12 pt paragraph gap |
45
+ | Caption | 9 pt / 1.40 | Keep close to its figure |
46
+ | Label | 8 pt | Uppercase only for short wayfinding labels |
47
+
48
+ Sentence case is the default. Do not make body passages uppercase. Long text flows; do not shrink the type to preserve a fixed page count.
49
+
50
+ ## Reusable components
51
+
52
+ Import `theme` from `themes/civic-spectrum` and the components from its `components.tsx`. Use them inside an OpenDoc `Document` receiving that theme.
53
+
54
+ - `CivicPages({title, section?, footer?, rail?, children})` supplies white stock, real repeating furniture, and optional opening rail. Its content flows naturally across pages.
55
+ - `CivicOpening({id, kicker, title, subtitle?, color?})` couples the square signal to the title and lead.
56
+ - `CivicSplit({id, main, aside})` establishes the four/two-column relationship. Use independent supporting material in the aside; do not rely on it for sequential prose continuation.
57
+ - `SquareSignal({id, label, color?})`, `CivicBadge({id, value, label, color?, filled?})`, and `SignalBlock({id, code, title, color?, children})` are reusable wayfinding elements.
58
+ - `SpectrumRail({height?})` carries the identity. `SpectrumLegend({id})` displays exact palette values when explaining the system.
59
+
60
+ Pass unique, stable IDs. Native `Heading`, `Paragraph`, `DataTable`, `Figure`, and `Callout` also consume this theme's rules; do not recreate their styling in each document.
61
+
62
+ ## Evidence, imagery, and application
63
+
64
+ Use direct labels, explicit units, and rectangular partitions when the data supports them. The specimen's 120 m² room is synthetic; its areas and percentages are selectable in the accompanying table. Native tables use an Ink header, inverse labels, 10 pt cell padding, and 0.5 pt horizontal rules. Captions describe the exhibit, and source notes identify its basis. Real evidence keeps its meaning even when it uses additional colors.
65
+
66
+ Images may fill the reading field or a deliberate wider band; preserve aspect ratio and use a nearby caption. A photograph can carry a public story, but it must not be filler. Logos retain supplied proportions and clear space. Do not invent a transit map, civic crest, or institutional endorsement.
67
+
68
+ ## Implementation and review
69
+
70
+ The system combines a six-color rail, square signals, asymmetric composition, and the Orient / Explain / Move structure. It uses bundled OpenDoc fonts and native page primitives. `index.ts` and reusable components are executable; keep these concrete specifications synchronized when changing them. Review every specimen page, narrow-column wraps, exact palette text, and table/figure labels in the exported PDF.