@12ui/design 0.2.71 → 0.2.73

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 (680) hide show
  1. package/README.md +248 -55
  2. package/SKILL.md +28 -33
  3. package/dist/cli-arguments.d.ts.map +1 -1
  4. package/dist/cli-arguments.js +3 -0
  5. package/dist/cli-arguments.js.map +1 -1
  6. package/dist/cli-branch-command.d.ts.map +1 -1
  7. package/dist/cli-branch-command.js +4 -0
  8. package/dist/cli-branch-command.js.map +1 -1
  9. package/dist/cli-capabilities.d.ts +35 -1
  10. package/dist/cli-capabilities.d.ts.map +1 -1
  11. package/dist/cli-capabilities.js +36 -1
  12. package/dist/cli-capabilities.js.map +1 -1
  13. package/dist/cli-corpus-command.d.ts +5 -4
  14. package/dist/cli-corpus-command.d.ts.map +1 -1
  15. package/dist/cli-corpus-command.js +17 -26
  16. package/dist/cli-corpus-command.js.map +1 -1
  17. package/dist/cli-corpus-run.js +1 -1
  18. package/dist/cli-corpus-run.js.map +1 -1
  19. package/dist/cli-draft-command.js +1 -1
  20. package/dist/cli-draft-command.js.map +1 -1
  21. package/dist/cli-help/design.d.ts +26 -6
  22. package/dist/cli-help/design.d.ts.map +1 -1
  23. package/dist/cli-help/design.js +39 -7
  24. package/dist/cli-help/design.js.map +1 -1
  25. package/dist/cli-help/index.d.ts +206 -7
  26. package/dist/cli-help/index.d.ts.map +1 -1
  27. package/dist/cli-help/index.js +4 -0
  28. package/dist/cli-help/index.js.map +1 -1
  29. package/dist/cli-help/meta.d.ts +1 -1
  30. package/dist/cli-help/meta.d.ts.map +1 -1
  31. package/dist/cli-help/meta.js +2 -1
  32. package/dist/cli-help/meta.js.map +1 -1
  33. package/dist/cli-help/scene.d.ts +96 -0
  34. package/dist/cli-help/scene.d.ts.map +1 -0
  35. package/dist/cli-help/scene.js +162 -0
  36. package/dist/cli-help/scene.js.map +1 -0
  37. package/dist/cli-help/workflow.d.ts +90 -0
  38. package/dist/cli-help/workflow.d.ts.map +1 -0
  39. package/dist/cli-help/workflow.js +89 -0
  40. package/dist/cli-help/workflow.js.map +1 -0
  41. package/dist/cli-open-browser.d.ts +7 -0
  42. package/dist/cli-open-browser.d.ts.map +1 -0
  43. package/dist/cli-open-browser.js +25 -0
  44. package/dist/cli-open-browser.js.map +1 -0
  45. package/dist/cli-prototype-command.d.ts +3 -1
  46. package/dist/cli-prototype-command.d.ts.map +1 -1
  47. package/dist/cli-prototype-command.js +33 -7
  48. package/dist/cli-prototype-command.js.map +1 -1
  49. package/dist/cli-review-command.d.ts.map +1 -1
  50. package/dist/cli-review-command.js +1 -16
  51. package/dist/cli-review-command.js.map +1 -1
  52. package/dist/cli-run.d.ts.map +1 -1
  53. package/dist/cli-run.js +41 -3
  54. package/dist/cli-run.js.map +1 -1
  55. package/dist/cli-scene-command.d.ts +3 -0
  56. package/dist/cli-scene-command.d.ts.map +1 -0
  57. package/dist/cli-scene-command.js +292 -0
  58. package/dist/cli-scene-command.js.map +1 -0
  59. package/dist/cli-usage.d.ts +8 -0
  60. package/dist/cli-usage.d.ts.map +1 -1
  61. package/dist/cli-usage.js +65 -6
  62. package/dist/cli-usage.js.map +1 -1
  63. package/dist/cli-workflow-command.d.ts +8 -0
  64. package/dist/cli-workflow-command.d.ts.map +1 -0
  65. package/dist/cli-workflow-command.js +97 -0
  66. package/dist/cli-workflow-command.js.map +1 -0
  67. package/dist/cli-workspace-command.d.ts +25 -0
  68. package/dist/cli-workspace-command.d.ts.map +1 -0
  69. package/dist/cli-workspace-command.js +95 -0
  70. package/dist/cli-workspace-command.js.map +1 -0
  71. package/dist/config.d.ts +6 -0
  72. package/dist/config.d.ts.map +1 -1
  73. package/dist/config.js +12 -4
  74. package/dist/config.js.map +1 -1
  75. package/dist/corpus-access.d.ts +11 -0
  76. package/dist/corpus-access.d.ts.map +1 -0
  77. package/dist/corpus-access.js +18 -0
  78. package/dist/corpus-access.js.map +1 -0
  79. package/dist/corpus-client.d.ts +11 -11
  80. package/dist/corpus-client.d.ts.map +1 -1
  81. package/dist/corpus-client.js +17 -6
  82. package/dist/corpus-client.js.map +1 -1
  83. package/dist/corpus-inspiration-failure.d.ts +1 -1
  84. package/dist/corpus-inspiration-failure.js +2 -2
  85. package/dist/corpus-inspiration-failure.js.map +1 -1
  86. package/dist/corpus-reference-download-retry.d.ts.map +1 -1
  87. package/dist/corpus-reference-download-retry.js +11 -1
  88. package/dist/corpus-reference-download-retry.js.map +1 -1
  89. package/dist/corpus-request-error.d.ts +2 -0
  90. package/dist/corpus-request-error.d.ts.map +1 -1
  91. package/dist/corpus-request-error.js +2 -0
  92. package/dist/corpus-request-error.js.map +1 -1
  93. package/dist/corpus-retry-guidance.d.ts +5 -0
  94. package/dist/corpus-retry-guidance.d.ts.map +1 -0
  95. package/dist/corpus-retry-guidance.js +18 -0
  96. package/dist/corpus-retry-guidance.js.map +1 -0
  97. package/dist/improve-pricing-plan.d.ts.map +1 -1
  98. package/dist/improve-pricing-plan.js +2 -4
  99. package/dist/improve-pricing-plan.js.map +1 -1
  100. package/dist/index.d.ts +10 -1
  101. package/dist/index.d.ts.map +1 -1
  102. package/dist/index.js +10 -1
  103. package/dist/index.js.map +1 -1
  104. package/dist/legacy-skill-catalog.d.ts.map +1 -1
  105. package/dist/legacy-skill-catalog.js +52 -0
  106. package/dist/legacy-skill-catalog.js.map +1 -1
  107. package/dist/mcp-slate-command.d.ts +31 -0
  108. package/dist/mcp-slate-command.d.ts.map +1 -0
  109. package/dist/mcp-slate-command.js +118 -0
  110. package/dist/mcp-slate-command.js.map +1 -0
  111. package/dist/mcp-slate-image.d.ts +22 -0
  112. package/dist/mcp-slate-image.d.ts.map +1 -0
  113. package/dist/mcp-slate-image.js +28 -0
  114. package/dist/mcp-slate-image.js.map +1 -0
  115. package/dist/mcp-slate-latest.d.ts +13 -0
  116. package/dist/mcp-slate-latest.d.ts.map +1 -0
  117. package/dist/mcp-slate-latest.js +34 -0
  118. package/dist/mcp-slate-latest.js.map +1 -0
  119. package/dist/mcp-slate-names.d.ts +25 -0
  120. package/dist/mcp-slate-names.d.ts.map +1 -0
  121. package/dist/mcp-slate-names.js +49 -0
  122. package/dist/mcp-slate-names.js.map +1 -0
  123. package/dist/mcp-slate-resource.d.ts +5 -0
  124. package/dist/mcp-slate-resource.d.ts.map +1 -0
  125. package/dist/mcp-slate-resource.js +37 -0
  126. package/dist/mcp-slate-resource.js.map +1 -0
  127. package/dist/mcp-slate-run.d.ts +41 -0
  128. package/dist/mcp-slate-run.d.ts.map +1 -0
  129. package/dist/mcp-slate-run.js +88 -0
  130. package/dist/mcp-slate-run.js.map +1 -0
  131. package/dist/mcp-slate-tool-defs.d.ts +61 -0
  132. package/dist/mcp-slate-tool-defs.d.ts.map +1 -0
  133. package/dist/mcp-slate-tool-defs.js +247 -0
  134. package/dist/mcp-slate-tool-defs.js.map +1 -0
  135. package/dist/mcp-slate-tools.d.ts +8 -0
  136. package/dist/mcp-slate-tools.d.ts.map +1 -0
  137. package/dist/mcp-slate-tools.js +45 -0
  138. package/dist/mcp-slate-tools.js.map +1 -0
  139. package/dist/mcp-slate-ui-copy.d.ts +134 -0
  140. package/dist/mcp-slate-ui-copy.d.ts.map +1 -0
  141. package/dist/mcp-slate-ui-copy.js +136 -0
  142. package/dist/mcp-slate-ui-copy.js.map +1 -0
  143. package/dist/mcp-slate-ui-script-bridge.d.ts +18 -0
  144. package/dist/mcp-slate-ui-script-bridge.d.ts.map +1 -0
  145. package/dist/mcp-slate-ui-script-bridge.js +137 -0
  146. package/dist/mcp-slate-ui-script-bridge.js.map +1 -0
  147. package/dist/mcp-slate-ui-script-browser.d.ts +12 -0
  148. package/dist/mcp-slate-ui-script-browser.d.ts.map +1 -0
  149. package/dist/mcp-slate-ui-script-browser.js +19 -0
  150. package/dist/mcp-slate-ui-script-browser.js.map +1 -0
  151. package/dist/mcp-slate-ui-script-dialog.d.ts +20 -0
  152. package/dist/mcp-slate-ui-script-dialog.d.ts.map +1 -0
  153. package/dist/mcp-slate-ui-script-dialog.js +332 -0
  154. package/dist/mcp-slate-ui-script-dialog.js.map +1 -0
  155. package/dist/mcp-slate-ui-script-inline.d.ts +10 -0
  156. package/dist/mcp-slate-ui-script-inline.d.ts.map +1 -0
  157. package/dist/mcp-slate-ui-script-inline.js +221 -0
  158. package/dist/mcp-slate-ui-script-inline.js.map +1 -0
  159. package/dist/mcp-slate-ui-script-inspiration.d.ts +12 -0
  160. package/dist/mcp-slate-ui-script-inspiration.d.ts.map +1 -0
  161. package/dist/mcp-slate-ui-script-inspiration.js +216 -0
  162. package/dist/mcp-slate-ui-script-inspiration.js.map +1 -0
  163. package/dist/mcp-slate-ui-script-more.d.ts +30 -0
  164. package/dist/mcp-slate-ui-script-more.d.ts.map +1 -0
  165. package/dist/mcp-slate-ui-script-more.js +225 -0
  166. package/dist/mcp-slate-ui-script-more.js.map +1 -0
  167. package/dist/mcp-slate-ui-script-progress.d.ts +7 -0
  168. package/dist/mcp-slate-ui-script-progress.d.ts.map +1 -0
  169. package/dist/mcp-slate-ui-script-progress.js +9 -0
  170. package/dist/mcp-slate-ui-script-progress.js.map +1 -0
  171. package/dist/mcp-slate-ui-script-remote.d.ts +28 -0
  172. package/dist/mcp-slate-ui-script-remote.d.ts.map +1 -0
  173. package/dist/mcp-slate-ui-script-remote.js +147 -0
  174. package/dist/mcp-slate-ui-script-remote.js.map +1 -0
  175. package/dist/mcp-slate-ui-script-scribble.d.ts +19 -0
  176. package/dist/mcp-slate-ui-script-scribble.d.ts.map +1 -0
  177. package/dist/mcp-slate-ui-script-scribble.js +114 -0
  178. package/dist/mcp-slate-ui-script-scribble.js.map +1 -0
  179. package/dist/mcp-slate-ui-script-select.d.ts +16 -0
  180. package/dist/mcp-slate-ui-script-select.d.ts.map +1 -0
  181. package/dist/mcp-slate-ui-script-select.js +73 -0
  182. package/dist/mcp-slate-ui-script-select.js.map +1 -0
  183. package/dist/mcp-slate-ui-script-stage.d.ts +11 -0
  184. package/dist/mcp-slate-ui-script-stage.d.ts.map +1 -0
  185. package/dist/mcp-slate-ui-script-stage.js +181 -0
  186. package/dist/mcp-slate-ui-script-stage.js.map +1 -0
  187. package/dist/mcp-slate-ui-script-state.d.ts +13 -0
  188. package/dist/mcp-slate-ui-script-state.d.ts.map +1 -0
  189. package/dist/mcp-slate-ui-script-state.js +306 -0
  190. package/dist/mcp-slate-ui-script-state.js.map +1 -0
  191. package/dist/mcp-slate-ui-script-thumbtools.d.ts +23 -0
  192. package/dist/mcp-slate-ui-script-thumbtools.d.ts.map +1 -0
  193. package/dist/mcp-slate-ui-script-thumbtools.js +103 -0
  194. package/dist/mcp-slate-ui-script-thumbtools.js.map +1 -0
  195. package/dist/mcp-slate-ui-script.d.ts +28 -0
  196. package/dist/mcp-slate-ui-script.d.ts.map +1 -0
  197. package/dist/mcp-slate-ui-script.js +58 -0
  198. package/dist/mcp-slate-ui-script.js.map +1 -0
  199. package/dist/mcp-slate-ui-styles-dialog.d.ts +17 -0
  200. package/dist/mcp-slate-ui-styles-dialog.d.ts.map +1 -0
  201. package/dist/mcp-slate-ui-styles-dialog.js +73 -0
  202. package/dist/mcp-slate-ui-styles-dialog.js.map +1 -0
  203. package/dist/mcp-slate-ui-styles-stage.d.ts +12 -0
  204. package/dist/mcp-slate-ui-styles-stage.d.ts.map +1 -0
  205. package/dist/mcp-slate-ui-styles-stage.js +53 -0
  206. package/dist/mcp-slate-ui-styles-stage.js.map +1 -0
  207. package/dist/mcp-slate-ui-styles-thumbtools.d.ts +10 -0
  208. package/dist/mcp-slate-ui-styles-thumbtools.d.ts.map +1 -0
  209. package/dist/mcp-slate-ui-styles-thumbtools.js +25 -0
  210. package/dist/mcp-slate-ui-styles-thumbtools.js.map +1 -0
  211. package/dist/mcp-slate-ui-styles.d.ts +13 -0
  212. package/dist/mcp-slate-ui-styles.d.ts.map +1 -0
  213. package/dist/mcp-slate-ui-styles.js +117 -0
  214. package/dist/mcp-slate-ui-styles.js.map +1 -0
  215. package/dist/mcp-slate-ui.d.ts +16 -0
  216. package/dist/mcp-slate-ui.d.ts.map +1 -0
  217. package/dist/mcp-slate-ui.js +58 -0
  218. package/dist/mcp-slate-ui.js.map +1 -0
  219. package/dist/mcp-slate-workspace-tools.d.ts +15 -0
  220. package/dist/mcp-slate-workspace-tools.d.ts.map +1 -0
  221. package/dist/mcp-slate-workspace-tools.js +155 -0
  222. package/dist/mcp-slate-workspace-tools.js.map +1 -0
  223. package/dist/mcp-tool-definitions.d.ts.map +1 -1
  224. package/dist/mcp-tool-definitions.js +9 -7
  225. package/dist/mcp-tool-definitions.js.map +1 -1
  226. package/dist/mcp-tool-handler.d.ts +8 -2
  227. package/dist/mcp-tool-handler.d.ts.map +1 -1
  228. package/dist/mcp-tool-handler.js +34 -13
  229. package/dist/mcp-tool-handler.js.map +1 -1
  230. package/dist/mcp-workflow-tools.d.ts +6 -0
  231. package/dist/mcp-workflow-tools.d.ts.map +1 -0
  232. package/dist/mcp-workflow-tools.js +108 -0
  233. package/dist/mcp-workflow-tools.js.map +1 -0
  234. package/dist/prototype-browsers.d.ts +8 -2
  235. package/dist/prototype-browsers.d.ts.map +1 -1
  236. package/dist/prototype-browsers.js +8 -3
  237. package/dist/prototype-browsers.js.map +1 -1
  238. package/dist/prototype-label-client.d.ts +5 -0
  239. package/dist/prototype-label-client.d.ts.map +1 -1
  240. package/dist/prototype-label-client.js.map +1 -1
  241. package/dist/prototype-poststep.d.ts +2 -2
  242. package/dist/prototype-poststep.d.ts.map +1 -1
  243. package/dist/prototype-poststep.js +3 -0
  244. package/dist/prototype-poststep.js.map +1 -1
  245. package/dist/prototype-process.js +1 -1
  246. package/dist/prototype-process.js.map +1 -1
  247. package/dist/prototype-run-record.d.ts +6 -2
  248. package/dist/prototype-run-record.d.ts.map +1 -1
  249. package/dist/prototype-run-record.js +6 -0
  250. package/dist/prototype-run-record.js.map +1 -1
  251. package/dist/prototype-runner.d.ts +2 -2
  252. package/dist/prototype-runner.d.ts.map +1 -1
  253. package/dist/prototype-runner.js +5 -2
  254. package/dist/prototype-runner.js.map +1 -1
  255. package/dist/prototype-workflow-contract.d.ts +13 -0
  256. package/dist/prototype-workflow-contract.d.ts.map +1 -0
  257. package/dist/prototype-workflow-contract.js +82 -0
  258. package/dist/prototype-workflow-contract.js.map +1 -0
  259. package/dist/prototype-workflow-labels.d.ts +29 -0
  260. package/dist/prototype-workflow-labels.d.ts.map +1 -0
  261. package/dist/prototype-workflow-labels.js +93 -0
  262. package/dist/prototype-workflow-labels.js.map +1 -0
  263. package/dist/run-journal-commands.d.ts.map +1 -1
  264. package/dist/run-journal-commands.js +24 -5
  265. package/dist/run-journal-commands.js.map +1 -1
  266. package/dist/scene/camera-model.d.ts +48 -0
  267. package/dist/scene/camera-model.d.ts.map +1 -0
  268. package/dist/scene/camera-model.js +89 -0
  269. package/dist/scene/camera-model.js.map +1 -0
  270. package/dist/scene/camera-solve.d.ts +58 -0
  271. package/dist/scene/camera-solve.d.ts.map +1 -0
  272. package/dist/scene/camera-solve.js +288 -0
  273. package/dist/scene/camera-solve.js.map +1 -0
  274. package/dist/scene/capture-plan.d.ts +28 -0
  275. package/dist/scene/capture-plan.d.ts.map +1 -0
  276. package/dist/scene/capture-plan.js +79 -0
  277. package/dist/scene/capture-plan.js.map +1 -0
  278. package/dist/scene/capture.d.ts +21 -0
  279. package/dist/scene/capture.d.ts.map +1 -0
  280. package/dist/scene/capture.js +118 -0
  281. package/dist/scene/capture.js.map +1 -0
  282. package/dist/scene/image-colors.d.ts +25 -0
  283. package/dist/scene/image-colors.d.ts.map +1 -0
  284. package/dist/scene/image-colors.js +110 -0
  285. package/dist/scene/image-colors.js.map +1 -0
  286. package/dist/scene/image-rectify.d.ts +25 -0
  287. package/dist/scene/image-rectify.d.ts.map +1 -0
  288. package/dist/scene/image-rectify.js +82 -0
  289. package/dist/scene/image-rectify.js.map +1 -0
  290. package/dist/scene/image-sheet.d.ts +19 -0
  291. package/dist/scene/image-sheet.d.ts.map +1 -0
  292. package/dist/scene/image-sheet.js +118 -0
  293. package/dist/scene/image-sheet.js.map +1 -0
  294. package/dist/scene/least-squares.d.ts +31 -0
  295. package/dist/scene/least-squares.d.ts.map +1 -0
  296. package/dist/scene/least-squares.js +173 -0
  297. package/dist/scene/least-squares.js.map +1 -0
  298. package/dist/scene/numbers.d.ts +17 -0
  299. package/dist/scene/numbers.d.ts.map +1 -0
  300. package/dist/scene/numbers.js +39 -0
  301. package/dist/scene/numbers.js.map +1 -0
  302. package/dist/scene/placement.d.ts +43 -0
  303. package/dist/scene/placement.d.ts.map +1 -0
  304. package/dist/scene/placement.js +107 -0
  305. package/dist/scene/placement.js.map +1 -0
  306. package/dist/scene/raster.d.ts +18 -0
  307. package/dist/scene/raster.d.ts.map +1 -0
  308. package/dist/scene/raster.js +31 -0
  309. package/dist/scene/raster.js.map +1 -0
  310. package/dist/scene/scene-kit.d.ts +20 -0
  311. package/dist/scene/scene-kit.d.ts.map +1 -0
  312. package/dist/scene/scene-kit.js +74 -0
  313. package/dist/scene/scene-kit.js.map +1 -0
  314. package/dist/scene/scene-verbs.d.ts +4 -0
  315. package/dist/scene/scene-verbs.d.ts.map +1 -0
  316. package/dist/scene/scene-verbs.js +5 -0
  317. package/dist/scene/scene-verbs.js.map +1 -0
  318. package/dist/scene/seeded-random.d.ts +20 -0
  319. package/dist/scene/seeded-random.d.ts.map +1 -0
  320. package/dist/scene/seeded-random.js +42 -0
  321. package/dist/scene/seeded-random.js.map +1 -0
  322. package/dist/scene/spec-expression.d.ts +25 -0
  323. package/dist/scene/spec-expression.d.ts.map +1 -0
  324. package/dist/scene/spec-expression.js +234 -0
  325. package/dist/scene/spec-expression.js.map +1 -0
  326. package/dist/scene/static-server.d.ts +13 -0
  327. package/dist/scene/static-server.d.ts.map +1 -0
  328. package/dist/scene/static-server.js +99 -0
  329. package/dist/scene/static-server.js.map +1 -0
  330. package/dist/server.d.ts +22 -2
  331. package/dist/server.d.ts.map +1 -1
  332. package/dist/server.js +44 -8
  333. package/dist/server.js.map +1 -1
  334. package/dist/slate-actions.d.ts +38 -0
  335. package/dist/slate-actions.d.ts.map +1 -0
  336. package/dist/slate-actions.js +102 -0
  337. package/dist/slate-actions.js.map +1 -0
  338. package/dist/slate-annotate.d.ts +36 -0
  339. package/dist/slate-annotate.d.ts.map +1 -0
  340. package/dist/slate-annotate.js +71 -0
  341. package/dist/slate-annotate.js.map +1 -0
  342. package/dist/slate-approvals.d.ts +61 -0
  343. package/dist/slate-approvals.d.ts.map +1 -0
  344. package/dist/slate-approvals.js +153 -0
  345. package/dist/slate-approvals.js.map +1 -0
  346. package/dist/slate-browser-decision.d.ts +30 -0
  347. package/dist/slate-browser-decision.d.ts.map +1 -0
  348. package/dist/slate-browser-decision.js +24 -0
  349. package/dist/slate-browser-decision.js.map +1 -0
  350. package/dist/slate-browser-host-script.d.ts +14 -0
  351. package/dist/slate-browser-host-script.d.ts.map +1 -0
  352. package/dist/slate-browser-host-script.js +125 -0
  353. package/dist/slate-browser-host-script.js.map +1 -0
  354. package/dist/slate-browser-host.d.ts +9 -0
  355. package/dist/slate-browser-host.d.ts.map +1 -0
  356. package/dist/slate-browser-host.js +37 -0
  357. package/dist/slate-browser-host.js.map +1 -0
  358. package/dist/slate-browser-server.d.ts +37 -0
  359. package/dist/slate-browser-server.d.ts.map +1 -0
  360. package/dist/slate-browser-server.js +186 -0
  361. package/dist/slate-browser-server.js.map +1 -0
  362. package/dist/slate-commit.d.ts +28 -0
  363. package/dist/slate-commit.d.ts.map +1 -0
  364. package/dist/slate-commit.js +218 -0
  365. package/dist/slate-commit.js.map +1 -0
  366. package/dist/slate-corpus.d.ts +14 -0
  367. package/dist/slate-corpus.d.ts.map +1 -0
  368. package/dist/slate-corpus.js +32 -0
  369. package/dist/slate-corpus.js.map +1 -0
  370. package/dist/slate-edit-prompt.d.ts +18 -0
  371. package/dist/slate-edit-prompt.d.ts.map +1 -0
  372. package/dist/slate-edit-prompt.js +41 -0
  373. package/dist/slate-edit-prompt.js.map +1 -0
  374. package/dist/slate-edit-runner.d.ts +4 -0
  375. package/dist/slate-edit-runner.d.ts.map +1 -0
  376. package/dist/slate-edit-runner.js +90 -0
  377. package/dist/slate-edit-runner.js.map +1 -0
  378. package/dist/slate-editability.d.ts +20 -0
  379. package/dist/slate-editability.d.ts.map +1 -0
  380. package/dist/slate-editability.js +19 -0
  381. package/dist/slate-editability.js.map +1 -0
  382. package/dist/slate-errors.d.ts +15 -0
  383. package/dist/slate-errors.d.ts.map +1 -0
  384. package/dist/slate-errors.js +21 -0
  385. package/dist/slate-errors.js.map +1 -0
  386. package/dist/slate-handoff-options.d.ts +40 -0
  387. package/dist/slate-handoff-options.d.ts.map +1 -0
  388. package/dist/slate-handoff-options.js +127 -0
  389. package/dist/slate-handoff-options.js.map +1 -0
  390. package/dist/slate-handoff.d.ts +11 -0
  391. package/dist/slate-handoff.d.ts.map +1 -0
  392. package/dist/slate-handoff.js +56 -0
  393. package/dist/slate-handoff.js.map +1 -0
  394. package/dist/slate-ids.d.ts +33 -0
  395. package/dist/slate-ids.d.ts.map +1 -0
  396. package/dist/slate-ids.js +47 -0
  397. package/dist/slate-ids.js.map +1 -0
  398. package/dist/slate-image-executor.d.ts +39 -0
  399. package/dist/slate-image-executor.d.ts.map +1 -0
  400. package/dist/slate-image-executor.js +52 -0
  401. package/dist/slate-image-executor.js.map +1 -0
  402. package/dist/slate-inspiration.d.ts +22 -0
  403. package/dist/slate-inspiration.d.ts.map +1 -0
  404. package/dist/slate-inspiration.js +112 -0
  405. package/dist/slate-inspiration.js.map +1 -0
  406. package/dist/slate-labels.d.ts +11 -0
  407. package/dist/slate-labels.d.ts.map +1 -0
  408. package/dist/slate-labels.js +32 -0
  409. package/dist/slate-labels.js.map +1 -0
  410. package/dist/slate-ledger.d.ts +29 -0
  411. package/dist/slate-ledger.d.ts.map +1 -0
  412. package/dist/slate-ledger.js +65 -0
  413. package/dist/slate-ledger.js.map +1 -0
  414. package/dist/slate-liveness.d.ts +26 -0
  415. package/dist/slate-liveness.d.ts.map +1 -0
  416. package/dist/slate-liveness.js +49 -0
  417. package/dist/slate-liveness.js.map +1 -0
  418. package/dist/slate-local-image.d.ts +19 -0
  419. package/dist/slate-local-image.d.ts.map +1 -0
  420. package/dist/slate-local-image.js +36 -0
  421. package/dist/slate-local-image.js.map +1 -0
  422. package/dist/slate-lock.d.ts +64 -0
  423. package/dist/slate-lock.d.ts.map +1 -0
  424. package/dist/slate-lock.js +178 -0
  425. package/dist/slate-lock.js.map +1 -0
  426. package/dist/slate-paths.d.ts +45 -0
  427. package/dist/slate-paths.d.ts.map +1 -0
  428. package/dist/slate-paths.js +132 -0
  429. package/dist/slate-paths.js.map +1 -0
  430. package/dist/slate-pick.d.ts +29 -0
  431. package/dist/slate-pick.d.ts.map +1 -0
  432. package/dist/slate-pick.js +55 -0
  433. package/dist/slate-pick.js.map +1 -0
  434. package/dist/slate-reference-ids.d.ts +6 -0
  435. package/dist/slate-reference-ids.d.ts.map +1 -0
  436. package/dist/slate-reference-ids.js +17 -0
  437. package/dist/slate-reference-ids.js.map +1 -0
  438. package/dist/slate-reference-store.d.ts +23 -0
  439. package/dist/slate-reference-store.d.ts.map +1 -0
  440. package/dist/slate-reference-store.js +46 -0
  441. package/dist/slate-reference-store.js.map +1 -0
  442. package/dist/slate-resume.d.ts +19 -0
  443. package/dist/slate-resume.d.ts.map +1 -0
  444. package/dist/slate-resume.js +94 -0
  445. package/dist/slate-resume.js.map +1 -0
  446. package/dist/slate-round-params.d.ts +20 -0
  447. package/dist/slate-round-params.d.ts.map +1 -0
  448. package/dist/slate-round-params.js +32 -0
  449. package/dist/slate-round-params.js.map +1 -0
  450. package/dist/slate-round-prompt.d.ts +18 -0
  451. package/dist/slate-round-prompt.d.ts.map +1 -0
  452. package/dist/slate-round-prompt.js +20 -0
  453. package/dist/slate-round-prompt.js.map +1 -0
  454. package/dist/slate-round-runner.d.ts +4 -0
  455. package/dist/slate-round-runner.d.ts.map +1 -0
  456. package/dist/slate-round-runner.js +125 -0
  457. package/dist/slate-round-runner.js.map +1 -0
  458. package/dist/slate-round-search.d.ts +7 -0
  459. package/dist/slate-round-search.d.ts.map +1 -0
  460. package/dist/slate-round-search.js +77 -0
  461. package/dist/slate-round-search.js.map +1 -0
  462. package/dist/slate-run-action.d.ts +14 -0
  463. package/dist/slate-run-action.d.ts.map +1 -0
  464. package/dist/slate-run-action.js +81 -0
  465. package/dist/slate-run-action.js.map +1 -0
  466. package/dist/slate-runner-context.d.ts +57 -0
  467. package/dist/slate-runner-context.d.ts.map +1 -0
  468. package/dist/slate-runner-context.js +79 -0
  469. package/dist/slate-runner-context.js.map +1 -0
  470. package/dist/slate-runner-failure.d.ts +8 -0
  471. package/dist/slate-runner-failure.d.ts.map +1 -0
  472. package/dist/slate-runner-failure.js +17 -0
  473. package/dist/slate-runner-failure.js.map +1 -0
  474. package/dist/slate-runner-flag.d.ts +3 -0
  475. package/dist/slate-runner-flag.d.ts.map +1 -0
  476. package/dist/slate-runner-flag.js +3 -0
  477. package/dist/slate-runner-flag.js.map +1 -0
  478. package/dist/slate-runner-main.d.ts +31 -0
  479. package/dist/slate-runner-main.d.ts.map +1 -0
  480. package/dist/slate-runner-main.js +132 -0
  481. package/dist/slate-runner-main.js.map +1 -0
  482. package/dist/slate-runner-spawn.d.ts +23 -0
  483. package/dist/slate-runner-spawn.d.ts.map +1 -0
  484. package/dist/slate-runner-spawn.js +27 -0
  485. package/dist/slate-runner-spawn.js.map +1 -0
  486. package/dist/slate-runtime.d.ts +38 -0
  487. package/dist/slate-runtime.d.ts.map +1 -0
  488. package/dist/slate-runtime.js +48 -0
  489. package/dist/slate-runtime.js.map +1 -0
  490. package/dist/slate-versions.d.ts +26 -0
  491. package/dist/slate-versions.d.ts.map +1 -0
  492. package/dist/slate-versions.js +110 -0
  493. package/dist/slate-versions.js.map +1 -0
  494. package/dist/slate-view-contract.d.ts +233 -0
  495. package/dist/slate-view-contract.d.ts.map +1 -0
  496. package/dist/slate-view-contract.js +17 -0
  497. package/dist/slate-view-contract.js.map +1 -0
  498. package/dist/slate-view-types.d.ts +2 -0
  499. package/dist/slate-view-types.d.ts.map +1 -0
  500. package/dist/slate-view-types.js +2 -0
  501. package/dist/slate-view-types.js.map +1 -0
  502. package/dist/slate-view.d.ts +19 -0
  503. package/dist/slate-view.d.ts.map +1 -0
  504. package/dist/slate-view.js +184 -0
  505. package/dist/slate-view.js.map +1 -0
  506. package/dist/slate-workspace-parse.d.ts +20 -0
  507. package/dist/slate-workspace-parse.d.ts.map +1 -0
  508. package/dist/slate-workspace-parse.js +437 -0
  509. package/dist/slate-workspace-parse.js.map +1 -0
  510. package/dist/slate-workspace-store.d.ts +44 -0
  511. package/dist/slate-workspace-store.d.ts.map +1 -0
  512. package/dist/slate-workspace-store.js +270 -0
  513. package/dist/slate-workspace-store.js.map +1 -0
  514. package/dist/slate-workspace-types.d.ts +176 -0
  515. package/dist/slate-workspace-types.d.ts.map +1 -0
  516. package/dist/slate-workspace-types.js +13 -0
  517. package/dist/slate-workspace-types.js.map +1 -0
  518. package/dist/workflow/adapter-12ui.d.ts +4 -0
  519. package/dist/workflow/adapter-12ui.d.ts.map +1 -0
  520. package/dist/workflow/adapter-12ui.js +147 -0
  521. package/dist/workflow/adapter-12ui.js.map +1 -0
  522. package/dist/workflow/adapter-layerdoc.d.ts +16 -0
  523. package/dist/workflow/adapter-layerdoc.d.ts.map +1 -0
  524. package/dist/workflow/adapter-layerdoc.js +116 -0
  525. package/dist/workflow/adapter-layerdoc.js.map +1 -0
  526. package/dist/workflow/adapter-openai.d.ts +4 -0
  527. package/dist/workflow/adapter-openai.d.ts.map +1 -0
  528. package/dist/workflow/adapter-openai.js +166 -0
  529. package/dist/workflow/adapter-openai.js.map +1 -0
  530. package/dist/workflow/adapter-process.d.ts +7 -0
  531. package/dist/workflow/adapter-process.d.ts.map +1 -0
  532. package/dist/workflow/adapter-process.js +174 -0
  533. package/dist/workflow/adapter-process.js.map +1 -0
  534. package/dist/workflow/adapter-prototype-labels.d.ts +15 -0
  535. package/dist/workflow/adapter-prototype-labels.d.ts.map +1 -0
  536. package/dist/workflow/adapter-prototype-labels.js +71 -0
  537. package/dist/workflow/adapter-prototype-labels.js.map +1 -0
  538. package/dist/workflow/adapter-types.d.ts +40 -0
  539. package/dist/workflow/adapter-types.d.ts.map +1 -0
  540. package/dist/workflow/adapter-types.js +2 -0
  541. package/dist/workflow/adapter-types.js.map +1 -0
  542. package/dist/workflow/adapter-utils.d.ts +11 -0
  543. package/dist/workflow/adapter-utils.d.ts.map +1 -0
  544. package/dist/workflow/adapter-utils.js +72 -0
  545. package/dist/workflow/adapter-utils.js.map +1 -0
  546. package/dist/workflow/adapters.d.ts +6 -0
  547. package/dist/workflow/adapters.d.ts.map +1 -0
  548. package/dist/workflow/adapters.js +25 -0
  549. package/dist/workflow/adapters.js.map +1 -0
  550. package/dist/workflow/artifact.d.ts +11 -0
  551. package/dist/workflow/artifact.d.ts.map +1 -0
  552. package/dist/workflow/artifact.js +94 -0
  553. package/dist/workflow/artifact.js.map +1 -0
  554. package/dist/workflow/bundle-collect.d.ts +8 -0
  555. package/dist/workflow/bundle-collect.d.ts.map +1 -0
  556. package/dist/workflow/bundle-collect.js +56 -0
  557. package/dist/workflow/bundle-collect.js.map +1 -0
  558. package/dist/workflow/bundle-export.d.ts +16 -0
  559. package/dist/workflow/bundle-export.d.ts.map +1 -0
  560. package/dist/workflow/bundle-export.js +174 -0
  561. package/dist/workflow/bundle-export.js.map +1 -0
  562. package/dist/workflow/bundle-paths.d.ts +7 -0
  563. package/dist/workflow/bundle-paths.d.ts.map +1 -0
  564. package/dist/workflow/bundle-paths.js +35 -0
  565. package/dist/workflow/bundle-paths.js.map +1 -0
  566. package/dist/workflow/bundle.d.ts +4 -0
  567. package/dist/workflow/bundle.d.ts.map +1 -0
  568. package/dist/workflow/bundle.js +4 -0
  569. package/dist/workflow/bundle.js.map +1 -0
  570. package/dist/workflow/capture.d.ts +36 -0
  571. package/dist/workflow/capture.d.ts.map +1 -0
  572. package/dist/workflow/capture.js +81 -0
  573. package/dist/workflow/capture.js.map +1 -0
  574. package/dist/workflow/continuation-branch.d.ts +15 -0
  575. package/dist/workflow/continuation-branch.d.ts.map +1 -0
  576. package/dist/workflow/continuation-branch.js +103 -0
  577. package/dist/workflow/continuation-branch.js.map +1 -0
  578. package/dist/workflow/continuation-plans.d.ts +38 -0
  579. package/dist/workflow/continuation-plans.d.ts.map +1 -0
  580. package/dist/workflow/continuation-plans.js +78 -0
  581. package/dist/workflow/continuation-plans.js.map +1 -0
  582. package/dist/workflow/continuation.d.ts +25 -0
  583. package/dist/workflow/continuation.d.ts.map +1 -0
  584. package/dist/workflow/continuation.js +89 -0
  585. package/dist/workflow/continuation.js.map +1 -0
  586. package/dist/workflow/layerdoc-reader.d.ts +27 -0
  587. package/dist/workflow/layerdoc-reader.d.ts.map +1 -0
  588. package/dist/workflow/layerdoc-reader.js +81 -0
  589. package/dist/workflow/layerdoc-reader.js.map +1 -0
  590. package/dist/workflow/project-evidence.d.ts +48 -0
  591. package/dist/workflow/project-evidence.d.ts.map +1 -0
  592. package/dist/workflow/project-evidence.js +200 -0
  593. package/dist/workflow/project-evidence.js.map +1 -0
  594. package/dist/workflow/providers.d.ts +35 -0
  595. package/dist/workflow/providers.d.ts.map +1 -0
  596. package/dist/workflow/providers.js +110 -0
  597. package/dist/workflow/providers.js.map +1 -0
  598. package/dist/workflow/recipes-layerdoc-validation.d.ts +4 -0
  599. package/dist/workflow/recipes-layerdoc-validation.d.ts.map +1 -0
  600. package/dist/workflow/recipes-layerdoc-validation.js +98 -0
  601. package/dist/workflow/recipes-layerdoc-validation.js.map +1 -0
  602. package/dist/workflow/recipes-result-validation.d.ts +6 -0
  603. package/dist/workflow/recipes-result-validation.d.ts.map +1 -0
  604. package/dist/workflow/recipes-result-validation.js +38 -0
  605. package/dist/workflow/recipes-result-validation.js.map +1 -0
  606. package/dist/workflow/recipes-schemas.d.ts +7 -0
  607. package/dist/workflow/recipes-schemas.d.ts.map +1 -0
  608. package/dist/workflow/recipes-schemas.js +67 -0
  609. package/dist/workflow/recipes-schemas.js.map +1 -0
  610. package/dist/workflow/recipes-validation.d.ts +14 -0
  611. package/dist/workflow/recipes-validation.d.ts.map +1 -0
  612. package/dist/workflow/recipes-validation.js +68 -0
  613. package/dist/workflow/recipes-validation.js.map +1 -0
  614. package/dist/workflow/recipes.d.ts +20 -0
  615. package/dist/workflow/recipes.d.ts.map +1 -0
  616. package/dist/workflow/recipes.js +167 -0
  617. package/dist/workflow/recipes.js.map +1 -0
  618. package/dist/workflow/routing.d.ts +4 -0
  619. package/dist/workflow/routing.d.ts.map +1 -0
  620. package/dist/workflow/routing.js +28 -0
  621. package/dist/workflow/routing.js.map +1 -0
  622. package/dist/workflow/schema.d.ts +5 -0
  623. package/dist/workflow/schema.d.ts.map +1 -0
  624. package/dist/workflow/schema.js +29 -0
  625. package/dist/workflow/schema.js.map +1 -0
  626. package/dist/workflow/service.d.ts +59 -0
  627. package/dist/workflow/service.d.ts.map +1 -0
  628. package/dist/workflow/service.js +170 -0
  629. package/dist/workflow/service.js.map +1 -0
  630. package/dist/workflow/store-json.d.ts +5 -0
  631. package/dist/workflow/store-json.d.ts.map +1 -0
  632. package/dist/workflow/store-json.js +35 -0
  633. package/dist/workflow/store-json.js.map +1 -0
  634. package/dist/workflow/store-lock.d.ts +3 -0
  635. package/dist/workflow/store-lock.d.ts.map +1 -0
  636. package/dist/workflow/store-lock.js +85 -0
  637. package/dist/workflow/store-lock.js.map +1 -0
  638. package/dist/workflow/store-paths.d.ts +17 -0
  639. package/dist/workflow/store-paths.d.ts.map +1 -0
  640. package/dist/workflow/store-paths.js +67 -0
  641. package/dist/workflow/store-paths.js.map +1 -0
  642. package/dist/workflow/store-validation.d.ts +7 -0
  643. package/dist/workflow/store-validation.d.ts.map +1 -0
  644. package/dist/workflow/store-validation.js +119 -0
  645. package/dist/workflow/store-validation.js.map +1 -0
  646. package/dist/workflow/store.d.ts +10 -0
  647. package/dist/workflow/store.d.ts.map +1 -0
  648. package/dist/workflow/store.js +193 -0
  649. package/dist/workflow/store.js.map +1 -0
  650. package/dist/workflow/types.d.ts +120 -0
  651. package/dist/workflow/types.d.ts.map +1 -0
  652. package/dist/workflow/types.js +15 -0
  653. package/dist/workflow/types.js.map +1 -0
  654. package/dist/workflow-transport.d.ts +28 -0
  655. package/dist/workflow-transport.d.ts.map +1 -0
  656. package/dist/workflow-transport.js +184 -0
  657. package/dist/workflow-transport.js.map +1 -0
  658. package/open-design.json +2 -2
  659. package/package.json +4 -1
  660. package/prototype-kit/tests/rules-check.mjs +9 -0
  661. package/runtime/codex-conversion/src/images/native-invoke.mjs +1 -1
  662. package/runtime/codex-conversion/src/images/native.mjs +8 -4
  663. package/runtime/layerdoc-validator.mjs +1860 -0
  664. package/scene-kit/starter/camera.js +10 -0
  665. package/scene-kit/starter/gobo.js +60 -0
  666. package/scene-kit/starter/index.html +23 -0
  667. package/scene-kit/starter/lib.js +84 -0
  668. package/scene-kit/starter/main.js +78 -0
  669. package/scene-kit/starter/scene.js +33 -0
  670. package/scene-kit/vendor/LICENSE +21 -0
  671. package/scene-kit/vendor/addons/geometries/RoundedBoxGeometry.js +216 -0
  672. package/scene-kit/vendor/addons/renderers/CSS3DRenderer.js +454 -0
  673. package/scene-kit/vendor/three.core.js +60586 -0
  674. package/scene-kit/vendor/three.module.js +19719 -0
  675. package/skills/12ui-design/SKILL.md +21 -61
  676. package/skills/12ui-design/improve.md +5 -1
  677. package/skills/12ui-design/inspire.md +8 -5
  678. package/skills/12ui-design/outputs.md +23 -2
  679. package/skills/12ui-design/scene.md +172 -0
  680. package/skills/12ui-design/session.md +161 -0
@@ -0,0 +1,1860 @@
1
+ // GENERATED from the canonical LayerDoc parser by scripts/layerdoc-validator-bundle.mjs. Do not edit.
2
+
3
+ // packages/layerdoc/src/core/css-shape.ts
4
+ var MAX_STYLE_PROPERTIES = 100;
5
+ var MAX_PROPERTY_LENGTH = 128;
6
+ var MAX_VALUE_LENGTH = 2048;
7
+ var UNSAFE_DECLARATION_BOUNDARY = /[<>{};\u0000-\u001f\u007f]/;
8
+ var EXTERNAL_OR_EXECUTABLE_CSS = /(?:@import\b|javascript\s*:|vbscript\s*:|-moz-binding\b|behavior\s*:|(?:url|src|image-set|-webkit-image-set|expression)\s*\()/i;
9
+ var UNSAFE_PROPERTY = /^(?:behavior|javascript|mozBinding|vbscript)$/i;
10
+ var UNITLESS_PROPERTIES = /* @__PURE__ */ new Set([
11
+ "animationIterationCount",
12
+ "aspectRatio",
13
+ "borderImageOutset",
14
+ "borderImageSlice",
15
+ "borderImageWidth",
16
+ "columnCount",
17
+ "columns",
18
+ "fillOpacity",
19
+ "flex",
20
+ "flexGrow",
21
+ "flexShrink",
22
+ "fontWeight",
23
+ "gridArea",
24
+ "gridColumn",
25
+ "gridColumnEnd",
26
+ "gridColumnStart",
27
+ "gridRow",
28
+ "gridRowEnd",
29
+ "gridRowStart",
30
+ "lineClamp",
31
+ "lineHeight",
32
+ "opacity",
33
+ "order",
34
+ "orphans",
35
+ "scale",
36
+ "stopOpacity",
37
+ "strokeMiterlimit",
38
+ "strokeOpacity",
39
+ "tabSize",
40
+ "widows",
41
+ "zIndex",
42
+ "zoom"
43
+ ]);
44
+ var LENGTH_PROPERTY = /(?:block|blur|bottom|basis|gap|height|indent|inset|left|margin|offset|padding|radius|right|size|spacing|spread|thickness|top|width)$/i;
45
+ var camelTail = (value) => value.split("-").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()).join("");
46
+ var SCALAR_LENGTH_ALIASES = {
47
+ borderRadiusPx: "borderRadius",
48
+ borderWidthPx: "borderWidth",
49
+ fontSizePx: "fontSize"
50
+ };
51
+ var allowedProperty = (value) => UNSAFE_PROPERTY.test(value) ? null : SCALAR_LENGTH_ALIASES[value] ?? value;
52
+ function normalizeCssPropertyName(value) {
53
+ if (typeof value !== "string") return null;
54
+ const raw = value.trim();
55
+ if (!raw || raw.length > MAX_PROPERTY_LENGTH || UNSAFE_DECLARATION_BOUNDARY.test(raw)) return null;
56
+ if (raw.startsWith("--")) return /^--[A-Za-z0-9_-]+$/.test(raw) ? raw : null;
57
+ const cssLike = raw.replace(/[\s_]+/g, "-").replace(/[^A-Za-z0-9-]+/g, "-");
58
+ if (/^-webkit-/i.test(cssLike)) return allowedProperty(`Webkit${camelTail(cssLike.slice(8))}`);
59
+ if (/^-moz-/i.test(cssLike)) return allowedProperty(`Moz${camelTail(cssLike.slice(5))}`);
60
+ if (/^-o-/i.test(cssLike)) return allowedProperty(`O${camelTail(cssLike.slice(3))}`);
61
+ if (/^-ms-/i.test(cssLike)) return allowedProperty(`ms${camelTail(cssLike.slice(4))}`);
62
+ if (!/^[A-Za-z][A-Za-z0-9-]*$/.test(cssLike)) return null;
63
+ if (!cssLike.includes("-")) {
64
+ return allowedProperty(/^[A-Z]+$/.test(cssLike) ? cssLike.toLowerCase() : cssLike.charAt(0).toLowerCase() + cssLike.slice(1));
65
+ }
66
+ const [first, ...rest] = cssLike.split("-").filter(Boolean);
67
+ return allowedProperty(`${first.toLowerCase()}${rest.map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()).join("")}`);
68
+ }
69
+ var numericCssValue = (property, value) => {
70
+ if (!Number.isFinite(value)) return null;
71
+ const normalized = Object.is(value, -0) ? 0 : value;
72
+ if (normalized === 0 || UNITLESS_PROPERTIES.has(property) || property.startsWith("--")) return String(normalized);
73
+ return LENGTH_PROPERTY.test(property) ? `${normalized}px` : String(normalized);
74
+ };
75
+ function normalizeCssPropertyValue(property, value) {
76
+ if (typeof value === "number") return numericCssValue(property, value);
77
+ if (Array.isArray(value)) {
78
+ const parts = value.map((part) => normalizeCssPropertyValue(property, part));
79
+ return parts.length && parts.every((part) => part !== null) ? parts.join(" ") : null;
80
+ }
81
+ if (value && typeof value === "object") {
82
+ const source = value;
83
+ if (source.css !== void 0) return normalizeCssPropertyValue(property, source.css);
84
+ if (source.value !== void 0) return normalizeCssPropertyValue(property, source.value);
85
+ return null;
86
+ }
87
+ if (typeof value !== "string") return null;
88
+ const candidate = value.trim();
89
+ if (!candidate || candidate.length > MAX_VALUE_LENGTH) return null;
90
+ if (UNSAFE_DECLARATION_BOUNDARY.test(candidate) || EXTERNAL_OR_EXECUTABLE_CSS.test(candidate)) return null;
91
+ if (/^-?(?:\d+(?:\.\d+)?|\.\d+)$/.test(candidate)) {
92
+ return numericCssValue(property, Number(candidate));
93
+ }
94
+ return candidate;
95
+ }
96
+ function normalizeCssStyleShape(value) {
97
+ const output = {};
98
+ for (const [rawProperty, rawValue] of Object.entries(value).slice(0, MAX_STYLE_PROPERTIES)) {
99
+ const property = normalizeCssPropertyName(rawProperty);
100
+ if (!property || UNSAFE_PROPERTY.test(property)) continue;
101
+ const normalized = normalizeCssPropertyValue(property, rawValue);
102
+ if (normalized !== null) output[property] = normalized;
103
+ }
104
+ return output;
105
+ }
106
+
107
+ // packages/layerdoc/src/core/css-named-colors.ts
108
+ var NAMED_CSS_COLORS = new Map(Object.entries({
109
+ aliceblue: "#f0f8ff",
110
+ antiquewhite: "#faebd7",
111
+ aqua: "#00ffff",
112
+ aquamarine: "#7fffd4",
113
+ azure: "#f0ffff",
114
+ beige: "#f5f5dc",
115
+ bisque: "#ffe4c4",
116
+ black: "#000000",
117
+ blanchedalmond: "#ffebcd",
118
+ blue: "#0000ff",
119
+ blueviolet: "#8a2be2",
120
+ brown: "#a52a2a",
121
+ burlywood: "#deb887",
122
+ cadetblue: "#5f9ea0",
123
+ chartreuse: "#7fff00",
124
+ chocolate: "#d2691e",
125
+ coral: "#ff7f50",
126
+ cornflowerblue: "#6495ed",
127
+ cornsilk: "#fff8dc",
128
+ crimson: "#dc143c",
129
+ cyan: "#00ffff",
130
+ darkblue: "#00008b",
131
+ darkcyan: "#008b8b",
132
+ darkgoldenrod: "#b8860b",
133
+ darkgray: "#a9a9a9",
134
+ darkgreen: "#006400",
135
+ darkgrey: "#a9a9a9",
136
+ darkkhaki: "#bdb76b",
137
+ darkmagenta: "#8b008b",
138
+ darkolivegreen: "#556b2f",
139
+ darkorange: "#ff8c00",
140
+ darkorchid: "#9932cc",
141
+ darkred: "#8b0000",
142
+ darksalmon: "#e9967a",
143
+ darkseagreen: "#8fbc8f",
144
+ darkslateblue: "#483d8b",
145
+ darkslategray: "#2f4f4f",
146
+ darkslategrey: "#2f4f4f",
147
+ darkturquoise: "#00ced1",
148
+ darkviolet: "#9400d3",
149
+ deeppink: "#ff1493",
150
+ deepskyblue: "#00bfff",
151
+ dimgray: "#696969",
152
+ dimgrey: "#696969",
153
+ dodgerblue: "#1e90ff",
154
+ firebrick: "#b22222",
155
+ floralwhite: "#fffaf0",
156
+ forestgreen: "#228b22",
157
+ fuchsia: "#ff00ff",
158
+ gainsboro: "#dcdcdc",
159
+ ghostwhite: "#f8f8ff",
160
+ gold: "#ffd700",
161
+ goldenrod: "#daa520",
162
+ gray: "#808080",
163
+ green: "#008000",
164
+ greenyellow: "#adff2f",
165
+ grey: "#808080",
166
+ honeydew: "#f0fff0",
167
+ hotpink: "#ff69b4",
168
+ indianred: "#cd5c5c",
169
+ indigo: "#4b0082",
170
+ ivory: "#fffff0",
171
+ khaki: "#f0e68c",
172
+ lavender: "#e6e6fa",
173
+ lavenderblush: "#fff0f5",
174
+ lawngreen: "#7cfc00",
175
+ lemonchiffon: "#fffacd",
176
+ lightblue: "#add8e6",
177
+ lightcoral: "#f08080",
178
+ lightcyan: "#e0ffff",
179
+ lightgoldenrodyellow: "#fafad2",
180
+ lightgray: "#d3d3d3",
181
+ lightgreen: "#90ee90",
182
+ lightgrey: "#d3d3d3",
183
+ lightpink: "#ffb6c1",
184
+ lightsalmon: "#ffa07a",
185
+ lightseagreen: "#20b2aa",
186
+ lightskyblue: "#87cefa",
187
+ lightslategray: "#778899",
188
+ lightslategrey: "#778899",
189
+ lightsteelblue: "#b0c4de",
190
+ lightyellow: "#ffffe0",
191
+ lime: "#00ff00",
192
+ limegreen: "#32cd32",
193
+ linen: "#faf0e6",
194
+ magenta: "#ff00ff",
195
+ maroon: "#800000",
196
+ mediumaquamarine: "#66cdaa",
197
+ mediumblue: "#0000cd",
198
+ mediumorchid: "#ba55d3",
199
+ mediumpurple: "#9370db",
200
+ mediumseagreen: "#3cb371",
201
+ mediumslateblue: "#7b68ee",
202
+ mediumspringgreen: "#00fa9a",
203
+ mediumturquoise: "#48d1cc",
204
+ mediumvioletred: "#c71585",
205
+ midnightblue: "#191970",
206
+ mintcream: "#f5fffa",
207
+ mistyrose: "#ffe4e1",
208
+ moccasin: "#ffe4b5",
209
+ navajowhite: "#ffdead",
210
+ navy: "#000080",
211
+ oldlace: "#fdf5e6",
212
+ olive: "#808000",
213
+ olivedrab: "#6b8e23",
214
+ orange: "#ffa500",
215
+ orangered: "#ff4500",
216
+ orchid: "#da70d6",
217
+ palegoldenrod: "#eee8aa",
218
+ palegreen: "#98fb98",
219
+ paleturquoise: "#afeeee",
220
+ palevioletred: "#db7093",
221
+ papayawhip: "#ffefd5",
222
+ peachpuff: "#ffdab9",
223
+ peru: "#cd853f",
224
+ pink: "#ffc0cb",
225
+ plum: "#dda0dd",
226
+ powderblue: "#b0e0e6",
227
+ purple: "#800080",
228
+ rebeccapurple: "#663399",
229
+ red: "#ff0000",
230
+ rosybrown: "#bc8f8f",
231
+ royalblue: "#4169e1",
232
+ saddlebrown: "#8b4513",
233
+ salmon: "#fa8072",
234
+ sandybrown: "#f4a460",
235
+ seagreen: "#2e8b57",
236
+ seashell: "#fff5ee",
237
+ sienna: "#a0522d",
238
+ silver: "#c0c0c0",
239
+ skyblue: "#87ceeb",
240
+ slateblue: "#6a5acd",
241
+ slategray: "#708090",
242
+ slategrey: "#708090",
243
+ snow: "#fffafa",
244
+ springgreen: "#00ff7f",
245
+ steelblue: "#4682b4",
246
+ tan: "#d2b48c",
247
+ teal: "#008080",
248
+ thistle: "#d8bfd8",
249
+ tomato: "#ff6347",
250
+ turquoise: "#40e0d0",
251
+ violet: "#ee82ee",
252
+ wheat: "#f5deb3",
253
+ white: "#ffffff",
254
+ whitesmoke: "#f5f5f5",
255
+ yellow: "#ffff00",
256
+ yellowgreen: "#9acd32"
257
+ }));
258
+
259
+ // packages/layerdoc/src/core/css-values.ts
260
+ var SAFE_COLOR = /^(?:#[0-9a-fA-F]{3,8}|rgba?\(\s*\d+(?:\.\d+)?\s*,\s*\d+(?:\.\d+)?\s*,\s*\d+(?:\.\d+)?(?:\s*,\s*(?:0|1|0?\.\d+))?\s*\))$/;
261
+ var UNSAFE_STYLE_BOUNDARY = /[<>{};\u0000-\u001f\u007f]/;
262
+ function sanitizeCssColor(value) {
263
+ const color2 = String(value ?? "").trim();
264
+ return SAFE_COLOR.test(color2) ? color2 : null;
265
+ }
266
+ function resolveDeclaredCssColor(value) {
267
+ const exact = sanitizeCssColor(value);
268
+ if (exact) return exact;
269
+ return NAMED_CSS_COLORS.get(String(value ?? "").trim().toLowerCase()) ?? null;
270
+ }
271
+ function isSafeStyleDescription(value) {
272
+ return !UNSAFE_STYLE_BOUNDARY.test(value);
273
+ }
274
+ var SURFACE_CSS_EDGE_BORDERS = Object.freeze([
275
+ "borderTop",
276
+ "borderRight",
277
+ "borderBottom",
278
+ "borderLeft"
279
+ ]);
280
+ var finiteCssNumber = String.raw`-?(?:\d+(?:\.\d+)?|\.\d+)`;
281
+ var cssLength = new RegExp(`^${finiteCssNumber}px$`);
282
+ var cssPercentage = new RegExp(`^${finiteCssNumber}%$`);
283
+ var cssShadowLength = String.raw`(?:0|${finiteCssNumber}px)`;
284
+ function parseSurfaceCss(value) {
285
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
286
+ throw new Error("style must be an object");
287
+ }
288
+ return normalizeCssStyleShape(value);
289
+ }
290
+
291
+ // packages/layerdoc/src/core/clip-path-coordinate-frame.ts
292
+ var PUBLIC_CLIP_PATH_FRAME = "canvas-px";
293
+ var COMMAND_AXES = Object.freeze({
294
+ M: ["x", "y"],
295
+ L: ["x", "y"],
296
+ H: ["x"],
297
+ V: ["y"],
298
+ C: ["x", "y", "x", "y", "x", "y"],
299
+ S: ["x", "y", "x", "y"],
300
+ Q: ["x", "y", "x", "y"],
301
+ T: ["x", "y"],
302
+ A: ["x", "y", "angle", "flag", "flag", "x", "y"],
303
+ Z: []
304
+ });
305
+
306
+ // packages/layerdoc/src/core/control-text-anchor.ts
307
+ var CONTROL_TEXT_VERTICAL_ANCHORS = [
308
+ "center",
309
+ "source-offset",
310
+ "top",
311
+ "baseline",
312
+ "bottom"
313
+ ];
314
+ var CONTROL_TEXT_HORIZONTAL_ANCHORS = [
315
+ "center",
316
+ "start",
317
+ "end",
318
+ "source-offset"
319
+ ];
320
+ var CONTROL_TEXT_ANCHOR_KEYS = /* @__PURE__ */ new Set(["vertical", "horizontal"]);
321
+ var parseControlTextAnchor = (value, path, issues) => {
322
+ if (value === void 0) return void 0;
323
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
324
+ issues.push(`${path} must be an object`);
325
+ return void 0;
326
+ }
327
+ const input = value;
328
+ for (const key of Object.keys(input)) {
329
+ if (!CONTROL_TEXT_ANCHOR_KEYS.has(key)) issues.push(`${path}.${key} is not a control-text anchor key`);
330
+ }
331
+ const output = {};
332
+ if (input.vertical !== void 0) {
333
+ if (!CONTROL_TEXT_VERTICAL_ANCHORS.includes(input.vertical)) {
334
+ issues.push(`${path}.vertical must be one of ${CONTROL_TEXT_VERTICAL_ANCHORS.join(", ")}`);
335
+ } else output.vertical = input.vertical;
336
+ }
337
+ if (input.horizontal !== void 0) {
338
+ if (!CONTROL_TEXT_HORIZONTAL_ANCHORS.includes(input.horizontal)) {
339
+ issues.push(`${path}.horizontal must be one of ${CONTROL_TEXT_HORIZONTAL_ANCHORS.join(", ")}`);
340
+ } else output.horizontal = input.horizontal;
341
+ }
342
+ if (output.vertical === void 0 && output.horizontal === void 0) {
343
+ issues.push(`${path} must declare vertical or horizontal`);
344
+ return void 0;
345
+ }
346
+ return output;
347
+ };
348
+
349
+ // packages/layerdoc/src/core/public-layerdoc-forward-compat.ts
350
+ var PROTOTYPE_MUTATING_KEYS = /* @__PURE__ */ new Set([
351
+ "__proto__",
352
+ "constructor",
353
+ "prototype"
354
+ ]);
355
+ var forwardUnknownKeys = (value, allowed, path, issues, options = {}) => {
356
+ let forwarded = null;
357
+ for (const key of Object.keys(value)) {
358
+ if (allowed.has(key)) continue;
359
+ if (options.reserved?.has(key) || PROTOTYPE_MUTATING_KEYS.has(key)) {
360
+ issues.push(`${path}.${key} is not allowed`);
361
+ continue;
362
+ }
363
+ (forwarded ??= {})[key] = value[key];
364
+ }
365
+ return forwarded;
366
+ };
367
+ var carryUnknownKeys = (output, forwarded) => {
368
+ if (forwarded) Object.assign(output, forwarded);
369
+ return output;
370
+ };
371
+ var refuseUnknownKeys = (value, allowed, path, issues) => {
372
+ for (const key of Object.keys(value)) {
373
+ if (!allowed.has(key)) issues.push(`${path}.${key} is not allowed`);
374
+ }
375
+ };
376
+
377
+ // packages/layerdoc/src/core/extraction-contract.ts
378
+ var EXTRACTION_CONTRACT_KEYS = /* @__PURE__ */ new Set([
379
+ "revision",
380
+ "promptRevision",
381
+ "schemaRevision"
382
+ ]);
383
+ var isSha256 = (value) => typeof value === "string" && /^[a-f0-9]{64}$/u.test(value);
384
+ var parseExtractionContract = (value, path, issues) => {
385
+ if (value === void 0) return void 0;
386
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
387
+ issues.push(`${path} must be an object`);
388
+ return void 0;
389
+ }
390
+ const input = value;
391
+ const forwarded = forwardUnknownKeys(input, EXTRACTION_CONTRACT_KEYS, path, issues);
392
+ if (!Number.isSafeInteger(input.revision) || Number(input.revision) < 1) {
393
+ issues.push(`${path}.revision must be a positive safe integer`);
394
+ }
395
+ if (!isSha256(input.promptRevision)) {
396
+ issues.push(`${path}.promptRevision must be a lowercase sha256`);
397
+ }
398
+ if (!isSha256(input.schemaRevision)) {
399
+ issues.push(`${path}.schemaRevision must be a lowercase sha256`);
400
+ }
401
+ if (!Number.isSafeInteger(input.revision) || Number(input.revision) < 1 || !isSha256(input.promptRevision) || !isSha256(input.schemaRevision)) return void 0;
402
+ return carryUnknownKeys({
403
+ revision: Number(input.revision),
404
+ promptRevision: input.promptRevision,
405
+ schemaRevision: input.schemaRevision
406
+ }, forwarded);
407
+ };
408
+
409
+ // packages/layerdoc/src/snap-text-ink.ts
410
+ var TEXT_INK_REFUSALS = [
411
+ "busy-background",
412
+ "no-credible-ink",
413
+ "mask-flooded",
414
+ "no-row-segments",
415
+ "declared-line-count",
416
+ "no-column-segments",
417
+ "no-move",
418
+ "area",
419
+ "single-line-allowance",
420
+ "ink-loss"
421
+ ];
422
+ var TEXT_INK_BASES = ["declared-color", "contrast"];
423
+
424
+ // packages/layerdoc/src/core/icon-svg.ts
425
+ var ALLOWED_TAGS = /* @__PURE__ */ new Set([
426
+ "circle",
427
+ "ellipse",
428
+ "g",
429
+ "line",
430
+ "path",
431
+ "polygon",
432
+ "polyline",
433
+ "rect",
434
+ "svg"
435
+ ]);
436
+ var DRAWING_TAGS = /* @__PURE__ */ new Set([
437
+ "circle",
438
+ "ellipse",
439
+ "line",
440
+ "path",
441
+ "polygon",
442
+ "polyline",
443
+ "rect"
444
+ ]);
445
+ var ALLOWED_ATTRIBUTES = /* @__PURE__ */ new Set([
446
+ "clip-rule",
447
+ "cx",
448
+ "cy",
449
+ "d",
450
+ "fill",
451
+ "fill-rule",
452
+ "height",
453
+ "opacity",
454
+ "points",
455
+ "preserveAspectRatio",
456
+ "r",
457
+ "rx",
458
+ "ry",
459
+ "stroke",
460
+ "stroke-linecap",
461
+ "stroke-linejoin",
462
+ "stroke-miterlimit",
463
+ "stroke-width",
464
+ "transform",
465
+ "viewBox",
466
+ "width",
467
+ "x",
468
+ "x1",
469
+ "x2",
470
+ "xmlns",
471
+ "y",
472
+ "y1",
473
+ "y2"
474
+ ]);
475
+ var OPENING_TAG = /<([a-zA-Z][\w:-]*)([^<>]*)>/g;
476
+ var ATTRIBUTE = /([a-zA-Z_:][\w:.-]*)\s*=\s*(?:"[^"]*"|'[^']*')/g;
477
+ var parseIconSvg = (input, path = "iconSvg") => {
478
+ if (typeof input !== "string" || !input.trim()) throw new Error(`${path} must be a non-empty SVG string`);
479
+ const svg = input.trim();
480
+ if (!/^<svg\b[\s\S]*<\/svg>$/.test(svg)) throw new Error(`${path} must have one svg root`);
481
+ if (/<!|<\?|&(?:#\d+|#x[a-f\d]+|[a-z][\w.-]*);|\b(?:href|style)\s*=|\bon[a-z]+\s*=|\burl\s*\(/i.test(svg)) {
482
+ throw new Error(`${path} contains executable or external SVG markup`);
483
+ }
484
+ const seenTags = [...svg.matchAll(/<\/?([a-zA-Z][\w:-]*)\b/g)];
485
+ for (const match of seenTags) {
486
+ if (!ALLOWED_TAGS.has(match[1])) throw new Error(`${path} contains unsupported <${match[1]}> markup`);
487
+ }
488
+ if (!seenTags.some((match) => DRAWING_TAGS.has(match[1]))) {
489
+ throw new Error(`${path} contains no drawing element`);
490
+ }
491
+ for (const tag of svg.matchAll(OPENING_TAG)) {
492
+ const attributes = tag[2];
493
+ const stripped = attributes.replace(ATTRIBUTE, "").replace(/\s|\//g, "");
494
+ if (stripped) throw new Error(`${path} contains malformed SVG attributes`);
495
+ for (const attribute of attributes.matchAll(ATTRIBUTE)) {
496
+ if (!ALLOWED_ATTRIBUTES.has(attribute[1])) {
497
+ throw new Error(`${path} contains unsupported ${attribute[1]} attribute`);
498
+ }
499
+ }
500
+ }
501
+ return svg;
502
+ };
503
+
504
+ // packages/layerdoc/src/core/repeated-rules.ts
505
+ var REPEATED_RULE_ORIENTATIONS = ["horizontal", "vertical"];
506
+ var MAX_REPEATED_RULE_SETS = 2;
507
+ var MAX_REPEATED_RULE_POSITIONS = 64;
508
+ var MAX_REPEATED_RULE_STROKE_RATIO = 0.1;
509
+ var ruleRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
510
+ var parseRepeatedRules = (value, path, issues) => {
511
+ if (value === void 0) return void 0;
512
+ if (!Array.isArray(value) || value.length < 1 || value.length > MAX_REPEATED_RULE_SETS) {
513
+ issues.push(`${path} must contain 1..${MAX_REPEATED_RULE_SETS} rule sets`);
514
+ return void 0;
515
+ }
516
+ const output = [];
517
+ const orientations = /* @__PURE__ */ new Set();
518
+ for (const [index, candidate] of value.entries()) {
519
+ const itemPath = `${path}[${index}]`;
520
+ const rule = ruleRecord(candidate);
521
+ if (!rule) {
522
+ issues.push(`${itemPath} must be an object`);
523
+ continue;
524
+ }
525
+ if (Object.keys(rule).some((key) => !["orientation", "positions", "stroke"].includes(key))) {
526
+ issues.push(`${itemPath} has an unknown repeated-rule key`);
527
+ continue;
528
+ }
529
+ const orientation = rule.orientation;
530
+ if (!REPEATED_RULE_ORIENTATIONS.includes(orientation)) {
531
+ issues.push(`${itemPath}.orientation must be horizontal or vertical`);
532
+ continue;
533
+ }
534
+ if (orientations.has(orientation)) {
535
+ issues.push(`${path} must not repeat a rule orientation`);
536
+ continue;
537
+ }
538
+ if (!Array.isArray(rule.positions) || rule.positions.length < 1 || rule.positions.length > MAX_REPEATED_RULE_POSITIONS || !rule.positions.every((position) => typeof position === "number" && Number.isFinite(position) && position > 0 && position < 1)) {
539
+ issues.push(`${itemPath}.positions must contain 1..${MAX_REPEATED_RULE_POSITIONS} interior fractions`);
540
+ continue;
541
+ }
542
+ const positions = [...rule.positions];
543
+ if (positions.some((position, at) => at > 0 && position <= positions[at - 1])) {
544
+ issues.push(`${itemPath}.positions must be strictly ascending`);
545
+ continue;
546
+ }
547
+ const stroke = ruleRecord(rule.stroke);
548
+ if (!stroke || Object.keys(stroke).some((key) => !["width", "color"].includes(key))) {
549
+ issues.push(`${itemPath}.stroke must contain width and color`);
550
+ continue;
551
+ }
552
+ const width = stroke.width;
553
+ const color2 = typeof stroke.color === "string" ? sanitizeCssColor(stroke.color) : null;
554
+ if (typeof width !== "number" || !Number.isFinite(width) || width <= 0 || width > MAX_REPEATED_RULE_STROKE_RATIO || !color2) {
555
+ issues.push(`${itemPath}.stroke must have a safe width and literal color`);
556
+ continue;
557
+ }
558
+ orientations.add(orientation);
559
+ output.push({
560
+ orientation,
561
+ positions,
562
+ stroke: { width, color: color2 }
563
+ });
564
+ }
565
+ return output.length === value.length ? output : void 0;
566
+ };
567
+
568
+ // packages/layerdoc/src/core/selection-control.ts
569
+ var SELECTION_CONTROL_KINDS = [
570
+ "checkbox",
571
+ "radio",
572
+ "toggle"
573
+ ];
574
+ var KIND_SET = new Set(SELECTION_CONTROL_KINDS);
575
+ var isSelectionControlKind = (value) => KIND_SET.has(String(value ?? "").trim().toLowerCase());
576
+ var finiteBox = (value) => {
577
+ if (!value || value.length !== 4) return null;
578
+ const box = value.map(Number);
579
+ return box.every(Number.isFinite) && box[2] > 0 && box[3] > 0 ? box : null;
580
+ };
581
+ var boxContains = (outer, inner) => inner[0] >= outer[0] && inner[1] >= outer[1] && inner[0] + inner[2] <= outer[0] + outer[2] && inner[1] + inner[3] <= outer[1] + outer[3];
582
+ var selectionControlDeclaration = (layer) => {
583
+ const normalizedKind2 = String(layer.checkableKind ?? "").trim().toLowerCase();
584
+ if (!isSelectionControlKind(normalizedKind2)) return null;
585
+ const box = finiteBox(layer.box);
586
+ const markerBox = finiteBox(layer.markerBox);
587
+ if (!box) throw new Error(`${normalizedKind2}.box must be a finite positive box`);
588
+ if (!markerBox) throw new Error(`${normalizedKind2}.markerBox must be a finite positive box`);
589
+ if (!boxContains(box, markerBox)) {
590
+ throw new Error(`${normalizedKind2}.markerBox must stay inside its control box`);
591
+ }
592
+ if (typeof layer.checked !== "boolean") {
593
+ throw new Error(`${normalizedKind2}.checked must be boolean`);
594
+ }
595
+ const markerColor = resolveDeclaredCssColor(layer.markerColor);
596
+ if (!markerColor) throw new Error(`${normalizedKind2}.markerColor must be a declared CSS color`);
597
+ return {
598
+ kind: normalizedKind2,
599
+ content: String(layer.content ?? ""),
600
+ group: String(layer.group ?? ""),
601
+ box,
602
+ markerBox,
603
+ markerColor,
604
+ checked: layer.checked
605
+ };
606
+ };
607
+
608
+ // packages/layerdoc/src/core/layer-representation.ts
609
+ var MIN_TEXT_AXIS_SCALE = 0.5;
610
+ var MAX_TEXT_AXIS_SCALE = 2;
611
+ var isValidTextAxisScale = (value) => typeof value === "number" && Number.isFinite(value) && Math.abs(value) >= MIN_TEXT_AXIS_SCALE && Math.abs(value) <= MAX_TEXT_AXIS_SCALE;
612
+ var TEXT_LAYER_KINDS = [
613
+ "text",
614
+ "heading",
615
+ "title",
616
+ "subtitle",
617
+ "paragraph",
618
+ "caption",
619
+ "label",
620
+ "link",
621
+ "textarea",
622
+ "button",
623
+ "input",
624
+ "badge"
625
+ ];
626
+ var NON_TEXT_LAYER_KINDS = [
627
+ "background",
628
+ "photo",
629
+ "texture",
630
+ "panel",
631
+ "card",
632
+ "icon",
633
+ "logo",
634
+ "divider",
635
+ "decoration",
636
+ "illustration",
637
+ "image",
638
+ "graphic",
639
+ "chart"
640
+ ];
641
+ var COMPLETE_RECTANGULAR_RASTER_LAYER_KINDS = [
642
+ "illustration",
643
+ "image",
644
+ "graphic",
645
+ "chart"
646
+ ];
647
+ var TEXT_KINDS = new Set(TEXT_LAYER_KINDS);
648
+ var NON_TEXT_KINDS = new Set(NON_TEXT_LAYER_KINDS);
649
+ var COMPLETE_RECTANGULAR_RASTER_KINDS = new Set(
650
+ COMPLETE_RECTANGULAR_RASTER_LAYER_KINDS
651
+ );
652
+ var isValidGoogleFontFamily = (value) => {
653
+ const family = String(value ?? "").trim();
654
+ return Boolean(family) && /^[\p{L}\p{N} _-]+$/u.test(family);
655
+ };
656
+
657
+ // packages/layerdoc/src/core/text-color-ranges.ts
658
+ var TEXT_COLOR_RANGE_KEYS = /* @__PURE__ */ new Set(["start", "end", "color"]);
659
+ var MAX_TEXT_COLOR_RANGES = 64;
660
+ var parseTextColorRanges = (value, content, path, issues) => {
661
+ if (value === void 0) return void 0;
662
+ if (!Array.isArray(value)) {
663
+ issues.push(`${path} must be an array`);
664
+ return void 0;
665
+ }
666
+ if (value.length > MAX_TEXT_COLOR_RANGES) {
667
+ issues.push(`${path} must not contain more than ${MAX_TEXT_COLOR_RANGES} entries`);
668
+ }
669
+ const output = [];
670
+ let previousEnd = 0;
671
+ value.slice(0, MAX_TEXT_COLOR_RANGES).forEach((candidate, index) => {
672
+ const itemPath = `${path}[${index}]`;
673
+ if (!candidate || typeof candidate !== "object" || Array.isArray(candidate)) {
674
+ issues.push(`${itemPath} must be an object`);
675
+ return;
676
+ }
677
+ const input = candidate;
678
+ const forwarded = forwardUnknownKeys(input, TEXT_COLOR_RANGE_KEYS, itemPath, issues);
679
+ const start = input.start;
680
+ const end = input.end;
681
+ if (!Number.isSafeInteger(start) || start < 0) {
682
+ issues.push(`${itemPath}.start must be a non-negative integer`);
683
+ }
684
+ if (!Number.isSafeInteger(end) || end <= 0) {
685
+ issues.push(`${itemPath}.end must be a positive integer`);
686
+ }
687
+ const color2 = typeof input.color === "string" ? sanitizeCssColor(input.color) : null;
688
+ if (!color2) issues.push(`${itemPath}.color must be a literal CSS color`);
689
+ if (!Number.isSafeInteger(start) || !Number.isSafeInteger(end) || start < 0 || end <= start || end > content.length || !color2) {
690
+ if (Number.isSafeInteger(start) && Number.isSafeInteger(end) && end <= start) issues.push(`${itemPath}.end must be greater than start`);
691
+ if (Number.isSafeInteger(end) && end > content.length) {
692
+ issues.push(`${itemPath}.end must not exceed content length`);
693
+ }
694
+ return;
695
+ }
696
+ if (start < previousEnd) {
697
+ issues.push(`${itemPath} must not overlap or precede the previous range`);
698
+ return;
699
+ }
700
+ if (!content.slice(start, end).trim()) {
701
+ issues.push(`${itemPath} must include visible text`);
702
+ return;
703
+ }
704
+ output.push(carryUnknownKeys({ start, end, color: color2 }, forwarded));
705
+ previousEnd = end;
706
+ });
707
+ return output.length > 0 ? output : void 0;
708
+ };
709
+
710
+ // packages/layerdoc/src/core/typographic-lockup.ts
711
+ var LOCKUP_KEYS = /* @__PURE__ */ new Set(["lines"]);
712
+ var LINE_KEYS = /* @__PURE__ */ new Set([
713
+ "content",
714
+ "relativeBox",
715
+ "fontSizeRatio",
716
+ "letterSpacingEm",
717
+ "lineHeight",
718
+ "fontWeight",
719
+ "fontStyle",
720
+ "googleFontFamily",
721
+ "color",
722
+ "align"
723
+ ]);
724
+ var record = (value, path, issues) => {
725
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
726
+ issues.push(`${path} must be an object`);
727
+ return null;
728
+ }
729
+ return value;
730
+ };
731
+ var finite = (value, path, issues) => {
732
+ if (typeof value !== "number" || !Number.isFinite(value)) {
733
+ issues.push(`${path} must be a finite number`);
734
+ return null;
735
+ }
736
+ return value;
737
+ };
738
+ var bounded = (value, path, issues, predicate, description) => {
739
+ const parsed = finite(value, path, issues);
740
+ if (parsed !== null && !predicate(parsed)) {
741
+ issues.push(`${path} ${description}`);
742
+ return null;
743
+ }
744
+ return parsed;
745
+ };
746
+ var parseRelativeBox = (value, path, issues) => {
747
+ if (!Array.isArray(value) || value.length !== 4) {
748
+ issues.push(`${path} must be a four-number relative box`);
749
+ return null;
750
+ }
751
+ const coordinates = value.map((coordinate, index) => finite(coordinate, `${path}[${index}]`, issues));
752
+ if (coordinates.some((coordinate) => coordinate === null)) return null;
753
+ const [x, y, width, height] = coordinates;
754
+ if (x < 0 || y < 0 || width <= 0 || height <= 0 || x + width > 1 || y + height > 1) {
755
+ issues.push(`${path} must stay within the owning logo's 0..1 box`);
756
+ return null;
757
+ }
758
+ return [x, y, width, height];
759
+ };
760
+ var exactKeys = (value, keys, path, issues) => {
761
+ for (const key of Object.keys(value)) {
762
+ if (!keys.has(key)) issues.push(`${path}.${key} is not permitted`);
763
+ }
764
+ };
765
+ var parseLine = (value, path, issues) => {
766
+ const input = record(value, path, issues);
767
+ if (!input) return null;
768
+ exactKeys(input, LINE_KEYS, path, issues);
769
+ const content = typeof input.content === "string" ? input.content : null;
770
+ if (content === null || !content.trim()) issues.push(`${path}.content must be non-empty text`);
771
+ else if (content.includes("\n") || content.length > 4096) {
772
+ issues.push(`${path}.content must be one visual row of at most 4096 characters`);
773
+ }
774
+ const relativeBox = parseRelativeBox(input.relativeBox, `${path}.relativeBox`, issues);
775
+ const fontSizeRatio = bounded(
776
+ input.fontSizeRatio,
777
+ `${path}.fontSizeRatio`,
778
+ issues,
779
+ (candidate) => candidate > 0 && candidate <= 1,
780
+ "must be greater than 0 and at most 1"
781
+ );
782
+ const letterSpacingEm = bounded(
783
+ input.letterSpacingEm,
784
+ `${path}.letterSpacingEm`,
785
+ issues,
786
+ (candidate) => candidate >= -0.5 && candidate <= 1,
787
+ "must be between -0.5 and 1"
788
+ );
789
+ const lineHeight = bounded(
790
+ input.lineHeight,
791
+ `${path}.lineHeight`,
792
+ issues,
793
+ (candidate) => candidate >= 0.5 && candidate <= 3,
794
+ "must be between 0.5 and 3"
795
+ );
796
+ const fontWeight = bounded(
797
+ input.fontWeight,
798
+ `${path}.fontWeight`,
799
+ issues,
800
+ (candidate) => Number.isInteger(candidate) && candidate >= 100 && candidate <= 900,
801
+ "must be an integer from 100 to 900"
802
+ );
803
+ const fontStyle = input.fontStyle === void 0 || input.fontStyle === null ? void 0 : input.fontStyle === "italic" ? "italic" : null;
804
+ if (fontStyle === null) issues.push(`${path}.fontStyle must be italic when present`);
805
+ const googleFontFamily = typeof input.googleFontFamily === "string" ? input.googleFontFamily.trim() : "";
806
+ if (!isValidGoogleFontFamily(googleFontFamily)) {
807
+ issues.push(`${path}.googleFontFamily must be a safe non-empty font family`);
808
+ }
809
+ const color2 = typeof input.color === "string" && resolveDeclaredCssColor(input.color) !== null ? input.color : null;
810
+ if (color2 === null) issues.push(`${path}.color must be one declared CSS colour`);
811
+ const align = ["left", "center", "right"].includes(String(input.align)) ? input.align : null;
812
+ if (align === null) issues.push(`${path}.align must be left, center, or right`);
813
+ if (content === null || !content.trim() || content.includes("\n") || content.length > 4096 || !relativeBox || fontSizeRatio === null || letterSpacingEm === null || lineHeight === null || fontWeight === null || fontStyle === null || !googleFontFamily || color2 === null || align === null) {
814
+ return null;
815
+ }
816
+ return {
817
+ content,
818
+ relativeBox,
819
+ fontSizeRatio,
820
+ letterSpacingEm,
821
+ lineHeight,
822
+ fontWeight,
823
+ ...fontStyle ? { fontStyle } : {},
824
+ googleFontFamily,
825
+ color: color2,
826
+ align
827
+ };
828
+ };
829
+ var parseTypographicLockup = (value, path, issues) => {
830
+ if (value === void 0) return void 0;
831
+ const input = record(value, path, issues);
832
+ if (!input) return void 0;
833
+ exactKeys(input, LOCKUP_KEYS, path, issues);
834
+ if (!Array.isArray(input.lines) || input.lines.length < 2 || input.lines.length > 8) {
835
+ issues.push(`${path}.lines must contain 2 to 8 rows`);
836
+ return void 0;
837
+ }
838
+ const lines = input.lines.map((line, index) => parseLine(line, `${path}.lines[${index}]`, issues));
839
+ if (lines.some((line) => line === null)) return void 0;
840
+ return { lines };
841
+ };
842
+ var validateTypographicLockupOwner = (args) => {
843
+ const { lockup } = args;
844
+ if (!lockup) return;
845
+ if (String(args.kind).trim().toLowerCase() !== "logo") {
846
+ args.issues.push(`${args.path}.typographicLockup requires kind logo`);
847
+ }
848
+ if (String(args.surface ?? "").trim().toLowerCase() === "raster") {
849
+ args.issues.push(`${args.path}.typographicLockup cannot own raster pixels`);
850
+ }
851
+ const expectedContent = lockup.lines.map((line) => line.content).join("\n");
852
+ if (args.content !== expectedContent) {
853
+ args.issues.push(`${args.path}.content must equal typographicLockup rows joined by newlines`);
854
+ }
855
+ };
856
+
857
+ // packages/layerdoc/src/core/surface-pattern.ts
858
+ var SURFACE_PATTERN_KEYS = /* @__PURE__ */ new Set([
859
+ "kind",
860
+ "stroke",
861
+ "spacingPx",
862
+ "angleDeg",
863
+ "crossAngleDeg",
864
+ "backgroundColor"
865
+ ]);
866
+ var SURFACE_PATTERN_STROKE_KEYS = /* @__PURE__ */ new Set(["color", "widthPx"]);
867
+ var MAX_PATTERN_SPACING_PX = 1e4;
868
+ var MAX_PATTERN_STROKE_WIDTH_PX = 1e4;
869
+ var MAX_PATTERN_ANGLE_DEG = 360;
870
+ var object = (value, path) => {
871
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
872
+ throw new Error(`${path} must be an object`);
873
+ }
874
+ return value;
875
+ };
876
+ var number = (value, path, minimum, maximum) => {
877
+ const parsed = Number(value);
878
+ if (!Number.isFinite(parsed) || parsed < minimum || parsed > maximum) {
879
+ throw new Error(`${path} must be a finite number from ${minimum} to ${maximum}`);
880
+ }
881
+ return parsed;
882
+ };
883
+ var color = (value, path) => {
884
+ const normalized = normalizeCssPropertyValue("color", value);
885
+ if (!normalized) throw new Error(`${path} must be a safe CSS color`);
886
+ return normalized;
887
+ };
888
+ var normalizedKind = (value, path) => {
889
+ const raw = String(value ?? "").trim().toLowerCase().replace(/[\s_-]+/g, "");
890
+ const aliases = {
891
+ hatch: "hatch",
892
+ crosshatch: "crosshatch",
893
+ stripes: "stripes",
894
+ stripe: "stripes",
895
+ dots: "dots",
896
+ dot: "dots"
897
+ };
898
+ const kind = aliases[raw];
899
+ if (!kind) throw new Error(`${path} must be hatch, crosshatch, stripes, or dots`);
900
+ return kind;
901
+ };
902
+ var normalizedAngle = (value, path) => {
903
+ const raw = number(value, path, -MAX_PATTERN_ANGLE_DEG, MAX_PATTERN_ANGLE_DEG);
904
+ const normalized = (raw % MAX_PATTERN_ANGLE_DEG + MAX_PATTERN_ANGLE_DEG) % MAX_PATTERN_ANGLE_DEG;
905
+ return Number(normalized.toFixed(6));
906
+ };
907
+ function parseSurfacePattern(value, path = "surfacePattern") {
908
+ const input = object(value, path);
909
+ for (const key of Object.keys(input)) {
910
+ if (!SURFACE_PATTERN_KEYS.has(key)) throw new Error(`${path}.${key} is not allowed`);
911
+ }
912
+ const kind = normalizedKind(input.kind, `${path}.kind`);
913
+ const strokeInput = object(input.stroke, `${path}.stroke`);
914
+ for (const key of Object.keys(strokeInput)) {
915
+ if (!SURFACE_PATTERN_STROKE_KEYS.has(key)) throw new Error(`${path}.stroke.${key} is not allowed`);
916
+ }
917
+ const stroke = {
918
+ color: color(strokeInput.color, `${path}.stroke.color`),
919
+ widthPx: number(strokeInput.widthPx, `${path}.stroke.widthPx`, 0.125, MAX_PATTERN_STROKE_WIDTH_PX)
920
+ };
921
+ const spacingPx = number(input.spacingPx, `${path}.spacingPx`, 1, MAX_PATTERN_SPACING_PX);
922
+ const angleDeg = normalizedAngle(input.angleDeg, `${path}.angleDeg`);
923
+ const backgroundColor = color(input.backgroundColor, `${path}.backgroundColor`);
924
+ const crossAngleDeg = input.crossAngleDeg === void 0 || input.crossAngleDeg === null ? void 0 : normalizedAngle(input.crossAngleDeg, `${path}.crossAngleDeg`);
925
+ if (kind === "crosshatch") {
926
+ if (crossAngleDeg === void 0) throw new Error(`${path}.crossAngleDeg is required for crosshatch`);
927
+ if (Math.abs((crossAngleDeg - angleDeg + 180) % 180) < 1e-6) {
928
+ throw new Error(`${path}.crossAngleDeg must differ from angleDeg for crosshatch`);
929
+ }
930
+ } else if (crossAngleDeg !== void 0) {
931
+ throw new Error(`${path}.crossAngleDeg is only valid for crosshatch`);
932
+ }
933
+ return {
934
+ kind,
935
+ stroke,
936
+ spacingPx,
937
+ angleDeg,
938
+ ...crossAngleDeg === void 0 ? {} : { crossAngleDeg },
939
+ backgroundColor
940
+ };
941
+ }
942
+
943
+ // packages/layerdoc/src/core/public-layerdoc.ts
944
+ var PUBLIC_LAYERDOC_MAX_CANVAS_SIDE = 1e4;
945
+ var PUBLIC_LAYERDOC_MAX_LAYERS = 2e3;
946
+ var PUBLIC_LAYERDOC_MAX_CONTENT_LENGTH = 2e4;
947
+ var PUBLIC_LAYERDOC_MAX_GROUP_LENGTH = 1024;
948
+ var PUBLIC_LAYERDOC_MAX_OPTIONAL_STRING_LENGTH = 4096;
949
+ var PUBLIC_LAYERDOC_MAX_KIND_LENGTH = 128;
950
+ var UNSUPPORTED_RENDER_CONTROL = /\u0000|[\u0001-\u0008\u000b\u000c\u000e-\u001f\u007f]/;
951
+ var PUBLIC_LAYER_GROUND_INK = ["erased", "carried"];
952
+ var PUBLIC_LAYER_GROUND_REGISTRATION = ["positioned-scene", "featureless-texture"];
953
+ var GROUND_FIELD_KEYS = /* @__PURE__ */ new Set([
954
+ "fill",
955
+ "bloom",
956
+ "aspect",
957
+ "structureLeft",
958
+ "edgeMatchesFill"
959
+ ]);
960
+ var PUBLIC_LAYER_GROUND_FIELD_CELLS = 40;
961
+ var GROUND_FIELD_HEX = /^#[0-9a-f]{6}$/u;
962
+ function parseGroundField(value, path, issues) {
963
+ if (value === void 0) return void 0;
964
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
965
+ issues.push(`${path} must be an object`);
966
+ return void 0;
967
+ }
968
+ const input = value;
969
+ for (const key of Object.keys(input)) {
970
+ if (!GROUND_FIELD_KEYS.has(key)) issues.push(`${path}.${key} is not a ground-field key`);
971
+ }
972
+ const fill = typeof input.fill === "string" && GROUND_FIELD_HEX.test(input.fill) ? input.fill : null;
973
+ if (fill === null) issues.push(`${path}.fill must be a #rrggbb color`);
974
+ const bloom = Array.isArray(input.bloom) && input.bloom.length === PUBLIC_LAYER_GROUND_FIELD_CELLS && input.bloom.every((cell) => typeof cell === "string" && GROUND_FIELD_HEX.test(cell)) ? input.bloom.slice() : null;
975
+ if (bloom === null) {
976
+ issues.push(`${path}.bloom must be ${PUBLIC_LAYER_GROUND_FIELD_CELLS} #rrggbb colors`);
977
+ }
978
+ const aspect = typeof input.aspect === "number" && Number.isFinite(input.aspect) && input.aspect > 0 ? input.aspect : null;
979
+ if (aspect === null) issues.push(`${path}.aspect must be a positive number`);
980
+ const structureLeft = typeof input.structureLeft === "number" && Number.isFinite(input.structureLeft) && input.structureLeft >= 0 && input.structureLeft <= 1 ? input.structureLeft : null;
981
+ if (structureLeft === null) issues.push(`${path}.structureLeft must be between 0 and 1`);
982
+ const edgeMatchesFill = input.edgeMatchesFill === void 0 ? void 0 : typeof input.edgeMatchesFill === "boolean" ? input.edgeMatchesFill : null;
983
+ if (edgeMatchesFill === null) issues.push(`${path}.edgeMatchesFill must be a boolean`);
984
+ if (fill === null || bloom === null || aspect === null || structureLeft === null || edgeMatchesFill === null) {
985
+ return void 0;
986
+ }
987
+ return {
988
+ fill,
989
+ bloom,
990
+ aspect,
991
+ structureLeft,
992
+ ...edgeMatchesFill === void 0 ? {} : { edgeMatchesFill }
993
+ };
994
+ }
995
+ var STRING_FIELDS = [
996
+ "surface",
997
+ "fontStyle",
998
+ "googleFontFamily",
999
+ "color",
1000
+ "markerColor",
1001
+ "align",
1002
+ "borderColor",
1003
+ "style"
1004
+ ];
1005
+ var NUMBER_FIELDS = [
1006
+ "fontSizePx",
1007
+ "fittedFontSizePx",
1008
+ "textScaleX",
1009
+ "textScaleY",
1010
+ "fontWeight",
1011
+ "textRotationDeg",
1012
+ "textSlantDeg",
1013
+ "borderRadiusPx",
1014
+ "borderWidthPx",
1015
+ "borderOpacity",
1016
+ "blurPx"
1017
+ ];
1018
+ var MEASURED_INK_KEYS = /* @__PURE__ */ new Set([
1019
+ "box",
1020
+ "rows",
1021
+ "basis",
1022
+ "marginPx",
1023
+ "refusal"
1024
+ ]);
1025
+ var DOCUMENT_RESERVED_KEYS = /* @__PURE__ */ new Set([
1026
+ "pinnedAssetDeclarations"
1027
+ ]);
1028
+ var PUBLIC_LAYER_KEYS = /* @__PURE__ */ new Set([
1029
+ "kind",
1030
+ "content",
1031
+ "group",
1032
+ "box",
1033
+ "typographicLockup",
1034
+ "labelBox",
1035
+ "controlTextAnchor",
1036
+ "markerBox",
1037
+ "checkableKind",
1038
+ "checked",
1039
+ "extractionIndex",
1040
+ "canvasBackdrop",
1041
+ "iconSvg",
1042
+ "repeatedRules",
1043
+ "measured",
1044
+ "resolvedStyle",
1045
+ "surfacePattern",
1046
+ "textColorRanges",
1047
+ "groundInk",
1048
+ "groundRegistration",
1049
+ "groundField",
1050
+ "clipPathFrame",
1051
+ ...STRING_FIELDS,
1052
+ ...NUMBER_FIELDS
1053
+ ]);
1054
+ var PUBLIC_LAYER_RESERVED_KEYS = /* @__PURE__ */ new Set([
1055
+ "pinnedAssetSha256",
1056
+ "assetFit",
1057
+ "assetSelectionProtected"
1058
+ ]);
1059
+ var SHARED_LEFT_RAIL_RELATION_KEYS = /* @__PURE__ */ new Set([
1060
+ "relationId",
1061
+ "relationKind",
1062
+ "memberExtractionIndices",
1063
+ "role",
1064
+ "container",
1065
+ "target",
1066
+ "writingDirection",
1067
+ "sourceProvenance",
1068
+ "measurementRevision",
1069
+ "evidenceId"
1070
+ ]);
1071
+ var SHARED_LEFT_RAIL_TARGET_KEYS = /* @__PURE__ */ new Set([
1072
+ "coordinateSpace",
1073
+ "x"
1074
+ ]);
1075
+ var exactKeys2 = (value, keys) => Object.keys(value).length === keys.size && Object.keys(value).every((key) => keys.has(key));
1076
+ var relationString = (value, max) => typeof value === "string" && value.length > 0 && value.length <= max && !UNSUPPORTED_RENDER_CONTROL.test(value);
1077
+ function parseSharedLeftRailRelations(value) {
1078
+ if (!Array.isArray(value)) return void 0;
1079
+ const relations = value.flatMap((candidate) => {
1080
+ if (!candidate || typeof candidate !== "object" || Array.isArray(candidate)) return [];
1081
+ const relation = candidate;
1082
+ if (!exactKeys2(relation, SHARED_LEFT_RAIL_RELATION_KEYS)) return [];
1083
+ if (!relation.target || typeof relation.target !== "object" || Array.isArray(relation.target)) {
1084
+ return [];
1085
+ }
1086
+ const target = relation.target;
1087
+ if (!exactKeys2(target, SHARED_LEFT_RAIL_TARGET_KEYS)) return [];
1088
+ if (!relationString(relation.relationId, PUBLIC_LAYERDOC_MAX_OPTIONAL_STRING_LENGTH) || relation.relationKind !== "shared-left-rail" || !Array.isArray(relation.memberExtractionIndices) || relation.memberExtractionIndices.length < 3 || relation.memberExtractionIndices.length > PUBLIC_LAYERDOC_MAX_LAYERS || !relation.memberExtractionIndices.every((index) => Number.isSafeInteger(index) && index >= 0) || new Set(relation.memberExtractionIndices).size !== relation.memberExtractionIndices.length || !relationString(relation.role, PUBLIC_LAYERDOC_MAX_OPTIONAL_STRING_LENGTH) || !relationString(relation.container, PUBLIC_LAYERDOC_MAX_GROUP_LENGTH) || target.coordinateSpace !== "prepared-source" && target.coordinateSpace !== "source" || typeof target.x !== "number" || !Number.isFinite(target.x) || target.x < 0 || relation.writingDirection !== "ltr" || relation.sourceProvenance !== "declared-extraction-boxes" || !relationString(relation.measurementRevision, PUBLIC_LAYERDOC_MAX_OPTIONAL_STRING_LENGTH) || !relationString(relation.evidenceId, PUBLIC_LAYERDOC_MAX_OPTIONAL_STRING_LENGTH)) return [];
1089
+ return [{
1090
+ relationId: relation.relationId,
1091
+ relationKind: "shared-left-rail",
1092
+ memberExtractionIndices: [...relation.memberExtractionIndices],
1093
+ role: relation.role,
1094
+ container: relation.container,
1095
+ target: {
1096
+ coordinateSpace: target.coordinateSpace,
1097
+ x: target.x
1098
+ },
1099
+ writingDirection: "ltr",
1100
+ sourceProvenance: "declared-extraction-boxes",
1101
+ measurementRevision: relation.measurementRevision,
1102
+ evidenceId: relation.evidenceId
1103
+ }];
1104
+ });
1105
+ return relations.length > 0 ? relations : void 0;
1106
+ }
1107
+ function record2(value, path, issues) {
1108
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
1109
+ issues.push(`${path} must be an object`);
1110
+ return null;
1111
+ }
1112
+ return value;
1113
+ }
1114
+ function finiteNumber(value, path, issues) {
1115
+ if (typeof value !== "number" || !Number.isFinite(value)) {
1116
+ issues.push(`${path} must be a finite number`);
1117
+ return null;
1118
+ }
1119
+ return value;
1120
+ }
1121
+ function parseQuad(value, path, issues) {
1122
+ if (!Array.isArray(value) || value.length !== 4) {
1123
+ issues.push(`${path} must contain exactly four numbers`);
1124
+ return null;
1125
+ }
1126
+ const numbers = value.map((part, index) => finiteNumber(part, `${path}[${index}]`, issues));
1127
+ if (numbers.some((part) => part === null)) return null;
1128
+ return numbers;
1129
+ }
1130
+ function parseMeasuredTextInk(value, path, issues) {
1131
+ const input = record2(value, path, issues);
1132
+ if (!input) return void 0;
1133
+ const forwarded = forwardUnknownKeys(
1134
+ input,
1135
+ MEASURED_INK_KEYS,
1136
+ path,
1137
+ issues
1138
+ );
1139
+ const rows = finiteNumber(input.rows, `${path}.rows`, issues);
1140
+ if (rows !== null && (!Number.isSafeInteger(rows) || rows < 0)) {
1141
+ issues.push(`${path}.rows must be a non-negative safe integer`);
1142
+ }
1143
+ if (!TEXT_INK_BASES.includes(input.basis)) {
1144
+ issues.push(`${path}.basis must be one of ${TEXT_INK_BASES.join(", ")}`);
1145
+ }
1146
+ const marginPx = parseQuad(input.marginPx, `${path}.marginPx`, issues);
1147
+ const box = input.box === void 0 ? void 0 : parseQuad(input.box, `${path}.box`, issues);
1148
+ if (box && (box[0] < 0 || box[1] < 0 || box[2] < 0 || box[3] < 0)) {
1149
+ issues.push(`${path}.box must have a non-negative origin and extent`);
1150
+ return void 0;
1151
+ }
1152
+ if (input.refusal !== void 0 && !TEXT_INK_REFUSALS.includes(input.refusal)) {
1153
+ issues.push(`${path}.refusal must be one of ${TEXT_INK_REFUSALS.join(", ")}`);
1154
+ }
1155
+ if (rows === null || marginPx === null || input.box !== void 0 && !box) return void 0;
1156
+ return carryUnknownKeys({
1157
+ ...box ? { box } : {},
1158
+ rows,
1159
+ basis: input.basis,
1160
+ marginPx,
1161
+ ...input.refusal === void 0 ? {} : { refusal: input.refusal }
1162
+ }, forwarded);
1163
+ }
1164
+
1165
+ // packages/layerdoc/src/core/public-layerdoc-v2.ts
1166
+ var PUBLIC_LAYERDOC_V2_VERSION = "2";
1167
+ var PUBLIC_ARTIFACT_PIXELS_V2 = ["source", "matted", "cleaned"];
1168
+ var PUBLIC_ARTIFACT_LINEAGE_V2 = ["prepared-source", "provider-upscale", "clean-output"];
1169
+ var PUBLIC_UPSCALE_PERIMETER_INTEGRITIES_V2 = ["guarded", "edge-exposed"];
1170
+ var MEASURED_MATTED_PUBLICATIONS = 73;
1171
+ var PUBLISH_MATTED_PROVENANCE = MEASURED_MATTED_PUBLICATIONS > 0;
1172
+
1173
+ // packages/layerdoc/src/core/public-layerdoc-v2-input-values.ts
1174
+ var SLOT_KINDS = {
1175
+ plate: "plate",
1176
+ plate2x: "plate2x",
1177
+ region2x: "region2x",
1178
+ cutout: "cutout",
1179
+ crop: "pixels"
1180
+ };
1181
+ var carriesPixelFields = (slotKind) => slotKind === "pixels" || slotKind === "region2x" || slotKind === "cutout";
1182
+ var ARTIFACT_ID = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;
1183
+ var IMAGE_MEDIA_TYPES = /* @__PURE__ */ new Set(["image/png", "image/jpeg", "image/webp", "image/svg+xml"]);
1184
+ var record3 = (value, path, issues) => {
1185
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
1186
+ issues.push(`${path} must be an object`);
1187
+ return null;
1188
+ }
1189
+ return value;
1190
+ };
1191
+ var ARTIFACT_REF_BASE_KEYS = [
1192
+ "artifactId",
1193
+ "url",
1194
+ "expiresAt",
1195
+ "mediaType",
1196
+ "width",
1197
+ "height",
1198
+ "scale"
1199
+ ];
1200
+ var ARTIFACT_REF_SLOT_KEYS = Object.freeze({
1201
+ plain: ARTIFACT_REF_BASE_KEYS,
1202
+ plate: [...ARTIFACT_REF_BASE_KEYS, "mode"],
1203
+ plate2x: [...ARTIFACT_REF_BASE_KEYS, "mode"],
1204
+ pixels: [...ARTIFACT_REF_BASE_KEYS, "pixels", "lineage", "carriesSourceContent"],
1205
+ region2x: [
1206
+ ...ARTIFACT_REF_BASE_KEYS,
1207
+ "pixels",
1208
+ "lineage",
1209
+ "carriesSourceContent",
1210
+ "upscalePerimeterIntegrity"
1211
+ ],
1212
+ cutout: [
1213
+ ...ARTIFACT_REF_BASE_KEYS,
1214
+ "pixels",
1215
+ "lineage",
1216
+ "carriesSourceContent",
1217
+ "carriesLayerContent"
1218
+ ]
1219
+ });
1220
+ var ARTIFACT_REF_RESERVED_KEYS = new Set(
1221
+ Object.values(ARTIFACT_REF_SLOT_KEYS).flat().filter((key) => !ARTIFACT_REF_BASE_KEYS.includes(key))
1222
+ );
1223
+ var ARTIFACT_REF_KEYS = /* @__PURE__ */ new Set([
1224
+ ...ARTIFACT_REF_BASE_KEYS,
1225
+ ...ARTIFACT_REF_RESERVED_KEYS
1226
+ ]);
1227
+ var ARTIFACT_SLOT_KEYS = new Set(Object.keys(SLOT_KINDS));
1228
+ var finiteNumber2 = (value, path, issues) => {
1229
+ if (typeof value !== "number" || !Number.isFinite(value)) {
1230
+ issues.push(`${path} must be a finite number`);
1231
+ return null;
1232
+ }
1233
+ return value;
1234
+ };
1235
+ var boundedString = (value, path, issues, options = {}) => {
1236
+ if (typeof value !== "string") {
1237
+ issues.push(`${path} must be a string`);
1238
+ return null;
1239
+ }
1240
+ if (/\u0000|[\u0001-\u0008\u000b\u000c\u000e-\u001f\u007f]/.test(value)) {
1241
+ issues.push(`${path} contains unsupported control characters`);
1242
+ }
1243
+ if (options.nonEmpty && value.trim().length === 0) issues.push(`${path} must not be empty`);
1244
+ if (options.max !== void 0 && value.length > options.max) {
1245
+ issues.push(`${path} must not exceed ${options.max} characters`);
1246
+ }
1247
+ return value;
1248
+ };
1249
+ var parseBox = (value, path, issues, allowNegativeOrigin = false) => {
1250
+ if (!Array.isArray(value) || value.length !== 4) {
1251
+ issues.push(`${path} must contain exactly four numbers`);
1252
+ return null;
1253
+ }
1254
+ const values = value.map((part, index) => finiteNumber2(part, `${path}[${index}]`, issues));
1255
+ if (values.some((part) => part === null)) return null;
1256
+ const box = values;
1257
+ if (!allowNegativeOrigin && (box[0] < 0 || box[1] < 0)) {
1258
+ issues.push(`${path} x and y must be non-negative`);
1259
+ }
1260
+ if (box[2] <= 0 || box[3] <= 0) issues.push(`${path} width and height must be positive`);
1261
+ return box;
1262
+ };
1263
+ var unionBoxes = (boxes) => {
1264
+ if (boxes.length === 0) return null;
1265
+ const left = Math.min(...boxes.map((box) => box[0]));
1266
+ const top = Math.min(...boxes.map((box) => box[1]));
1267
+ const right = Math.max(...boxes.map((box) => box[0] + box[2]));
1268
+ const bottom = Math.max(...boxes.map((box) => box[1] + box[3]));
1269
+ return [left, top, right - left, bottom - top];
1270
+ };
1271
+ var parseArtifactRef = (value, path, issues, requireUrl, slotKind) => {
1272
+ const input = record3(value, path, issues);
1273
+ if (!input) return null;
1274
+ const plate = slotKind === "plate";
1275
+ const forwarded = forwardUnknownKeys(
1276
+ input,
1277
+ new Set(ARTIFACT_REF_SLOT_KEYS[slotKind]),
1278
+ path,
1279
+ issues,
1280
+ { reserved: ARTIFACT_REF_RESERVED_KEYS }
1281
+ );
1282
+ const artifactId = boundedString(input.artifactId, `${path}.artifactId`, issues, { nonEmpty: true, max: 128 });
1283
+ if (artifactId && !ARTIFACT_ID.test(artifactId)) issues.push(`${path}.artifactId has an invalid format`);
1284
+ const url = input.url === void 0 ? void 0 : boundedString(input.url, `${path}.url`, issues, { nonEmpty: true, max: 2048 });
1285
+ const expiresAt = input.expiresAt === void 0 ? void 0 : boundedString(input.expiresAt, `${path}.expiresAt`, issues, { nonEmpty: true, max: 64 });
1286
+ if (requireUrl && (!url || !expiresAt)) issues.push(`${path} must include url and expiresAt`);
1287
+ if (url && !expiresAt || !url && expiresAt) issues.push(`${path}.url and expiresAt must be supplied together`);
1288
+ if (url) {
1289
+ try {
1290
+ const parsed = new URL(url);
1291
+ if (parsed.protocol !== "https:" && parsed.protocol !== "http:") issues.push(`${path}.url must use http or https`);
1292
+ } catch {
1293
+ issues.push(`${path}.url must be an absolute URL`);
1294
+ }
1295
+ }
1296
+ if (expiresAt && !Number.isFinite(Date.parse(expiresAt))) issues.push(`${path}.expiresAt must be an ISO timestamp`);
1297
+ const mediaType = input.mediaType === void 0 ? void 0 : boundedString(input.mediaType, `${path}.mediaType`, issues, { nonEmpty: true, max: 64 });
1298
+ if (mediaType && !IMAGE_MEDIA_TYPES.has(mediaType.toLowerCase())) {
1299
+ issues.push(`${path}.mediaType must be image/png, image/jpeg, image/webp, or image/svg+xml`);
1300
+ }
1301
+ const dimensions = { width: void 0, height: void 0 };
1302
+ for (const field of ["width", "height"]) {
1303
+ if (input[field] === void 0) continue;
1304
+ const parsed = finiteNumber2(input[field], `${path}.${field}`, issues);
1305
+ if (parsed !== null) {
1306
+ if (!Number.isInteger(parsed) || parsed <= 0) issues.push(`${path}.${field} must be a positive integer`);
1307
+ else dimensions[field] = parsed;
1308
+ }
1309
+ }
1310
+ let scale;
1311
+ if (input.scale !== void 0) {
1312
+ const parsed = finiteNumber2(input.scale, `${path}.scale`, issues);
1313
+ if (parsed !== null) {
1314
+ if (parsed <= 0) issues.push(`${path}.scale must be positive`);
1315
+ else scale = parsed;
1316
+ }
1317
+ }
1318
+ let mode;
1319
+ if (plate || slotKind === "plate2x" && input.mode !== void 0) {
1320
+ if (input.mode !== "plate" && input.mode !== "overlay") issues.push(`${path}.mode must be plate or overlay`);
1321
+ else mode = input.mode;
1322
+ }
1323
+ let pixels;
1324
+ if (carriesPixelFields(slotKind) && input.pixels !== void 0) {
1325
+ if (!PUBLIC_ARTIFACT_PIXELS_V2.includes(input.pixels)) {
1326
+ issues.push(`${path}.pixels must be ${PUBLIC_ARTIFACT_PIXELS_V2.join(", ")}`);
1327
+ } else {
1328
+ pixels = input.pixels;
1329
+ }
1330
+ }
1331
+ let lineage;
1332
+ if (carriesPixelFields(slotKind) && input.lineage !== void 0) {
1333
+ if (!PUBLIC_ARTIFACT_LINEAGE_V2.includes(input.lineage)) {
1334
+ issues.push(`${path}.lineage must be ${PUBLIC_ARTIFACT_LINEAGE_V2.join(", ")}`);
1335
+ } else {
1336
+ lineage = input.lineage;
1337
+ }
1338
+ }
1339
+ let carriesSourceContent;
1340
+ if (carriesPixelFields(slotKind) && input.carriesSourceContent !== void 0) {
1341
+ if (typeof input.carriesSourceContent !== "boolean") {
1342
+ issues.push(`${path}.carriesSourceContent must be a boolean`);
1343
+ } else {
1344
+ carriesSourceContent = input.carriesSourceContent;
1345
+ }
1346
+ }
1347
+ let upscalePerimeterIntegrity;
1348
+ if (slotKind === "region2x" && input.upscalePerimeterIntegrity !== void 0) {
1349
+ if (!PUBLIC_UPSCALE_PERIMETER_INTEGRITIES_V2.includes(
1350
+ input.upscalePerimeterIntegrity
1351
+ )) {
1352
+ issues.push(
1353
+ `${path}.upscalePerimeterIntegrity must be ${PUBLIC_UPSCALE_PERIMETER_INTEGRITIES_V2.join(" or ")}`
1354
+ );
1355
+ } else {
1356
+ upscalePerimeterIntegrity = input.upscalePerimeterIntegrity;
1357
+ }
1358
+ }
1359
+ let carriesLayerContent;
1360
+ if (slotKind === "cutout" && input.carriesLayerContent !== void 0) {
1361
+ if (typeof input.carriesLayerContent !== "boolean") {
1362
+ issues.push(`${path}.carriesLayerContent must be a boolean`);
1363
+ } else {
1364
+ carriesLayerContent = input.carriesLayerContent;
1365
+ }
1366
+ }
1367
+ if (!artifactId) return null;
1368
+ const output = {
1369
+ artifactId,
1370
+ ...url ? { url } : {},
1371
+ ...expiresAt ? { expiresAt } : {},
1372
+ ...mediaType ? { mediaType: mediaType.toLowerCase() } : {},
1373
+ ...dimensions.width ? { width: dimensions.width } : {},
1374
+ ...dimensions.height ? { height: dimensions.height } : {},
1375
+ ...scale ? { scale } : {}
1376
+ };
1377
+ return carryUnknownKeys({
1378
+ ...output,
1379
+ ...mode ? { mode } : {},
1380
+ ...pixels ? { pixels } : {},
1381
+ ...lineage ? { lineage } : {},
1382
+ ...carriesSourceContent !== void 0 ? { carriesSourceContent } : {},
1383
+ ...upscalePerimeterIntegrity ? { upscalePerimeterIntegrity } : {},
1384
+ ...carriesLayerContent !== void 0 ? { carriesLayerContent } : {}
1385
+ }, forwarded);
1386
+ };
1387
+ var parseArtifacts = (value, path, issues, requireUrl) => {
1388
+ if (value === void 0) return void 0;
1389
+ const input = record3(value, path, issues);
1390
+ if (!input) return void 0;
1391
+ refuseUnknownKeys(input, ARTIFACT_SLOT_KEYS, path, issues);
1392
+ const output = {};
1393
+ for (const slot of ["plate", "plate2x", "region2x", "cutout", "crop"]) {
1394
+ if (input[slot] === void 0) continue;
1395
+ const parsed = parseArtifactRef(input[slot], `${path}.${slot}`, issues, requireUrl, SLOT_KINDS[slot]);
1396
+ if (parsed) output[slot] = parsed;
1397
+ }
1398
+ if (output.plate2x && !output.plate) {
1399
+ issues.push(`${path}.plate2x requires plate so its cleanup mode is defined`);
1400
+ }
1401
+ return Object.keys(output).length ? output : void 0;
1402
+ };
1403
+
1404
+ // packages/layerdoc/src/core/public-layerdoc-v2-input.ts
1405
+ var MAX_GROUP_DEPTH = 512;
1406
+ var MAX_TOTAL_NODES = PUBLIC_LAYERDOC_MAX_LAYERS * (MAX_GROUP_DEPTH + 1);
1407
+ var PublicLayerDocV2ValidationError = class extends Error {
1408
+ issues;
1409
+ constructor(issues) {
1410
+ super(`Invalid PublicLayerDocV2: ${issues.join("; ")}`);
1411
+ this.name = "PublicLayerDocV2ValidationError";
1412
+ this.issues = issues;
1413
+ }
1414
+ };
1415
+ var LEAF_KEYS = /* @__PURE__ */ new Set([
1416
+ "kind",
1417
+ "content",
1418
+ "z",
1419
+ "extractionIndex",
1420
+ "box",
1421
+ "typographicLockup",
1422
+ "labelBox",
1423
+ "controlTextAnchor",
1424
+ "markerBox",
1425
+ "checkableKind",
1426
+ "checked",
1427
+ "repeatedRules",
1428
+ "canvasBackdrop",
1429
+ "surface",
1430
+ "surfacePattern",
1431
+ "fontSizePx",
1432
+ "fittedFontSizePx",
1433
+ "textScaleX",
1434
+ "textScaleY",
1435
+ "fontWeight",
1436
+ "fontStyle",
1437
+ "textColorRanges",
1438
+ "googleFontFamily",
1439
+ "iconSvg",
1440
+ "color",
1441
+ "markerColor",
1442
+ "align",
1443
+ "textRotationDeg",
1444
+ "textSlantDeg",
1445
+ "styleHint",
1446
+ "style",
1447
+ "measured",
1448
+ "artifacts",
1449
+ "hidden",
1450
+ "assetCrop",
1451
+ "sourceFallback",
1452
+ "groundInk",
1453
+ "groundRegistration",
1454
+ "groundField",
1455
+ "clipPathFrame"
1456
+ ]);
1457
+ var LEAF_RESERVED_KEYS = /* @__PURE__ */ new Set([
1458
+ "borderRadiusPx",
1459
+ "borderWidthPx",
1460
+ "blurPx",
1461
+ ...PUBLIC_LAYER_RESERVED_KEYS
1462
+ ]);
1463
+ var MEASURED_KEYS = /* @__PURE__ */ new Set(["ink"]);
1464
+ var GROUP_KEYS = /* @__PURE__ */ new Set([
1465
+ "kind",
1466
+ "name",
1467
+ "box",
1468
+ "children",
1469
+ "hidden"
1470
+ ]);
1471
+ var DOCUMENT_KEYS = /* @__PURE__ */ new Set([
1472
+ "version",
1473
+ "canvas",
1474
+ "source",
1475
+ "extractionContract",
1476
+ "layoutRelations",
1477
+ "layers"
1478
+ ]);
1479
+ var CANVAS_KEYS = /* @__PURE__ */ new Set(["width", "height"]);
1480
+ var LEAF_STRING_FIELDS = [
1481
+ "surface",
1482
+ "fontStyle",
1483
+ "googleFontFamily",
1484
+ "color",
1485
+ "markerColor",
1486
+ "align"
1487
+ ];
1488
+ var LEAF_NUMBER_FIELDS = [
1489
+ "fontSizePx",
1490
+ "fittedFontSizePx",
1491
+ "textScaleX",
1492
+ "textScaleY",
1493
+ "fontWeight",
1494
+ "textRotationDeg",
1495
+ "textSlantDeg"
1496
+ ];
1497
+ var parseLeaf = (input, path, issues, requireUrl, allowCanvasOverflow) => {
1498
+ const forwarded = forwardUnknownKeys(input, LEAF_KEYS, path, issues, {
1499
+ reserved: LEAF_RESERVED_KEYS
1500
+ });
1501
+ const kind = boundedString(input.kind, `${path}.kind`, issues, {
1502
+ nonEmpty: true,
1503
+ max: PUBLIC_LAYERDOC_MAX_KIND_LENGTH
1504
+ });
1505
+ const content = boundedString(input.content, `${path}.content`, issues, {
1506
+ max: PUBLIC_LAYERDOC_MAX_CONTENT_LENGTH
1507
+ });
1508
+ const z = finiteNumber2(input.z, `${path}.z`, issues);
1509
+ if (z !== null && (!Number.isInteger(z) || z < 0)) issues.push(`${path}.z must be a non-negative integer`);
1510
+ const box = parseBox(input.box, `${path}.box`, issues, allowCanvasOverflow);
1511
+ if (!kind || content === null || z === null || !box) return null;
1512
+ const output = { kind, content, z, box };
1513
+ const typographicLockup = parseTypographicLockup(
1514
+ input.typographicLockup,
1515
+ `${path}.typographicLockup`,
1516
+ issues
1517
+ );
1518
+ if (typographicLockup) output.typographicLockup = typographicLockup;
1519
+ if (input.labelBox !== void 0) {
1520
+ const labelBox = parseBox(input.labelBox, `${path}.labelBox`, issues, allowCanvasOverflow);
1521
+ if (labelBox) output.labelBox = labelBox;
1522
+ }
1523
+ const controlTextAnchor = parseControlTextAnchor(
1524
+ input.controlTextAnchor,
1525
+ `${path}.controlTextAnchor`,
1526
+ issues
1527
+ );
1528
+ if (controlTextAnchor) output.controlTextAnchor = controlTextAnchor;
1529
+ if (input.markerBox !== void 0) {
1530
+ const markerBox = parseBox(input.markerBox, `${path}.markerBox`, issues, allowCanvasOverflow);
1531
+ if (markerBox) output.markerBox = markerBox;
1532
+ }
1533
+ if (input.checkableKind !== void 0) {
1534
+ if (!["checkbox", "radio", "toggle"].includes(String(input.checkableKind))) {
1535
+ issues.push(`${path}.checkableKind must be checkbox, radio, or toggle`);
1536
+ } else {
1537
+ output.checkableKind = input.checkableKind;
1538
+ }
1539
+ }
1540
+ if (input.checked !== void 0) {
1541
+ if (typeof input.checked !== "boolean") issues.push(`${path}.checked must be a boolean`);
1542
+ else output.checked = input.checked;
1543
+ }
1544
+ const repeatedRules = parseRepeatedRules(input.repeatedRules, `${path}.repeatedRules`, issues);
1545
+ if (repeatedRules) output.repeatedRules = repeatedRules;
1546
+ if (input.extractionIndex !== void 0) {
1547
+ const extractionIndex = finiteNumber2(
1548
+ input.extractionIndex,
1549
+ `${path}.extractionIndex`,
1550
+ issues
1551
+ );
1552
+ if (extractionIndex !== null && (!Number.isSafeInteger(extractionIndex) || extractionIndex < 0)) {
1553
+ issues.push(`${path}.extractionIndex must be a non-negative safe integer`);
1554
+ } else if (extractionIndex !== null) {
1555
+ output.extractionIndex = extractionIndex;
1556
+ }
1557
+ }
1558
+ if (input.canvasBackdrop !== void 0) {
1559
+ if (input.canvasBackdrop !== true) issues.push(`${path}.canvasBackdrop must be true`);
1560
+ else output.canvasBackdrop = true;
1561
+ }
1562
+ if (input.assetCrop !== void 0) {
1563
+ const crop = parseBox(input.assetCrop, `${path}.assetCrop`, issues);
1564
+ if (crop) {
1565
+ if (crop[0] + crop[2] > 1.001 || crop[1] + crop[3] > 1.001) {
1566
+ issues.push(`${path}.assetCrop must stay within normalized source bounds`);
1567
+ } else output.assetCrop = crop;
1568
+ }
1569
+ }
1570
+ if (input.hidden !== void 0) {
1571
+ if (typeof input.hidden !== "boolean") issues.push(`${path}.hidden must be a boolean`);
1572
+ else if (input.hidden) output.hidden = true;
1573
+ }
1574
+ if (input.sourceFallback !== void 0) {
1575
+ if (input.sourceFallback !== "disabled") issues.push(`${path}.sourceFallback must be disabled`);
1576
+ else output.sourceFallback = "disabled";
1577
+ }
1578
+ if (input.groundInk !== void 0) {
1579
+ if (!PUBLIC_LAYER_GROUND_INK.includes(input.groundInk)) {
1580
+ issues.push(`${path}.groundInk must be ${PUBLIC_LAYER_GROUND_INK.join(" or ")}`);
1581
+ } else output.groundInk = input.groundInk;
1582
+ }
1583
+ if (input.surfacePattern !== void 0) {
1584
+ try {
1585
+ output.surfacePattern = parseSurfacePattern(input.surfacePattern, `${path}.surfacePattern`);
1586
+ } catch (error) {
1587
+ issues.push(error instanceof Error ? error.message : `${path}.surfacePattern is invalid`);
1588
+ }
1589
+ }
1590
+ if (input.clipPathFrame !== void 0) {
1591
+ if (input.clipPathFrame !== PUBLIC_CLIP_PATH_FRAME) {
1592
+ issues.push(`${path}.clipPathFrame must be ${PUBLIC_CLIP_PATH_FRAME}`);
1593
+ } else {
1594
+ output.clipPathFrame = PUBLIC_CLIP_PATH_FRAME;
1595
+ }
1596
+ }
1597
+ if (input.groundRegistration !== void 0) {
1598
+ if (!PUBLIC_LAYER_GROUND_REGISTRATION.includes(
1599
+ input.groundRegistration
1600
+ )) {
1601
+ issues.push(`${path}.groundRegistration must be ${PUBLIC_LAYER_GROUND_REGISTRATION.join(" or ")}`);
1602
+ } else output.groundRegistration = input.groundRegistration;
1603
+ }
1604
+ const groundField = parseGroundField(input.groundField, `${path}.groundField`, issues);
1605
+ if (groundField) output.groundField = groundField;
1606
+ if (input.iconSvg !== void 0) {
1607
+ try {
1608
+ output.iconSvg = parseIconSvg(input.iconSvg, `${path}.iconSvg`);
1609
+ } catch (error) {
1610
+ issues.push(error instanceof Error ? error.message : `${path}.iconSvg is invalid`);
1611
+ }
1612
+ }
1613
+ for (const field of LEAF_STRING_FIELDS) {
1614
+ if (input[field] === void 0) continue;
1615
+ const parsed = boundedString(input[field], `${path}.${field}`, issues, {
1616
+ max: PUBLIC_LAYERDOC_MAX_OPTIONAL_STRING_LENGTH
1617
+ });
1618
+ if (parsed !== null) output[field] = parsed;
1619
+ }
1620
+ validateTypographicLockupOwner({
1621
+ kind: output.kind,
1622
+ content: output.content,
1623
+ surface: output.surface,
1624
+ lockup: output.typographicLockup,
1625
+ path,
1626
+ issues
1627
+ });
1628
+ if (input.styleHint !== void 0) {
1629
+ const parsed = boundedString(input.styleHint, `${path}.styleHint`, issues, {
1630
+ max: PUBLIC_LAYERDOC_MAX_OPTIONAL_STRING_LENGTH
1631
+ });
1632
+ if (parsed !== null) {
1633
+ if (!isSafeStyleDescription(parsed)) {
1634
+ issues.push(`${path}.styleHint must be descriptive text without CSS or HTML boundaries`);
1635
+ } else {
1636
+ output.styleHint = parsed;
1637
+ }
1638
+ }
1639
+ }
1640
+ for (const field of LEAF_NUMBER_FIELDS) {
1641
+ if (input[field] === void 0) continue;
1642
+ const parsed = finiteNumber2(input[field], `${path}.${field}`, issues);
1643
+ if (parsed !== null) output[field] = parsed;
1644
+ }
1645
+ if (output.fittedFontSizePx !== void 0) {
1646
+ if (output.fittedFontSizePx <= 0) issues.push(`${path}.fittedFontSizePx must be positive`);
1647
+ if (output.fontSizePx === void 0) issues.push(`${path}.fittedFontSizePx requires fontSizePx`);
1648
+ else if (output.fittedFontSizePx > output.fontSizePx) {
1649
+ issues.push(`${path}.fittedFontSizePx must not exceed fontSizePx`);
1650
+ }
1651
+ }
1652
+ for (const field of ["textScaleX", "textScaleY"]) {
1653
+ const value = output[field];
1654
+ if (value !== void 0 && !isValidTextAxisScale(value)) {
1655
+ issues.push(
1656
+ `${path}.${field} must have magnitude from ${MIN_TEXT_AXIS_SCALE} to ${MAX_TEXT_AXIS_SCALE}`
1657
+ );
1658
+ }
1659
+ }
1660
+ const textColorRanges = parseTextColorRanges(
1661
+ input.textColorRanges,
1662
+ content,
1663
+ `${path}.textColorRanges`,
1664
+ issues
1665
+ );
1666
+ if (textColorRanges) output.textColorRanges = textColorRanges;
1667
+ if (input.style !== void 0) {
1668
+ try {
1669
+ output.style = parseSurfaceCss(input.style);
1670
+ } catch (error) {
1671
+ issues.push(`${path}.${error instanceof Error ? error.message : "style is invalid"}`);
1672
+ }
1673
+ }
1674
+ if (output.clipPathFrame && !output.style?.clipPath?.trim().startsWith("path(")) {
1675
+ issues.push(`${path}.clipPathFrame requires style.clipPath path(...)`);
1676
+ }
1677
+ const hasCheckableFact = output.checkableKind !== void 0 || output.markerBox !== void 0 || output.checked !== void 0 || output.markerColor !== void 0;
1678
+ if (hasCheckableFact) {
1679
+ if (output.kind.trim().toLowerCase() !== "input") {
1680
+ issues.push(`${path} checkable facts require kind input`);
1681
+ }
1682
+ if (output.checkableKind === void 0) {
1683
+ issues.push(`${path}.checkableKind is required with checkable facts`);
1684
+ } else {
1685
+ try {
1686
+ selectionControlDeclaration(output);
1687
+ } catch (error) {
1688
+ issues.push(`${path}.${error instanceof Error ? error.message : "checkable declaration is invalid"}`);
1689
+ }
1690
+ }
1691
+ }
1692
+ if (input.measured !== void 0) {
1693
+ const measured = record3(input.measured, `${path}.measured`, issues);
1694
+ if (measured) {
1695
+ const forwardedMeasured = forwardUnknownKeys(measured, MEASURED_KEYS, `${path}.measured`, issues);
1696
+ if (measured.ink !== void 0) {
1697
+ const parsedInk = parseMeasuredTextInk(measured.ink, `${path}.measured.ink`, issues);
1698
+ if (parsedInk) output.measured = { ink: parsedInk };
1699
+ }
1700
+ if (forwardedMeasured) output.measured = carryUnknownKeys(output.measured ?? {}, forwardedMeasured);
1701
+ }
1702
+ }
1703
+ const artifacts = parseArtifacts(input.artifacts, `${path}.artifacts`, issues, requireUrl);
1704
+ if (artifacts) output.artifacts = artifacts;
1705
+ return carryUnknownKeys(output, forwarded);
1706
+ };
1707
+ function parsePublicLayerDocV2(value, options = {}) {
1708
+ const issues = [];
1709
+ const input = record3(value, "document", issues);
1710
+ if (!input) throw new PublicLayerDocV2ValidationError(issues);
1711
+ const forwardedDocument = forwardUnknownKeys(
1712
+ input,
1713
+ DOCUMENT_KEYS,
1714
+ "document",
1715
+ issues,
1716
+ { reserved: DOCUMENT_RESERVED_KEYS }
1717
+ );
1718
+ if (input.version !== PUBLIC_LAYERDOC_V2_VERSION) issues.push(`document.version must be ${PUBLIC_LAYERDOC_V2_VERSION}`);
1719
+ const extractionContract = parseExtractionContract(
1720
+ input.extractionContract,
1721
+ "document.extractionContract",
1722
+ issues
1723
+ );
1724
+ const layoutRelations = parseSharedLeftRailRelations(input.layoutRelations);
1725
+ const canvasInput = record3(input.canvas, "canvas", issues);
1726
+ let width = null;
1727
+ let height = null;
1728
+ let forwardedCanvas = null;
1729
+ if (canvasInput) {
1730
+ forwardedCanvas = forwardUnknownKeys(canvasInput, CANVAS_KEYS, "canvas", issues);
1731
+ width = finiteNumber2(canvasInput.width, "canvas.width", issues);
1732
+ height = finiteNumber2(canvasInput.height, "canvas.height", issues);
1733
+ for (const [name, part] of [["width", width], ["height", height]]) {
1734
+ if (part !== null && (!Number.isInteger(part) || part <= 0 || part > PUBLIC_LAYERDOC_MAX_CANVAS_SIDE)) {
1735
+ issues.push(`canvas.${name} must be a positive integer no greater than ${PUBLIC_LAYERDOC_MAX_CANVAS_SIDE}`);
1736
+ }
1737
+ }
1738
+ }
1739
+ const requireUrl = options.requireHydratedArtifactUrls === true;
1740
+ const allowCanvasOverflow = options.allowCanvasOverflow === true;
1741
+ const source = input.source === void 0 ? null : parseArtifactRef(input.source, "source", issues, requireUrl, "plain");
1742
+ if (!source) issues.push("document.source is required");
1743
+ if (source && (source.width === void 0 || source.height === void 0)) {
1744
+ issues.push("source must include width and height");
1745
+ }
1746
+ if (source && width && height) {
1747
+ if (source.width !== void 0 && source.width !== width) issues.push("source.width must match canvas.width");
1748
+ if (source.height !== void 0 && source.height !== height) issues.push("source.height must match canvas.height");
1749
+ }
1750
+ const leaves = [];
1751
+ let nodeCount = 0;
1752
+ const parseNodes = (nodes, path, depth, groupPathLength) => {
1753
+ if (!Array.isArray(nodes)) {
1754
+ issues.push(`${path} must be an array`);
1755
+ return [];
1756
+ }
1757
+ if (depth > MAX_GROUP_DEPTH) {
1758
+ issues.push(`${path} exceeds the maximum group depth of ${MAX_GROUP_DEPTH}`);
1759
+ return [];
1760
+ }
1761
+ const output = [];
1762
+ nodes.forEach((nodeValue, index) => {
1763
+ nodeCount += 1;
1764
+ if (nodeCount > MAX_TOTAL_NODES) return;
1765
+ const nodePath = `${path}[${index}]`;
1766
+ const node = record3(nodeValue, nodePath, issues);
1767
+ if (!node) return;
1768
+ if (Object.prototype.hasOwnProperty.call(node, "children")) {
1769
+ const forwardedGroup = forwardUnknownKeys(
1770
+ node,
1771
+ GROUP_KEYS,
1772
+ nodePath,
1773
+ issues
1774
+ );
1775
+ if (node.kind !== "group") issues.push(`${nodePath}.kind must be group when children is present`);
1776
+ const name = boundedString(node.name, `${nodePath}.name`, issues, {
1777
+ nonEmpty: true,
1778
+ max: PUBLIC_LAYERDOC_MAX_GROUP_LENGTH
1779
+ });
1780
+ if (name?.includes("/")) issues.push(`${nodePath}.name must not contain /`);
1781
+ parseBox(node.box, `${nodePath}.box`, issues, allowCanvasOverflow);
1782
+ const nestedGroupPathLength = name ? groupPathLength + (groupPathLength > 0 ? 1 : 0) + name.length : groupPathLength;
1783
+ if (nestedGroupPathLength > PUBLIC_LAYERDOC_MAX_GROUP_LENGTH) {
1784
+ issues.push(`${nodePath} aggregate group path must not exceed ${PUBLIC_LAYERDOC_MAX_GROUP_LENGTH} characters`);
1785
+ }
1786
+ const children = parseNodes(
1787
+ node.children,
1788
+ `${nodePath}.children`,
1789
+ depth + 1,
1790
+ nestedGroupPathLength
1791
+ );
1792
+ if (children.length === 0) issues.push(`${nodePath}.children must not be empty`);
1793
+ const measured = unionBoxes(children.map((child) => child.box));
1794
+ if (name && measured && nestedGroupPathLength <= PUBLIC_LAYERDOC_MAX_GROUP_LENGTH) {
1795
+ if (node.hidden !== void 0 && typeof node.hidden !== "boolean") {
1796
+ issues.push(`${nodePath}.hidden must be a boolean`);
1797
+ }
1798
+ output.push(carryUnknownKeys({
1799
+ kind: "group",
1800
+ name,
1801
+ box: measured,
1802
+ ...node.hidden === true ? { hidden: true } : {},
1803
+ children
1804
+ }, forwardedGroup));
1805
+ }
1806
+ return;
1807
+ }
1808
+ const leaf = parseLeaf(node, nodePath, issues, requireUrl, allowCanvasOverflow);
1809
+ if (leaf) {
1810
+ leaves.push(leaf);
1811
+ output.push(leaf);
1812
+ }
1813
+ });
1814
+ return output;
1815
+ };
1816
+ const layers = parseNodes(input.layers, "layers", 0, 0);
1817
+ if (nodeCount > MAX_TOTAL_NODES) issues.push(`document must not contain more than ${MAX_TOTAL_NODES} total nodes`);
1818
+ if (leaves.length > PUBLIC_LAYERDOC_MAX_LAYERS) {
1819
+ issues.push(`document must not contain more than ${PUBLIC_LAYERDOC_MAX_LAYERS} leaf layers`);
1820
+ }
1821
+ const zValues = new Set(leaves.map((leaf) => leaf.z));
1822
+ if (zValues.size !== leaves.length || [...zValues].some((z) => z < 0 || z >= leaves.length)) {
1823
+ issues.push("leaf z values must be unique and contiguous from 0");
1824
+ }
1825
+ const extractionIndices = leaves.flatMap((leaf) => leaf.extractionIndex === void 0 ? [] : [leaf.extractionIndex]);
1826
+ if (new Set(extractionIndices).size !== extractionIndices.length) {
1827
+ issues.push("leaf extractionIndex values must be unique when present");
1828
+ }
1829
+ if (!allowCanvasOverflow && width !== null && height !== null) {
1830
+ leaves.forEach((leaf) => {
1831
+ if (leaf.box[0] + leaf.box[2] > width || leaf.box[1] + leaf.box[3] > height) {
1832
+ issues.push(`leaf z=${leaf.z} box must stay inside the canvas`);
1833
+ }
1834
+ });
1835
+ }
1836
+ const artifactIds = /* @__PURE__ */ new Set();
1837
+ const collectRef = (ref) => {
1838
+ if (artifactIds.has(ref.artifactId)) issues.push(`artifactId ${ref.artifactId} is referenced more than once`);
1839
+ artifactIds.add(ref.artifactId);
1840
+ };
1841
+ if (source) collectRef(source);
1842
+ for (const leaf of leaves) {
1843
+ if (!leaf.artifacts) continue;
1844
+ for (const ref of Object.values(leaf.artifacts)) if (ref) collectRef(ref);
1845
+ }
1846
+ if (issues.length || width === null || height === null || !source) {
1847
+ throw new PublicLayerDocV2ValidationError(issues);
1848
+ }
1849
+ return carryUnknownKeys({
1850
+ version: PUBLIC_LAYERDOC_V2_VERSION,
1851
+ canvas: carryUnknownKeys({ width, height }, forwardedCanvas),
1852
+ source,
1853
+ ...extractionContract ? { extractionContract } : {},
1854
+ ...layoutRelations ? { layoutRelations } : {},
1855
+ layers
1856
+ }, forwardedDocument);
1857
+ }
1858
+ export {
1859
+ parsePublicLayerDocV2
1860
+ };