@tangle-network/agent-app 0.43.56 → 0.43.57

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 (352) hide show
  1. package/dist/DesignCanvas-UNL34LS2.js +12 -0
  2. package/dist/DesignCanvasEditor-FJIVYOA2.js +13 -0
  3. package/dist/IntakeInterview-3ZIQMZS6.js +8 -0
  4. package/dist/InvitationsPanel-CJ7DR4F7.js +8 -0
  5. package/dist/MembersPanel-BB4OD2KB.js +8 -0
  6. package/dist/{TimelineEditor-I35SJJAJ.js → TimelineEditor-2ECKSU6P.js} +3 -3
  7. package/dist/{VaultPane-DrQ_tH6c.d.ts → VaultPane-BDP6SB_K.d.ts} +1 -0
  8. package/dist/{access-BZ81Btt5.d.ts → access-490O6aOU.d.ts} +16 -1
  9. package/dist/app-auth/index.d.ts +6 -1
  10. package/dist/app-auth/index.js +3 -3
  11. package/dist/app-auth/index.js.map +1 -1
  12. package/dist/{apply-Gk4raT2j.d.ts → apply-6wlMOLf8.d.ts} +30 -1
  13. package/dist/assets/index.d.ts +41 -0
  14. package/dist/assets/index.js +1 -1
  15. package/dist/assistant/index.d.ts +26 -6
  16. package/dist/assistant/index.js +9 -9
  17. package/dist/assistant/index.js.map +1 -1
  18. package/dist/{attachment-validation-D0csjCvz.d.ts → attachment-validation-tPRp-PP1.d.ts} +7 -1
  19. package/dist/{auth-DuptSkWh.d.ts → auth-_FU8w01b.d.ts} +4 -1
  20. package/dist/billing/index.d.ts +8 -0
  21. package/dist/billing/index.js +1 -1
  22. package/dist/brand/index.d.ts +2 -0
  23. package/dist/brand/index.js.map +1 -1
  24. package/dist/brand-extraction/index.d.ts +3 -0
  25. package/dist/brand-extraction/index.js.map +1 -1
  26. package/dist/catalog/index.d.ts +2 -0
  27. package/dist/catalog/index.js +1 -1
  28. package/dist/chat-routes/index.d.ts +41 -10
  29. package/dist/chat-routes/index.js +15 -15
  30. package/dist/chat-routes/index.js.map +1 -1
  31. package/dist/chat-store/index.d.ts +18 -4
  32. package/dist/chat-store/index.js +4 -4
  33. package/dist/chat-store/index.js.map +1 -1
  34. package/dist/{chunk-H5FM75MR.js → chunk-22GLESKE.js} +3 -3
  35. package/dist/chunk-22GLESKE.js.map +1 -0
  36. package/dist/{chunk-WEBBJBDH.js → chunk-2DRYTJHI.js} +1 -1
  37. package/dist/chunk-2DRYTJHI.js.map +1 -0
  38. package/dist/{chunk-7EVZUIHW.js → chunk-3EJ6SFJI.js} +1 -1
  39. package/dist/chunk-3EJ6SFJI.js.map +1 -0
  40. package/dist/{chunk-HRJJH3RX.js → chunk-3OFQFW5K.js} +4 -4
  41. package/dist/chunk-3OFQFW5K.js.map +1 -0
  42. package/dist/{chunk-7SUPA2YT.js → chunk-4KKXZQPT.js} +2 -2
  43. package/dist/chunk-4KKXZQPT.js.map +1 -0
  44. package/dist/{chunk-5PTGEJZL.js → chunk-5SD6HT2V.js} +1 -1
  45. package/dist/chunk-5SD6HT2V.js.map +1 -0
  46. package/dist/{chunk-7C64WKAH.js → chunk-5SXS3YAB.js} +2 -2
  47. package/dist/{chunk-L2TG5DBW.js → chunk-5TESA4SN.js} +1 -1
  48. package/dist/chunk-5TESA4SN.js.map +1 -0
  49. package/dist/{chunk-63CE7FEZ.js → chunk-6XIAPIW6.js} +1 -1
  50. package/dist/chunk-6XIAPIW6.js.map +1 -0
  51. package/dist/{chunk-MFRCM32T.js → chunk-7CTIUCQ4.js} +1 -1
  52. package/dist/chunk-7CTIUCQ4.js.map +1 -0
  53. package/dist/{chunk-6KVH5SP5.js → chunk-7YW6EBDX.js} +2 -2
  54. package/dist/chunk-7YW6EBDX.js.map +1 -0
  55. package/dist/{chunk-ZXNXAQAH.js → chunk-AP2UXKUK.js} +1 -1
  56. package/dist/chunk-AP2UXKUK.js.map +1 -0
  57. package/dist/{chunk-K63OWUDJ.js → chunk-BPSV5AA2.js} +2 -2
  58. package/dist/chunk-BPSV5AA2.js.map +1 -0
  59. package/dist/{chunk-MFI4ZM7W.js → chunk-BT4QFCTB.js} +1 -1
  60. package/dist/chunk-BT4QFCTB.js.map +1 -0
  61. package/dist/{chunk-ZYBWGSAZ.js → chunk-BVKQKGRK.js} +1 -1
  62. package/dist/chunk-BVKQKGRK.js.map +1 -0
  63. package/dist/{chunk-RVUISYUE.js → chunk-C3NSB66C.js} +7 -7
  64. package/dist/chunk-C3NSB66C.js.map +1 -0
  65. package/dist/{chunk-BQV42AFK.js → chunk-CCVWR33L.js} +1 -1
  66. package/dist/chunk-CCVWR33L.js.map +1 -0
  67. package/dist/{chunk-MCJSS6SM.js → chunk-CQZSAR77.js} +1 -1
  68. package/dist/chunk-CQZSAR77.js.map +1 -0
  69. package/dist/{chunk-3SVAA3MA.js → chunk-DJ4VJIH5.js} +1 -1
  70. package/dist/chunk-DJ4VJIH5.js.map +1 -0
  71. package/dist/{chunk-XKBIYSSM.js → chunk-DTSPS2HV.js} +3 -3
  72. package/dist/chunk-DTSPS2HV.js.map +1 -0
  73. package/dist/{chunk-4QN75UHX.js → chunk-E7N67FYI.js} +8 -8
  74. package/dist/chunk-E7N67FYI.js.map +1 -0
  75. package/dist/{chunk-2QI7XV2T.js → chunk-FBVLEGEG.js} +1 -1
  76. package/dist/{chunk-2QI7XV2T.js.map → chunk-FBVLEGEG.js.map} +1 -1
  77. package/dist/{chunk-5RMIUJDI.js → chunk-FKCB5FTD.js} +1 -1
  78. package/dist/chunk-FKCB5FTD.js.map +1 -0
  79. package/dist/{chunk-EEPJGZJW.js → chunk-GPBRL2XR.js} +1 -1
  80. package/dist/chunk-GPBRL2XR.js.map +1 -0
  81. package/dist/{chunk-G3HCU7TA.js → chunk-GXE6KHTS.js} +1 -1
  82. package/dist/chunk-GXE6KHTS.js.map +1 -0
  83. package/dist/{chunk-65P3HJY3.js → chunk-HCOROIRT.js} +1 -1
  84. package/dist/chunk-HCOROIRT.js.map +1 -0
  85. package/dist/{chunk-54GSK2KK.js → chunk-HYTIHYNV.js} +2 -2
  86. package/dist/chunk-HYTIHYNV.js.map +1 -0
  87. package/dist/{chunk-5MG74GVQ.js → chunk-IG46XCZM.js} +3 -3
  88. package/dist/chunk-IG46XCZM.js.map +1 -0
  89. package/dist/{chunk-ND3XEGBE.js → chunk-JDEGS53O.js} +1 -1
  90. package/dist/chunk-JDEGS53O.js.map +1 -0
  91. package/dist/{chunk-7W5XSTUF.js → chunk-JML7WKWU.js} +1 -1
  92. package/dist/chunk-JML7WKWU.js.map +1 -0
  93. package/dist/{chunk-Q4TKVF3L.js → chunk-JTLYXUEV.js} +1 -1
  94. package/dist/chunk-JTLYXUEV.js.map +1 -0
  95. package/dist/{chunk-CCRVDLV3.js → chunk-JWBZ74TW.js} +2 -2
  96. package/dist/chunk-JWBZ74TW.js.map +1 -0
  97. package/dist/{chunk-ZU5GNSOJ.js → chunk-K3LIPKFV.js} +3 -3
  98. package/dist/chunk-K3LIPKFV.js.map +1 -0
  99. package/dist/{chunk-GQRL6VNU.js → chunk-LGBO24FL.js} +1 -1
  100. package/dist/chunk-LGBO24FL.js.map +1 -0
  101. package/dist/{chunk-SWUVTGMR.js → chunk-MEUNTJL5.js} +3 -3
  102. package/dist/{chunk-SWUVTGMR.js.map → chunk-MEUNTJL5.js.map} +1 -1
  103. package/dist/{chunk-YNALYIQ3.js → chunk-NLSSFLLS.js} +1 -1
  104. package/dist/chunk-NLSSFLLS.js.map +1 -0
  105. package/dist/{chunk-HFC4BTWJ.js → chunk-PTUMBMVH.js} +1 -1
  106. package/dist/chunk-PTUMBMVH.js.map +1 -0
  107. package/dist/{chunk-R4NOKZMD.js → chunk-ROLFDOMJ.js} +3 -3
  108. package/dist/{chunk-NYATNLRK.js → chunk-RT5RKAFX.js} +1 -1
  109. package/dist/chunk-RT5RKAFX.js.map +1 -0
  110. package/dist/{chunk-GNL3MG5J.js → chunk-S564OFTL.js} +2 -2
  111. package/dist/{chunk-GUSCYE3S.js → chunk-TQOFR6XY.js} +1 -1
  112. package/dist/chunk-TQOFR6XY.js.map +1 -0
  113. package/dist/{chunk-47C6PJCW.js → chunk-TZO3SOUL.js} +1 -1
  114. package/dist/chunk-TZO3SOUL.js.map +1 -0
  115. package/dist/{chunk-YGUNTIT5.js → chunk-UKTYKG57.js} +1 -1
  116. package/dist/chunk-UKTYKG57.js.map +1 -0
  117. package/dist/{chunk-23LUHHHN.js → chunk-VCOD5AOR.js} +1 -1
  118. package/dist/chunk-VCOD5AOR.js.map +1 -0
  119. package/dist/{chunk-5I72FRZY.js → chunk-VOJB7MVG.js} +2 -2
  120. package/dist/{chunk-XWJXZ6WE.js → chunk-VTWKH4YU.js} +2 -2
  121. package/dist/chunk-VTWKH4YU.js.map +1 -0
  122. package/dist/{chunk-4K7BZYO7.js → chunk-VWAEWOWK.js} +3 -3
  123. package/dist/chunk-VWAEWOWK.js.map +1 -0
  124. package/dist/{chunk-M2EBUDZ7.js → chunk-VWOPOLVO.js} +2 -2
  125. package/dist/chunk-VWOPOLVO.js.map +1 -0
  126. package/dist/{chunk-BN2USWIR.js → chunk-VYECQAGM.js} +2 -2
  127. package/dist/chunk-VYECQAGM.js.map +1 -0
  128. package/dist/{chunk-SIXYZ2FB.js → chunk-YJMCRXQQ.js} +1 -1
  129. package/dist/chunk-YJMCRXQQ.js.map +1 -0
  130. package/dist/{chunk-PJC4NXPA.js → chunk-YKBDH2UY.js} +3 -3
  131. package/dist/chunk-YKBDH2UY.js.map +1 -0
  132. package/dist/{chunk-XAWFPMAR.js → chunk-YKOM4ZLQ.js} +1 -1
  133. package/dist/chunk-YKOM4ZLQ.js.map +1 -0
  134. package/dist/{chunk-TKVJE63N.js → chunk-YRMLYFVR.js} +3 -3
  135. package/dist/chunk-YRMLYFVR.js.map +1 -0
  136. package/dist/{chunk-USYXHDKE.js → chunk-YZ6KQULN.js} +2 -2
  137. package/dist/{command-stack-B_-WNfZU.d.ts → command-stack-TNPWJCzW.d.ts} +14 -2
  138. package/dist/{completion-Kaqp_tWk.d.ts → completion-CvcNUz07.d.ts} +1 -1
  139. package/dist/config/index.d.ts +1 -1
  140. package/dist/{contract-KfqJh_au.d.ts → contract-TjB68uqA.d.ts} +17 -0
  141. package/dist/design-canvas/drizzle.d.ts +10 -2
  142. package/dist/design-canvas/drizzle.js.map +1 -1
  143. package/dist/design-canvas/index.d.ts +29 -11
  144. package/dist/design-canvas/index.js +1070 -17
  145. package/dist/design-canvas/index.js.map +1 -1
  146. package/dist/design-canvas-react/engine.d.ts +42 -6
  147. package/dist/design-canvas-react/engine.js +4 -4
  148. package/dist/design-canvas-react/index.d.ts +12 -7
  149. package/dist/design-canvas-react/index.js +11 -11
  150. package/dist/design-canvas-react/index.js.map +1 -1
  151. package/dist/design-canvas-react/lazy.d.ts +4 -4
  152. package/dist/design-canvas-react/lazy.js +1 -1
  153. package/dist/durable-chat/index.d.ts +46 -1
  154. package/dist/durable-chat/index.js +3 -3
  155. package/dist/eval/index.d.ts +1 -1
  156. package/dist/{export-presets-DAsU5Wal.d.ts → export-presets-mgVulRaV.d.ts} +10 -1
  157. package/dist/{flow-types-Cb_AblZs.d.ts → flow-types-CqomVAUN.d.ts} +1 -0
  158. package/dist/harness/index.d.ts +5 -0
  159. package/dist/harness/index.js +1 -1
  160. package/dist/index.d.ts +10 -18
  161. package/dist/index.js +30 -231
  162. package/dist/intakes/api.d.ts +3 -2
  163. package/dist/intakes/api.js +3 -3
  164. package/dist/intakes/api.js.map +1 -1
  165. package/dist/intakes/drizzle.d.ts +10 -2
  166. package/dist/intakes/drizzle.js +3 -3
  167. package/dist/intakes/drizzle.js.map +1 -1
  168. package/dist/intakes/index.d.ts +2 -2
  169. package/dist/intakes/index.js +2 -2
  170. package/dist/intakes-react/index.d.ts +2 -1
  171. package/dist/intakes-react/index.js +2 -2
  172. package/dist/intakes-react/lazy.d.ts +2 -1
  173. package/dist/intakes-react/lazy.js +1 -1
  174. package/dist/intakes-react/lazy.js.map +1 -1
  175. package/dist/integrations/index.d.ts +4 -0
  176. package/dist/integrations/index.js +1 -1
  177. package/dist/interactions/index.d.ts +13 -2
  178. package/dist/interactions/index.js +2 -2
  179. package/dist/{invitations-CZ5G2tIn.d.ts → invitations-DoYMvXea.d.ts} +11 -1
  180. package/dist/{invitations-schema-DaMO4hZE.d.ts → invitations-schema-_fI7HkJP.d.ts} +5 -1
  181. package/dist/knowledge/index.d.ts +2 -0
  182. package/dist/knowledge/index.js +1 -1
  183. package/dist/knowledge-loop/index.d.ts +4 -1
  184. package/dist/knowledge-loop/index.js +1 -1
  185. package/dist/{lazy-C7LiVeFt.d.ts → lazy-DrkVyDpe.d.ts} +2 -2
  186. package/dist/{mcp-BHfIoGLW.d.ts → mcp-BjPqQ-3C.d.ts} +4 -2
  187. package/dist/{mcp-rpc-DLw_r9PQ.d.ts → mcp-rpc-BfUOsalw.d.ts} +3 -0
  188. package/dist/missions/index.d.ts +25 -0
  189. package/dist/missions/index.js +1 -1
  190. package/dist/{model-Bzi5i63l.d.ts → model-C8U0HZxL.d.ts} +1 -0
  191. package/dist/{model-dF2h4xT9.d.ts → model-DmdkIteM.d.ts} +19 -0
  192. package/dist/{model-BBwyOuWG.d.ts → model-DnfO_PdJ.d.ts} +25 -1
  193. package/dist/model-resolution/index.d.ts +10 -0
  194. package/dist/model-resolution/index.js.map +1 -1
  195. package/dist/{operations-DLIvvD00.d.ts → operations-ByJ6yXOW.d.ts} +20 -2
  196. package/dist/{parts-1sRYSPjF.d.ts → parts-n9XUon0a.d.ts} +29 -1
  197. package/dist/plans/index.d.ts +6 -0
  198. package/dist/plans/index.js +1 -1
  199. package/dist/platform/index.d.ts +24 -2
  200. package/dist/platform/index.js +3 -3
  201. package/dist/platform/index.js.map +1 -1
  202. package/dist/preflight/index.d.ts +3 -0
  203. package/dist/preflight/index.js +1 -1
  204. package/dist/preset-cloudflare/index.d.ts +4 -1
  205. package/dist/preset-cloudflare/index.js +2 -2
  206. package/dist/redact/index.d.ts +5 -0
  207. package/dist/redact/index.js +1 -1
  208. package/dist/{roles-BC1n4t37.d.ts → roles-B4nU3jDi.d.ts} +12 -0
  209. package/dist/run/index.d.ts +3 -0
  210. package/dist/run/index.js +1 -1
  211. package/dist/run/index.js.map +1 -1
  212. package/dist/runtime/index.d.ts +11 -4
  213. package/dist/runtime/index.js +4 -4
  214. package/dist/sandbox/index.d.ts +96 -3
  215. package/dist/sandbox/index.js +6 -6
  216. package/dist/{sandbox-terminal-BIIC__CP.d.ts → sandbox-terminal-ChNEdHF8.d.ts} +5 -0
  217. package/dist/sequences/drizzle.d.ts +11 -1
  218. package/dist/sequences/drizzle.js +1 -1
  219. package/dist/sequences/drizzle.js.map +1 -1
  220. package/dist/sequences/index.d.ts +32 -7
  221. package/dist/sequences/index.js +1562 -47
  222. package/dist/sequences/index.js.map +1 -1
  223. package/dist/sequences-react/index.d.ts +32 -2
  224. package/dist/sequences-react/index.js +3 -3
  225. package/dist/sequences-react/index.js.map +1 -1
  226. package/dist/{sso-CNOsARMJ.d.ts → sso-Cm00S61u.d.ts} +13 -0
  227. package/dist/{stale-turn-lock-C8Na1cFZ.d.ts → stale-turn-lock-DucQzvXu.d.ts} +2 -0
  228. package/dist/store/index.d.ts +5 -0
  229. package/dist/store/index.js.map +1 -1
  230. package/dist/{store-gckrNq-g.d.ts → store-B7LLlk9p.d.ts} +22 -1
  231. package/dist/{store-CFyxgTlD.d.ts → store-CqfDtnPQ.d.ts} +8 -2
  232. package/dist/stream/index.d.ts +10 -4
  233. package/dist/stream/index.js +4 -4
  234. package/dist/{stream-normalizer-DWvtmY6F.d.ts → stream-normalizer-C3M--r6y.d.ts} +17 -1
  235. package/dist/studio/index.d.ts +37 -0
  236. package/dist/studio/index.js +1 -1
  237. package/dist/studio-react/index.d.ts +3 -0
  238. package/dist/studio-react/index.js +1 -1
  239. package/dist/studio-react/index.js.map +1 -1
  240. package/dist/tangle/index.d.ts +3 -0
  241. package/dist/tangle/index.js +1 -1
  242. package/dist/teams/drizzle.d.ts +8 -4
  243. package/dist/teams/drizzle.js +1 -1
  244. package/dist/teams/drizzle.js.map +1 -1
  245. package/dist/teams/index.d.ts +4 -2
  246. package/dist/teams/index.js +3 -3
  247. package/dist/teams/invitations-api.d.ts +10 -4
  248. package/dist/teams/invitations-api.js +4 -4
  249. package/dist/teams/invitations-api.js.map +1 -1
  250. package/dist/teams/members-api.d.ts +4 -2
  251. package/dist/teams/members-api.js +3 -3
  252. package/dist/teams/resend.d.ts +5 -4
  253. package/dist/teams/resend.js +1 -1
  254. package/dist/teams/resend.js.map +1 -1
  255. package/dist/teams-react/index.d.ts +7 -2
  256. package/dist/teams-react/index.js +3 -3
  257. package/dist/teams-react/lazy.d.ts +5 -2
  258. package/dist/teams-react/lazy.js +2 -2
  259. package/dist/teams-react/lazy.js.map +1 -1
  260. package/dist/theme/index.d.ts +2 -0
  261. package/dist/theme/index.js +1 -1
  262. package/dist/theme/tailwind-preset.d.ts +1 -0
  263. package/dist/theme/tailwind-preset.js.map +1 -1
  264. package/dist/theme-contract/cli.js +1 -1
  265. package/dist/theme-contract/index.d.ts +3 -0
  266. package/dist/theme-contract/index.js +1 -1
  267. package/dist/tools/index.d.ts +13 -6
  268. package/dist/tools/index.js +3 -3
  269. package/dist/trace/index.d.ts +6 -1
  270. package/dist/trace/index.js +2 -2
  271. package/dist/{turn-buffer-C9mEgoop.d.ts → turn-buffer-DGnAPKwa.d.ts} +6 -0
  272. package/dist/turn-stream/index.d.ts +28 -2
  273. package/dist/turn-stream/index.js +1 -1
  274. package/dist/turn-stream/index.js.map +1 -1
  275. package/dist/{types-BEOvc_ue.d.ts → types-CBRyqijY.d.ts} +10 -0
  276. package/dist/vault/index.d.ts +1 -1
  277. package/dist/vault/lazy.d.ts +3 -2
  278. package/dist/vault/lazy.js.map +1 -1
  279. package/dist/web/index.d.ts +4 -0
  280. package/dist/web/index.js +1 -1
  281. package/dist/web-react/index.d.ts +51 -8
  282. package/dist/web-react/index.js +9 -9
  283. package/dist/web-react/terminal.d.ts +2 -2
  284. package/dist/web-react/terminal.js +1 -1
  285. package/package.json +3 -2
  286. package/dist/DesignCanvas-5DJAFDNC.js +0 -12
  287. package/dist/DesignCanvasEditor-XUJZARSN.js +0 -13
  288. package/dist/IntakeInterview-WHVKMNQW.js +0 -8
  289. package/dist/InvitationsPanel-XUUWZBPV.js +0 -8
  290. package/dist/MembersPanel-FOVHWUQ3.js +0 -8
  291. package/dist/chunk-23LUHHHN.js.map +0 -1
  292. package/dist/chunk-3SVAA3MA.js.map +0 -1
  293. package/dist/chunk-47C6PJCW.js.map +0 -1
  294. package/dist/chunk-4K7BZYO7.js.map +0 -1
  295. package/dist/chunk-4QN75UHX.js.map +0 -1
  296. package/dist/chunk-54GSK2KK.js.map +0 -1
  297. package/dist/chunk-5MG74GVQ.js.map +0 -1
  298. package/dist/chunk-5PTGEJZL.js.map +0 -1
  299. package/dist/chunk-5RMIUJDI.js.map +0 -1
  300. package/dist/chunk-63CE7FEZ.js.map +0 -1
  301. package/dist/chunk-65P3HJY3.js.map +0 -1
  302. package/dist/chunk-6KVH5SP5.js.map +0 -1
  303. package/dist/chunk-7EVZUIHW.js.map +0 -1
  304. package/dist/chunk-7SUPA2YT.js.map +0 -1
  305. package/dist/chunk-7W5XSTUF.js.map +0 -1
  306. package/dist/chunk-BN2USWIR.js.map +0 -1
  307. package/dist/chunk-BQV42AFK.js.map +0 -1
  308. package/dist/chunk-CCRVDLV3.js.map +0 -1
  309. package/dist/chunk-EEPJGZJW.js.map +0 -1
  310. package/dist/chunk-G3HCU7TA.js.map +0 -1
  311. package/dist/chunk-GQRL6VNU.js.map +0 -1
  312. package/dist/chunk-GUSCYE3S.js.map +0 -1
  313. package/dist/chunk-H5FM75MR.js.map +0 -1
  314. package/dist/chunk-HFC4BTWJ.js.map +0 -1
  315. package/dist/chunk-HRJJH3RX.js.map +0 -1
  316. package/dist/chunk-K63OWUDJ.js.map +0 -1
  317. package/dist/chunk-L2TG5DBW.js.map +0 -1
  318. package/dist/chunk-M2EBUDZ7.js.map +0 -1
  319. package/dist/chunk-MCJSS6SM.js.map +0 -1
  320. package/dist/chunk-MFI4ZM7W.js.map +0 -1
  321. package/dist/chunk-MFRCM32T.js.map +0 -1
  322. package/dist/chunk-ND3XEGBE.js.map +0 -1
  323. package/dist/chunk-NEOV2NQ3.js +0 -1617
  324. package/dist/chunk-NEOV2NQ3.js.map +0 -1
  325. package/dist/chunk-NYATNLRK.js.map +0 -1
  326. package/dist/chunk-PJC4NXPA.js.map +0 -1
  327. package/dist/chunk-Q4TKVF3L.js.map +0 -1
  328. package/dist/chunk-RVUISYUE.js.map +0 -1
  329. package/dist/chunk-SIXYZ2FB.js.map +0 -1
  330. package/dist/chunk-TKVJE63N.js.map +0 -1
  331. package/dist/chunk-WEBBJBDH.js.map +0 -1
  332. package/dist/chunk-WFMUDX5J.js +0 -1092
  333. package/dist/chunk-WFMUDX5J.js.map +0 -1
  334. package/dist/chunk-XAWFPMAR.js.map +0 -1
  335. package/dist/chunk-XKBIYSSM.js.map +0 -1
  336. package/dist/chunk-XWJXZ6WE.js.map +0 -1
  337. package/dist/chunk-YGUNTIT5.js.map +0 -1
  338. package/dist/chunk-YNALYIQ3.js.map +0 -1
  339. package/dist/chunk-ZU5GNSOJ.js.map +0 -1
  340. package/dist/chunk-ZXNXAQAH.js.map +0 -1
  341. package/dist/chunk-ZYBWGSAZ.js.map +0 -1
  342. /package/dist/{DesignCanvas-5DJAFDNC.js.map → DesignCanvas-UNL34LS2.js.map} +0 -0
  343. /package/dist/{DesignCanvasEditor-XUJZARSN.js.map → DesignCanvasEditor-FJIVYOA2.js.map} +0 -0
  344. /package/dist/{IntakeInterview-WHVKMNQW.js.map → IntakeInterview-3ZIQMZS6.js.map} +0 -0
  345. /package/dist/{InvitationsPanel-XUUWZBPV.js.map → InvitationsPanel-CJ7DR4F7.js.map} +0 -0
  346. /package/dist/{MembersPanel-FOVHWUQ3.js.map → MembersPanel-BB4OD2KB.js.map} +0 -0
  347. /package/dist/{TimelineEditor-I35SJJAJ.js.map → TimelineEditor-2ECKSU6P.js.map} +0 -0
  348. /package/dist/{chunk-7C64WKAH.js.map → chunk-5SXS3YAB.js.map} +0 -0
  349. /package/dist/{chunk-R4NOKZMD.js.map → chunk-ROLFDOMJ.js.map} +0 -0
  350. /package/dist/{chunk-GNL3MG5J.js.map → chunk-S564OFTL.js.map} +0 -0
  351. /package/dist/{chunk-5I72FRZY.js.map → chunk-VOJB7MVG.js.map} +0 -0
  352. /package/dist/{chunk-USYXHDKE.js.map → chunk-YZ6KQULN.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/stream/turn-identity.ts","../src/stream/turn-buffer.ts"],"sourcesContent":["import type { JsonRecord } from './stream-normalizer'\n\n/** Define the structure of a chat message stored for a specific conversation turn */\nexport interface PersistedChatMessageForTurn {\n id: string\n role: 'user' | 'assistant' | 'system' | 'tool'\n content: string\n parts: Array<Record<string, unknown>> | null\n}\n\n/** Represent a chat turn with resolved user message insertion and prior message context */\nexport interface ResolvedChatTurn {\n turnIndex: number\n shouldInsertUserMessage: boolean\n priorMessages: PersistedChatMessageForTurn[]\n userParts: JsonRecord[]\n}\n\n/** Normalize and validate a client turn ID string ensuring it meets format and length requirements */\nexport function normalizeClientTurnId(value: unknown): string | undefined {\n if (value === undefined || value === null) return undefined\n if (typeof value !== 'string') throw new Error('turnId must be a string')\n const trimmed = value.trim()\n if (!trimmed) throw new Error('turnId must not be blank')\n if (trimmed.length > 160) throw new Error('turnId is too long')\n if (!/^[A-Za-z0-9:_-]+$/.test(trimmed)) {\n throw new Error('turnId contains unsupported characters')\n }\n return trimmed\n}\n\n/** Build an array of text parts with optional turn ID for user input */\nexport function buildUserTextParts(text: string, turnId: string | undefined): JsonRecord[] {\n const part: JsonRecord = { type: 'text', text }\n if (turnId) part.turnId = turnId\n return [part]\n}\n\n/** Resolve whether a message contains any part with the specified turn ID */\nexport function messageHasTurnId(message: PersistedChatMessageForTurn, turnId: string): boolean {\n for (const part of message.parts ?? []) {\n if (part && typeof part === 'object' && String(part.turnId ?? '') === turnId) {\n return true\n }\n }\n return false\n}\n\n/** Resolve a chat turn by determining message reuse and constructing user message parts */\nexport function resolveChatTurn(input: {\n existingMessages: PersistedChatMessageForTurn[]\n userContent: string\n turnId?: string\n}): ResolvedChatTurn {\n const { existingMessages, userContent, turnId } = input\n const reusableIndex = findReusableUserMessageIndex(existingMessages, userContent, turnId)\n if (reusableIndex >= 0) {\n return {\n turnIndex: countUserMessages(existingMessages.slice(0, reusableIndex)),\n shouldInsertUserMessage: false,\n priorMessages: existingMessages.slice(0, reusableIndex),\n userParts: buildUserTextParts(userContent, turnId),\n }\n }\n\n return {\n turnIndex: countUserMessages(existingMessages),\n shouldInsertUserMessage: true,\n priorMessages: existingMessages,\n userParts: buildUserTextParts(userContent, turnId),\n }\n}\n\nfunction findReusableUserMessageIndex(\n messages: PersistedChatMessageForTurn[],\n userContent: string,\n turnId: string | undefined,\n): number {\n if (turnId) {\n for (let index = messages.length - 1; index >= 0; index -= 1) {\n const message = messages[index]\n if (message?.role === 'user' && messageHasTurnId(message, turnId)) return index\n }\n }\n\n const latest = messages.at(-1)\n if (latest?.role === 'user' && latest.content === userContent) {\n return messages.length - 1\n }\n\n return -1\n}\n\nfunction countUserMessages(messages: PersistedChatMessageForTurn[]): number {\n return messages.filter((message) => message.role === 'user').length\n}\n","/**\n * Resumable chat turns — the router-path answer to \"streams resume on\n * disconnect\" (issue #27). A turn's loop events are teed into a store as they\n * stream; the turn keeps running under `ctx.waitUntil` when the client drops;\n * a reconnecting client replays the buffered tail by sequence number and\n * keeps following until the turn completes.\n *\n * POST /chat/stream → pumpBufferedTurn(...) + live NDJSON\n * GET /chat/stream/:turnId → replayTurnEvents({ fromSeq }) → NDJSON\n *\n * Storage is a structural seam ({@link TurnEventStore}); a D1 implementation\n * ships here because that's what Cloudflare products have (KV is unsuitable:\n * eventually consistent cross-isolate). Per-token deltas would mean hundreds\n * of rows per turn, so consecutive text/reasoning deltas are coalesced within\n * a flush window before they are persisted — replay yields slightly chunkier\n * deltas with identical concatenation.\n */\n\nexport type TurnStatus = 'running' | 'complete' | 'error'\n\n/** Represent a buffered turn event with a sequence number and serialized event data */\nexport interface BufferedTurnEvent {\n seq: number\n /** The serialized event line (JSON string, no trailing newline). */\n event: string\n}\n\n/** Manage and query turn events and their lifecycle statuses within a scoped event store */\nexport interface TurnEventStore {\n append(turnId: string, events: BufferedTurnEvent[]): Promise<void>\n read(turnId: string, fromSeq: number): Promise<BufferedTurnEvent[]>\n /** Record turn lifecycle. `scopeId` (a thread/session id) is optional and lets\n * {@link TurnEventStore.listRunning} rediscover this turn after a client reload\n * loses the turnId; stores that don't track scope ignore it. */\n setStatus(turnId: string, status: TurnStatus, scopeId?: string): Promise<void>\n getStatus(turnId: string): Promise<TurnStatus | null>\n /** Running turnIds for a scope, newest first — so a reloaded client (clientRunId\n * lost) can find and resume the in-flight turn. Optional: a store records it\n * only if `setStatus` was given a `scopeId`. */\n listRunning?(scopeId: string): Promise<string[]>\n}\n\n// ── coalescing ────────────────────────────────────────────────────────────\n\ntype AnyRecord = Record<string, unknown>\n\nfunction deltaTypeOf(ev: unknown): 'text' | 'reasoning' | null {\n const e = ev as AnyRecord | null\n if (!e || typeof e !== 'object') return null\n const inner = (e.kind === 'event' ? (e.event as AnyRecord | undefined) : e) as AnyRecord | undefined\n if (!inner || typeof inner !== 'object') return null\n if ((inner.type === 'text' || inner.type === 'reasoning') && typeof inner.text === 'string') {\n return inner.type\n }\n return null\n}\n\n/** Merge consecutive text/reasoning deltas of the same type into one event.\n * Concatenation-preserving: replaying the coalesced stream produces the same\n * accumulated text as the original. */\nexport function coalesceDeltas(events: unknown[]): unknown[] {\n const out: unknown[] = []\n for (const ev of events) {\n const type = deltaTypeOf(ev)\n const prev = out[out.length - 1]\n if (type && prev && deltaTypeOf(prev) === type) {\n const read = (x: unknown): AnyRecord =>\n ((x as AnyRecord).kind === 'event' ? (x as AnyRecord).event : x) as AnyRecord\n const merged = JSON.parse(JSON.stringify(prev)) as AnyRecord\n read(merged).text = String(read(prev).text) + String(read(ev).text)\n out[out.length - 1] = merged\n continue\n }\n out.push(ev)\n }\n return out\n}\n\nfunction asPartUpdate(ev: unknown): { partId: unknown; delta: unknown } | null {\n const e = ev as AnyRecord | null\n if (!e || typeof e !== 'object' || e.type !== 'message.part.updated') return null\n const data = e.data as AnyRecord | undefined\n if (!data || typeof data !== 'object') return null\n const part = data.part as AnyRecord | undefined\n const partId = part?.id ?? data.partId ?? part?.partId ?? null\n return { partId, delta: data.delta }\n}\n\n/**\n * Coalesce consecutive `message.part.updated` deltas for the SAME part into one\n * event. agent-runtime products stream `ChatStreamEvent` NDJSON\n * (`{type:'message.part.updated', data:{part, delta}}`); pumped through the\n * buffer with the default tool-loop coalescer, every per-token delta persists as\n * its own row because that coalescer never recognizes the shape. Pass this as\n * {@link PumpBufferedTurnOptions.coalesce} instead.\n *\n * Concatenation-preserving for BOTH consumer styles: the merged event keeps the\n * LATEST event's `data.part` (already the cumulative accumulation) and sets\n * `data.delta` to the concatenation of the merged deltas, so a client that\n * appends `delta` and one that reads the cumulative `part` both reconstruct the\n * identical final text.\n */\nexport function coalesceChatStreamEvents(events: unknown[]): unknown[] {\n const out: unknown[] = []\n for (const ev of events) {\n const cur = asPartUpdate(ev)\n const prevEv = out[out.length - 1]\n const prev = prevEv ? asPartUpdate(prevEv) : null\n if (cur && prev && cur.partId != null && cur.partId === prev.partId) {\n // Base the merged row on the latest event (its `part` is the most complete\n // accumulation); carry forward the summed delta.\n const merged = JSON.parse(JSON.stringify(ev)) as AnyRecord\n ;(merged.data as AnyRecord).delta = String(prev.delta ?? '') + String(cur.delta ?? '')\n out[out.length - 1] = merged\n continue\n }\n out.push(ev)\n }\n return out\n}\n\n// ── buffering core (the tap) ────────────────────────────────────────────────\n\n/** Define options for buffering and flushing turn events with optional live client delivery and event coalescing */\nexport interface BufferedTurnOptions {\n store: TurnEventStore\n turnId: string\n /** Deliver one serialized line to the live client. Throwing here (client\n * disconnected) does NOT stop buffering — events keep persisting. */\n write?: (line: string) => Promise<void> | void\n /** Flush buffered events to the store at most this often. Default 400ms. */\n flushIntervalMs?: number\n /** Per-flush coalescer. Default {@link coalesceDeltas} (tool-loop text/reasoning\n * deltas). agent-runtime products streaming `ChatStreamEvent` pass\n * {@link coalesceChatStreamEvents} so per-token deltas don't each persist as a\n * row. Must be concatenation-preserving. */\n coalesce?: (events: unknown[]) => unknown[]\n /** Optional scope (thread/session id) recorded with the turn status, so\n * {@link TurnEventStore.listRunning} can find this turn after a reload. */\n scopeId?: string\n}\n\n/** A push-driven buffer for a turn whose producer the caller does NOT own. */\nexport interface BufferedTurnTap {\n /** Buffer one event: persist (coalesced, on the flush window) + best-effort\n * live-deliver. Wire to a push source's per-event hook (e.g. agent-runtime\n * `handleChatTurn`'s `hooks.onEvent`). Marks the turn 'running' on first call. */\n onEvent(raw: unknown): Promise<void>\n /** Settle the turn: final flush + set status. Call after the producer resolves\n * ('complete') or rejects ('error'). 'error' flushes what was produced first. */\n done(status?: Extract<TurnStatus, 'complete' | 'error'>): Promise<void>\n}\n\n/**\n * The buffering core. Sequence-numbers every event, delivers it to `write`\n * (best-effort — a disconnected client never stops buffering), and flushes to\n * the store in coalesced batches. Drives both transports:\n *\n * • {@link pumpBufferedTurn} — when you OWN an `AsyncIterable` producer.\n * • this tap (`onEvent`/`done`) — when the producer owns iteration and only\n * hands you a push callback (agent-runtime `handleChatTurn`'s `hooks.onEvent`\n * + the finished body). Durability stays here in the shell; the engine needs\n * no `TurnEventStore` seam.\n */\nexport function createBufferedTurnTap(opts: BufferedTurnOptions): BufferedTurnTap {\n const flushIntervalMs = opts.flushIntervalMs ?? 400\n const coalesce = opts.coalesce ?? coalesceDeltas\n const startedAt = Date.now()\n let seq = 0\n let clientGone = false\n let pending: unknown[] = []\n let lastFlush = Date.now()\n let started = false\n\n async function flush(): Promise<void> {\n if (pending.length === 0) return\n const batch = coalesce(pending)\n pending = []\n const rows = batch.map((ev) => ({ seq: ++seq, event: JSON.stringify(ev) }))\n await opts.store.append(opts.turnId, rows)\n lastFlush = Date.now()\n }\n\n async function ensureStarted(): Promise<void> {\n if (started) return\n started = true\n await opts.store.setStatus(opts.turnId, 'running', opts.scopeId)\n }\n\n return {\n async onEvent(raw) {\n await ensureStarted()\n // Stamp ms-since-turn-start so any stored turn is replayable AND traceable\n // (see ../trace) from the same buffered rows.\n const ev = raw && typeof raw === 'object' ? { ...(raw as Record<string, unknown>), _t: Date.now() - startedAt } : raw\n pending.push(ev)\n if (!clientGone && opts.write) {\n try {\n // Live delivery carries a provisional ordering hint, not the persisted\n // seq (coalescing changes seq assignment); clients resume with the\n // seqs from replay, or 0 for \"everything\".\n await opts.write(JSON.stringify(ev))\n } catch {\n clientGone = true\n }\n }\n if (Date.now() - lastFlush >= flushIntervalMs) await flush()\n },\n async done(status = 'complete') {\n await ensureStarted()\n if (status === 'error') {\n await flush().catch(() => {})\n await opts.store.setStatus(opts.turnId, 'error', opts.scopeId).catch(() => {})\n return\n }\n await flush()\n await opts.store.setStatus(opts.turnId, 'complete', opts.scopeId)\n },\n }\n}\n\n// ── pump (producer side) ──────────────────────────────────────────────────\n\n/** Define options to pump data from an asynchronous iterable source with buffered turn control */\nexport interface PumpBufferedTurnOptions extends BufferedTurnOptions {\n source: AsyncIterable<unknown>\n}\n\n/**\n * Drive a turn to completion regardless of the live client, when you OWN the\n * producer as an `AsyncIterable`. A thin driver over {@link createBufferedTurnTap}.\n * Returns a promise that resolves when the turn finishes — hand it to\n * `ctx.waitUntil` so a disconnect can't kill the turn. Never rejects on\n * client-write failure; a source error marks the turn 'error' (after flushing\n * what was produced) and rethrows.\n */\nexport async function pumpBufferedTurn(opts: PumpBufferedTurnOptions): Promise<void> {\n const tap = createBufferedTurnTap(opts)\n try {\n for await (const raw of opts.source) await tap.onEvent(raw)\n await tap.done('complete')\n } catch (err) {\n await tap.done('error')\n throw err\n }\n}\n\n// ── replay (consumer side) ────────────────────────────────────────────────\n\n/** Define options for replaying turn events with control over sequence, polling, and timeout */\nexport interface ReplayTurnEventsOptions {\n store: TurnEventStore\n turnId: string\n /** Replay strictly after this sequence number (0 = from the beginning). */\n fromSeq?: number\n /** Poll cadence while the turn is still running. Default 500ms. */\n pollMs?: number\n /** Give up following a 'running' turn after this long. Default 120s. */\n timeoutMs?: number\n}\n\n/**\n * Yield buffered events after `fromSeq`, then keep polling while the turn is\n * still 'running' until it completes, errors, or times out. Terminates with a\n * final `{seq: -1, event: '{\"type\":\"turn_status\",...}'}` marker so clients\n * know why the replay ended.\n */\nexport async function* replayTurnEvents(opts: ReplayTurnEventsOptions): AsyncGenerator<BufferedTurnEvent> {\n const pollMs = opts.pollMs ?? 500\n const timeoutMs = opts.timeoutMs ?? 120_000\n let cursor = opts.fromSeq ?? 0\n const deadline = Date.now() + timeoutMs\n\n for (;;) {\n const batch = await opts.store.read(opts.turnId, cursor)\n for (const row of batch) {\n cursor = Math.max(cursor, row.seq)\n yield row\n }\n const status = await opts.store.getStatus(opts.turnId)\n if (status !== 'running') {\n yield { seq: -1, event: JSON.stringify({ type: 'turn_status', status: status ?? 'unknown' }) }\n return\n }\n if (Date.now() >= deadline) {\n yield { seq: -1, event: JSON.stringify({ type: 'turn_status', status: 'timeout' }) }\n return\n }\n await new Promise((r) => setTimeout(r, pollMs))\n }\n}\n\n// ── D1 store ──────────────────────────────────────────────────────────────\n\n/** Minimal structural D1 contract (Cloudflare `D1Database` satisfies it). */\nexport interface D1LikeForTurns {\n prepare(sql: string): {\n bind(...values: unknown[]): {\n run(): Promise<unknown>\n all<T = Record<string, unknown>>(): Promise<{ results: T[] }>\n first<T = Record<string, unknown>>(): Promise<T | null>\n }\n }\n}\n\n/** Schema for the D1 store — append to the product's migrations. */\nexport const TURN_EVENTS_MIGRATION_SQL = `\nCREATE TABLE IF NOT EXISTS turn_events (\n turnId TEXT NOT NULL,\n seq INTEGER NOT NULL,\n event TEXT NOT NULL,\n PRIMARY KEY (turnId, seq)\n);\nCREATE TABLE IF NOT EXISTS turn_status (\n turnId TEXT PRIMARY KEY,\n status TEXT NOT NULL,\n scopeId TEXT,\n updatedAt TEXT NOT NULL\n);\nCREATE INDEX IF NOT EXISTS idx_turn_status_scope ON turn_status (scopeId, status);\n`\n\n/** For deployments whose `turn_status` table predates `scopeId`/`listRunning` —\n * run once to add the column (the CREATE above already includes it for new\n * deployments). SQLite ignores a duplicate-add error if already applied. */\nexport const TURN_STATUS_SCOPE_MIGRATION_SQL = `ALTER TABLE turn_status ADD COLUMN scopeId TEXT;`\n\n/** Resolve a TurnEventStore that appends and reads turn events using a D1-like database interface */\nexport function createD1TurnEventStore(db: D1LikeForTurns): TurnEventStore {\n return {\n async append(turnId, events) {\n if (!events.length) return\n // One multi-row insert per flush window keeps write volume bounded.\n const placeholders = events.map(() => '(?, ?, ?)').join(', ')\n const values = events.flatMap((e) => [turnId, e.seq, e.event])\n await db.prepare(`INSERT OR IGNORE INTO turn_events (turnId, seq, event) VALUES ${placeholders}`).bind(...values).run()\n },\n async read(turnId, fromSeq) {\n const { results } = await db\n .prepare('SELECT seq, event FROM turn_events WHERE turnId = ? AND seq > ? ORDER BY seq ASC')\n .bind(turnId, fromSeq)\n .all<{ seq: number; event: string }>()\n return results\n },\n async setStatus(turnId, status, scopeId) {\n // COALESCE preserves a scopeId set on the initial 'running' write when a\n // later 'complete'/'error' write passes none.\n await db\n .prepare(\n 'INSERT INTO turn_status (turnId, status, scopeId, updatedAt) VALUES (?, ?, ?, ?) ON CONFLICT(turnId) DO UPDATE SET status = excluded.status, scopeId = COALESCE(excluded.scopeId, turn_status.scopeId), updatedAt = excluded.updatedAt',\n )\n .bind(turnId, status, scopeId ?? null, new Date().toISOString())\n .run()\n },\n async getStatus(turnId) {\n const row = await db.prepare('SELECT status FROM turn_status WHERE turnId = ?').bind(turnId).first<{ status: TurnStatus }>()\n return row?.status ?? null\n },\n async listRunning(scopeId) {\n const { results } = await db\n .prepare(\"SELECT turnId FROM turn_status WHERE scopeId = ? AND status = 'running' ORDER BY updatedAt DESC\")\n .bind(scopeId)\n .all<{ turnId: string }>()\n return results.map((r) => r.turnId)\n },\n }\n}\n\n/** In-memory store for tests and keyless local dev. */\nexport function createMemoryTurnEventStore(): TurnEventStore {\n const events = new Map<string, BufferedTurnEvent[]>()\n const status = new Map<string, TurnStatus>()\n const scopes = new Map<string, string>()\n const order: string[] = []\n return {\n async append(turnId, rows) {\n const list = events.get(turnId) ?? []\n list.push(...rows)\n events.set(turnId, list)\n },\n async read(turnId, fromSeq) {\n return (events.get(turnId) ?? []).filter((e) => e.seq > fromSeq)\n },\n async setStatus(turnId, s, scopeId) {\n status.set(turnId, s)\n if (scopeId) scopes.set(turnId, scopeId)\n if (!order.includes(turnId)) order.push(turnId)\n },\n async getStatus(turnId) {\n return status.get(turnId) ?? null\n },\n async listRunning(scopeId) {\n // Newest first, mirroring the D1 store's `ORDER BY updatedAt DESC`.\n return [...order].reverse().filter((t) => status.get(t) === 'running' && scopes.get(t) === scopeId)\n },\n }\n}\n"],"mappings":";AAmBO,SAAS,sBAAsB,OAAoC;AACxE,MAAI,UAAU,UAAa,UAAU,KAAM,QAAO;AAClD,MAAI,OAAO,UAAU,SAAU,OAAM,IAAI,MAAM,yBAAyB;AACxE,QAAM,UAAU,MAAM,KAAK;AAC3B,MAAI,CAAC,QAAS,OAAM,IAAI,MAAM,0BAA0B;AACxD,MAAI,QAAQ,SAAS,IAAK,OAAM,IAAI,MAAM,oBAAoB;AAC9D,MAAI,CAAC,oBAAoB,KAAK,OAAO,GAAG;AACtC,UAAM,IAAI,MAAM,wCAAwC;AAAA,EAC1D;AACA,SAAO;AACT;AAGO,SAAS,mBAAmB,MAAc,QAA0C;AACzF,QAAM,OAAmB,EAAE,MAAM,QAAQ,KAAK;AAC9C,MAAI,OAAQ,MAAK,SAAS;AAC1B,SAAO,CAAC,IAAI;AACd;AAGO,SAAS,iBAAiB,SAAsC,QAAyB;AAC9F,aAAW,QAAQ,QAAQ,SAAS,CAAC,GAAG;AACtC,QAAI,QAAQ,OAAO,SAAS,YAAY,OAAO,KAAK,UAAU,EAAE,MAAM,QAAQ;AAC5E,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAGO,SAAS,gBAAgB,OAIX;AACnB,QAAM,EAAE,kBAAkB,aAAa,OAAO,IAAI;AAClD,QAAM,gBAAgB,6BAA6B,kBAAkB,aAAa,MAAM;AACxF,MAAI,iBAAiB,GAAG;AACtB,WAAO;AAAA,MACL,WAAW,kBAAkB,iBAAiB,MAAM,GAAG,aAAa,CAAC;AAAA,MACrE,yBAAyB;AAAA,MACzB,eAAe,iBAAiB,MAAM,GAAG,aAAa;AAAA,MACtD,WAAW,mBAAmB,aAAa,MAAM;AAAA,IACnD;AAAA,EACF;AAEA,SAAO;AAAA,IACL,WAAW,kBAAkB,gBAAgB;AAAA,IAC7C,yBAAyB;AAAA,IACzB,eAAe;AAAA,IACf,WAAW,mBAAmB,aAAa,MAAM;AAAA,EACnD;AACF;AAEA,SAAS,6BACP,UACA,aACA,QACQ;AACR,MAAI,QAAQ;AACV,aAAS,QAAQ,SAAS,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG;AAC5D,YAAM,UAAU,SAAS,KAAK;AAC9B,UAAI,SAAS,SAAS,UAAU,iBAAiB,SAAS,MAAM,EAAG,QAAO;AAAA,IAC5E;AAAA,EACF;AAEA,QAAM,SAAS,SAAS,GAAG,EAAE;AAC7B,MAAI,QAAQ,SAAS,UAAU,OAAO,YAAY,aAAa;AAC7D,WAAO,SAAS,SAAS;AAAA,EAC3B;AAEA,SAAO;AACT;AAEA,SAAS,kBAAkB,UAAiD;AAC1E,SAAO,SAAS,OAAO,CAAC,YAAY,QAAQ,SAAS,MAAM,EAAE;AAC/D;;;ACjDA,SAAS,YAAY,IAA0C;AAC7D,QAAM,IAAI;AACV,MAAI,CAAC,KAAK,OAAO,MAAM,SAAU,QAAO;AACxC,QAAM,QAAS,EAAE,SAAS,UAAW,EAAE,QAAkC;AACzE,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,OAAK,MAAM,SAAS,UAAU,MAAM,SAAS,gBAAgB,OAAO,MAAM,SAAS,UAAU;AAC3F,WAAO,MAAM;AAAA,EACf;AACA,SAAO;AACT;AAKO,SAAS,eAAe,QAA8B;AAC3D,QAAM,MAAiB,CAAC;AACxB,aAAW,MAAM,QAAQ;AACvB,UAAM,OAAO,YAAY,EAAE;AAC3B,UAAM,OAAO,IAAI,IAAI,SAAS,CAAC;AAC/B,QAAI,QAAQ,QAAQ,YAAY,IAAI,MAAM,MAAM;AAC9C,YAAM,OAAO,CAAC,MACV,EAAgB,SAAS,UAAW,EAAgB,QAAQ;AAChE,YAAM,SAAS,KAAK,MAAM,KAAK,UAAU,IAAI,CAAC;AAC9C,WAAK,MAAM,EAAE,OAAO,OAAO,KAAK,IAAI,EAAE,IAAI,IAAI,OAAO,KAAK,EAAE,EAAE,IAAI;AAClE,UAAI,IAAI,SAAS,CAAC,IAAI;AACtB;AAAA,IACF;AACA,QAAI,KAAK,EAAE;AAAA,EACb;AACA,SAAO;AACT;AAEA,SAAS,aAAa,IAAyD;AAC7E,QAAM,IAAI;AACV,MAAI,CAAC,KAAK,OAAO,MAAM,YAAY,EAAE,SAAS,uBAAwB,QAAO;AAC7E,QAAM,OAAO,EAAE;AACf,MAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO;AAC9C,QAAM,OAAO,KAAK;AAClB,QAAM,SAAS,MAAM,MAAM,KAAK,UAAU,MAAM,UAAU;AAC1D,SAAO,EAAE,QAAQ,OAAO,KAAK,MAAM;AACrC;AAgBO,SAAS,yBAAyB,QAA8B;AACrE,QAAM,MAAiB,CAAC;AACxB,aAAW,MAAM,QAAQ;AACvB,UAAM,MAAM,aAAa,EAAE;AAC3B,UAAM,SAAS,IAAI,IAAI,SAAS,CAAC;AACjC,UAAM,OAAO,SAAS,aAAa,MAAM,IAAI;AAC7C,QAAI,OAAO,QAAQ,IAAI,UAAU,QAAQ,IAAI,WAAW,KAAK,QAAQ;AAGnE,YAAM,SAAS,KAAK,MAAM,KAAK,UAAU,EAAE,CAAC;AAC3C,MAAC,OAAO,KAAmB,QAAQ,OAAO,KAAK,SAAS,EAAE,IAAI,OAAO,IAAI,SAAS,EAAE;AACrF,UAAI,IAAI,SAAS,CAAC,IAAI;AACtB;AAAA,IACF;AACA,QAAI,KAAK,EAAE;AAAA,EACb;AACA,SAAO;AACT;AA6CO,SAAS,sBAAsB,MAA4C;AAChF,QAAM,kBAAkB,KAAK,mBAAmB;AAChD,QAAM,WAAW,KAAK,YAAY;AAClC,QAAM,YAAY,KAAK,IAAI;AAC3B,MAAI,MAAM;AACV,MAAI,aAAa;AACjB,MAAI,UAAqB,CAAC;AAC1B,MAAI,YAAY,KAAK,IAAI;AACzB,MAAI,UAAU;AAEd,iBAAe,QAAuB;AACpC,QAAI,QAAQ,WAAW,EAAG;AAC1B,UAAM,QAAQ,SAAS,OAAO;AAC9B,cAAU,CAAC;AACX,UAAM,OAAO,MAAM,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,KAAK,OAAO,KAAK,UAAU,EAAE,EAAE,EAAE;AAC1E,UAAM,KAAK,MAAM,OAAO,KAAK,QAAQ,IAAI;AACzC,gBAAY,KAAK,IAAI;AAAA,EACvB;AAEA,iBAAe,gBAA+B;AAC5C,QAAI,QAAS;AACb,cAAU;AACV,UAAM,KAAK,MAAM,UAAU,KAAK,QAAQ,WAAW,KAAK,OAAO;AAAA,EACjE;AAEA,SAAO;AAAA,IACL,MAAM,QAAQ,KAAK;AACjB,YAAM,cAAc;AAGpB,YAAM,KAAK,OAAO,OAAO,QAAQ,WAAW,EAAE,GAAI,KAAiC,IAAI,KAAK,IAAI,IAAI,UAAU,IAAI;AAClH,cAAQ,KAAK,EAAE;AACf,UAAI,CAAC,cAAc,KAAK,OAAO;AAC7B,YAAI;AAIF,gBAAM,KAAK,MAAM,KAAK,UAAU,EAAE,CAAC;AAAA,QACrC,QAAQ;AACN,uBAAa;AAAA,QACf;AAAA,MACF;AACA,UAAI,KAAK,IAAI,IAAI,aAAa,gBAAiB,OAAM,MAAM;AAAA,IAC7D;AAAA,IACA,MAAM,KAAK,SAAS,YAAY;AAC9B,YAAM,cAAc;AACpB,UAAI,WAAW,SAAS;AACtB,cAAM,MAAM,EAAE,MAAM,MAAM;AAAA,QAAC,CAAC;AAC5B,cAAM,KAAK,MAAM,UAAU,KAAK,QAAQ,SAAS,KAAK,OAAO,EAAE,MAAM,MAAM;AAAA,QAAC,CAAC;AAC7E;AAAA,MACF;AACA,YAAM,MAAM;AACZ,YAAM,KAAK,MAAM,UAAU,KAAK,QAAQ,YAAY,KAAK,OAAO;AAAA,IAClE;AAAA,EACF;AACF;AAiBA,eAAsB,iBAAiB,MAA8C;AACnF,QAAM,MAAM,sBAAsB,IAAI;AACtC,MAAI;AACF,qBAAiB,OAAO,KAAK,OAAQ,OAAM,IAAI,QAAQ,GAAG;AAC1D,UAAM,IAAI,KAAK,UAAU;AAAA,EAC3B,SAAS,KAAK;AACZ,UAAM,IAAI,KAAK,OAAO;AACtB,UAAM;AAAA,EACR;AACF;AAsBA,gBAAuB,iBAAiB,MAAkE;AACxG,QAAM,SAAS,KAAK,UAAU;AAC9B,QAAM,YAAY,KAAK,aAAa;AACpC,MAAI,SAAS,KAAK,WAAW;AAC7B,QAAM,WAAW,KAAK,IAAI,IAAI;AAE9B,aAAS;AACP,UAAM,QAAQ,MAAM,KAAK,MAAM,KAAK,KAAK,QAAQ,MAAM;AACvD,eAAW,OAAO,OAAO;AACvB,eAAS,KAAK,IAAI,QAAQ,IAAI,GAAG;AACjC,YAAM;AAAA,IACR;AACA,UAAM,SAAS,MAAM,KAAK,MAAM,UAAU,KAAK,MAAM;AACrD,QAAI,WAAW,WAAW;AACxB,YAAM,EAAE,KAAK,IAAI,OAAO,KAAK,UAAU,EAAE,MAAM,eAAe,QAAQ,UAAU,UAAU,CAAC,EAAE;AAC7F;AAAA,IACF;AACA,QAAI,KAAK,IAAI,KAAK,UAAU;AAC1B,YAAM,EAAE,KAAK,IAAI,OAAO,KAAK,UAAU,EAAE,MAAM,eAAe,QAAQ,UAAU,CAAC,EAAE;AACnF;AAAA,IACF;AACA,UAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC;AAAA,EAChD;AACF;AAgBO,IAAM,4BAA4B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmBlC,IAAM,kCAAkC;AAGxC,SAAS,uBAAuB,IAAoC;AACzE,SAAO;AAAA,IACL,MAAM,OAAO,QAAQ,QAAQ;AAC3B,UAAI,CAAC,OAAO,OAAQ;AAEpB,YAAM,eAAe,OAAO,IAAI,MAAM,WAAW,EAAE,KAAK,IAAI;AAC5D,YAAM,SAAS,OAAO,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC;AAC7D,YAAM,GAAG,QAAQ,iEAAiE,YAAY,EAAE,EAAE,KAAK,GAAG,MAAM,EAAE,IAAI;AAAA,IACxH;AAAA,IACA,MAAM,KAAK,QAAQ,SAAS;AAC1B,YAAM,EAAE,QAAQ,IAAI,MAAM,GACvB,QAAQ,kFAAkF,EAC1F,KAAK,QAAQ,OAAO,EACpB,IAAoC;AACvC,aAAO;AAAA,IACT;AAAA,IACA,MAAM,UAAU,QAAQ,QAAQ,SAAS;AAGvC,YAAM,GACH;AAAA,QACC;AAAA,MACF,EACC,KAAK,QAAQ,QAAQ,WAAW,OAAM,oBAAI,KAAK,GAAE,YAAY,CAAC,EAC9D,IAAI;AAAA,IACT;AAAA,IACA,MAAM,UAAU,QAAQ;AACtB,YAAM,MAAM,MAAM,GAAG,QAAQ,iDAAiD,EAAE,KAAK,MAAM,EAAE,MAA8B;AAC3H,aAAO,KAAK,UAAU;AAAA,IACxB;AAAA,IACA,MAAM,YAAY,SAAS;AACzB,YAAM,EAAE,QAAQ,IAAI,MAAM,GACvB,QAAQ,iGAAiG,EACzG,KAAK,OAAO,EACZ,IAAwB;AAC3B,aAAO,QAAQ,IAAI,CAAC,MAAM,EAAE,MAAM;AAAA,IACpC;AAAA,EACF;AACF;AAGO,SAAS,6BAA6C;AAC3D,QAAM,SAAS,oBAAI,IAAiC;AACpD,QAAM,SAAS,oBAAI,IAAwB;AAC3C,QAAM,SAAS,oBAAI,IAAoB;AACvC,QAAM,QAAkB,CAAC;AACzB,SAAO;AAAA,IACL,MAAM,OAAO,QAAQ,MAAM;AACzB,YAAM,OAAO,OAAO,IAAI,MAAM,KAAK,CAAC;AACpC,WAAK,KAAK,GAAG,IAAI;AACjB,aAAO,IAAI,QAAQ,IAAI;AAAA,IACzB;AAAA,IACA,MAAM,KAAK,QAAQ,SAAS;AAC1B,cAAQ,OAAO,IAAI,MAAM,KAAK,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,MAAM,OAAO;AAAA,IACjE;AAAA,IACA,MAAM,UAAU,QAAQ,GAAG,SAAS;AAClC,aAAO,IAAI,QAAQ,CAAC;AACpB,UAAI,QAAS,QAAO,IAAI,QAAQ,OAAO;AACvC,UAAI,CAAC,MAAM,SAAS,MAAM,EAAG,OAAM,KAAK,MAAM;AAAA,IAChD;AAAA,IACA,MAAM,UAAU,QAAQ;AACtB,aAAO,OAAO,IAAI,MAAM,KAAK;AAAA,IAC/B;AAAA,IACA,MAAM,YAAY,SAAS;AAEzB,aAAO,CAAC,GAAG,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,MAAM,OAAO,IAAI,CAAC,MAAM,aAAa,OAAO,IAAI,CAAC,MAAM,OAAO;AAAA,IACpG;AAAA,EACF;AACF;","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  validateAnswer
3
- } from "./chunk-ND3XEGBE.js";
3
+ } from "./chunk-JDEGS53O.js";
4
4
 
5
5
  // src/intakes-react/components/IntakeInterview.tsx
6
6
  import { useEffect, useState } from "react";
@@ -209,4 +209,4 @@ function normalize(question, value) {
209
209
  export {
210
210
  IntakeInterview
211
211
  };
212
- //# sourceMappingURL=chunk-5I72FRZY.js.map
212
+ //# sourceMappingURL=chunk-VOJB7MVG.js.map
@@ -3,7 +3,7 @@ import {
3
3
  applySceneOperations,
4
4
  requireElement,
5
5
  requirePage
6
- } from "./chunk-M2EBUDZ7.js";
6
+ } from "./chunk-VWOPOLVO.js";
7
7
 
8
8
  // src/design-canvas-react/engine/command-stack.ts
9
9
  var SCENE_COMMAND_HISTORY_LIMIT = 200;
@@ -601,4 +601,4 @@ export {
601
601
  bindSlotCommand,
602
602
  setDocumentTitleCommand
603
603
  };
604
- //# sourceMappingURL=chunk-XWJXZ6WE.js.map
604
+ //# sourceMappingURL=chunk-VTWKH4YU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/design-canvas-react/engine/command-stack.ts","../src/design-canvas-react/engine/commands.ts"],"sourcesContent":["/**\n * Undo/redo command stack over immutable `EditorSceneState`.\n *\n * History entries hold COMMANDS (state transforms + durable operations\n * captured at construction), never snapshots. Rebasing the document via\n * `reset()` therefore cannot stale the history: a later undo re-applies the\n * inverse transform to whatever document is current. If the rebase removed an\n * element a historical command targets, that transform throws (fail loud)\n * rather than silently editing the wrong element.\n *\n * `setView` updates volatile view state (zoom/pan/selection/toggles) without\n * touching history — view changes are never undo steps.\n */\n\nimport type { SceneDocument } from '../../design-canvas/model'\nimport type { EditorSceneState, SceneCommand, SceneCommandStack } from '../contracts'\n\n/** Oldest entries are dropped past this bound; redo stack is cleared on execute. */\nexport const SCENE_COMMAND_HISTORY_LIMIT = 200\n\n/**\n * The base {@link SceneCommandStack} plus the two command-specific recovery\n * primitives the undo/redo persistence path needs. `rollback` (on the base\n * contract) undoes a failed COMMIT; these undo a failed UNDO/REDO persist.\n * Defined here (not on the shared contract) so consumers that take the stack as\n * `ReturnType<typeof createSceneCommandStack>` see them without a contract bump.\n */\nexport interface SceneCommandStackWithReapply extends SceneCommandStack {\n /**\n * A persisted UNDO rejected: re-apply that command's FORWARD transform (move\n * it redo→undo). Mirrors `rollback`'s command-specific contract — it acts on\n * the captured command, not blindly on the redo-stack top, so an interleaved\n * edit cannot make it re-apply the wrong command. No-op if the command is not\n * the top of the redo stack (a newer edit reshaped history — the next\n * `reset()` reconciles).\n */\n reexecute(command: SceneCommand): void\n /**\n * A persisted REDO rejected: re-apply that command's INVERSE transform (move\n * it undo→redo). The redo-side mirror of `reexecute`. No-op unless the command\n * is the top of the undo stack.\n */\n reundo(command: SceneCommand): void\n}\n\n/** Create a command stack for scene editing with reapply capabilities based on the given document and page ID */\nexport function createSceneCommandStack(document: SceneDocument, activePageId: string): SceneCommandStackWithReapply {\n let state: EditorSceneState = {\n document,\n activePageId,\n selectedElementIds: [],\n zoom: 1,\n panX: 0,\n panY: 0,\n gridEnabled: false,\n gridSize: 10,\n snapEnabled: true,\n showRulers: true,\n showBleed: false,\n }\n\n const undoStack: SceneCommand[] = []\n const redoStack: SceneCommand[] = []\n const listeners = new Set<() => void>()\n\n const notify = (): void => {\n for (const listener of [...listeners]) listener()\n }\n\n return {\n execute(command: SceneCommand): void {\n state = command.execute(state)\n undoStack.push(command)\n if (undoStack.length > SCENE_COMMAND_HISTORY_LIMIT) {\n undoStack.splice(0, undoStack.length - SCENE_COMMAND_HISTORY_LIMIT)\n }\n redoStack.length = 0\n notify()\n },\n\n // Both transforms run BEFORE the stacks move: a throwing transform (e.g.\n // missing element after reset()) leaves history and state exactly as they\n // were. The entry is never silently destroyed — the caller can retry after\n // the next server refresh restores the target.\n undo(): SceneCommand {\n const command = undoStack[undoStack.length - 1]\n if (!command) throw new Error('nothing to undo — guard with canUndo() before calling undo()')\n state = command.undo(state)\n undoStack.pop()\n redoStack.push(command)\n notify()\n return command\n },\n\n redo(): SceneCommand {\n const command = redoStack[redoStack.length - 1]\n if (!command) throw new Error('nothing to redo — guard with canRedo() before calling redo()')\n state = command.execute(state)\n redoStack.pop()\n undoStack.push(command)\n notify()\n return command\n },\n\n canUndo(): boolean {\n return undoStack.length > 0\n },\n\n canRedo(): boolean {\n return redoStack.length > 0\n },\n\n subscribe(listener: () => void): () => void {\n listeners.add(listener)\n return () => {\n listeners.delete(listener)\n }\n },\n\n getState(): EditorSceneState {\n return state\n },\n\n setView(patch: Partial<Omit<EditorSceneState, 'document'>>): void {\n state = { ...state, ...patch }\n notify()\n },\n\n // A persisted UNDO rejected: the server still has `command` applied, but the\n // local undo already removed it (and a later execute may have cleared the\n // redo stack). Deterministically re-converge — mirror of `rollback`, in the\n // forward direction: re-apply the command's FORWARD transform to current\n // state and ensure it lives on the undo stack (so a later undo can remove it\n // again). Idempotent: if the command is already on the undo stack (the undo\n // never actually left local history), this is a no-op. For disjoint edits the\n // forward transform commutes past commands executed while the undo was\n // pending, so their net effect is preserved.\n reexecute(command: SceneCommand): void {\n if (undoStack.includes(command)) return\n state = command.execute(state)\n const redoIdx = redoStack.lastIndexOf(command)\n if (redoIdx !== -1) redoStack.splice(redoIdx, 1)\n undoStack.push(command)\n notify()\n },\n\n // A persisted REDO rejected: the server does NOT have `command` applied, but\n // the local redo just applied it forward and put it on the undo stack.\n // Re-apply its INVERSE and move it to the redo stack — the redo-side mirror\n // of `reexecute`. No-op if the command is not on the undo stack.\n reundo(command: SceneCommand): void {\n const undoIdx = undoStack.lastIndexOf(command)\n if (undoIdx === -1) return\n state = command.undo(state)\n undoStack.splice(undoIdx, 1)\n if (!redoStack.includes(command)) redoStack.push(command)\n notify()\n },\n\n rollback(command: SceneCommand): void {\n const idx = undoStack.lastIndexOf(command)\n // Command not in history — stale or double-fire rejection handler; no-op.\n if (idx === -1) return\n\n // Apply the command's inverse against the current state. For non-overlapping\n // edits (different elements or different attributes) this is exact: the\n // inverse commutes freely past all subsequent commands. For overlapping edits\n // on the same attribute the result is defined but not semantically perfect;\n // the persistence layer should trigger an onResyncRequired refetch in that\n // case so the server document reconciles.\n state = command.undo(state)\n\n // Splice the target command out of the undo stack.\n undoStack.splice(idx, 1)\n\n // Clear the redo stack: its entries were computed relative to a history that\n // included this command, so they are now stale.\n redoStack.length = 0\n\n notify()\n },\n\n /** Rebase onto a server-refreshed document. History survives; selection\n * drops ids the refresh removed so view state never dangles. */\n reset(newDocument: SceneDocument): void {\n // Collect all live element ids across all pages for selection cleanup\n const liveElementIds = new Set<string>()\n for (const page of newDocument.pages) {\n collectElementIds(page.elements, liveElementIds)\n }\n // If the active page was removed, fall back to the first page\n const activePageExists = newDocument.pages.some((p) => p.id === state.activePageId)\n const activePageId = activePageExists ? state.activePageId : (newDocument.pages[0]?.id ?? state.activePageId)\n state = {\n ...state,\n document: newDocument,\n activePageId,\n selectedElementIds: state.selectedElementIds.filter((id) => liveElementIds.has(id)),\n }\n notify()\n },\n }\n}\n\nfunction collectElementIds(elements: ReturnType<typeof Array.prototype.slice>, ids: Set<string>): void {\n for (const el of elements as Array<{ id: string; kind: string; children?: unknown[] }>) {\n ids.add(el.id)\n if (el.kind === 'group' && Array.isArray(el.children)) {\n collectElementIds(el.children as Array<{ id: string; kind: string; children?: unknown[] }>, ids)\n }\n }\n}\n","/**\n * Concrete `SceneCommand` factories for the design-canvas editor. Every factory\n * captures the inverse from PRE-state at construction — undo is a value\n * computed once, never re-derived from current state later. Local execute/undo\n * update `EditorSceneState` immutably by routing through `applySceneOperation`\n * so optimistic state matches what the server-side dispatcher will persist.\n *\n * Drag gestures coalesce: pointer moves update volatile state, ONE command\n * executes on pointer release with (finalAttrs, priorAttrs). `setAttrsCommand`\n * is that gesture command — one undo step per drag/transform/toolbar change.\n * `multiSetAttrsCommand` collects N set_attrs ops into one undo step for\n * multi-select transforms.\n *\n * Group/ungroup route through `applySceneOperation` so the group-origin\n * rebasing in `apply.ts` is the single source of truth for both optimistic and\n * server state.\n */\n\nimport type { SceneDocument, SceneElement, ScenePage } from '../../design-canvas/model'\nimport { requireElement, requirePage } from '../../design-canvas/model'\nimport { applySceneOperation, applySceneOperations } from '../../design-canvas/apply'\nimport type {\n AddElementOperation,\n DeleteElementOperation,\n SceneAttrsPatch,\n SceneOperation,\n} from '../../design-canvas/operations'\nimport type { EditorSceneState, SceneCommand } from '../contracts'\n\n// ---------------------------------------------------------------------------\n// Shared helpers\n// ---------------------------------------------------------------------------\n\nfunction applyOps(state: EditorSceneState, ops: SceneOperation[]): EditorSceneState {\n return { ...state, document: applySceneOperations(state.document, ops) }\n}\n\nfunction applyOp(state: EditorSceneState, op: SceneOperation): EditorSceneState {\n return { ...state, document: applySceneOperation(state.document, op) }\n}\n\n// ---------------------------------------------------------------------------\n// add_element / inverse = delete_element\n// ---------------------------------------------------------------------------\n\n/** Define input parameters for adding a scene element with optional index and parent group ID */\nexport interface AddElementInput {\n pageId: string\n element: SceneElement\n /** Insertion z-index within owner; omitted → top. */\n index?: number\n /** Parent group id; omitted → page root. */\n parentGroupId?: string\n}\n\n/** Create a command to add an element to a scene with optional positioning and grouping */\nexport function addElementCommand(input: AddElementInput): SceneCommand {\n const addOp: SceneOperation = {\n type: 'add_element',\n pageId: input.pageId,\n element: structuredClone(input.element),\n ...(input.index !== undefined ? { index: input.index } : {}),\n ...(input.parentGroupId !== undefined ? { parentGroupId: input.parentGroupId } : {}),\n }\n const deleteOp: SceneOperation = {\n type: 'delete_element',\n pageId: input.pageId,\n elementId: input.element.id,\n }\n\n return {\n label: `Add ${input.element.kind}`,\n execute: (state) => applyOp(state, addOp),\n undo: (state) => applyOp(state, deleteOp),\n operations: () => [structuredClone(addOp)],\n inverseOperations: () => [structuredClone(deleteOp)],\n }\n}\n\n// ---------------------------------------------------------------------------\n// set_attrs — THE gesture command (one undo step per drag/transform)\n// ---------------------------------------------------------------------------\n\n/** Define input parameters for setting element attributes within a specific page context */\nexport interface SetAttrsInput {\n pageId: string\n elementId: string\n /** Final attribute values after the gesture. */\n attrs: SceneAttrsPatch\n /** Attribute values BEFORE the gesture began — inverse is built from these. */\n priorAttrs: SceneAttrsPatch\n}\n\n/** Create a command to set attributes on a scene element with undo capability */\nexport function setAttrsCommand(input: SetAttrsInput): SceneCommand {\n const forwardOp: SceneOperation = {\n type: 'set_attrs',\n pageId: input.pageId,\n elementId: input.elementId,\n attrs: structuredClone(input.attrs),\n }\n const inverseOp: SceneOperation = {\n type: 'set_attrs',\n pageId: input.pageId,\n elementId: input.elementId,\n attrs: structuredClone(input.priorAttrs),\n }\n\n return {\n label: 'Edit element',\n execute: (state) => applyOp(state, forwardOp),\n undo: (state) => applyOp(state, inverseOp),\n operations: () => [structuredClone(forwardOp)],\n inverseOperations: () => [structuredClone(inverseOp)],\n }\n}\n\n// ---------------------------------------------------------------------------\n// multi-select set_attrs — N set_attrs ops, one undo step\n// ---------------------------------------------------------------------------\n\n/** Define an entry linking page and element IDs with current and prior scene attribute patches */\nexport interface MultiSetAttrsEntry {\n pageId: string\n elementId: string\n attrs: SceneAttrsPatch\n priorAttrs: SceneAttrsPatch\n}\n\n/** Build a scene command to set multiple attributes on elements across pages */\nexport function multiSetAttrsCommand(entries: MultiSetAttrsEntry[]): SceneCommand {\n if (entries.length === 0) throw new Error('multiSetAttrsCommand: entries must not be empty')\n\n const forwardOps: SceneOperation[] = entries.map((e) => ({\n type: 'set_attrs' as const,\n pageId: e.pageId,\n elementId: e.elementId,\n attrs: structuredClone(e.attrs),\n }))\n const inverseOps: SceneOperation[] = entries.map((e) => ({\n type: 'set_attrs' as const,\n pageId: e.pageId,\n elementId: e.elementId,\n attrs: structuredClone(e.priorAttrs),\n }))\n\n return {\n label: `Edit ${entries.length} elements`,\n execute: (state) => applyOps(state, forwardOps),\n undo: (state) => applyOps(state, inverseOps),\n operations: () => structuredClone(forwardOps),\n inverseOperations: () => structuredClone(inverseOps),\n }\n}\n\n// ---------------------------------------------------------------------------\n// reorder_element\n// ---------------------------------------------------------------------------\n\n/** Define input parameters to reorder an element within a page */\nexport interface ReorderElementInput {\n pageId: string\n elementId: string\n toIndex: number\n}\n\n/** Resolve a command to reorder an element within a scene by moving it to a specified index */\nexport function reorderElementCommand(input: ReorderElementInput): SceneCommand {\n // Capture the element's current index at construction for the inverse\n let capturedFromIndex: number | null = null\n\n const forwardOp: SceneOperation = {\n type: 'reorder_element',\n pageId: input.pageId,\n elementId: input.elementId,\n toIndex: input.toIndex,\n }\n\n return {\n label: 'Reorder element',\n execute: (state) => {\n // Guard: on redo the element is already at toIndex, so we must not\n // overwrite the captured origin with the wrong position.\n if (capturedFromIndex === null) {\n const page = requirePage(state.document, input.pageId)\n const { index } = requireElement(page, input.elementId)\n capturedFromIndex = index\n }\n return applyOp(state, forwardOp)\n },\n undo: (state) => {\n if (capturedFromIndex === null) {\n throw new Error('reorderElementCommand: undo called before execute')\n }\n return applyOp(state, {\n type: 'reorder_element',\n pageId: input.pageId,\n elementId: input.elementId,\n toIndex: capturedFromIndex,\n })\n },\n operations: () => [structuredClone(forwardOp)],\n inverseOperations: () => {\n if (capturedFromIndex === null) {\n throw new Error('reorderElementCommand: inverseOperations called before execute')\n }\n return [{\n type: 'reorder_element' as const,\n pageId: input.pageId,\n elementId: input.elementId,\n toIndex: capturedFromIndex,\n }]\n },\n }\n}\n\n// ---------------------------------------------------------------------------\n// delete_element / inverse = add_element (full snapshot + index + parent)\n// ---------------------------------------------------------------------------\n\n/** Define input parameters required to delete an element from a specific page in a document */\nexport interface DeleteElementInput {\n document: SceneDocument\n pageId: string\n elementId: string\n}\n\n/** Resolve a command to delete an element from a specified page in the document */\nexport function deleteElementCommand(input: DeleteElementInput): SceneCommand {\n const page = requirePage(input.document, input.pageId)\n const { element, owner, index } = requireElement(page, input.elementId)\n const snapshot = structuredClone(element)\n\n // Determine parentGroupId by finding which group owns this element\n const parentGroupId = findParentGroupId(page, owner)\n\n const deleteOp: DeleteElementOperation = {\n type: 'delete_element',\n pageId: input.pageId,\n elementId: input.elementId,\n }\n const addOp: AddElementOperation = {\n type: 'add_element',\n pageId: input.pageId,\n element: snapshot,\n index,\n ...(parentGroupId !== undefined ? { parentGroupId } : {}),\n }\n\n return {\n label: `Delete ${element.kind}`,\n execute: (state) => {\n const next = applyOp(state, deleteOp)\n return {\n ...next,\n selectedElementIds: next.selectedElementIds.filter((id) => id !== input.elementId),\n }\n },\n undo: (state) => applyOp(state, addOp),\n operations: () => [structuredClone(deleteOp)],\n inverseOperations: () => [structuredClone(addOp)],\n }\n}\n\nfunction findParentGroupId(page: ScenePage, owner: SceneElement[]): string | undefined {\n if (owner === page.elements) return undefined\n // Walk the element tree looking for a group whose children === owner\n return findGroupWithChildren(page.elements, owner)\n}\n\nfunction findGroupWithChildren(elements: SceneElement[], target: SceneElement[]): string | undefined {\n for (const el of elements) {\n if (el.kind === 'group') {\n if (el.children === target) return el.id\n const found = findGroupWithChildren(el.children, target)\n if (found !== undefined) return found\n }\n }\n return undefined\n}\n\n// ---------------------------------------------------------------------------\n// group_elements / inverse = ungroup_element\n// ---------------------------------------------------------------------------\n\n/** Define input parameters for grouping elements within a scene document on a specific page */\nexport interface GroupElementsInput {\n document: SceneDocument\n pageId: string\n elementIds: string[]\n groupId: string\n name?: string\n}\n\n/** Create a command to group multiple elements into a single group within a scene */\nexport function groupElementsCommand(input: GroupElementsInput): SceneCommand {\n if (input.elementIds.length < 2) {\n throw new Error('groupElementsCommand: requires ≥ 2 elementIds')\n }\n\n const groupOp: SceneOperation = {\n type: 'group_elements',\n pageId: input.pageId,\n elementIds: input.elementIds.slice(),\n groupId: input.groupId,\n ...(input.name !== undefined ? { name: input.name } : {}),\n }\n const ungroupOp: SceneOperation = {\n type: 'ungroup_element',\n pageId: input.pageId,\n groupId: input.groupId,\n }\n\n return {\n label: `Group ${input.elementIds.length} elements`,\n execute: (state) => {\n const next = applyOp(state, groupOp)\n return {\n ...next,\n selectedElementIds: [input.groupId],\n }\n },\n undo: (state) => {\n const next = applyOp(state, ungroupOp)\n return { ...next, selectedElementIds: input.elementIds.slice() }\n },\n operations: () => [structuredClone(groupOp)],\n inverseOperations: () => [structuredClone(ungroupOp)],\n }\n}\n\n// ---------------------------------------------------------------------------\n// ungroup_element / inverse = group_elements (re-using original ids)\n// ---------------------------------------------------------------------------\n\n/** Define input parameters required to ungroup elements within a specific page and group */\nexport interface UngroupElementInput {\n document: SceneDocument\n pageId: string\n groupId: string\n}\n\n/** Resolve a command to ungroup a group element into its child elements within a scene */\nexport function ungroupElementCommand(input: UngroupElementInput): SceneCommand {\n const page = requirePage(input.document, input.pageId)\n const { element } = requireElement(page, input.groupId)\n if (element.kind !== 'group') {\n throw new Error(`ungroupElementCommand: element ${input.groupId} is kind ${element.kind}, not group`)\n }\n const childIds = element.children.map((c) => c.id)\n\n const ungroupOp: SceneOperation = {\n type: 'ungroup_element',\n pageId: input.pageId,\n groupId: input.groupId,\n }\n const regroupOp: SceneOperation = {\n type: 'group_elements',\n pageId: input.pageId,\n elementIds: childIds,\n groupId: input.groupId,\n name: element.name,\n }\n\n return {\n label: `Ungroup`,\n execute: (state) => {\n const next = applyOp(state, ungroupOp)\n return { ...next, selectedElementIds: childIds.slice() }\n },\n undo: (state) => {\n const next = applyOp(state, regroupOp)\n return { ...next, selectedElementIds: [input.groupId] }\n },\n operations: () => [structuredClone(ungroupOp)],\n inverseOperations: () => [structuredClone(regroupOp)],\n }\n}\n\n// ---------------------------------------------------------------------------\n// Page commands\n// ---------------------------------------------------------------------------\n\n/** Define input parameters for adding a new page with optional settings and position index */\nexport interface AddPageInput {\n pageId: string\n options?: import('../../design-canvas/model').NewPageOptions\n index?: number\n}\n\n/** Create a command to add a page with optional settings and index in the scene */\nexport function addPageCommand(input: AddPageInput): SceneCommand {\n const addOp: SceneOperation = {\n type: 'add_page',\n pageId: input.pageId,\n ...(input.options !== undefined ? { options: input.options } : {}),\n ...(input.index !== undefined ? { index: input.index } : {}),\n }\n const deleteOp: SceneOperation = { type: 'delete_page', pageId: input.pageId }\n\n return {\n label: 'Add page',\n execute: (state) => {\n const next = applyOp(state, addOp)\n return { ...next, activePageId: input.pageId }\n },\n undo: (state) => {\n const next = applyOp(state, deleteOp)\n // Switch active page to first surviving page if we deleted the active one\n const activeExists = next.document.pages.some((p) => p.id === next.activePageId)\n return activeExists ? next : { ...next, activePageId: next.document.pages[0]!.id }\n },\n operations: () => [structuredClone(addOp)],\n inverseOperations: () => [structuredClone(deleteOp)],\n }\n}\n\n/** Define input parameters required to duplicate a page within a scene document */\nexport interface DuplicatePageInput {\n document: SceneDocument\n sourcePageId: string\n /** Caller-minted id for the copy. */\n pageId: string\n}\n\n/** Create a command to duplicate a page and prepare its deletion operation in the scene */\nexport function duplicatePageCommand(input: DuplicatePageInput): SceneCommand {\n requirePage(input.document, input.sourcePageId)\n\n const dupOp: SceneOperation = {\n type: 'duplicate_page',\n sourcePageId: input.sourcePageId,\n pageId: input.pageId,\n }\n const deleteOp: SceneOperation = { type: 'delete_page', pageId: input.pageId }\n\n return {\n label: 'Duplicate page',\n execute: (state) => {\n const next = applyOp(state, dupOp)\n return { ...next, activePageId: input.pageId }\n },\n undo: (state) => {\n const next = applyOp(state, deleteOp)\n const activeExists = next.document.pages.some((p) => p.id === next.activePageId)\n return activeExists ? next : { ...next, activePageId: input.sourcePageId }\n },\n operations: () => [structuredClone(dupOp)],\n inverseOperations: () => [structuredClone(deleteOp)],\n }\n}\n\n/** Define input parameters required to delete a page from a scene document */\nexport interface DeletePageInput {\n document: SceneDocument\n pageId: string\n}\n\n/** Delete a page from a document ensuring it is not the last remaining page */\nexport function deletePageCommand(input: DeletePageInput): SceneCommand {\n if (input.document.pages.length <= 1) {\n throw new Error('deletePageCommand: cannot delete the last page')\n }\n const page = requirePage(input.document, input.pageId)\n const currentIndex = input.document.pages.findIndex((p) => p.id === input.pageId)\n const snapshot = structuredClone(page)\n\n const deleteOp: SceneOperation = { type: 'delete_page', pageId: input.pageId }\n\n // Undo uses add_page + per-element add_element to restore the full snapshot.\n // The page shell is added first, then elements are inserted in z-order so\n // subsequent undo/redo round-trips see the correct stack. This also makes\n // inverseOperations() safe to emit server-side: the server will see the same\n // full restore instead of a bare shell.\n function buildRestoreOps(): SceneOperation[] {\n const ops: SceneOperation[] = [\n {\n type: 'add_page',\n pageId: snapshot.id,\n options: {\n name: snapshot.name,\n width: snapshot.width,\n height: snapshot.height,\n background: snapshot.background,\n },\n index: currentIndex,\n },\n ]\n if (snapshot.bleed) {\n ops.push({ type: 'set_page_props', pageId: snapshot.id, bleed: snapshot.bleed })\n }\n if (snapshot.guides.vertical.length > 0 || snapshot.guides.horizontal.length > 0) {\n ops.push({ type: 'set_page_guides', pageId: snapshot.id, guides: snapshot.guides })\n }\n for (let i = 0; i < snapshot.elements.length; i++) {\n ops.push({\n type: 'add_element',\n pageId: snapshot.id,\n element: structuredClone(snapshot.elements[i]!),\n index: i,\n })\n }\n return ops\n }\n\n return {\n label: 'Delete page',\n execute: (state) => {\n const next = applyOp(state, deleteOp)\n const activeExists = next.document.pages.some((p) => p.id === next.activePageId)\n if (activeExists) return next\n const fallbackIndex = Math.min(currentIndex, next.document.pages.length - 1)\n return { ...next, activePageId: next.document.pages[fallbackIndex]!.id }\n },\n undo: (state) => {\n const next = applyOps(state, buildRestoreOps())\n return { ...next, activePageId: input.pageId }\n },\n operations: () => [structuredClone(deleteOp)],\n inverseOperations: () => buildRestoreOps(),\n }\n}\n\n/** Define input parameters to reorder a page by specifying its ID and target index */\nexport interface ReorderPageInput {\n pageId: string\n toIndex: number\n}\n\n/** Create a command to reorder a page to a specified index within a scene */\nexport function reorderPageCommand(input: ReorderPageInput): SceneCommand {\n let capturedFromIndex: number | null = null\n\n const forwardOp: SceneOperation = {\n type: 'reorder_page',\n pageId: input.pageId,\n toIndex: input.toIndex,\n }\n\n return {\n label: 'Reorder page',\n execute: (state) => {\n // Guard: on redo the page is already at toIndex; capture only on first execute.\n if (capturedFromIndex === null) {\n capturedFromIndex = state.document.pages.findIndex((p) => p.id === input.pageId)\n if (capturedFromIndex === -1) throw new Error(`reorderPageCommand: page ${input.pageId} not found`)\n }\n return applyOp(state, forwardOp)\n },\n undo: (state) => {\n if (capturedFromIndex === null) throw new Error('reorderPageCommand: undo called before execute')\n return applyOp(state, {\n type: 'reorder_page',\n pageId: input.pageId,\n toIndex: capturedFromIndex,\n })\n },\n operations: () => [structuredClone(forwardOp)],\n inverseOperations: () => {\n if (capturedFromIndex === null) throw new Error('reorderPageCommand: inverseOperations called before execute')\n return [{ type: 'reorder_page' as const, pageId: input.pageId, toIndex: capturedFromIndex }]\n },\n }\n}\n\n/** Define input parameters for setting properties on a specific page within a scene document */\nexport interface SetPagePropsInput {\n document: SceneDocument\n pageId: string\n props: {\n name?: string\n width?: number\n height?: number\n background?: string\n bleed?: import('../../design-canvas/model').PageBleed | null\n }\n}\n\n/** Build a command to update page properties based on the provided input */\nexport function setPagePropsCommand(input: SetPagePropsInput): SceneCommand {\n const page = requirePage(input.document, input.pageId)\n const prior: NonNullable<import('../../design-canvas/operations').SetPagePropsOperation> = {\n type: 'set_page_props',\n pageId: input.pageId,\n ...(input.props.name !== undefined ? { name: page.name } : {}),\n ...(input.props.width !== undefined ? { width: page.width } : {}),\n ...(input.props.height !== undefined ? { height: page.height } : {}),\n ...(input.props.background !== undefined ? { background: page.background } : {}),\n ...(input.props.bleed !== undefined ? { bleed: page.bleed } : {}),\n }\n\n const forwardOp: SceneOperation = {\n type: 'set_page_props',\n pageId: input.pageId,\n ...input.props,\n }\n\n return {\n label: 'Edit page',\n execute: (state) => applyOp(state, forwardOp),\n undo: (state) => applyOp(state, prior),\n operations: () => [structuredClone(forwardOp)],\n inverseOperations: () => [structuredClone(prior) as SceneOperation],\n }\n}\n\n/** Define input parameters for setting guides on a specific page within a document */\nexport interface SetPageGuidesInput {\n document: SceneDocument\n pageId: string\n guides: import('../../design-canvas/model').PageGuides\n}\n\n/** Create a command to update page guides with undo support */\nexport function setPageGuidesCommand(input: SetPageGuidesInput): SceneCommand {\n const page = requirePage(input.document, input.pageId)\n const priorGuides = structuredClone(page.guides)\n\n const forwardOp: SceneOperation = {\n type: 'set_page_guides',\n pageId: input.pageId,\n guides: structuredClone(input.guides),\n }\n const inverseOp: SceneOperation = {\n type: 'set_page_guides',\n pageId: input.pageId,\n guides: priorGuides,\n }\n\n return {\n label: 'Edit guides',\n execute: (state) => applyOp(state, forwardOp),\n undo: (state) => applyOp(state, inverseOp),\n operations: () => [structuredClone(forwardOp)],\n inverseOperations: () => [structuredClone(inverseOp)],\n }\n}\n\n// ---------------------------------------------------------------------------\n// bind_slot\n// ---------------------------------------------------------------------------\n\n/** Define input parameters for binding a slot within a scene document element */\nexport interface BindSlotInput {\n document: SceneDocument\n pageId: string\n elementId: string\n slot: string | null\n}\n\n/** Bind a slot to an element within a page and generate the corresponding scene command */\nexport function bindSlotCommand(input: BindSlotInput): SceneCommand {\n const page = requirePage(input.document, input.pageId)\n const { element } = requireElement(page, input.elementId)\n const priorSlot = element.slot ?? null\n\n const forwardOp: SceneOperation = {\n type: 'bind_slot',\n pageId: input.pageId,\n elementId: input.elementId,\n slot: input.slot,\n }\n const inverseOp: SceneOperation = {\n type: 'bind_slot',\n pageId: input.pageId,\n elementId: input.elementId,\n slot: priorSlot,\n }\n\n return {\n label: input.slot === null ? 'Unbind slot' : `Bind slot \"${input.slot}\"`,\n execute: (state) => applyOp(state, forwardOp),\n undo: (state) => applyOp(state, inverseOp),\n operations: () => [structuredClone(forwardOp)],\n inverseOperations: () => [structuredClone(inverseOp)],\n }\n}\n\n// ---------------------------------------------------------------------------\n// set_document_title\n// ---------------------------------------------------------------------------\n\n/** Define input parameters for setting the title of a scene document */\nexport interface SetDocumentTitleInput {\n document: SceneDocument\n title: string\n}\n\n/** Resolve a command to rename a document title with undo and redo operations */\nexport function setDocumentTitleCommand(input: SetDocumentTitleInput): SceneCommand {\n const priorTitle = input.document.title\n\n const forwardOp: SceneOperation = { type: 'set_document_title', title: input.title }\n const inverseOp: SceneOperation = { type: 'set_document_title', title: priorTitle }\n\n return {\n label: `Rename document`,\n execute: (state) => applyOp(state, forwardOp),\n undo: (state) => applyOp(state, inverseOp),\n operations: () => [structuredClone(forwardOp)],\n inverseOperations: () => [structuredClone(inverseOp)],\n }\n}\n"],"mappings":"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","names":["activePageId"]}
@@ -3,11 +3,11 @@ import {
3
3
  markComplete,
4
4
  payloadComplete,
5
5
  withAnswer
6
- } from "./chunk-USYXHDKE.js";
6
+ } from "./chunk-YZ6KQULN.js";
7
7
  import {
8
8
  getQuestion,
9
9
  validateAnswer
10
- } from "./chunk-ND3XEGBE.js";
10
+ } from "./chunk-JDEGS53O.js";
11
11
 
12
12
  // src/intakes/drizzle/store.ts
13
13
  import { eq } from "drizzle-orm";
@@ -121,4 +121,4 @@ export {
121
121
  createUserIntakeStore,
122
122
  createProjectIntakeStore
123
123
  };
124
- //# sourceMappingURL=chunk-4K7BZYO7.js.map
124
+ //# sourceMappingURL=chunk-VWAEWOWK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/intakes/drizzle/store.ts"],"sourcesContent":["/**\n * Drizzle-backed store over the tables from `createIntakeTables`. One store\n * builder per scope: `createUserIntakeStore` (keyed on userId) and\n * `createProjectIntakeStore` (keyed on workspaceId). Each returns the same\n * three-method surface — `get` / `save` / `complete` — so the api handlers and\n * the UI talk to one shape regardless of scope.\n *\n * Works against any SQLite drizzle driver (better-sqlite3, D1, libsql): the\n * builders are awaited, never `.run()`/`.all()`, so sync and async drivers\n * behave identically.\n *\n * Validation is fail-loud and pure (from the `./intakes` leaf). `save` runs\n * `validateAnswer` before writing, so an invalid answer can never enter the\n * payload; `complete` runs `payloadComplete` and refuses to stamp an\n * incomplete (or stale-graph) intake — it throws a typed `IntakeError` rather\n * than silently writing a half-finished onboarding state.\n *\n * `getProjectIntakeStore` pins `workspaceId` in every WHERE clause; RBAC runs\n * in the route before the store is built, but the scope key is enforced here\n * too, so a leaked id can never read or write across the boundary.\n *\n * Imports `drizzle-orm`, so this is a subpath, never re-exported from root.\n */\n\nimport { eq } from 'drizzle-orm'\nimport type { BaseSQLiteDatabase } from 'drizzle-orm/sqlite-core'\nimport {\n type IntakeAnswerValue,\n type IntakeGraph,\n getQuestion,\n validateAnswer,\n} from '../model'\nimport {\n type IntakePayload,\n emptyPayload,\n markComplete,\n payloadComplete,\n withAnswer,\n} from '../completion'\nimport type { ProjectIntakeTable, UserIntakeTable } from './schema'\n\n/** Any SQLite drizzle database — `any` erases driver-specific generics so\n * better-sqlite3, D1, and libsql handles all fit. */\nexport type IntakeDatabase = BaseSQLiteDatabase<'sync' | 'async', any, any>\n\n/** A loaded intake: the payload plus whether it is complete against the graph. */\nexport interface IntakeState {\n payload: IntakePayload\n completed: boolean\n completedAt: Date | null\n}\n\n/** Define error codes representing specific intake validation failures */\nexport type IntakeErrorCode = 'invalid-answer' | 'unknown-question' | 'incomplete' | 'stale-graph'\n\n/** Thrown by store mutations on a refused write — callers map it to a 4xx. */\nexport class IntakeError extends Error {\n readonly code: IntakeErrorCode\n constructor(code: IntakeErrorCode, message: string) {\n super(message)\n this.name = 'IntakeError'\n this.code = code\n }\n}\n\n/** The three-method store surface, identical for both scopes. */\nexport interface IntakeStore {\n /** Load the current intake, or seed an empty payload when none exists yet. */\n get(): Promise<IntakeState>\n /** Validate and persist one answer; returns the updated state. */\n save(questionId: string, value: IntakeAnswerValue): Promise<IntakeState>\n /** Stamp the intake complete; throws IntakeError when not yet completable. */\n complete(): Promise<IntakeState>\n}\n\ninterface IntakeTableShape {\n id: any\n graphId: any\n payload: any\n completedAt: any\n updatedAt: any\n}\n\ninterface ScopedStoreOptions {\n db: IntakeDatabase\n graph: IntakeGraph\n table: IntakeTableShape\n /** The scope column (userIntake.userId or projectIntake.workspaceId). */\n scopeColumn: any\n scopeValue: string\n /** Extra columns to set on insert (the scope key). */\n insertScope: Record<string, unknown>\n}\n\nfunction createScopedStore(opts: ScopedStoreOptions): IntakeStore {\n const { db, graph, table, scopeColumn, scopeValue, insertScope } = opts\n\n async function loadRow() {\n const [row] = await db\n .select()\n .from(table as any)\n .where(eq(scopeColumn, scopeValue))\n .limit(1)\n return (row ?? null) as\n | { id: string; graphId: string; payload: unknown; completedAt: Date | number | null }\n | null\n }\n\n function toState(\n row: { graphId: string; payload: unknown; completedAt: Date | number | null } | null,\n ): IntakeState {\n if (!row) {\n return { payload: emptyPayload(graph), completed: false, completedAt: null }\n }\n const payload = normalizePayload(row.payload, row.graphId)\n const completedAt = toDate(row.completedAt)\n return {\n payload,\n completed: completedAt != null && payloadComplete(graph, payload),\n completedAt,\n }\n }\n\n async function get(): Promise<IntakeState> {\n return toState(await loadRow())\n }\n\n async function upsertPayload(payload: IntakePayload, completedAt: Date | null) {\n const existing = await loadRow()\n if (existing) {\n await db\n .update(table as any)\n .set({ graphId: payload.graphId, payload, completedAt, updatedAt: new Date() })\n .where(eq(scopeColumn, scopeValue))\n return\n }\n await db.insert(table as any).values({\n ...insertScope,\n graphId: payload.graphId,\n payload,\n completedAt,\n })\n }\n\n async function save(questionId: string, value: IntakeAnswerValue): Promise<IntakeState> {\n const question = getQuestion(graph, questionId)\n if (!question) throw new IntakeError('unknown-question', `No question '${questionId}' in intake '${graph.id}'`)\n const validity = validateAnswer(question, value)\n if (!validity.ok) {\n throw new IntakeError('invalid-answer', `Answer to '${questionId}' rejected: ${validity.reason}`)\n }\n\n const current = await get()\n const next = withAnswer(current.payload, questionId, value)\n await upsertPayload(next, current.completedAt)\n return toState({ graphId: next.graphId, payload: next, completedAt: current.completedAt })\n }\n\n async function complete(): Promise<IntakeState> {\n const current = await get()\n if (current.payload.graphId !== graph.id) {\n throw new IntakeError('stale-graph', `Intake payload was collected against '${current.payload.graphId}', not '${graph.id}'`)\n }\n if (!payloadComplete(graph, current.payload)) {\n throw new IntakeError('incomplete', `Intake '${graph.id}' has unanswered required questions`)\n }\n const completedPayload = markComplete(current.payload)\n const completedAt = new Date(completedPayload.completedAt!)\n await upsertPayload(completedPayload, completedAt)\n return { payload: completedPayload, completed: true, completedAt }\n }\n\n return { get, save, complete }\n}\n\n/** Define options required to create a user intake store for onboarding data collection */\nexport interface CreateUserIntakeStoreOptions {\n db: IntakeDatabase\n /** The user-intake table from createIntakeTables. */\n table: UserIntakeTable\n /** The intake definition this store collects answers against. */\n graph: IntakeGraph\n /** The user whose onboarding this is. */\n userId: string\n}\n\n/** Build the per-user onboarding store, scoped to one userId. */\nexport function createUserIntakeStore(opts: CreateUserIntakeStoreOptions): IntakeStore {\n return createScopedStore({\n db: opts.db,\n graph: opts.graph,\n table: opts.table as unknown as IntakeTableShape,\n scopeColumn: opts.table.userId,\n scopeValue: opts.userId,\n insertScope: { userId: opts.userId },\n })\n}\n\n/** Define options required to create a project intake store including database, table, graph, and workspace ID */\nexport interface CreateProjectIntakeStoreOptions {\n db: IntakeDatabase\n /** The project-intake table from createIntakeTables (workspace scope). */\n table: ProjectIntakeTable\n graph: IntakeGraph\n /** The workspace this intake is attached to. */\n workspaceId: string\n}\n\n/** Build the per-project store, scoped to one workspaceId. */\nexport function createProjectIntakeStore(opts: CreateProjectIntakeStoreOptions): IntakeStore {\n return createScopedStore({\n db: opts.db,\n graph: opts.graph,\n table: opts.table as unknown as IntakeTableShape,\n scopeColumn: opts.table.workspaceId,\n scopeValue: opts.workspaceId,\n insertScope: { workspaceId: opts.workspaceId },\n })\n}\n\nfunction normalizePayload(raw: unknown, graphId: string): IntakePayload {\n if (raw && typeof raw === 'object' && 'answers' in (raw as Record<string, unknown>)) {\n const candidate = raw as Partial<IntakePayload>\n return {\n graphId: candidate.graphId ?? graphId,\n answers: candidate.answers ?? {},\n ...(candidate.completedAt ? { completedAt: candidate.completedAt } : {}),\n }\n }\n return { graphId, answers: {} }\n}\n\nfunction toDate(value: Date | number | null | undefined): Date | null {\n if (value == null) return null\n return value instanceof Date ? value : new Date(Number(value) * (Number(value) < 1e12 ? 1000 : 1))\n}\n"],"mappings":"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","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  assertMediaUrl
3
- } from "./chunk-HFC4BTWJ.js";
3
+ } from "./chunk-PTUMBMVH.js";
4
4
 
5
5
  // src/design-canvas/model.ts
6
6
  var SCENE_SCHEMA_VERSION = 1;
@@ -1001,4 +1001,4 @@ export {
1001
1001
  scalePageForChannelPreset,
1002
1002
  bleedAwareExportRect
1003
1003
  };
1004
- //# sourceMappingURL=chunk-M2EBUDZ7.js.map
1004
+ //# sourceMappingURL=chunk-VWOPOLVO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/design-canvas/model.ts","../src/design-canvas/validate.ts","../src/design-canvas/apply.ts","../src/design-canvas/export-presets.ts"],"sourcesContent":["/**\n * Design-canvas scene model — the product-agnostic document behind the visual\n * asset editor. A document is an ordered list of pages; a page is an ordered\n * list of elements (index order IS z-order, bottom→top); every element is a\n * typed node with a closed attribute vocabulary. The whole document\n * serializes as one JSON value and persists atomically with a revision\n * counter (see ./store) — every canvas action is a durable operation against\n * this schema, which is what makes the canvas automatable: agents and\n * external data sources mutate the same document the editor renders.\n *\n * Units are CSS pixels throughout; `settings.dpi` carries the print\n * conversion factor for bleed/trim-aware exports. Angles are degrees.\n * Nothing here touches Konva, React, or a database.\n */\n\nimport { assertMediaUrl } from '../web'\n\n/** Define the current version number of the scene schema */\nexport const SCENE_SCHEMA_VERSION = 1\n\n/** Define the structure and properties of a scene document including version, title, pages, settings, and metadata */\nexport interface SceneDocument {\n schemaVersion: typeof SCENE_SCHEMA_VERSION\n title: string\n pages: ScenePage[]\n settings: SceneSettings\n metadata: Record<string, unknown>\n}\n\n/** Define settings for scene export including print conversion factor for unit calculations */\nexport interface SceneSettings {\n /** Print conversion factor for mm↔px math at export; 96 = CSS default. */\n dpi: number\n}\n\n/** Per-side bleed extents in px, drawn OUTSIDE the page bounds. Trim = the\n * page rect itself; exports may include or exclude the bleed area. */\nexport interface PageBleed {\n top: number\n right: number\n bottom: number\n left: number\n}\n\n/** Saved ruler guides, in page coordinates. */\nexport interface PageGuides {\n vertical: number[]\n horizontal: number[]\n}\n\n/** Define the structure and properties of a scene page including layout, background, and elements */\nexport interface ScenePage {\n id: string\n name: string\n width: number\n height: number\n /** Page background fill (color string); elements paint over it. */\n background: string\n bleed: PageBleed | null\n guides: PageGuides\n elements: SceneElement[]\n}\n\n// ---------------------------------------------------------------------------\n// Elements\n// ---------------------------------------------------------------------------\n\n/** Attributes every element carries. `x`/`y` are the element's top-left in\n * page coordinates (for `group`, children are relative to the group origin).\n * `slot` names a template binding point — `apply_data` targets it. */\nexport interface SceneElementBase {\n id: string\n name: string\n x: number\n y: number\n /** Degrees, clockwise, about the element's top-left origin (Konva default). */\n rotation: number\n /** 0..1 */\n opacity: number\n locked: boolean\n visible: boolean\n slot?: string\n}\n\n/** Define a rectangular scene element with size, fill, optional stroke, and corner radius properties */\nexport interface RectElement extends SceneElementBase {\n kind: 'rect'\n width: number\n height: number\n fill: string\n stroke?: string\n strokeWidth?: number\n cornerRadius?: number\n}\n\n/** Define properties for an ellipse element including dimensions, fill, and optional stroke details */\nexport interface EllipseElement extends SceneElementBase {\n kind: 'ellipse'\n width: number\n height: number\n fill: string\n stroke?: string\n strokeWidth?: number\n}\n\n/** Define a line element with points, stroke, stroke width, and optional dash pattern */\nexport interface LineElement extends SceneElementBase {\n kind: 'line'\n /** Flat [x0, y0, x1, y1, ...] relative to (x, y); ≥ 2 points. */\n points: number[]\n stroke: string\n strokeWidth: number\n dash?: number[]\n}\n\n/** Define properties for a text element including content, style, alignment, and layout parameters */\nexport interface TextElement extends SceneElementBase {\n kind: 'text'\n text: string\n /** Wrap width; height derives from content. */\n width: number\n fontFamily: string\n fontSize: number\n fontStyle: 'normal' | 'bold' | 'italic' | 'bold italic'\n fill: string\n align: 'left' | 'center' | 'right'\n lineHeight: number\n letterSpacing: number\n}\n\n/** Define properties for an image element including source, dimensions, and fit mode */\nexport interface ImageElement extends SceneElementBase {\n kind: 'image'\n width: number\n height: number\n /** http(s) or rooted /api/ path — same boundary rule as sequences media. */\n src: string\n /** How the source maps into the frame; 'fill' stretches, 'cover' crops. */\n fit: 'fill' | 'cover' | 'contain'\n}\n\n/** Video placed on a canvas renders and exports as its poster frame — motion\n * belongs to the sequences surface; this keeps video assets placeable in\n * static layouts (e.g. a thumbnail mock) without a playback engine. */\nexport interface VideoElement extends SceneElementBase {\n kind: 'video'\n width: number\n height: number\n src: string\n posterSrc?: string\n}\n\n/** Define a group element that contains multiple child scene elements */\nexport interface GroupElement extends SceneElementBase {\n kind: 'group'\n children: SceneElement[]\n}\n\n/** Represent a graphical element in a scene including shapes, text, media, or groups */\nexport type SceneElement =\n | RectElement\n | EllipseElement\n | LineElement\n | TextElement\n | ImageElement\n | VideoElement\n | GroupElement\n\n/** Extract the kind property from a SceneElement to identify its element type */\nexport type SceneElementKind = SceneElement['kind']\n\n/** Define all valid kinds of scene elements used in the application */\nexport const SCENE_ELEMENT_KINDS: readonly SceneElementKind[] = [\n 'rect', 'ellipse', 'line', 'text', 'image', 'video', 'group',\n] as const\n\n// ---------------------------------------------------------------------------\n// Geometry\n// ---------------------------------------------------------------------------\n\n/** Define rectangular boundaries with position and size properties */\nexport interface Bounds {\n x: number\n y: number\n width: number\n height: number\n}\n\n/** Unrotated local extent of an element (line/group derive from content). */\nexport function elementExtent(element: SceneElement): { width: number; height: number } {\n switch (element.kind) {\n case 'rect':\n case 'ellipse':\n case 'image':\n case 'video':\n return { width: element.width, height: element.height }\n case 'text':\n // Height derives from content at render time; the model exposes a\n // deterministic estimate so layout math (snapping, describe) never\n // depends on a canvas context: lines × fontSize × lineHeight.\n return {\n width: element.width,\n height: estimateTextHeight(element),\n }\n case 'line': {\n let maxX = 0\n let maxY = 0\n for (let i = 0; i < element.points.length; i += 2) {\n maxX = Math.max(maxX, Math.abs(element.points[i]!))\n maxY = Math.max(maxY, Math.abs(element.points[i + 1]!))\n }\n return { width: maxX, height: maxY }\n }\n case 'group': {\n // minX/minY track the negative-space corner: a rotated child whose AABB\n // extends left/above the group origin contributes negative values, so\n // they must seed from the first child, not 0 (0 would clip them).\n let minX = 0, minY = 0, maxX = 0, maxY = 0\n for (const child of element.children) {\n const aabb = elementAabb(child)\n minX = Math.min(minX, aabb.x)\n minY = Math.min(minY, aabb.y)\n maxX = Math.max(maxX, aabb.x + aabb.width)\n maxY = Math.max(maxY, aabb.y + aabb.height)\n }\n return { width: maxX - minX, height: maxY - minY }\n }\n }\n}\n\n/** Estimate the height of multiline text based on font size and line height */\nexport function estimateTextHeight(element: Pick<TextElement, 'text' | 'fontSize' | 'lineHeight'>): number {\n const lines = element.text.length === 0 ? 1 : element.text.split('\\n').length\n return lines * element.fontSize * element.lineHeight\n}\n\n/** Axis-aligned bounding box in the parent's coordinate space, accounting for\n * rotation about the element's top-left origin. */\nexport function elementAabb(element: SceneElement): Bounds {\n const { width, height } = elementExtent(element)\n if (element.rotation % 360 === 0) {\n return { x: element.x, y: element.y, width, height }\n }\n const rad = (element.rotation * Math.PI) / 180\n const cos = Math.cos(rad)\n const sin = Math.sin(rad)\n const corners: Array<[number, number]> = [\n [0, 0],\n [width * cos, width * sin],\n [-height * sin, height * cos],\n [width * cos - height * sin, width * sin + height * cos],\n ]\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity\n for (const [cx, cy] of corners) {\n minX = Math.min(minX, cx); minY = Math.min(minY, cy)\n maxX = Math.max(maxX, cx); maxY = Math.max(maxY, cy)\n }\n return { x: element.x + minX, y: element.y + minY, width: maxX - minX, height: maxY - minY }\n}\n\n/** Determine if two rectangular bounds overlap or intersect each other */\nexport function boundsIntersect(a: Bounds, b: Bounds): boolean {\n return a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y\n}\n\n// ---------------------------------------------------------------------------\n// Lookup + traversal\n// ---------------------------------------------------------------------------\n\n/** Resolve and return a page by ID from a document or throw an error if not found */\nexport function requirePage(document: SceneDocument, pageId: string): ScenePage {\n const page = document.pages.find((candidate) => candidate.id === pageId)\n if (!page) throw new Error(`page ${pageId} not found in document`)\n return page\n}\n\n/** Depth-first search across a page including group children. Returns the\n * element and the array that owns it (page.elements or a group's children),\n * so callers can splice in place. */\nexport function findElement(page: ScenePage, elementId: string): { element: SceneElement; owner: SceneElement[]; index: number } | null {\n const stack: SceneElement[][] = [page.elements]\n while (stack.length > 0) {\n const owner = stack.pop()!\n for (let index = 0; index < owner.length; index += 1) {\n const element = owner[index]!\n if (element.id === elementId) return { element, owner, index }\n if (element.kind === 'group') stack.push(element.children)\n }\n }\n return null\n}\n\n/** Resolve and return the element, its owner array, and index from the page by element ID */\nexport function requireElement(page: ScenePage, elementId: string): { element: SceneElement; owner: SceneElement[]; index: number } {\n const found = findElement(page, elementId)\n if (!found) throw new Error(`element ${elementId} not found on page ${page.id}`)\n return found\n}\n\n/** All slot names declared across the document — the template's fillable\n * surface. Duplicate slot names are a validation error (see ./validate). */\nexport function collectSlots(document: SceneDocument): Map<string, { pageId: string; elementId: string; kind: SceneElementKind }> {\n const slots = new Map<string, { pageId: string; elementId: string; kind: SceneElementKind }>()\n for (const page of document.pages) {\n const stack = [...page.elements]\n while (stack.length > 0) {\n const element = stack.pop()!\n if (element.slot) {\n if (slots.has(element.slot)) throw new Error(`duplicate slot name \"${element.slot}\"`)\n slots.set(element.slot, { pageId: page.id, elementId: element.id, kind: element.kind })\n }\n if (element.kind === 'group') stack.push(...element.children)\n }\n }\n return slots\n}\n\n// ---------------------------------------------------------------------------\n// Construction\n// ---------------------------------------------------------------------------\n\n/** Define options to configure a new page including name, dimensions, and background color */\nexport interface NewPageOptions {\n name?: string\n width?: number\n height?: number\n background?: string\n}\n\n/** Create a new empty SceneDocument with a title and optional initial page settings */\nexport function createEmptyDocument(title: string, page?: NewPageOptions): SceneDocument {\n return {\n schemaVersion: SCENE_SCHEMA_VERSION,\n title,\n pages: [createPage(page ?? {}, 'page-1')],\n settings: { dpi: 96 },\n metadata: {},\n }\n}\n\n/** Create a new ScenePage with specified options and a unique identifier */\nexport function createPage(options: NewPageOptions, id: string): ScenePage {\n const width = options.width ?? 1080\n const height = options.height ?? 1080\n assertPositiveFinite(width, 'page width')\n assertPositiveFinite(height, 'page height')\n return {\n id,\n name: options.name ?? 'Page',\n width,\n height,\n background: options.background ?? '#ffffff',\n bleed: null,\n guides: { vertical: [], horizontal: [] },\n elements: [],\n }\n}\n\n/** Assert that a value is a positive finite number and throw an error with a label if not */\nexport function assertPositiveFinite(value: number, label: string): void {\n if (!Number.isFinite(value) || value <= 0) throw new Error(`${label} must be a positive finite number`)\n}\n\n/** Assert that a value is a finite number and throw an error with a label if not */\nexport function assertFinite(value: number, label: string): void {\n if (!Number.isFinite(value)) throw new Error(`${label} must be a finite number`)\n}\n\n/** Valid hex lengths are exactly 3 (rgb), 4 (rgba), 6 (rrggbb), or 8\n * (rrggbbaa) digits — `{3,8}` wrongly admitted 5- and 7-digit junk that no\n * renderer accepts. */\nconst HEX_COLOR = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/\nconst RGB_COLOR = /^rgba?\\(\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*(?:,\\s*(?:0|1|0?\\.\\d+)\\s*)?\\)$/\n\n/** Validate that a string is a hex, rgb(a), or 'transparent' color and throw an error if not */\nexport function assertColor(value: string, label: string): void {\n if (value === 'transparent' || HEX_COLOR.test(value)) return\n const rgb = RGB_COLOR.exec(value)\n if (rgb && rgbChannelsInRange(rgb)) return\n throw new Error(`${label} must be a hex/rgb(a) color or 'transparent', got \"${value}\"`)\n}\n\n/** Each of the three rgb channels must be 0..255 — the pattern alone admits\n * values like `rgb(999,0,0)` which clamp or render wrong. */\nfunction rgbChannelsInRange(match: RegExpExecArray): boolean {\n for (let i = 1; i <= 3; i += 1) {\n const channel = Number(match[i])\n if (channel > 255) return false\n }\n return true\n}\n\n/** Media boundary rule shared with sequences: remote http(s) or a rooted\n * /api/ path — never sandbox-local files or data:/blob: blobs. Delegates to the\n * canonical `assertMediaUrl` boundary in `../web`; the two surfaces share ONE\n * rule (trims, named-rejects local/inline schemes) so they cannot drift. */\nexport function assertSceneMediaSrc(value: string, label: string): void {\n assertMediaUrl(value, label)\n}\n","/**\n * Pre-write validation for scene operations. Every rule runs against a\n * `SceneDocument` snapshot BEFORE any mutation, so a rejected batch leaves no\n * partial state. Batch errors carry the shape `operation N (type): reason` —\n * precise enough for an LLM planner to repair the offending operation and\n * resubmit.\n *\n * Validation is static: a batch is checked against the document as given, so\n * an operation may not reference entities created by an earlier operation in\n * the same batch. Dispatchers that chain operations must refresh the document\n * between applications and validate per-operation.\n *\n * Slot typing contract (for apply_data bindings):\n * text elements → value is any string\n * image elements → value must pass assertSceneMediaSrc (src rewrite)\n * video elements → value must pass assertSceneMediaSrc (src rewrite)\n * rect elements → value must pass assertColor (fill recolor)\n * ellipse elements → value must pass assertColor (fill recolor)\n * line elements → value must pass assertColor (stroke recolor)\n * group elements → value must pass assertColor (fill/stroke passed down to children)\n */\n\nimport {\n assertColor,\n assertFinite,\n assertPositiveFinite,\n assertSceneMediaSrc,\n collectSlots,\n findElement,\n requireElement,\n requirePage,\n} from './model'\nimport type { SceneDocument, SceneElement, SceneElementKind } from './model'\nimport type {\n AddElementOperation,\n ApplyDataOperation,\n BindSlotOperation,\n DeleteElementOperation,\n DeletePageOperation,\n DuplicatePageOperation,\n GroupElementsOperation,\n ReorderElementOperation,\n ReorderPageOperation,\n SceneAttrsPatch,\n SceneOperation,\n SetAttrsOperation,\n SetDocumentTitleOperation,\n SetPageGuidesOperation,\n SetPagePropsOperation,\n UngroupElementOperation,\n} from './operations'\n\n// ---------------------------------------------------------------------------\n// Public entry\n// ---------------------------------------------------------------------------\n\n/** Validate each scene operation against the document and throw detailed errors for invalid operations */\nexport function validateSceneOperations(document: SceneDocument, operations: SceneOperation[]): void {\n operations.forEach((operation, index) => {\n try {\n validateSceneOperation(document, operation)\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error)\n throw new Error(`operation ${index + 1} (${operation.type}): ${reason}`)\n }\n })\n}\n\n/** Validate a scene operation against the document to ensure it meets required constraints */\nexport function validateSceneOperation(document: SceneDocument, operation: SceneOperation): void {\n switch (operation.type) {\n case 'add_element':\n return validateAddElement(document, operation)\n case 'set_attrs':\n return validateSetAttrs(document, operation)\n case 'reorder_element':\n return validateReorderElement(document, operation)\n case 'delete_element':\n return validateDeleteElement(document, operation)\n case 'group_elements':\n return validateGroupElements(document, operation)\n case 'ungroup_element':\n return validateUngroupElement(document, operation)\n case 'add_page':\n return validateAddPage(operation)\n case 'duplicate_page':\n return validateDuplicatePage(document, operation)\n case 'delete_page':\n return validateDeletePage(document, operation)\n case 'reorder_page':\n return validateReorderPage(document, operation)\n case 'set_page_props':\n return validateSetPageProps(document, operation)\n case 'set_page_guides':\n return validateSetPageGuides(document, operation)\n case 'bind_slot':\n return validateBindSlot(document, operation)\n case 'apply_data':\n return validateApplyData(document, operation)\n case 'set_document_title':\n return validateSetDocumentTitle(operation)\n default: {\n const unknown = operation as { type?: unknown }\n throw new Error(`unsupported operation type ${JSON.stringify(unknown.type)}`)\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Per-operation validators\n// ---------------------------------------------------------------------------\n\nfunction validateAddElement(document: SceneDocument, op: AddElementOperation): void {\n const page = requirePage(document, op.pageId)\n assertUniqueIdDocumentWide(document, op.element.id)\n if (op.parentGroupId !== undefined) {\n const { element: parent } = requireElement(page, op.parentGroupId)\n if (parent.kind !== 'group') {\n throw new Error(`parentGroupId \"${op.parentGroupId}\" is a ${parent.kind}, not a group`)\n }\n }\n if (op.index !== undefined) {\n const owner = op.parentGroupId\n ? (() => {\n const { element: g } = requireElement(page, op.parentGroupId)\n return (g as { kind: 'group'; children: SceneElement[] }).children\n })()\n : page.elements\n if (op.index < 0 || op.index > owner.length) {\n throw new Error(`index ${op.index} out of range (owner has ${owner.length} elements)`)\n }\n }\n validateElementAttrs(op.element.kind, op.element as unknown as SceneAttrsPatch, true)\n}\n\nfunction validateSetAttrs(document: SceneDocument, op: SetAttrsOperation): void {\n const page = requirePage(document, op.pageId)\n const { element } = requireElement(page, op.elementId)\n // A patch that ONLY unlocks is always permitted even on a locked element.\n const isUnlockOnly = Object.keys(op.attrs).length === 1 && op.attrs.locked === false\n if (element.locked && !isUnlockOnly) {\n throw new Error(`element \"${op.elementId}\" is locked; unlock it first (pass attrs: {locked: false}) before making other changes`)\n }\n validateElementAttrs(element.kind, op.attrs, false)\n}\n\nfunction validateReorderElement(document: SceneDocument, op: ReorderElementOperation): void {\n const page = requirePage(document, op.pageId)\n const { element, owner } = requireElement(page, op.elementId)\n if (element.locked) {\n throw new Error(`element \"${op.elementId}\" is locked; unlock it before reordering`)\n }\n // toIndex is the insertion point after splice-remove; owner.length-1 is valid\n // (element becomes last). owner.length itself is out-of-range post-remove.\n if (op.toIndex < 0 || op.toIndex >= owner.length) {\n throw new Error(`toIndex ${op.toIndex} out of range (owner has ${owner.length} elements)`)\n }\n}\n\nfunction validateDeleteElement(document: SceneDocument, op: DeleteElementOperation): void {\n const page = requirePage(document, op.pageId)\n const { element } = requireElement(page, op.elementId)\n if (element.locked) {\n throw new Error(`element \"${op.elementId}\" is locked; unlock it before deleting`)\n }\n}\n\nfunction validateGroupElements(document: SceneDocument, op: GroupElementsOperation): void {\n if (op.elementIds.length < 2) {\n throw new Error(`group_elements requires ≥ 2 element ids (got ${op.elementIds.length})`)\n }\n assertUniqueIdDocumentWide(document, op.groupId)\n const page = requirePage(document, op.pageId)\n // Resolve all targets and check siblings + locked\n const owners = op.elementIds.map((id) => {\n const { element, owner } = requireElement(page, id)\n if (element.locked) throw new Error(`element \"${id}\" is locked; unlock before grouping`)\n return owner\n })\n // All must share the exact same owner array reference (sibling check)\n const firstOwner = owners[0]\n for (let i = 1; i < owners.length; i++) {\n if (owners[i] !== firstOwner) {\n throw new Error(`elements are not siblings — they must all share the same parent (page root or one group)`)\n }\n }\n}\n\nfunction validateUngroupElement(document: SceneDocument, op: UngroupElementOperation): void {\n const page = requirePage(document, op.pageId)\n const { element } = requireElement(page, op.groupId)\n if (element.kind !== 'group') {\n throw new Error(`element \"${op.groupId}\" is a ${element.kind}, not a group`)\n }\n}\n\nfunction validateAddPage(op: { options?: { width?: number; height?: number; background?: string } }): void {\n const opts = op.options\n if (!opts) return\n if (opts.width !== undefined) assertPositiveFinite(opts.width, 'page width')\n if (opts.height !== undefined) assertPositiveFinite(opts.height, 'page height')\n if (opts.background !== undefined) assertColor(opts.background, 'page background')\n}\n\nfunction validateDuplicatePage(document: SceneDocument, op: DuplicatePageOperation): void {\n requirePage(document, op.sourcePageId)\n const existing = document.pages.find((p) => p.id === op.pageId)\n if (existing) throw new Error(`pageId \"${op.pageId}\" already exists in the document`)\n}\n\nfunction validateDeletePage(document: SceneDocument, op: DeletePageOperation): void {\n requirePage(document, op.pageId)\n if (document.pages.length === 1) {\n throw new Error('cannot delete the last remaining page')\n }\n}\n\nfunction validateReorderPage(document: SceneDocument, op: ReorderPageOperation): void {\n requirePage(document, op.pageId)\n if (op.toIndex < 0 || op.toIndex >= document.pages.length) {\n throw new Error(`toIndex ${op.toIndex} out of range (document has ${document.pages.length} pages)`)\n }\n}\n\nfunction validateSetPageProps(document: SceneDocument, op: SetPagePropsOperation): void {\n requirePage(document, op.pageId)\n if (op.width !== undefined) assertPositiveFinite(op.width, 'page width')\n if (op.height !== undefined) assertPositiveFinite(op.height, 'page height')\n if (op.background !== undefined) assertColor(op.background, 'page background')\n if (op.bleed != null) {\n assertNonNegativeFinite(op.bleed.top, 'bleed.top')\n assertNonNegativeFinite(op.bleed.right, 'bleed.right')\n assertNonNegativeFinite(op.bleed.bottom, 'bleed.bottom')\n assertNonNegativeFinite(op.bleed.left, 'bleed.left')\n }\n}\n\nfunction validateSetPageGuides(document: SceneDocument, op: SetPageGuidesOperation): void {\n requirePage(document, op.pageId)\n for (const pos of op.guides.vertical) {\n if (!Number.isFinite(pos)) throw new Error(`guide position ${pos} is not finite`)\n }\n for (const pos of op.guides.horizontal) {\n if (!Number.isFinite(pos)) throw new Error(`guide position ${pos} is not finite`)\n }\n}\n\nfunction validateBindSlot(document: SceneDocument, op: BindSlotOperation): void {\n const page = requirePage(document, op.pageId)\n requireElement(page, op.elementId)\n if (op.slot === null) return\n // Slot names must be unique document-wide; a re-bind of the SAME element to\n // its own current slot name is fine (idempotent) — collectSlots throws on\n // duplicates owned by DIFFERENT elements, so we check manually.\n for (const p of document.pages) {\n const stack = [...p.elements]\n while (stack.length > 0) {\n const el = stack.pop()!\n if (el.slot === op.slot && el.id !== op.elementId) {\n throw new Error(`slot \"${op.slot}\" is already bound to element \"${el.id}\" on page \"${p.id}\"`)\n }\n if (el.kind === 'group') stack.push(...el.children)\n }\n }\n}\n\nfunction validateApplyData(document: SceneDocument, op: ApplyDataOperation): void {\n // Build the slot map; collectSlots throws on internal duplicates\n const slots = collectSlots(document)\n for (const [slotName, value] of Object.entries(op.bindings)) {\n const slot = slots.get(slotName)\n if (!slot) {\n throw new Error(`slot \"${slotName}\" does not exist in the document`)\n }\n validateSlotValue(slotName, slot.kind, value)\n }\n}\n\nfunction validateSetDocumentTitle(op: SetDocumentTitleOperation): void {\n if (op.title.trim().length === 0) throw new Error('title must be non-empty')\n}\n\n// ---------------------------------------------------------------------------\n// Element attr validation\n// ---------------------------------------------------------------------------\n\n/** Attributes present on EVERY element kind (SceneElementBase minus id/kind). */\nconst BASE_ATTRS = new Set([\n 'name', 'x', 'y', 'rotation', 'opacity', 'locked', 'visible', 'slot',\n])\n\n/** Per-kind allowed attributes (beyond base). */\nconst KIND_ATTRS: Record<SceneElementKind, Set<string>> = {\n rect: new Set(['width', 'height', 'fill', 'stroke', 'strokeWidth', 'cornerRadius']),\n ellipse: new Set(['width', 'height', 'fill', 'stroke', 'strokeWidth']),\n line: new Set(['points', 'stroke', 'strokeWidth', 'dash']),\n text: new Set(['text', 'width', 'fontFamily', 'fontSize', 'fontStyle', 'fill', 'align', 'lineHeight', 'letterSpacing']),\n image: new Set(['width', 'height', 'src', 'fit']),\n video: new Set(['width', 'height', 'src', 'posterSrc']),\n group: new Set([]),\n}\n\nconst FONT_STYLES = new Set(['normal', 'bold', 'italic', 'bold italic'])\nconst ALIGN_VALUES = new Set(['left', 'center', 'right'])\nconst FIT_VALUES = new Set(['fill', 'cover', 'contain'])\n\n/**\n * Validates attribute patches (or full element attrs for add_element).\n * `isConstruction` = true when validating a new element (required fields\n * must be present); false for a partial set_attrs patch.\n */\nfunction validateElementAttrs(\n kind: SceneElementKind,\n attrs: SceneAttrsPatch,\n isConstruction: boolean,\n): void {\n const allowed = KIND_ATTRS[kind]\n\n // Foreign attribute check: reject any key that is neither base nor kind-specific.\n for (const key of Object.keys(attrs)) {\n if (key === 'id' || key === 'kind' || key === 'children') continue\n if (!BASE_ATTRS.has(key) && !allowed.has(key)) {\n throw new Error(`attribute \"${key}\" is not valid for a ${kind} element`)\n }\n }\n\n // Base attribute validation\n if (attrs.opacity !== undefined) {\n if (typeof attrs.opacity !== 'number' || !Number.isFinite(attrs.opacity) || attrs.opacity < 0 || attrs.opacity > 1) {\n throw new Error('opacity must be a number in [0, 1]')\n }\n }\n if (attrs.x !== undefined) assertFinite(attrs.x, 'x')\n if (attrs.y !== undefined) assertFinite(attrs.y, 'y')\n if (attrs.rotation !== undefined) assertFinite(attrs.rotation, 'rotation')\n\n // Kind-specific attribute validation\n switch (kind) {\n case 'rect':\n case 'ellipse':\n case 'image':\n case 'video':\n if (attrs.width !== undefined) assertPositiveFinite(attrs.width, 'width')\n if (attrs.height !== undefined) assertPositiveFinite(attrs.height, 'height')\n break\n case 'text':\n if (attrs.width !== undefined) assertPositiveFinite(attrs.width, 'width')\n if (attrs.fontSize !== undefined) assertPositiveFinite(attrs.fontSize, 'fontSize')\n if (attrs.lineHeight !== undefined) {\n if (typeof attrs.lineHeight !== 'number' || !Number.isFinite(attrs.lineHeight) || attrs.lineHeight <= 0) {\n throw new Error('lineHeight must be a positive finite number')\n }\n }\n if (attrs.fontStyle !== undefined && !FONT_STYLES.has(attrs.fontStyle)) {\n throw new Error(`fontStyle must be one of: ${[...FONT_STYLES].join(', ')}`)\n }\n if (attrs.align !== undefined && !ALIGN_VALUES.has(attrs.align)) {\n throw new Error(`align must be one of: ${[...ALIGN_VALUES].join(', ')}`)\n }\n break\n case 'line':\n if (attrs.points !== undefined) {\n if (!Array.isArray(attrs.points) || attrs.points.length < 4 || attrs.points.length % 2 !== 0) {\n throw new Error('points must be an even-length array with at least 4 numbers (2 points)')\n }\n for (let i = 0; i < attrs.points.length; i++) {\n if (!Number.isFinite(attrs.points[i])) {\n throw new Error(`points[${i}] is not finite`)\n }\n }\n }\n if (attrs.strokeWidth !== undefined) assertPositiveFinite(attrs.strokeWidth, 'strokeWidth')\n break\n case 'group':\n // Group geometry derives from children; no width/height attrs.\n break\n }\n\n // Color validation for fill/stroke\n if (attrs.fill !== undefined) assertColor(attrs.fill, 'fill')\n if (attrs.stroke !== undefined) assertColor(attrs.stroke, 'stroke')\n if (attrs.strokeWidth !== undefined && kind !== 'line') {\n assertPositiveFinite(attrs.strokeWidth, 'strokeWidth')\n }\n\n // Image/video src\n if (attrs.src !== undefined) assertSceneMediaSrc(attrs.src, 'src')\n if ((attrs as { posterSrc?: string }).posterSrc !== undefined) {\n assertSceneMediaSrc((attrs as { posterSrc: string }).posterSrc, 'posterSrc')\n }\n\n // fit\n if (attrs.fit !== undefined && !FIT_VALUES.has(attrs.fit)) {\n throw new Error(`fit must be one of: ${[...FIT_VALUES].join(', ')}`)\n }\n\n // Construction-time required-field checks\n if (isConstruction) {\n validateRequiredConstructionAttrs(kind, attrs)\n }\n}\n\nfunction validateRequiredConstructionAttrs(kind: SceneElementKind, attrs: SceneAttrsPatch): void {\n switch (kind) {\n case 'rect':\n requireAttrPresent(attrs, 'width', kind)\n requireAttrPresent(attrs, 'height', kind)\n requireAttrPresent(attrs, 'fill', kind)\n break\n case 'ellipse':\n requireAttrPresent(attrs, 'width', kind)\n requireAttrPresent(attrs, 'height', kind)\n requireAttrPresent(attrs, 'fill', kind)\n break\n case 'line':\n requireAttrPresent(attrs, 'points', kind)\n requireAttrPresent(attrs, 'stroke', kind)\n requireAttrPresent(attrs, 'strokeWidth', kind)\n break\n case 'text':\n requireAttrPresent(attrs, 'text', kind)\n requireAttrPresent(attrs, 'width', kind)\n requireAttrPresent(attrs, 'fontFamily', kind)\n requireAttrPresent(attrs, 'fontSize', kind)\n requireAttrPresent(attrs, 'fontStyle', kind)\n requireAttrPresent(attrs, 'fill', kind)\n requireAttrPresent(attrs, 'align', kind)\n requireAttrPresent(attrs, 'lineHeight', kind)\n requireAttrPresent(attrs, 'letterSpacing', kind)\n break\n case 'image':\n requireAttrPresent(attrs, 'width', kind)\n requireAttrPresent(attrs, 'height', kind)\n requireAttrPresent(attrs, 'src', kind)\n requireAttrPresent(attrs, 'fit', kind)\n break\n case 'video':\n requireAttrPresent(attrs, 'width', kind)\n requireAttrPresent(attrs, 'height', kind)\n requireAttrPresent(attrs, 'src', kind)\n break\n case 'group':\n // Groups are created empty; children are added separately.\n break\n }\n}\n\nfunction requireAttrPresent(attrs: SceneAttrsPatch, key: string, kind: SceneElementKind): void {\n if ((attrs as Record<string, unknown>)[key] === undefined) {\n throw new Error(`${key} is required when constructing a ${kind} element`)\n }\n}\n\n// ---------------------------------------------------------------------------\n// Slot value typing (apply_data)\n// ---------------------------------------------------------------------------\n\n/**\n * Validates that a slot binding value matches the slot element's kind.\n * text → any string; image/video → media src; rect/ellipse/line/group → color.\n */\nexport function validateSlotValue(slotName: string, elementKind: SceneElementKind, value: string): void {\n switch (elementKind) {\n case 'text':\n // Any string is valid for a text slot.\n return\n case 'image':\n case 'video':\n try {\n assertSceneMediaSrc(value, `slot \"${slotName}\" value`)\n } catch (e) {\n throw new Error(\n `slot \"${slotName}\" is bound to a ${elementKind} element — value must be an http(s) URL or a rooted /api/ path (got \"${value}\")`,\n )\n }\n return\n case 'rect':\n case 'ellipse':\n case 'line':\n case 'group':\n try {\n assertColor(value, `slot \"${slotName}\" value`)\n } catch {\n throw new Error(\n `slot \"${slotName}\" is bound to a ${elementKind} element — value must be a color (hex/rgb(a)/transparent) for fill/stroke recolor (got \"${value}\")`,\n )\n }\n return\n }\n}\n\n// ---------------------------------------------------------------------------\n// Document-wide uniqueness\n// ---------------------------------------------------------------------------\n\nfunction assertUniqueIdDocumentWide(document: SceneDocument, id: string): void {\n for (const page of document.pages) {\n if (page.id === id) throw new Error(`id \"${id}\" is already used by a page`)\n const stack = [...page.elements]\n while (stack.length > 0) {\n const el = stack.pop()!\n if (el.id === id) throw new Error(`id \"${id}\" is already used by element on page \"${page.id}\"`)\n if (el.kind === 'group') stack.push(...el.children)\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Internal guards\n// ---------------------------------------------------------------------------\n\nfunction assertNonNegativeFinite(value: number, label: string): void {\n if (!Number.isFinite(value) || value < 0) {\n throw new Error(`${label} must be a non-negative finite number`)\n }\n}\n","/**\n * Pure application of validated scene operations to a SceneDocument.\n * `applySceneOperations` deep-clones the document then mutates the clone,\n * returning the new document and per-op results. It never touches the store,\n * a clock, or a PRNG — all id generation goes through the caller-supplied\n * `mintId` option so callers control determinism (counter in tests,\n * crypto.randomUUID in production).\n *\n * Rotation semantics for group/ungroup:\n * Group: children retain their absolute rotation. The group origin is the\n * min-x, min-y corner of the AABB union of all member elements. Children\n * are rebased so their position in group-local space equals\n * (element.x - group.x, element.y - group.y). A rotated child appears at\n * the same absolute page position after grouping because the group's additive\n * translation preserves the child's own-origin transform.\n * Ungroup: inverse — child.x += group.x, child.y += group.y; rotation stays.\n * This is consistent with Konva's transform-about-own-origin model without\n * needing a full matrix concatenation for the common case.\n *\n * `storeApplyScenePlan` layers store I/O on top: getDocument → validate →\n * apply → saveDocument(expectedRev) → recordDecision, retrying once on\n * stale-rev by refetch + revalidate + reapply.\n */\n\nimport {\n assertColor,\n assertSceneMediaSrc,\n collectSlots,\n createPage,\n elementAabb,\n requireElement,\n requirePage,\n} from './model'\nimport type {\n GroupElement,\n NewPageOptions,\n SceneDocument,\n SceneElement,\n ScenePage,\n} from './model'\nimport type {\n AddElementOperation,\n AddPageOperation,\n ApplyDataOperation,\n BindSlotOperation,\n DeleteElementOperation,\n DeletePageOperation,\n DuplicatePageOperation,\n GroupElementsOperation,\n ReorderElementOperation,\n ReorderPageOperation,\n SceneOperation,\n ScenePlan,\n SetAttrsOperation,\n SetDocumentTitleOperation,\n SetPageGuidesOperation,\n SetPagePropsOperation,\n UngroupElementOperation,\n} from './operations'\nimport type { NewSceneDecision, SceneDocumentRecord, SceneStore } from './store'\nimport { validateSceneOperations } from './validate'\n\n// ---------------------------------------------------------------------------\n// Result types\n// ---------------------------------------------------------------------------\n\n/** Represent the result of applying changes to a scene as an element, page, or entire document */\nexport type SceneApplyResult =\n | { kind: 'element'; pageId: string; element: SceneElement }\n | { kind: 'page'; page: ScenePage }\n | { kind: 'document' }\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\n/** Resolve element ID conflicts by providing fresh unique identifiers during scene application */\nexport interface ApplySceneOptions {\n /**\n * Provides fresh ids when duplicate_page re-mints element ids. Never called\n * by any other operation. Counter-based in tests; crypto.randomUUID in\n * production (wrapped so `mintId()` has no arguments, matching this signature).\n */\n mintId: () => string\n}\n\n// ---------------------------------------------------------------------------\n// Public: pure apply\n// ---------------------------------------------------------------------------\n\n/** Full form: returns the new document AND per-op results. `mintId` must be\n * provided when any operation in the list may be `duplicate_page` (which\n * re-mints element ids); for all other operation types it is never called. */\nexport function applySceneOperations(\n document: SceneDocument,\n operations: SceneOperation[],\n options: ApplySceneOptions,\n): { document: SceneDocument; results: SceneApplyResult[] }\n\n/** Convenience 2-arg form: returns the new document directly. Uses a\n * monotonic counter as the mintId so `duplicate_page` never collides within\n * a single call (suitable for editor-local optimistic state; server will\n * re-mint on persist). */\nexport function applySceneOperations(\n document: SceneDocument,\n operations: SceneOperation[],\n): SceneDocument\n\nexport function applySceneOperations(\n document: SceneDocument,\n operations: SceneOperation[],\n options?: ApplySceneOptions,\n): { document: SceneDocument; results: SceneApplyResult[] } | SceneDocument {\n const opts = options ?? { mintId: makeCounter() }\n const doc = deepCloneDocument(document)\n const results: SceneApplyResult[] = []\n for (const operation of operations) {\n results.push(applyOneOperation(doc, operation, opts))\n }\n return options !== undefined ? { document: doc, results } : doc\n}\n\n/** Apply a single operation to a document and return the new document.\n * Equivalent to `applySceneOperations(doc, [op])` but returns `SceneDocument`\n * directly — the common case in editor commands and tests. */\nexport function applySceneOperation(\n document: SceneDocument,\n operation: SceneOperation,\n): SceneDocument {\n return applySceneOperations(document, [operation])\n}\n\nfunction makeCounter(): () => string {\n let n = 0\n return () => `minted-${(n += 1)}`\n}\n\n// ---------------------------------------------------------------------------\n// Public: store-integrated helper\n// ---------------------------------------------------------------------------\n\n/** Detects the stale-revision sentinel thrown by drizzle-store. The store\n * throws a plain Error whose message contains \"stale rev\" — no custom class\n * is needed because the store contract documents exactly this phrase. */\nfunction isStaleRevError(err: unknown): boolean {\n return err instanceof Error && /stale rev/i.test(err.message)\n}\n\n/** Resolve and apply a scene plan to the store with specified actor context and generate results */\nexport async function storeApplyScenePlan(\n store: SceneStore,\n plan: ScenePlan,\n opts: { actorKind: NewSceneDecision['kind']; mintId: () => string },\n): Promise<{ record: SceneDocumentRecord; results: SceneApplyResult[] }> {\n let { document, rev } = await store.getDocument()\n\n validateSceneOperations(document, plan.operations)\n let applied = applySceneOperations(document, plan.operations, { mintId: opts.mintId })\n\n let record: SceneDocumentRecord\n try {\n record = await store.saveDocument(applied.document, rev)\n } catch (firstError) {\n // Only retry for stale-rev conflicts. Any other error (network, constraint,\n // permissions) is a hard failure — retrying would risk a double-apply if\n // the first save actually succeeded but the acknowledgement was lost.\n if (!isStaleRevError(firstError)) throw firstError\n const refreshed = await store.getDocument()\n validateSceneOperations(refreshed.document, plan.operations)\n applied = applySceneOperations(refreshed.document, plan.operations, { mintId: opts.mintId })\n try {\n record = await store.saveDocument(applied.document, refreshed.rev)\n } catch (secondError) {\n const reason = secondError instanceof Error ? secondError.message : String(secondError)\n throw new Error(`storeApplyScenePlan: stale rev persists after retry — ${reason}`)\n }\n }\n\n const opTypeCounts: Record<string, number> = {}\n for (const op of plan.operations) {\n opTypeCounts[op.type] = (opTypeCounts[op.type] ?? 0) + 1\n }\n\n await store.recordDecision({\n kind: opts.actorKind,\n instruction: plan.summary,\n metadata: { opTypeCounts, operationCount: plan.operations.length },\n })\n\n return { record, results: applied.results }\n}\n\n// ---------------------------------------------------------------------------\n// Per-operation dispatch (mutates cloned doc in-place)\n// ---------------------------------------------------------------------------\n\nfunction applyOneOperation(\n doc: SceneDocument,\n operation: SceneOperation,\n options: ApplySceneOptions,\n): SceneApplyResult {\n switch (operation.type) {\n case 'add_element':\n return applyAddElement(doc, operation)\n case 'set_attrs':\n return applySetAttrs(doc, operation)\n case 'reorder_element':\n return applyReorderElement(doc, operation)\n case 'delete_element':\n return applyDeleteElement(doc, operation)\n case 'group_elements':\n return applyGroupElements(doc, operation)\n case 'ungroup_element':\n return applyUngroupElement(doc, operation)\n case 'add_page':\n return applyAddPage(doc, operation)\n case 'duplicate_page':\n return applyDuplicatePage(doc, operation, options)\n case 'delete_page':\n return applyDeletePage(doc, operation)\n case 'reorder_page':\n return applyReorderPage(doc, operation)\n case 'set_page_props':\n return applySetPageProps(doc, operation)\n case 'set_page_guides':\n return applySetPageGuides(doc, operation)\n case 'bind_slot':\n return applyBindSlot(doc, operation)\n case 'apply_data':\n return applyApplyData(doc, operation)\n case 'set_document_title':\n return applySetDocumentTitle(doc, operation)\n }\n}\n\n// ---------------------------------------------------------------------------\n// Operation implementations (all mutate the deep-cloned doc)\n// ---------------------------------------------------------------------------\n\nfunction applyAddElement(doc: SceneDocument, op: AddElementOperation): SceneApplyResult {\n const page = requirePage(doc, op.pageId)\n const owner: SceneElement[] = op.parentGroupId !== undefined\n ? (() => {\n const { element: g } = requireElement(page, op.parentGroupId)\n return (g as GroupElement).children\n })()\n : page.elements\n const index = op.index !== undefined ? op.index : owner.length\n owner.splice(index, 0, op.element)\n return { kind: 'element', pageId: op.pageId, element: op.element }\n}\n\nfunction applySetAttrs(doc: SceneDocument, op: SetAttrsOperation): SceneApplyResult {\n const page = requirePage(doc, op.pageId)\n const { element, owner, index } = requireElement(page, op.elementId)\n const patched = { ...element, ...op.attrs } as SceneElement\n owner[index] = patched\n return { kind: 'element', pageId: op.pageId, element: patched }\n}\n\nfunction applyReorderElement(doc: SceneDocument, op: ReorderElementOperation): SceneApplyResult {\n const page = requirePage(doc, op.pageId)\n const { element, owner, index } = requireElement(page, op.elementId)\n owner.splice(index, 1)\n owner.splice(op.toIndex, 0, element)\n return { kind: 'element', pageId: op.pageId, element }\n}\n\nfunction applyDeleteElement(doc: SceneDocument, op: DeleteElementOperation): SceneApplyResult {\n const page = requirePage(doc, op.pageId)\n const { element, owner, index } = requireElement(page, op.elementId)\n owner.splice(index, 1)\n return { kind: 'element', pageId: op.pageId, element }\n}\n\nfunction applyGroupElements(doc: SceneDocument, op: GroupElementsOperation): SceneApplyResult {\n const page = requirePage(doc, op.pageId)\n const members = op.elementIds.map((id) => requireElement(page, id))\n\n // Group origin = min AABB corner of all members in the owner coordinate space.\n let minX = Infinity, minY = Infinity\n for (const { element } of members) {\n const aabb = elementAabb(element)\n if (aabb.x < minX) minX = aabb.x\n if (aabb.y < minY) minY = aabb.y\n }\n\n const owner = members[0]!.owner\n // Sort ascending by index to preserve z-order in children array.\n const sortedByIndex = [...members].sort((a, b) => a.index - b.index)\n\n // Children retain rotation; x/y rebased to group-local space.\n const children: SceneElement[] = sortedByIndex.map(({ element }) => ({\n ...element,\n x: element.x - minX,\n y: element.y - minY,\n }))\n\n // Remove in reverse order to avoid index drift.\n for (const { index } of [...sortedByIndex].reverse()) {\n owner.splice(index, 1)\n }\n\n // Group inserted at the slot vacated by the bottommost former member.\n const insertAt = sortedByIndex[0]!.index\n\n const group: GroupElement = {\n id: op.groupId,\n kind: 'group',\n name: op.name ?? 'Group',\n x: minX,\n y: minY,\n rotation: 0,\n opacity: 1,\n locked: false,\n visible: true,\n children,\n }\n\n owner.splice(insertAt, 0, group)\n return { kind: 'element', pageId: op.pageId, element: group }\n}\n\nfunction applyUngroupElement(doc: SceneDocument, op: UngroupElementOperation): SceneApplyResult {\n const page = requirePage(doc, op.pageId)\n const { element: groupEl, owner, index: groupIndex } = requireElement(page, op.groupId)\n const group = groupEl as GroupElement\n\n // Re-absolutize: child.x/y += group.x/y; rotation unchanged.\n const promoted: SceneElement[] = group.children.map((child) => ({\n ...child,\n x: child.x + group.x,\n y: child.y + group.y,\n }))\n\n owner.splice(groupIndex, 1, ...promoted)\n return { kind: 'element', pageId: op.pageId, element: groupEl }\n}\n\nfunction applyAddPage(doc: SceneDocument, op: AddPageOperation): SceneApplyResult {\n const opts: NewPageOptions = op.options ?? {}\n const page = createPage(opts, op.pageId)\n const index = op.index !== undefined ? op.index : doc.pages.length\n doc.pages.splice(index, 0, page)\n return { kind: 'page', page }\n}\n\nfunction applyDuplicatePage(\n doc: SceneDocument,\n op: DuplicatePageOperation,\n options: ApplySceneOptions,\n): SceneApplyResult {\n const source = requirePage(doc, op.sourcePageId)\n const copy: ScenePage = JSON.parse(JSON.stringify(source)) as ScenePage\n copy.id = op.pageId\n // Re-mint all element ids so the copy has no id collisions with the source.\n remintElementIds(copy.elements, options.mintId)\n doc.pages.push(copy)\n return { kind: 'page', page: copy }\n}\n\nfunction remintElementIds(elements: SceneElement[], mintId: () => string): void {\n for (let i = 0; i < elements.length; i++) {\n const el = elements[i]!\n const newEl: SceneElement = { ...el, id: mintId() }\n if (newEl.kind === 'group') {\n remintElementIds((newEl as GroupElement).children, mintId)\n }\n elements[i] = newEl\n }\n}\n\nfunction applyDeletePage(doc: SceneDocument, op: DeletePageOperation): SceneApplyResult {\n if (doc.pages.length <= 1) throw new Error('delete_page: cannot delete the last page')\n const index = doc.pages.findIndex((p) => p.id === op.pageId)\n if (index < 0) throw new Error(`page ${op.pageId} not found`)\n const [page] = doc.pages.splice(index, 1) as [ScenePage]\n return { kind: 'page', page }\n}\n\nfunction applyReorderPage(doc: SceneDocument, op: ReorderPageOperation): SceneApplyResult {\n const index = doc.pages.findIndex((p) => p.id === op.pageId)\n if (index < 0) throw new Error(`page ${op.pageId} not found`)\n const [page] = doc.pages.splice(index, 1) as [ScenePage]\n doc.pages.splice(op.toIndex, 0, page)\n return { kind: 'page', page }\n}\n\nfunction applySetPageProps(doc: SceneDocument, op: SetPagePropsOperation): SceneApplyResult {\n const page = requirePage(doc, op.pageId)\n if (op.name !== undefined) page.name = op.name\n if (op.width !== undefined) page.width = op.width\n if (op.height !== undefined) page.height = op.height\n if (op.background !== undefined) page.background = op.background\n if (op.bleed !== undefined) page.bleed = op.bleed\n return { kind: 'page', page }\n}\n\nfunction applySetPageGuides(doc: SceneDocument, op: SetPageGuidesOperation): SceneApplyResult {\n const page = requirePage(doc, op.pageId)\n page.guides = op.guides\n return { kind: 'page', page }\n}\n\nfunction applyBindSlot(doc: SceneDocument, op: BindSlotOperation): SceneApplyResult {\n const page = requirePage(doc, op.pageId)\n const { element, owner, index } = requireElement(page, op.elementId)\n const patched: SceneElement = op.slot === null ? omitSlot(element) : { ...element, slot: op.slot }\n owner[index] = patched\n return { kind: 'element', pageId: op.pageId, element: patched }\n}\n\nfunction omitSlot(element: SceneElement): SceneElement {\n const { slot: _slot, ...rest } = element as SceneElement & { slot?: string }\n return rest as SceneElement\n}\n\nfunction applyApplyData(doc: SceneDocument, op: ApplyDataOperation): SceneApplyResult {\n const slots = collectSlots(doc)\n for (const [slotName, value] of Object.entries(op.bindings)) {\n const slot = slots.get(slotName)\n if (!slot) throw new Error(`slot \"${slotName}\" not found in document`)\n const page = requirePage(doc, slot.pageId)\n const { element, owner, index } = requireElement(page, slot.elementId)\n owner[index] = applySlotValue(element, value)\n }\n return { kind: 'document' }\n}\n\nfunction applySlotValue(element: SceneElement, value: string): SceneElement {\n switch (element.kind) {\n case 'text':\n return { ...element, text: value }\n case 'image':\n case 'video':\n assertSceneMediaSrc(value, 'slot value')\n return { ...element, src: value }\n case 'rect':\n case 'ellipse':\n assertColor(value, 'slot value')\n return { ...element, fill: value }\n case 'line':\n assertColor(value, 'slot value')\n return { ...element, stroke: value }\n case 'group':\n // Group recolor: propagate fill/stroke to children that carry the property.\n assertColor(value, 'slot value')\n return recolorGroupChildren(element as GroupElement, value)\n }\n}\n\nfunction recolorGroupChildren(group: GroupElement, color: string): GroupElement {\n const children = group.children.map((child): SceneElement => {\n switch (child.kind) {\n case 'rect':\n case 'ellipse':\n return { ...child, fill: color }\n case 'line':\n return { ...child, stroke: color }\n case 'text':\n return { ...child, fill: color }\n case 'image':\n case 'video':\n return child\n case 'group':\n return recolorGroupChildren(child, color)\n }\n })\n return { ...group, children }\n}\n\nfunction applySetDocumentTitle(doc: SceneDocument, op: SetDocumentTitleOperation): SceneApplyResult {\n doc.title = op.title\n return { kind: 'document' }\n}\n\n// ---------------------------------------------------------------------------\n// Deep clone\n// ---------------------------------------------------------------------------\n\nfunction deepCloneDocument(document: SceneDocument): SceneDocument {\n return JSON.parse(JSON.stringify(document)) as SceneDocument\n}\n","/**\n * Page size presets, channel-size output presets, and export math for the\n * design canvas.\n *\n * Size presets (SizePreset / SIZE_PRESETS) describe page dimensions for the\n * new-page dialog. Export presets (ExportPreset / EXPORT_PRESETS) pin pixel\n * ratio, output dimensions, bleed, and format for the export dialog and the\n * MCP export tool. Channel presets (ChannelPreset / CHANNEL_PRESETS) are the\n * fixed output resolutions the export UI offers; `scaleForPreset` + the\n * letterbox helper derive Konva stage parameters from them.\n *\n * All dimensions are CSS pixels at 96 DPI unless noted otherwise.\n */\n\nimport type { Bounds, PageBleed, ScenePage } from './model'\n\n/** Define size presets with identifiers, labels, categories, and dimensions for various media types */\nexport interface SizePreset {\n id: string\n label: string\n category: 'social' | 'print' | 'presentation' | 'custom'\n width: number\n height: number\n}\n\n/** Provide predefined size presets for social, presentation, and print categories */\nexport const SIZE_PRESETS: readonly SizePreset[] = [\n // Social\n { id: 'instagram-square', label: 'Instagram — Square', category: 'social', width: 1080, height: 1080 },\n { id: 'instagram-portrait', label: 'Instagram — Portrait', category: 'social', width: 1080, height: 1350 },\n { id: 'instagram-story', label: 'Instagram Story', category: 'social', width: 1080, height: 1920 },\n { id: 'twitter-post', label: 'X / Twitter Post', category: 'social', width: 1200, height: 675 },\n { id: 'linkedin-post', label: 'LinkedIn Post', category: 'social', width: 1200, height: 627 },\n { id: 'facebook-post', label: 'Facebook Post', category: 'social', width: 1200, height: 630 },\n { id: 'youtube-thumbnail', label: 'YouTube Thumbnail', category: 'social', width: 1280, height: 720 },\n { id: 'og-image', label: 'Open Graph Image', category: 'social', width: 1200, height: 630 },\n // Presentation\n { id: 'slide-16-9', label: 'Slide — 16:9', category: 'presentation', width: 1920, height: 1080 },\n { id: 'slide-4-3', label: 'Slide — 4:3', category: 'presentation', width: 1024, height: 768 },\n // Print (96 DPI px equivalents of A4, Letter — products may scale at export)\n { id: 'a4-landscape', label: 'A4 Landscape', category: 'print', width: 1123, height: 794 },\n { id: 'a4-portrait', label: 'A4 Portrait', category: 'print', width: 794, height: 1123 },\n { id: 'us-letter-landscape', label: 'US Letter Landscape', category: 'print', width: 1100, height: 850 },\n { id: 'us-letter-portrait', label: 'US Letter Portrait', category: 'print', width: 850, height: 1100 },\n] as const\n\n/** Resolve a size preset by its identifier or return null if not found */\nexport function findPreset(id: string): SizePreset | null {\n return SIZE_PRESETS.find((p) => p.id === id) ?? null\n}\n\n/** Match a (width, height) pair against the preset table. Returns the first\n * exact match or null — used to drive the dropdown selection indicator. */\nexport function matchPreset(width: number, height: number): SizePreset | null {\n return SIZE_PRESETS.find((p) => p.width === width && p.height === height) ?? null\n}\n\n// ---------------------------------------------------------------------------\n// Export quality presets\n// ---------------------------------------------------------------------------\n\n/** Define supported image export formats as PNG or JPEG */\nexport type ExportFormat = 'png' | 'jpeg'\n\n/**\n * Export quality preset — pins pixel density, optional output dimensions,\n * bleed inclusion, and raster format so callers pass a preset id rather than\n * a full parameter bag.\n *\n * `outputWidth` / `outputHeight`: when non-null, the pixel ratio is derived\n * from the crop rect width (see `scaleForPreset`) so the output is exactly\n * this many pixels wide. When null, `pixelRatio` applies directly.\n */\nexport interface ExportPreset {\n name: string\n /** Target pixels-per-document-px for stage.toDataURL. */\n pixelRatio: number\n outputWidth: number | null\n outputHeight: number | null\n /** Whether bleed margins are included in the crop rect. */\n includeBleed: boolean\n format: ExportFormat\n}\n\n/** Provide predefined export configurations for various social media and image formats */\nexport const EXPORT_PRESETS: Record<string, ExportPreset> = {\n 'instagram-square': {\n name: 'Instagram square (1080×1080)',\n pixelRatio: 1,\n outputWidth: 1080,\n outputHeight: 1080,\n includeBleed: false,\n format: 'jpeg',\n },\n 'instagram-portrait': {\n name: 'Instagram portrait (1080×1350)',\n pixelRatio: 1,\n outputWidth: 1080,\n outputHeight: 1350,\n includeBleed: false,\n format: 'jpeg',\n },\n 'twitter-card': {\n name: 'Twitter/X card (1200×675)',\n pixelRatio: 1,\n outputWidth: 1200,\n outputHeight: 675,\n includeBleed: false,\n format: 'jpeg',\n },\n 'og-image': {\n name: 'OG image (1200×630)',\n pixelRatio: 1,\n outputWidth: 1200,\n outputHeight: 630,\n includeBleed: false,\n format: 'png',\n },\n 'print-a4': {\n name: 'Print A4 (300 dpi)',\n pixelRatio: 3.125,\n outputWidth: null,\n outputHeight: null,\n includeBleed: true,\n format: 'png',\n },\n 'screen-2x': {\n name: 'Screen @2×',\n pixelRatio: 2,\n outputWidth: null,\n outputHeight: null,\n includeBleed: false,\n format: 'png',\n },\n} as const\n\n// ---------------------------------------------------------------------------\n// Crop + scale math (pure, no canvas context)\n// ---------------------------------------------------------------------------\n\n/** Define crop rectangle coordinates and dimensions for exporting content within page bounds */\nexport interface ExportCropRect {\n /** Page-coordinate origin. Negative when bleed extends outside page bounds. */\n x: number\n y: number\n width: number\n height: number\n}\n\n/**\n * Crop rectangle in page coordinates for a given page, optionally expanded to\n * include bleed margins. Bleed extends OUTSIDE the page bounds, so the origin\n * goes negative when bleed is included.\n *\n * When `includeBleed` is true but `page.bleed` is null, the page rect is\n * returned unchanged — the caller must not assume symmetric expansion.\n */\nexport function bleedAwareExportBounds(page: ScenePage, includeBleed: boolean): ExportCropRect {\n if (!includeBleed || page.bleed === null) {\n return { x: 0, y: 0, width: page.width, height: page.height }\n }\n const bleed: PageBleed = page.bleed\n return {\n x: -bleed.left,\n y: -bleed.top,\n width: page.width + bleed.left + bleed.right,\n height: page.height + bleed.top + bleed.bottom,\n }\n}\n\n/**\n * Pixel ratio for stage.toDataURL given a crop rect and an export preset.\n *\n * When the preset pins `outputWidth`, the ratio is derived from the crop rect\n * width so the final raster is exactly that many pixels wide. When there is no\n * output pin, the preset's declared `pixelRatio` is returned directly.\n *\n * The crop rect must already account for bleed inclusion before this call.\n */\nexport function scaleForPreset(preset: ExportPreset, cropRect: ExportCropRect): number {\n if (preset.outputWidth !== null) {\n if (cropRect.width <= 0) {\n throw new Error(`export crop width must be positive, got ${cropRect.width}`)\n }\n return preset.outputWidth / cropRect.width\n }\n return preset.pixelRatio\n}\n\n// ---------------------------------------------------------------------------\n// Channel-size presets (fixed output resolutions for the export UI)\n// ---------------------------------------------------------------------------\n\n/** Define a preset configuration for a channel including its id, label, width, and height */\nexport interface ChannelPreset {\n id: string\n label: string\n width: number\n height: number\n}\n\n/**\n * Fixed output resolution presets for the channel/platform export dialog.\n * Width × height are OUTPUT pixels (the raster the export produces), not page\n * CSS px — they describe the target delivery format, not the canvas layout.\n * The a4_print_2480x3508 preset corresponds to A4 at 300 dpi.\n */\nexport const CHANNEL_PRESETS: readonly ChannelPreset[] = [\n { id: 'square_1080', label: 'Square (1080×1080)', width: 1080, height: 1080 },\n { id: 'portrait_1080x1350', label: 'Portrait (1080×1350)', width: 1080, height: 1350 },\n { id: 'story_1080x1920', label: 'Story (1080×1920)', width: 1080, height: 1920 },\n { id: 'landscape_1200x628', label: 'Landscape (1200×628)', width: 1200, height: 628 },\n { id: 'wide_1920x1080', label: 'Wide (1920×1080)', width: 1920, height: 1080 },\n { id: 'og_1200x630', label: 'Open Graph (1200×630)', width: 1200, height: 630 },\n { id: 'a4_print_2480x3508', label: 'A4 Print (2480×3508 · 300 dpi)', width: 2480, height: 3508 },\n] as const\n\n/** Resolve a valid channel preset identifier from the predefined channel presets array */\nexport type ChannelPresetId = (typeof CHANNEL_PRESETS)[number]['id']\n\n/** Throws when the id is unknown — callers should only pass ids sourced from\n * `CHANNEL_PRESETS`. */\nexport function requireChannelPreset(id: string): ChannelPreset {\n const found = CHANNEL_PRESETS.find((p) => p.id === id)\n if (!found) {\n throw new Error(\n `unknown channel preset \"${id}\" — valid ids: ${CHANNEL_PRESETS.map((p) => p.id).join(', ')}`,\n )\n }\n return found\n}\n\n// ---------------------------------------------------------------------------\n// Letterbox scale math (page → channel preset, centered contain)\n// ---------------------------------------------------------------------------\n\n/** Define the pixel ratio and horizontal offset for scaling a Konva stage to a channel preset size */\nexport interface ChannelScaleResult {\n /**\n * Konva stage pixelRatio: the stage logical size stays at page dimensions;\n * the backing canvas renders at `pixelRatio × page` px. Setting Konva's\n * pixelRatio to this value yields an output canvas exactly\n * `channelPreset.width × channelPreset.height` pixels.\n */\n pixelRatio: number\n /**\n * Horizontal letterbox offset in PAGE-coordinate px. Add to the stage x\n * translation so the page is centered horizontally in the output frame.\n * Zero when the page fills the full width after scaling.\n */\n offsetX: number\n /**\n * Vertical letterbox offset in PAGE-coordinate px. Add to the stage y\n * translation. Zero when the page fills the full height.\n */\n offsetY: number\n fit: 'contain'\n}\n\n/**\n * Computes the Konva stage parameters to render `page` centered inside\n * `channelPreset` without cropping (contain / letterbox).\n *\n * Exact-ratio fast path: when page and preset share the same aspect ratio\n * (within 1e-9 floating-point tolerance) both offsets are 0 and pixelRatio\n * is exact.\n *\n * Example — 1080×1080 page into 1920×1080 preset:\n * scaleX = 1920/1080 ≈ 1.7778, scaleY = 1080/1080 = 1.0\n * pixelRatio = 1.0, rendered page = 1080×1080 px\n * offsetX = (1920 − 1080) / 2 / 1.0 = 420 page-px, offsetY = 0\n */\nexport function scalePageForChannelPreset(\n page: Pick<ScenePage, 'width' | 'height'>,\n channelPreset: ChannelPreset,\n): ChannelScaleResult {\n if (page.width <= 0 || page.height <= 0) {\n throw new Error(`page dimensions must be positive; got ${page.width}×${page.height}`)\n }\n\n const scaleX = channelPreset.width / page.width\n const scaleY = channelPreset.height / page.height\n const pixelRatio = Math.min(scaleX, scaleY)\n\n const renderedW = page.width * pixelRatio\n const renderedH = page.height * pixelRatio\n\n // Back-project padding into page coordinates so the Konva offset is in the\n // stage's own coordinate space\n const offsetX = ((channelPreset.width - renderedW) / 2) / pixelRatio\n const offsetY = ((channelPreset.height - renderedH) / 2) / pixelRatio\n\n return { pixelRatio, offsetX, offsetY, fit: 'contain' }\n}\n\n// ---------------------------------------------------------------------------\n// Bleed-aware trim bounds (no-arg bleed variant for templates/channel exports)\n// ---------------------------------------------------------------------------\n\n/**\n * Export rectangle in page coordinates that includes bleed margins when\n * present. When `page.bleed` is null, returns the trim rectangle (origin 0,0;\n * size = page dimensions).\n *\n * The bleed rectangle extends OUTSIDE the page: x and y are negative (bleed\n * bleeds off the left/top edge), width and height exceed the page by the\n * combined bleed on each axis. Pass into Konva's clip/export bounds to\n * include the bleed zone in the render.\n *\n * Named `bleedAwareExportRect` to avoid collision with the two-arg\n * `bleedAwareExportBounds(page, includeBleed)` above.\n */\nexport function bleedAwareExportRect(page: Pick<ScenePage, 'width' | 'height' | 'bleed'>): Bounds {\n if (page.bleed === null) {\n return { x: 0, y: 0, width: page.width, height: page.height }\n }\n const bleed: PageBleed = page.bleed\n return {\n x: -bleed.left,\n y: -bleed.top,\n width: page.width + bleed.left + bleed.right,\n height: page.height + bleed.top + bleed.bottom,\n }\n}\n"],"mappings":"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","names":[]}
@@ -4,7 +4,7 @@ import {
4
4
  boundsIntersect,
5
5
  elementAabb,
6
6
  scaleForPreset
7
- } from "./chunk-M2EBUDZ7.js";
7
+ } from "./chunk-VWOPOLVO.js";
8
8
 
9
9
  // src/design-canvas-react/engine/snap.ts
10
10
  var KIND_PRIORITY = {
@@ -440,4 +440,4 @@ export {
440
440
  buildInsertImageOp,
441
441
  DEFAULT_INSERT_TEMPLATES
442
442
  };
443
- //# sourceMappingURL=chunk-BN2USWIR.js.map
443
+ //# sourceMappingURL=chunk-VYECQAGM.js.map