@aglyn/plugins-ai 1.0.0-beta.229 → 1.0.0-beta.231

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 (340) hide show
  1. package/README.md +3 -3
  2. package/package.json +17 -17
  3. package/src/lib/activity/ai-activity-actions.js +7 -1
  4. package/src/lib/activity/ai-activity-actions.js.map +1 -1
  5. package/src/lib/components/ai-assist-provider-on-host.component.d.ts +66 -0
  6. package/src/lib/components/ai-assist-provider-on-host.component.js +78 -0
  7. package/src/lib/components/ai-assist-provider-on-host.component.js.map +1 -0
  8. package/src/lib/components/ai-assist-provider.component.js +9 -10
  9. package/src/lib/components/ai-assist-provider.component.js.map +1 -1
  10. package/src/lib/components/ai-automation-zones.d.ts +38 -0
  11. package/src/lib/components/ai-automation-zones.js +5 -1
  12. package/src/lib/components/ai-automation-zones.js.map +1 -1
  13. package/src/lib/components/ai-brief-dialog.component.d.ts +20 -2
  14. package/src/lib/components/ai-brief-dialog.component.js +87 -8
  15. package/src/lib/components/ai-brief-dialog.component.js.map +1 -1
  16. package/src/lib/components/ai-campaign-create.component.d.ts +54 -0
  17. package/src/lib/components/ai-campaign-create.component.js +270 -0
  18. package/src/lib/components/ai-campaign-create.component.js.map +1 -0
  19. package/src/lib/components/ai-describe-automation.component.d.ts +8 -3
  20. package/src/lib/components/ai-describe-automation.component.js +15 -6
  21. package/src/lib/components/ai-describe-automation.component.js.map +1 -1
  22. package/src/lib/components/ai-describe-button.component.d.ts +20 -8
  23. package/src/lib/components/ai-describe-button.component.js +19 -36
  24. package/src/lib/components/ai-describe-button.component.js.map +1 -1
  25. package/src/lib/components/ai-describe-email.component.d.ts +31 -0
  26. package/src/lib/components/ai-describe-email.component.js +22 -0
  27. package/src/lib/components/ai-describe-email.component.js.map +1 -0
  28. package/src/lib/components/ai-describe-org-automation.component.d.ts +36 -0
  29. package/src/lib/components/ai-describe-org-automation.component.js +238 -0
  30. package/src/lib/components/ai-describe-org-automation.component.js.map +1 -0
  31. package/src/lib/components/ai-experiment-cards.component.d.ts +9 -1
  32. package/src/lib/components/ai-experiment-cards.component.js +104 -18
  33. package/src/lib/components/ai-experiment-cards.component.js.map +1 -1
  34. package/src/lib/components/ai-explain-automation.component.js +1 -5
  35. package/src/lib/components/ai-explain-automation.component.js.map +1 -1
  36. package/src/lib/components/ai-funnel-zones.component.d.ts +61 -0
  37. package/src/lib/components/ai-funnel-zones.component.js +178 -0
  38. package/src/lib/components/ai-funnel-zones.component.js.map +1 -0
  39. package/src/lib/components/ai-insight-card.component.d.ts +42 -0
  40. package/src/lib/components/ai-insight-card.component.js +137 -0
  41. package/src/lib/components/ai-insight-card.component.js.map +1 -0
  42. package/src/lib/components/ai-insight-dialog.component.d.ts +6 -0
  43. package/src/lib/components/ai-insight-dialog.component.js +9 -3
  44. package/src/lib/components/ai-insight-dialog.component.js.map +1 -1
  45. package/src/lib/components/ai-job-plan.component.d.ts +7 -2
  46. package/src/lib/components/ai-job-plan.component.js +38 -6
  47. package/src/lib/components/ai-job-plan.component.js.map +1 -1
  48. package/src/lib/components/ai-job-requests.d.ts +17 -1
  49. package/src/lib/components/ai-job-requests.js +39 -3
  50. package/src/lib/components/ai-job-requests.js.map +1 -1
  51. package/src/lib/components/ai-logic-zones.d.ts +64 -0
  52. package/src/lib/components/ai-logic-zones.js +18 -0
  53. package/src/lib/components/ai-logic-zones.js.map +1 -0
  54. package/src/lib/components/ai-logic.component.d.ts +77 -0
  55. package/src/lib/components/ai-logic.component.js +553 -0
  56. package/src/lib/components/ai-logic.component.js.map +1 -0
  57. package/src/lib/components/ai-marketing-insight.component.d.ts +30 -0
  58. package/src/lib/components/ai-marketing-insight.component.js +80 -0
  59. package/src/lib/components/ai-marketing-insight.component.js.map +1 -0
  60. package/src/lib/components/ai-media-create.component.d.ts +55 -0
  61. package/src/lib/components/ai-media-create.component.js +433 -0
  62. package/src/lib/components/ai-media-create.component.js.map +1 -0
  63. package/src/lib/components/ai-overlay-cards.component.d.ts +83 -0
  64. package/src/lib/components/ai-overlay-cards.component.js +505 -0
  65. package/src/lib/components/ai-overlay-cards.component.js.map +1 -0
  66. package/src/lib/components/ai-permissions-on-host.component.d.ts +3 -46
  67. package/src/lib/components/ai-permissions-on-host.component.js +5 -53
  68. package/src/lib/components/ai-permissions-on-host.component.js.map +1 -1
  69. package/src/lib/components/ai-product-zones.d.ts +5 -0
  70. package/src/lib/components/ai-product-zones.js +1 -1
  71. package/src/lib/components/ai-product-zones.js.map +1 -1
  72. package/src/lib/components/ai-products-create-button.component.d.ts +42 -0
  73. package/src/lib/components/ai-products-create-button.component.js +67 -0
  74. package/src/lib/components/ai-products-create-button.component.js.map +1 -0
  75. package/src/lib/components/ai-products-hub-card.component.js +100 -81
  76. package/src/lib/components/ai-products-hub-card.component.js.map +1 -1
  77. package/src/lib/components/ai-revise-automation.component.d.ts +16 -0
  78. package/src/lib/components/ai-revise-automation.component.js +207 -0
  79. package/src/lib/components/ai-revise-automation.component.js.map +1 -0
  80. package/src/lib/components/ai-site-build-page.component.js +160 -24
  81. package/src/lib/components/ai-site-build-page.component.js.map +1 -1
  82. package/src/lib/components/ai-upsell-dialog.component.d.ts +53 -0
  83. package/src/lib/components/ai-upsell-dialog.component.js +177 -0
  84. package/src/lib/components/ai-upsell-dialog.component.js.map +1 -0
  85. package/src/lib/components/assist-build-card.component.d.ts +42 -0
  86. package/src/lib/components/assist-build-card.component.js +183 -0
  87. package/src/lib/components/assist-build-card.component.js.map +1 -0
  88. package/src/lib/components/assist-edit-canvas.d.ts +2 -0
  89. package/src/lib/components/assist-edit-canvas.js +56 -1
  90. package/src/lib/components/assist-edit-canvas.js.map +1 -1
  91. package/src/lib/components/assist-jobs-drawer.component.js +48 -3
  92. package/src/lib/components/assist-jobs-drawer.component.js.map +1 -1
  93. package/src/lib/components/assist-panel.component.js +51 -2
  94. package/src/lib/components/assist-panel.component.js.map +1 -1
  95. package/src/lib/components/use-ai-job-run.d.ts +3 -14
  96. package/src/lib/components/use-ai-job-run.js +0 -50
  97. package/src/lib/components/use-ai-job-run.js.map +1 -1
  98. package/src/lib/jobs/ai-build-capabilities.d.ts +58 -0
  99. package/src/lib/jobs/ai-build-capabilities.js +256 -0
  100. package/src/lib/jobs/ai-build-capabilities.js.map +1 -0
  101. package/src/lib/jobs/ai-build-unit-outcome.d.ts +52 -0
  102. package/src/lib/jobs/ai-build-unit-outcome.js +140 -0
  103. package/src/lib/jobs/ai-build-unit-outcome.js.map +1 -0
  104. package/src/lib/jobs/ai-job-auto-confirm.d.ts +8 -0
  105. package/src/lib/jobs/ai-job-auto-confirm.js +30 -6
  106. package/src/lib/jobs/ai-job-auto-confirm.js.map +1 -1
  107. package/src/lib/jobs/ai-job-build-step.d.ts +144 -0
  108. package/src/lib/jobs/ai-job-build-step.js +668 -0
  109. package/src/lib/jobs/ai-job-build-step.js.map +1 -0
  110. package/src/lib/jobs/ai-job-draft-ids.js +9 -1
  111. package/src/lib/jobs/ai-job-draft-ids.js.map +1 -1
  112. package/src/lib/jobs/ai-job-drafts.d.ts +14 -4
  113. package/src/lib/jobs/ai-job-drafts.js +25 -4
  114. package/src/lib/jobs/ai-job-drafts.js.map +1 -1
  115. package/src/lib/jobs/ai-job-generation.d.ts +8 -0
  116. package/src/lib/jobs/ai-job-generation.js +13 -2
  117. package/src/lib/jobs/ai-job-generation.js.map +1 -1
  118. package/src/lib/jobs/ai-job-insight-step.js +8 -1
  119. package/src/lib/jobs/ai-job-insight-step.js.map +1 -1
  120. package/src/lib/jobs/ai-job-layout-language.d.ts +73 -0
  121. package/src/lib/jobs/ai-job-layout-language.js +194 -0
  122. package/src/lib/jobs/ai-job-layout-language.js.map +1 -0
  123. package/src/lib/jobs/ai-job-layout-site-pages.d.ts +13 -2
  124. package/src/lib/jobs/ai-job-layout-site-pages.js +18 -2
  125. package/src/lib/jobs/ai-job-layout-site-pages.js.map +1 -1
  126. package/src/lib/jobs/ai-job-layout-step.d.ts +5 -0
  127. package/src/lib/jobs/ai-job-layout-step.js +105 -5
  128. package/src/lib/jobs/ai-job-layout-step.js.map +1 -1
  129. package/src/lib/jobs/ai-job-logic-step.d.ts +107 -0
  130. package/src/lib/jobs/ai-job-logic-step.js +395 -0
  131. package/src/lib/jobs/ai-job-logic-step.js.map +1 -0
  132. package/src/lib/jobs/ai-job-overlay-copy.d.ts +70 -0
  133. package/src/lib/jobs/ai-job-overlay-copy.js +178 -0
  134. package/src/lib/jobs/ai-job-overlay-copy.js.map +1 -0
  135. package/src/lib/jobs/ai-job-page-language.d.ts +149 -0
  136. package/src/lib/jobs/ai-job-page-language.js +355 -0
  137. package/src/lib/jobs/ai-job-page-language.js.map +1 -0
  138. package/src/lib/jobs/ai-job-page-sections.d.ts +37 -1
  139. package/src/lib/jobs/ai-job-page-sections.js +93 -11
  140. package/src/lib/jobs/ai-job-page-sections.js.map +1 -1
  141. package/src/lib/jobs/ai-job-page-step.d.ts +4 -4
  142. package/src/lib/jobs/ai-job-page-step.js +111 -20
  143. package/src/lib/jobs/ai-job-page-step.js.map +1 -1
  144. package/src/lib/jobs/ai-job-plan-step.d.ts +27 -2
  145. package/src/lib/jobs/ai-job-plan-step.js +87 -13
  146. package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
  147. package/src/lib/jobs/ai-job-site-step.d.ts +19 -1
  148. package/src/lib/jobs/ai-job-site-step.js +220 -61
  149. package/src/lib/jobs/ai-job-site-step.js.map +1 -1
  150. package/src/lib/jobs/ai-job-text-step.d.ts +22 -1
  151. package/src/lib/jobs/ai-job-text-step.js +12 -0
  152. package/src/lib/jobs/ai-job-text-step.js.map +1 -1
  153. package/src/lib/jobs/ai-job-workflow-step.d.ts +54 -4
  154. package/src/lib/jobs/ai-job-workflow-step.js +320 -15
  155. package/src/lib/jobs/ai-job-workflow-step.js.map +1 -1
  156. package/src/lib/jobs/ai-jobs.d.ts +80 -2
  157. package/src/lib/jobs/ai-jobs.js +391 -18
  158. package/src/lib/jobs/ai-jobs.js.map +1 -1
  159. package/src/lib/jobs/ai-layout-full-height.d.ts +40 -0
  160. package/src/lib/jobs/ai-layout-full-height.js +82 -0
  161. package/src/lib/jobs/ai-layout-full-height.js.map +1 -0
  162. package/src/lib/jobs/ai-layout-site-facts.d.ts +54 -0
  163. package/src/lib/jobs/ai-layout-site-facts.js +153 -0
  164. package/src/lib/jobs/ai-layout-site-facts.js.map +1 -0
  165. package/src/lib/jobs/ai-logic-records.d.ts +40 -0
  166. package/src/lib/jobs/ai-logic-records.js +55 -0
  167. package/src/lib/jobs/ai-logic-records.js.map +1 -0
  168. package/src/lib/jobs/ai-site-publish.d.ts +7 -0
  169. package/src/lib/jobs/ai-site-publish.js +9 -0
  170. package/src/lib/jobs/ai-site-publish.js.map +1 -1
  171. package/src/lib/jobs/ai-workflow-records.d.ts +4 -0
  172. package/src/lib/jobs/ai-workflow-records.js +40 -1
  173. package/src/lib/jobs/ai-workflow-records.js.map +1 -1
  174. package/src/lib/layout-language/ai-layout-compiler.d.ts +145 -0
  175. package/src/lib/layout-language/ai-layout-compiler.js +1148 -0
  176. package/src/lib/layout-language/ai-layout-compiler.js.map +1 -0
  177. package/src/lib/layout-language/ai-layout-copy.d.ts +73 -0
  178. package/src/lib/layout-language/ai-layout-copy.js +137 -0
  179. package/src/lib/layout-language/ai-layout-copy.js.map +1 -0
  180. package/src/lib/layout-language/ai-layout-frame.d.ts +52 -0
  181. package/src/lib/layout-language/ai-layout-frame.js +457 -0
  182. package/src/lib/layout-language/ai-layout-frame.js.map +1 -0
  183. package/src/lib/layout-language/ai-layout-gaps.d.ts +63 -0
  184. package/src/lib/layout-language/ai-layout-gaps.js +345 -0
  185. package/src/lib/layout-language/ai-layout-gaps.js.map +1 -0
  186. package/src/lib/layout-language/ai-layout-language.d.ts +161 -0
  187. package/src/lib/layout-language/ai-layout-language.js +446 -0
  188. package/src/lib/layout-language/ai-layout-language.js.map +1 -0
  189. package/src/lib/layout-language/ai-layout-links.d.ts +80 -0
  190. package/src/lib/layout-language/ai-layout-links.js +109 -0
  191. package/src/lib/layout-language/ai-layout-links.js.map +1 -0
  192. package/src/lib/layout-language/ai-layout-store.d.ts +39 -0
  193. package/src/lib/layout-language/ai-layout-store.js +69 -0
  194. package/src/lib/layout-language/ai-layout-store.js.map +1 -0
  195. package/src/lib/layout-language/ai-layout-tree.d.ts +59 -0
  196. package/src/lib/layout-language/ai-layout-tree.js +84 -0
  197. package/src/lib/layout-language/ai-layout-tree.js.map +1 -0
  198. package/src/lib/lazy-widget.d.ts +45 -0
  199. package/src/lib/lazy-widget.js +53 -0
  200. package/src/lib/lazy-widget.js.map +1 -0
  201. package/src/lib/model/ai-automation-draft.d.ts +18 -0
  202. package/src/lib/model/ai-automation-draft.js +86 -0
  203. package/src/lib/model/ai-automation-draft.js.map +1 -1
  204. package/src/lib/model/ai-build-job.d.ts +201 -0
  205. package/src/lib/model/ai-build-job.js +472 -0
  206. package/src/lib/model/ai-build-job.js.map +1 -0
  207. package/src/lib/model/ai-build-plan.d.ts +61 -0
  208. package/src/lib/model/ai-build-plan.js +154 -9
  209. package/src/lib/model/ai-build-plan.js.map +1 -1
  210. package/src/lib/model/ai-build-progress.d.ts +73 -0
  211. package/src/lib/model/ai-build-progress.js +170 -0
  212. package/src/lib/model/ai-build-progress.js.map +1 -0
  213. package/src/lib/model/ai-host-publish-context.d.ts +51 -0
  214. package/src/lib/model/ai-host-publish-context.js +104 -0
  215. package/src/lib/model/ai-host-publish-context.js.map +1 -0
  216. package/src/lib/model/ai-insight.d.ts +20 -10
  217. package/src/lib/model/ai-insight.js +72 -9
  218. package/src/lib/model/ai-insight.js.map +1 -1
  219. package/src/lib/model/ai-job-activity.d.ts +22 -0
  220. package/src/lib/model/ai-job-activity.js +25 -2
  221. package/src/lib/model/ai-job-activity.js.map +1 -1
  222. package/src/lib/model/ai-job-failure-copy.d.ts +38 -1
  223. package/src/lib/model/ai-job-failure-copy.js +56 -1
  224. package/src/lib/model/ai-job-failure-copy.js.map +1 -1
  225. package/src/lib/model/ai-job-notice.d.ts +3 -1
  226. package/src/lib/model/ai-job-notice.js +31 -9
  227. package/src/lib/model/ai-job-notice.js.map +1 -1
  228. package/src/lib/model/ai-jobs.types.d.ts +99 -2
  229. package/src/lib/model/ai-jobs.types.js +3 -1
  230. package/src/lib/model/ai-jobs.types.js.map +1 -1
  231. package/src/lib/model/ai-logic-job.d.ts +108 -0
  232. package/src/lib/model/ai-logic-job.js +327 -0
  233. package/src/lib/model/ai-logic-job.js.map +1 -0
  234. package/src/lib/model/ai-media-credits.d.ts +52 -0
  235. package/src/lib/model/ai-media-credits.js +61 -0
  236. package/src/lib/model/ai-media-credits.js.map +1 -0
  237. package/src/lib/model/ai-overlay-copy.d.ts +114 -0
  238. package/src/lib/model/ai-overlay-copy.js +175 -0
  239. package/src/lib/model/ai-overlay-copy.js.map +1 -0
  240. package/src/lib/model/ai-site-build-progress.d.ts +25 -4
  241. package/src/lib/model/ai-site-build-progress.js +194 -11
  242. package/src/lib/model/ai-site-build-progress.js.map +1 -1
  243. package/src/lib/model/ai-site-job.d.ts +8 -0
  244. package/src/lib/model/ai-site-job.js +9 -0
  245. package/src/lib/model/ai-site-job.js.map +1 -1
  246. package/src/lib/model/ai-site-start-seo.d.ts +1 -1
  247. package/src/lib/model/ai-site-start.d.ts +5 -2
  248. package/src/lib/model/ai-site-start.js +5 -2
  249. package/src/lib/model/ai-site-start.js.map +1 -1
  250. package/src/lib/model/ai-svg.d.ts +69 -0
  251. package/src/lib/model/ai-svg.js +265 -0
  252. package/src/lib/model/ai-svg.js.map +1 -0
  253. package/src/lib/model/ai-usage-by-user.d.ts +3 -2
  254. package/src/lib/model/ai-usage-by-user.js.map +1 -1
  255. package/src/lib/model/ai-workflow-job.d.ts +92 -4
  256. package/src/lib/model/ai-workflow-job.js +124 -7
  257. package/src/lib/model/ai-workflow-job.js.map +1 -1
  258. package/src/lib/model/assist-build.d.ts +58 -0
  259. package/src/lib/model/assist-build.js +52 -0
  260. package/src/lib/model/assist-build.js.map +1 -0
  261. package/src/lib/model/assist-edit.d.ts +48 -3
  262. package/src/lib/model/assist-edit.js +48 -4
  263. package/src/lib/model/assist-edit.js.map +1 -1
  264. package/src/lib/plugin-config.js +2 -0
  265. package/src/lib/plugin-config.js.map +1 -1
  266. package/src/lib/plugin.js +308 -47
  267. package/src/lib/plugin.js.map +1 -1
  268. package/src/lib/providers/catalog.d.ts +82 -5
  269. package/src/lib/providers/catalog.js +83 -12
  270. package/src/lib/providers/catalog.js.map +1 -1
  271. package/src/lib/providers/image-contract.d.ts +116 -0
  272. package/src/lib/providers/image-contract.js +74 -0
  273. package/src/lib/providers/image-contract.js.map +1 -0
  274. package/src/lib/providers/model-choice.js +11 -0
  275. package/src/lib/providers/model-choice.js.map +1 -1
  276. package/src/lib/providers/routing.js +18 -0
  277. package/src/lib/providers/routing.js.map +1 -1
  278. package/src/lib/providers/vertex-image.d.ts +121 -0
  279. package/src/lib/providers/vertex-image.js +312 -0
  280. package/src/lib/providers/vertex-image.js.map +1 -0
  281. package/src/lib/runtime/ai-doctrine-validators.d.ts +101 -0
  282. package/src/lib/runtime/ai-doctrine-validators.js +525 -4
  283. package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
  284. package/src/lib/runtime/ai-doctrine.js +21 -6
  285. package/src/lib/runtime/ai-doctrine.js.map +1 -1
  286. package/src/lib/runtime/ai-eval-live.js +4 -0
  287. package/src/lib/runtime/ai-eval-live.js.map +1 -1
  288. package/src/lib/runtime/ai-eval.d.ts +15 -1
  289. package/src/lib/runtime/ai-eval.js +52 -1
  290. package/src/lib/runtime/ai-eval.js.map +1 -1
  291. package/src/lib/runtime/ai-icon-library.d.ts +257 -0
  292. package/src/lib/runtime/ai-icon-library.js +254 -0
  293. package/src/lib/runtime/ai-icon-library.js.map +1 -0
  294. package/src/lib/runtime/ai-node-tree.d.ts +9 -0
  295. package/src/lib/runtime/ai-node-tree.js +30 -4
  296. package/src/lib/runtime/ai-node-tree.js.map +1 -1
  297. package/src/lib/runtime/ai-palette.d.ts +6 -0
  298. package/src/lib/runtime/ai-palette.generated.js +70 -0
  299. package/src/lib/runtime/ai-palette.generated.js.map +1 -1
  300. package/src/lib/runtime/ai-palette.js.map +1 -1
  301. package/src/lib/runtime/experiment-variant-copy.d.ts +34 -0
  302. package/src/lib/runtime/experiment-variant-copy.js +102 -0
  303. package/src/lib/runtime/experiment-variant-copy.js.map +1 -0
  304. package/src/lib/server/ai-experiment-versions.d.ts +51 -0
  305. package/src/lib/server/ai-experiment-versions.js +270 -0
  306. package/src/lib/server/ai-experiment-versions.js.map +1 -0
  307. package/src/lib/server/ai-jobs-resume.js +74 -4
  308. package/src/lib/server/ai-jobs-resume.js.map +1 -1
  309. package/src/lib/server/ai-media-image.d.ts +66 -0
  310. package/src/lib/server/ai-media-image.js +521 -0
  311. package/src/lib/server/ai-media-image.js.map +1 -0
  312. package/src/lib/server/ai-media-svg.d.ts +91 -0
  313. package/src/lib/server/ai-media-svg.js +186 -0
  314. package/src/lib/server/ai-media-svg.js.map +1 -0
  315. package/src/lib/server/assist-build.d.ts +54 -0
  316. package/src/lib/server/assist-build.js +121 -0
  317. package/src/lib/server/assist-build.js.map +1 -0
  318. package/src/lib/server/assist-chat.js +108 -12
  319. package/src/lib/server/assist-chat.js.map +1 -1
  320. package/src/lib/server/assist-edit.js +213 -3
  321. package/src/lib/server/assist-edit.js.map +1 -1
  322. package/src/lib/server/assist-view-context.js +242 -4
  323. package/src/lib/server/assist-view-context.js.map +1 -1
  324. package/src/lib/server.js +26 -0
  325. package/src/lib/server.js.map +1 -1
  326. package/src/lib/tools/ai-logic-tool.d.ts +27 -0
  327. package/src/lib/tools/ai-logic-tool.js +207 -0
  328. package/src/lib/tools/ai-logic-tool.js.map +1 -0
  329. package/src/lib/tools/ai-overlay-tool.d.ts +35 -0
  330. package/src/lib/tools/ai-overlay-tool.js +107 -0
  331. package/src/lib/tools/ai-overlay-tool.js.map +1 -0
  332. package/src/lib/tools/ai-workflow-tool.d.ts +17 -2
  333. package/src/lib/tools/ai-workflow-tool.js +47 -14
  334. package/src/lib/tools/ai-workflow-tool.js.map +1 -1
  335. package/src/lib/usage/assist-job-refund.d.ts +28 -1
  336. package/src/lib/usage/assist-job-refund.js +44 -9
  337. package/src/lib/usage/assist-job-refund.js.map +1 -1
  338. package/src/lib/usage/assist-usage.d.ts +5 -0
  339. package/src/lib/usage/assist-usage.js +2 -0
  340. package/src/lib/usage/assist-usage.js.map +1 -1
@@ -0,0 +1,1148 @@
1
+ import { _ as _extends } from "@swc/helpers/_/_extends";
2
+ /**
3
+ * @license
4
+ * Copyright 2026 Aglyn LLC
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */ import { REUSABLE_INSTANCE_COMPONENT_ID } from "@aglyn/aglyn/app-utils/reusable-component-keys";
18
+ import { CANVAS_ROOT_ELEMENT_ID } from "@aglyn/aglyn/foundation/constants/canvas";
19
+ import { AI_ICON_COMPONENT_ID, aiIconOfWord, AI_ICON_LIBRARY } from "../runtime/ai-icon-library.js";
20
+ import { AI_INSTANCE_REF_PROP } from "../runtime/ai-node-tree.js";
21
+ import { aiPageScrollInteraction } from "../runtime/ai-page-links.js";
22
+ import { aiLayoutFitText, aiLayoutQuoteGap, aiLayoutWords } from "./ai-layout-copy.js";
23
+ import { AI_LAYOUT_GROUP_KINDS, AI_LAYOUT_MAX_ITEMS } from "./ai-layout-language.js";
24
+ import { aiLayoutResolveLink } from "./ai-layout-links.js";
25
+ import { AI_LAYOUT_FRAMES, AiLayoutTreeBuilder } from "./ai-layout-tree.js";
26
+ /** A section root's id where the caller gives none. */ function sectionIdOf(index) {
27
+ return `section-${index + 1}`;
28
+ }
29
+ /** The most pictures a page carries; each beyond it is one more empty slot to fill. */ export const AI_LAYOUT_MAX_IMAGES = 3;
30
+ /** The most `brand` or `dark` bands a page shows; more and none stands out. */ export const AI_LAYOUT_MAX_STRONG_BANDS = 2;
31
+ const SECTION_PADDING = {
32
+ xs: 8,
33
+ md: 12
34
+ };
35
+ const HERO_PADDING = {
36
+ xs: 10,
37
+ md: 14
38
+ };
39
+ const formIdsOf = (targets)=>new Set(targets.forms.map((form)=>form.id));
40
+ const componentOf = (targets, id)=>{
41
+ var _targets_components_find;
42
+ return id ? (_targets_components_find = targets.components.find((component)=>component.id === id)) != null ? _targets_components_find : null : null;
43
+ };
44
+ /**
45
+ * The section of this page that places a form: one whose plan places one, or
46
+ * whose design places one by its id.
47
+ */ function formSectionOf(sections, plan, targets) {
48
+ const forms = formIdsOf(targets);
49
+ const planned = plan.sections.findIndex((section)=>section.uses.some((ref)=>forms.has(ref)));
50
+ if (planned !== -1) return planned;
51
+ const designed = sections.findIndex((section)=>section.blocks.some((block)=>block.kind === 'form' && (!block.to || forms.has(block.to))));
52
+ return designed === -1 ? null : designed;
53
+ }
54
+ /** Compiles a page designed in the layout language into the tree it stores. */ export function aiCompileLayoutPage(sections, plan, targets, options) {
55
+ const tree = new AiLayoutTreeBuilder();
56
+ const page = {
57
+ tree,
58
+ plan,
59
+ targets,
60
+ options,
61
+ settled: [],
62
+ scrollTo: {},
63
+ images: 0,
64
+ strong: {
65
+ brand: 0,
66
+ dark: 0
67
+ },
68
+ formSection: formSectionOf(sections, plan, targets),
69
+ pageIcon: pageIconOf(sections),
70
+ formsPlaced: new Set()
71
+ };
72
+ const roots = plan.sections.map((_, index)=>{
73
+ var _sections_index;
74
+ const section = (_sections_index = sections[index]) != null ? _sections_index : {
75
+ blocks: []
76
+ };
77
+ return compileSection(page, section, index);
78
+ });
79
+ const rootId = tree.add('div', null, null, roots, 'page', CANVAS_ROOT_ELEMENT_ID);
80
+ return {
81
+ tree: {
82
+ rootId,
83
+ nodes: tree.nodes
84
+ },
85
+ sectionRoots: roots,
86
+ scrollTo: page.scrollTo,
87
+ settled: page.settled
88
+ };
89
+ }
90
+ /** The first icon the design names anywhere, else a sparkle: what an empty picture shows. */ function pageIconOf(sections) {
91
+ for (const section of sections){
92
+ for (const block of section.blocks){
93
+ var _block_items;
94
+ const own = aiIconOfWord(block.icon);
95
+ if (own) return own;
96
+ for (const item of (_block_items = block.items) != null ? _block_items : []){
97
+ const icon = aiIconOfWord(item.icon);
98
+ if (icon) return icon;
99
+ }
100
+ }
101
+ }
102
+ return AI_ICON_LIBRARY.sparkle;
103
+ }
104
+ // ── A section ─────────────────────────────────────────────────────────────
105
+ function compileSection(page, raw, index) {
106
+ var _raw_band, _ref;
107
+ var _page_plan_sections_index_name, _page_plan_sections_index, _page_options_sectionIds;
108
+ const at = `sections[${index}]`;
109
+ const band = settleBand(page, (_raw_band = raw.band) != null ? _raw_band : 'plain', at);
110
+ const scope = {
111
+ page,
112
+ index,
113
+ at,
114
+ band,
115
+ centered: raw.align === 'center',
116
+ level: index === 0 ? 1 : 2,
117
+ headed: false,
118
+ itemsLeft: AI_LAYOUT_MAX_ITEMS,
119
+ link: {
120
+ sections: page.plan.sections.map((section)=>section.name),
121
+ from: index,
122
+ formSection: page.formSection
123
+ }
124
+ };
125
+ // A quote is a gap the owner fills, and a published page shows no gap (AGL-3660).
126
+ const blocks = placePlanned(scope, raw).filter((block)=>{
127
+ if (block.kind !== 'quotes') return true;
128
+ page.settled.push({
129
+ at,
130
+ what: 'a quotes group left out: a published page shows no customer words the brief did not give'
131
+ });
132
+ return false;
133
+ });
134
+ const cols = raw.cols && raw.cols.length >= 2 ? raw.cols : null;
135
+ // Above the row, the row's columns, and below it.
136
+ const head = [];
137
+ const tail = [];
138
+ const columns = cols ? cols.map(()=>[]) : [];
139
+ let placed = false;
140
+ for (const block of blocks){
141
+ if (cols && block.col !== undefined) {
142
+ columns[Math.min(block.col, cols.length - 1)].push(block);
143
+ placed = true;
144
+ } else if (placed) {
145
+ tail.push(block);
146
+ } else {
147
+ head.push(block);
148
+ }
149
+ }
150
+ let filled = columns.map((column, position)=>{
151
+ var _ref;
152
+ return {
153
+ column,
154
+ weight: (_ref = cols == null ? void 0 : cols[position]) != null ? _ref : 1
155
+ };
156
+ }).filter((entry)=>entry.column.length);
157
+ // A row whose columns each hold only one kind of group — a card a column —
158
+ // is that group, laid out by the compiler rather than column by column.
159
+ const groups = filled.flatMap((entry)=>entry.column);
160
+ if (filled.length >= 2 && groups.every((block)=>isItemGroup(block) && block.kind === groups[0].kind && block.to === groups[0].to)) {
161
+ head.push(_extends({}, groups[0], {
162
+ col: undefined,
163
+ items: groups.flatMap((block)=>{
164
+ var _block_items;
165
+ return (_block_items = block.items) != null ? _block_items : [];
166
+ })
167
+ }));
168
+ page.settled.push({
169
+ at,
170
+ what: `a ${groups[0].kind} group split over ${filled.length} columns drawn as one`
171
+ });
172
+ filled = [];
173
+ }
174
+ // A row whose columns all say the same kind of thing, three or more across,
175
+ // is a group of cards: one design, the words the columns gave.
176
+ if (filled.length >= 3 && sameShape(filled.map((entry)=>entry.column))) {
177
+ head.push(columnsAsCards(filled.map((entry)=>entry.column)));
178
+ page.settled.push({
179
+ at,
180
+ what: `${filled.length} like columns drawn as cards`
181
+ });
182
+ filled = [];
183
+ }
184
+ if (filled.length === 1) {
185
+ // One column with anything in it is no row.
186
+ head.push(...filled[0].column);
187
+ filled = [];
188
+ }
189
+ // The section's heading leads its outline: a heading with no words is no
190
+ // heading, the first section always carries the page's one h1, and a
191
+ // heading written after a group whose titles sit under it moves above it.
192
+ const inOrder = ()=>head.concat(filled.flatMap((entry)=>entry.column), tail);
193
+ const speaks = (block)=>block.kind === 'heading' && !!aiLayoutWords(block.text, 'heading', page.targets.facts);
194
+ for (const list of [
195
+ head,
196
+ tail,
197
+ ...filled.map((entry)=>entry.column)
198
+ ]){
199
+ for(let at = list.length - 1; at >= 0; at -= 1)if (list[at].kind === 'heading' && !speaks(list[at])) list.splice(at, 1);
200
+ }
201
+ if (index === 0 && !inOrder().some(speaks)) {
202
+ head.unshift({
203
+ kind: 'heading',
204
+ text: page.plan.title
205
+ });
206
+ page.settled.push({
207
+ at,
208
+ what: "no heading; the page's title written as its h1"
209
+ });
210
+ }
211
+ const order = inOrder();
212
+ const first = order.findIndex(speaks);
213
+ if (first > 0 && order.slice(0, first).some((block)=>block.kind === 'cards' || block.kind === 'steps' || block.kind === 'component')) {
214
+ const lead = order[first];
215
+ for (const list of [
216
+ head,
217
+ tail,
218
+ ...filled.map((entry)=>entry.column)
219
+ ]){
220
+ const at = list.indexOf(lead);
221
+ if (at !== -1) list.splice(at, 1);
222
+ }
223
+ head.unshift(_extends({}, lead, {
224
+ col: undefined
225
+ }));
226
+ page.settled.push({
227
+ at,
228
+ what: 'the heading moved above the group it heads'
229
+ });
230
+ }
231
+ filled = filled.filter((entry)=>entry.column.length);
232
+ if (filled.length === 1) {
233
+ head.push(...filled[0].column);
234
+ filled = [];
235
+ }
236
+ const wide = filled.length > 0 || [
237
+ ...head,
238
+ ...tail
239
+ ].some((block)=>isWideGroup(block));
240
+ const parts = [];
241
+ const headId = compileFlow(scope, head, 'full');
242
+ if (headId) parts.push(centered(scope, headId, wide));
243
+ if (filled.length) parts.push(compileRow(scope, filled));
244
+ const tailId = compileFlow(scope, tail, 'full');
245
+ if (tailId) parts.push(centered(scope, tailId, wide));
246
+ // A frame whose content came to nothing is taken out, leaves first.
247
+ for(let at = parts.length - 1; at >= 0; at -= 1){
248
+ var _part_nodes;
249
+ page.tree.prune(parts[at]);
250
+ const part = page.tree.nodes[parts[at]];
251
+ if (AI_LAYOUT_FRAMES.has(part.componentId) && !((_part_nodes = part.nodes) == null ? void 0 : _part_nodes.length)) {
252
+ delete page.tree.nodes[parts[at]];
253
+ parts.splice(at, 1);
254
+ }
255
+ }
256
+ if (!parts.length) {
257
+ var _page_plan_sections_index1;
258
+ // Nothing the design gave this section could be shown: it keeps its
259
+ // place on the page under the name its plan gives it.
260
+ const fallback = compileFlow(scope, [
261
+ {
262
+ kind: 'heading',
263
+ text: ((_page_plan_sections_index1 = page.plan.sections[index]) == null ? void 0 : _page_plan_sections_index1.name) || page.plan.title
264
+ }
265
+ ], 'full');
266
+ if (fallback) parts.push(fallback);
267
+ page.settled.push({
268
+ at,
269
+ what: 'nothing to show; the section named by its plan'
270
+ });
271
+ }
272
+ const tree = page.tree;
273
+ const content = parts.length === 1 ? parts[0] : // margins, which un-centers a reading-width head (AGL-3660).
274
+ tree.add('muiStack', {
275
+ spacing: '6',
276
+ useFlexGap: true
277
+ }, null, parts, 'content');
278
+ const container = tree.add('muiContainer', {
279
+ maxWidth: wide ? 'lg' : 'md'
280
+ }, {
281
+ py: index === 0 ? _extends({}, HERO_PADDING) : _extends({}, SECTION_PADDING)
282
+ }, [
283
+ content
284
+ ], 'container');
285
+ const name = ((_page_plan_sections_index = page.plan.sections[index]) == null ? void 0 : (_page_plan_sections_index_name = _page_plan_sections_index.name) == null ? void 0 : _page_plan_sections_index_name.trim()) || `Section ${index + 1}`;
286
+ return tree.add('section', _extends({
287
+ element: 'section',
288
+ ariaLabel: aiLayoutFitText(name, 'note') || `Section ${index + 1}`
289
+ }, band === 'dark' ? {
290
+ colorScheme: 'dark'
291
+ } : {}), bandSx(band), [
292
+ container
293
+ ], 'section', (_ref = (_page_options_sectionIds = page.options.sectionIds) == null ? void 0 : _page_options_sectionIds[index]) != null ? _ref : sectionIdOf(index));
294
+ }
295
+ /** A band the page has room for: past two brand or two dark bands, a soft one instead. */ function settleBand(page, band, at) {
296
+ if (band !== 'brand' && band !== 'dark') return band;
297
+ if (page.strong[band] >= AI_LAYOUT_MAX_STRONG_BANDS) {
298
+ page.settled.push({
299
+ at: `${at}.band`,
300
+ what: `a third ${band} band drawn soft`
301
+ });
302
+ return 'soft';
303
+ }
304
+ page.strong[band] += 1;
305
+ return band;
306
+ }
307
+ /** A band's own colors, as palette roles: the dark band pins the scheme instead. */ export function bandSx(band) {
308
+ if (band === 'soft') return {
309
+ bgcolor: 'background.paper'
310
+ };
311
+ if (band === 'brand') return {
312
+ bgcolor: 'primary.main',
313
+ color: 'primary.contrastText'
314
+ };
315
+ return null;
316
+ }
317
+ /** A group whose items sit side by side. */ function isItemGroup(block) {
318
+ return block.kind === 'cards' || block.kind === 'steps' || block.kind === 'stats' || block.kind === 'quotes';
319
+ }
320
+ /** Whether a block spans more than a reading column: a row of several items. */ function isWideGroup(block) {
321
+ var _ref;
322
+ var _block_items;
323
+ return (block.kind === 'cards' || block.kind === 'steps' || block.kind === 'stats' || block.kind === 'quotes') && ((_ref = (_block_items = block.items) == null ? void 0 : _block_items.length) != null ? _ref : 0) >= 2;
324
+ }
325
+ /** A full-width flow centered on a wide section is held to a reading width. */ function centered(scope, flowId, wide) {
326
+ var _flow_nodes;
327
+ const flow = scope.page.tree.nodes[flowId];
328
+ const holdsGroup = ((_flow_nodes = flow.nodes) != null ? _flow_nodes : []).some((id)=>{
329
+ var _scope_page_tree_nodes_id;
330
+ return ((_scope_page_tree_nodes_id = scope.page.tree.nodes[id]) == null ? void 0 : _scope_page_tree_nodes_id.componentId) === 'muiGrid';
331
+ });
332
+ if (!wide || !scope.centered || holdsGroup) return flowId;
333
+ return scope.page.tree.add('muiContainer', {
334
+ maxWidth: 'md',
335
+ disableGutters: true
336
+ }, null, [
337
+ flowId
338
+ ], 'measure');
339
+ }
340
+ /**
341
+ * The section's blocks with what its plan places in it: a form or a
342
+ * component the plan line names and the design left out is added where the
343
+ * section ends, and a `form` or `component` block naming nothing takes the
344
+ * one the plan line names.
345
+ */ function placePlanned(scope, raw) {
346
+ var _ref;
347
+ var _page_plan_sections_index;
348
+ const { page, index, at } = scope;
349
+ const forms = formIdsOf(page.targets);
350
+ const uses = (_ref = (_page_plan_sections_index = page.plan.sections[index]) == null ? void 0 : _page_plan_sections_index.uses) != null ? _ref : [];
351
+ const plannedForms = uses.filter((ref)=>forms.has(ref));
352
+ const plannedComponents = uses.filter((ref)=>componentOf(page.targets, ref));
353
+ const blocks = raw.blocks.map((block)=>_extends({}, block, block.items ? {
354
+ items: [
355
+ ...block.items
356
+ ]
357
+ } : {}));
358
+ const lastCol = raw.cols && raw.cols.length >= 2 ? raw.cols.length - 1 : undefined;
359
+ for (const block of blocks){
360
+ if (block.kind === 'form' && !(block.to && forms.has(block.to))) {
361
+ var _plannedForms_;
362
+ const only = page.targets.forms.length === 1 ? page.targets.forms[0].id : undefined;
363
+ block.to = (_plannedForms_ = plannedForms[0]) != null ? _plannedForms_ : only;
364
+ }
365
+ if ((block.kind === 'component' || block.kind === 'cards') && block.to && !componentOf(page.targets, block.to)) {
366
+ if (block.kind === 'component') block.to = plannedComponents[0];
367
+ else delete block.to;
368
+ }
369
+ if (block.kind === 'component' && !block.to) block.to = plannedComponents[0];
370
+ }
371
+ for (const form of plannedForms){
372
+ if (!blocks.some((block)=>block.kind === 'form' && block.to === form)) {
373
+ blocks.push(_extends({
374
+ kind: 'form',
375
+ to: form
376
+ }, lastCol !== undefined ? {
377
+ col: lastCol
378
+ } : {}));
379
+ page.settled.push({
380
+ at,
381
+ what: `the planned form ${form} placed`
382
+ });
383
+ }
384
+ }
385
+ for (const component of plannedComponents){
386
+ if (blocks.some((block)=>(block.kind === 'component' || block.kind === 'cards') && block.to === component)) continue;
387
+ // A group the design drew where the plan places a component is that component's placements.
388
+ const group = blocks.find((block)=>AI_LAYOUT_GROUP_KINDS.has(block.kind) && block.kind !== 'faq' && block.kind !== 'list' && !block.to);
389
+ if (group) {
390
+ group.to = component;
391
+ continue;
392
+ }
393
+ blocks.push(_extends({
394
+ kind: 'component',
395
+ to: component
396
+ }, lastCol !== undefined ? {
397
+ col: lastCol
398
+ } : {}));
399
+ page.settled.push({
400
+ at,
401
+ what: `the planned component ${component} placed`
402
+ });
403
+ }
404
+ return blocks.filter((block)=>{
405
+ if ((block.kind === 'form' || block.kind === 'component') && !block.to) {
406
+ page.settled.push({
407
+ at,
408
+ what: `a ${block.kind} with nothing to place; left out`
409
+ });
410
+ return false;
411
+ }
412
+ // A form is placed once a page: a second copy of the same form asks a
413
+ // visitor the same thing twice.
414
+ if (block.kind === 'form' && block.to) {
415
+ if (page.formsPlaced.has(block.to)) {
416
+ page.settled.push({
417
+ at,
418
+ what: `the form ${block.to} again; left out`
419
+ });
420
+ return false;
421
+ }
422
+ page.formsPlaced.add(block.to);
423
+ }
424
+ return true;
425
+ });
426
+ }
427
+ /** The block kinds a column holds, as a column's shape is compared. */ function shapeOf(column) {
428
+ return column.map((block)=>block.kind).join(',');
429
+ }
430
+ function sameShape(columns) {
431
+ const first = shapeOf(columns[0]);
432
+ return columns.every((column)=>shapeOf(column) === first) && columns[0].some((block)=>block.kind === 'heading') && columns[0].every((block)=>[
433
+ 'heading',
434
+ 'text',
435
+ 'lede',
436
+ 'eyebrow',
437
+ 'image',
438
+ 'note'
439
+ ].includes(block.kind));
440
+ }
441
+ /** Like columns as one group of cards: each column's heading its title, its words its text. */ function columnsAsCards(columns) {
442
+ return {
443
+ kind: 'cards',
444
+ items: columns.map((column)=>{
445
+ var _ref;
446
+ var _column_find, _column_find1;
447
+ const title = (_ref = (_column_find = column.find((block)=>block.kind === 'heading')) == null ? void 0 : _column_find.text) != null ? _ref : '';
448
+ const words = column.filter((block)=>block.kind === 'text' || block.kind === 'lede' || block.kind === 'note').map((block)=>{
449
+ var _block_text;
450
+ return (_block_text = block.text) != null ? _block_text : '';
451
+ }).join(' ');
452
+ const icon = (_column_find1 = column.find((block)=>block.icon)) == null ? void 0 : _column_find1.icon;
453
+ return _extends({
454
+ title,
455
+ text: words
456
+ }, icon ? {
457
+ icon
458
+ } : {});
459
+ })
460
+ };
461
+ }
462
+ // ── A row of columns ──────────────────────────────────────────────────────
463
+ /** Spans out of twelve for relative widths: each at least three, summing to twelve. */ export function aiLayoutSpans(weights) {
464
+ const total = weights.reduce((sum, weight)=>sum + weight, 0);
465
+ const spans = weights.map((weight)=>Math.max(3, Math.round(weight / total * 12)));
466
+ let over = spans.reduce((sum, span)=>sum + span, 0) - 12;
467
+ while(over !== 0){
468
+ // Take from (or give to) the widest column that can spare it.
469
+ const order = spans.map((span, position)=>({
470
+ span,
471
+ position
472
+ })).sort((a, b)=>over > 0 ? b.span - a.span : a.span - b.span);
473
+ const pick = order.find((entry)=>over > 0 ? entry.span > 3 : true);
474
+ if (!pick) break;
475
+ spans[pick.position] += over > 0 ? -1 : 1;
476
+ over += over > 0 ? -1 : 1;
477
+ }
478
+ return spans;
479
+ }
480
+ export function compileRow(scope, columns) {
481
+ const tree = scope.page.tree;
482
+ const spans = aiLayoutSpans(columns.map((entry)=>entry.weight));
483
+ const items = columns.map((entry, position)=>{
484
+ const span = spans[position];
485
+ const flow = compileFlow(scope, entry.column, span >= 8 ? 'full' : span >= 5 ? 'half' : 'narrow');
486
+ const size = columns.length >= 4 ? `xs:12 sm:6 md:${span}` : `xs:12 md:${span}`;
487
+ return tree.add('muiGrid', {
488
+ size
489
+ }, null, [
490
+ flow
491
+ ], 'column');
492
+ });
493
+ return tree.add('muiGrid', {
494
+ container: true,
495
+ spacing: columns.length >= 3 ? '4' : '6'
496
+ }, {
497
+ alignItems: 'center'
498
+ }, items, 'row');
499
+ }
500
+ /** A column of blocks, top to bottom, with buttons side by side; `null` when nothing in it compiles. */ export function compileFlow(scope, blocks, room) {
501
+ const tree = scope.page.tree;
502
+ const children = [];
503
+ let buttons = [];
504
+ const flushButtons = ()=>{
505
+ if (!buttons.length) return;
506
+ children.push(buttons.length === 1 ? buttons[0] : tree.add('muiStack', _extends({
507
+ direction: 'row',
508
+ spacing: '2',
509
+ useFlexGap: true,
510
+ flexWrap: 'wrap'
511
+ }, scope.centered && room === 'full' ? {
512
+ justifyContent: 'center'
513
+ } : {}), null, buttons, 'actions'));
514
+ buttons = [];
515
+ };
516
+ for (const block of blocks){
517
+ if (block.kind === 'button') {
518
+ const id = compileButton(scope, block);
519
+ if (id) buttons.push(id);
520
+ continue;
521
+ }
522
+ flushButtons();
523
+ const id = compileBlock(scope, block, room);
524
+ if (id) children.push(id);
525
+ }
526
+ flushButtons();
527
+ if (!children.length) return null;
528
+ // One block needs no flow around it.
529
+ if (children.length === 1) return children[0];
530
+ const align = scope.centered && room === 'full';
531
+ // A flow whose words open with a label, a heading and a lede reads as one
532
+ // block at a tighter spacing than the groups under it.
533
+ return tree.add('muiStack', _extends({
534
+ spacing: hasGroup(tree, children) ? '4' : '2.5'
535
+ }, align ? {
536
+ alignItems: 'center'
537
+ } : {}), null, children, 'flow');
538
+ }
539
+ function hasGroup(tree, ids) {
540
+ return ids.some((id)=>{
541
+ var _ref;
542
+ var _tree_nodes_id;
543
+ return [
544
+ 'muiGrid',
545
+ 'muiList'
546
+ ].includes((_ref = (_tree_nodes_id = tree.nodes[id]) == null ? void 0 : _tree_nodes_id.componentId) != null ? _ref : '');
547
+ });
548
+ }
549
+ function compileBlock(scope, block, room) {
550
+ switch(block.kind){
551
+ case 'eyebrow':
552
+ return words(scope, block, 'eyebrow', 'overline', {
553
+ component: 'p'
554
+ }, accent(scope));
555
+ case 'heading':
556
+ return heading(scope, block);
557
+ case 'lede':
558
+ return words(scope, block, 'lede', 'lede', {}, muted(scope));
559
+ case 'text':
560
+ return words(scope, block, 'text', 'body1', {}, muted(scope));
561
+ case 'note':
562
+ return words(scope, block, 'note', 'body2', {}, muted(scope));
563
+ case 'image':
564
+ return image(scope, block, room);
565
+ case 'form':
566
+ return form(scope, block);
567
+ case 'component':
568
+ return component(scope, block);
569
+ case 'list':
570
+ return list(scope, block);
571
+ case 'faq':
572
+ return faq(scope, block);
573
+ case 'cards':
574
+ case 'steps':
575
+ case 'stats':
576
+ case 'quotes':
577
+ return group(scope, block, room);
578
+ default:
579
+ return null;
580
+ }
581
+ }
582
+ /** Secondary words' color: muted text, or the band's own on a brand band. */ function muted(scope) {
583
+ return scope.band === 'brand' ? null : {
584
+ color: 'text.secondary'
585
+ };
586
+ }
587
+ /** An accent's color: the brand's, or the band's own on a brand band. */ function accent(scope) {
588
+ return scope.band === 'brand' ? null : {
589
+ color: 'primary.main'
590
+ };
591
+ }
592
+ function align(scope) {
593
+ return scope.centered ? {
594
+ align: 'center'
595
+ } : {};
596
+ }
597
+ function words(scope, block, place, variant, props, sx) {
598
+ const text = aiLayoutWords(block.text, place, scope.page.targets.facts);
599
+ if (!text) return null;
600
+ return scope.page.tree.add('muiTypography', _extends({
601
+ children: text,
602
+ variant
603
+ }, props, align(scope)), sx, null, place);
604
+ }
605
+ /** A heading at its place in the outline: the section's own, or one under it. */ function heading(scope, block) {
606
+ if (scope.frame) {
607
+ const label = aiLayoutWords(block.text, 'itemTitle', scope.page.targets.facts);
608
+ return label ? scope.page.tree.add('muiTypography', _extends({
609
+ children: label,
610
+ variant: 'subtitle1',
611
+ component: 'p'
612
+ }, align(scope)), null, null, 'label') : null;
613
+ }
614
+ const own = !scope.headed;
615
+ const level = own ? scope.level : scope.level + 1;
616
+ const place = level === 1 ? 'title' : own ? 'heading' : 'itemTitle';
617
+ const text = aiLayoutWords(block.text, place, scope.page.targets.facts);
618
+ if (!text) return null;
619
+ scope.headed = scope.headed || own;
620
+ const variant = level === 1 ? block.style === 'large' ? 'displayXl' : 'h1' : own ? 'h2' : 'h4';
621
+ return scope.page.tree.add('muiTypography', _extends({
622
+ children: text,
623
+ variant,
624
+ component: `h${level}`
625
+ }, align(scope)), null, null, 'heading');
626
+ }
627
+ /** The level an item's title takes: one under the section's heading, or h2 in a section with none yet. */ function itemLevel(scope) {
628
+ return scope.headed ? scope.level + 1 : Math.max(2, scope.level);
629
+ }
630
+ /** The element an item's title renders as: a heading on a page, a label in the frame. */ function itemElement(scope) {
631
+ return scope.frame ? 'p' : `h${itemLevel(scope)}`;
632
+ }
633
+ function compileButton(scope, block) {
634
+ var _block_style;
635
+ const label = aiLayoutFitText(block.text, 'label');
636
+ if (!label) return null;
637
+ const destination = aiLayoutResolveLink(block.to, label, scope.link, scope.page.targets);
638
+ if (!destination) {
639
+ scope.page.settled.push({
640
+ at: scope.at,
641
+ what: `the button "${label}" has nowhere to go; left out`
642
+ });
643
+ return null;
644
+ }
645
+ const style = (_block_style = block.style) != null ? _block_style : 'primary';
646
+ const onBrand = scope.band === 'brand';
647
+ const look = style === 'quiet' ? {
648
+ variant: 'text',
649
+ color: onBrand ? 'inherit' : 'primary'
650
+ } : style === 'secondary' ? {
651
+ variant: 'outlined',
652
+ color: onBrand ? 'inherit' : 'primary'
653
+ } : {
654
+ variant: 'contained',
655
+ color: onBrand ? 'secondary' : 'primary'
656
+ };
657
+ const id = scope.page.tree.add('muiButton', _extends({
658
+ children: label
659
+ }, look, {
660
+ size: scope.index === 0 || block.style === 'large' ? 'large' : 'medium'
661
+ }, destinationProps(destination)), null, null, 'button');
662
+ linkTo(scope, id, destination);
663
+ return id;
664
+ }
665
+ /**
666
+ * A link to a section of this page carries the platform's Scroll to element
667
+ * interaction to that section's root (AGL-3097), by the id the page stores it
668
+ * under.
669
+ */ function linkTo(scope, id, destination) {
670
+ var _ref, _ref1;
671
+ var _page_options_sectionIds, _page_plan_sections_destination_index;
672
+ if (destination.kind !== 'section') return;
673
+ const { page } = scope;
674
+ page.scrollTo[id] = destination.index;
675
+ const target = (_ref = (_page_options_sectionIds = page.options.sectionIds) == null ? void 0 : _page_options_sectionIds[destination.index]) != null ? _ref : sectionIdOf(destination.index);
676
+ const name = (_ref1 = (_page_plan_sections_destination_index = page.plan.sections[destination.index]) == null ? void 0 : _page_plan_sections_destination_index.name) != null ? _ref1 : `section ${destination.index + 1}`;
677
+ page.tree.nodes[id].interactions = [
678
+ aiPageScrollInteraction(target, name)
679
+ ];
680
+ }
681
+ export function destinationProps(destination) {
682
+ if (destination.kind === 'page') return {
683
+ screenId: destination.screenId
684
+ };
685
+ if (destination.kind === 'href') return {
686
+ href: destination.href,
687
+ target: '_blank'
688
+ };
689
+ return {};
690
+ }
691
+ /**
692
+ * A picture slot: a soft frame at a stock shape showing an icon until the
693
+ * owner places the picture, which then fills it. Its description is its alt
694
+ * text (rule 9), and no source is set: a picture comes from the media library.
695
+ */ function image(scope, block, room) {
696
+ var _aiIconOfWord;
697
+ const { page } = scope;
698
+ const alt = aiLayoutFitText(block.text, 'alt');
699
+ if (!alt) return null;
700
+ if (page.images >= maxImages(page)) {
701
+ page.settled.push({
702
+ at: scope.at,
703
+ what: `a picture past the page's ${AI_LAYOUT_MAX_IMAGES}; left out`
704
+ });
705
+ return null;
706
+ }
707
+ page.images += 1;
708
+ const icon = (_aiIconOfWord = aiIconOfWord(block.icon)) != null ? _aiIconOfWord : page.pageIcon;
709
+ const tree = page.tree;
710
+ const mark = tree.add(AI_ICON_COMPONENT_ID, {
711
+ iconId: icon.id,
712
+ size: '64'
713
+ }, {
714
+ color: 'primary.main'
715
+ }, null, 'imageIcon');
716
+ const picture = tree.add('image', {
717
+ alt,
718
+ objectFit: 'cover'
719
+ }, {
720
+ position: 'absolute',
721
+ top: 0,
722
+ left: 0,
723
+ width: '100%',
724
+ height: '100%'
725
+ }, null, 'image');
726
+ return tree.add('muiBox', null, {
727
+ position: 'relative',
728
+ display: 'flex',
729
+ alignItems: 'center',
730
+ justifyContent: 'center',
731
+ overflow: 'hidden',
732
+ borderRadius: 4,
733
+ bgcolor: 'action.hover',
734
+ // The frame's shape follows its room, so no two slots of a page share one style.
735
+ aspectRatio: room === 'full' ? page.images === 1 ? '16 / 9' : '21 / 9' : room === 'half' ? '4 / 3' : page.images === 1 ? '1 / 1' : '3 / 4'
736
+ }, [
737
+ mark,
738
+ picture
739
+ ], 'frame');
740
+ }
741
+ /** A saved form, framed as a card so it reads as the section's one task. */ function form(scope, block) {
742
+ const tree = scope.page.tree;
743
+ const placed = tree.add('form', {
744
+ formId: block.to
745
+ }, null, null, 'form');
746
+ const content = tree.add('muiCardContent', null, {
747
+ p: {
748
+ xs: 3,
749
+ md: 4
750
+ }
751
+ }, [
752
+ placed
753
+ ], 'formContent');
754
+ return tree.add('muiCard', {
755
+ variant: 'outlined'
756
+ }, null, [
757
+ content
758
+ ], 'formCard');
759
+ }
760
+ /** A reusable component placed by its id, its props filled from the block's items. */ function component(scope, block) {
761
+ var _block_items;
762
+ const declared = componentOf(scope.page.targets, block.to);
763
+ if (!declared) return null;
764
+ const values = {};
765
+ for (const item of (_block_items = block.items) != null ? _block_items : []){
766
+ const name = item.title.trim();
767
+ if (name in declared.props && item.text.trim()) values[name] = aiLayoutWords(item.text, 'text', scope.page.targets.facts);
768
+ }
769
+ // An instance fills at least one prop (rule 1): the block's words, else the
770
+ // name its section has in the plan, rather than the component's placeholder.
771
+ if (!Object.values(values).some(Boolean)) {
772
+ var _scope_page_plan_sections_scope_index;
773
+ const first = textProps(declared.props)[0];
774
+ const words = aiLayoutWords(block.text, 'text', scope.page.targets.facts) || aiLayoutWords((_scope_page_plan_sections_scope_index = scope.page.plan.sections[scope.index]) == null ? void 0 : _scope_page_plan_sections_scope_index.name, 'itemTitle', scope.page.targets.facts);
775
+ if (first && words) values[first] = words;
776
+ }
777
+ for (const [name, value] of Object.entries(values))if (!value) delete values[name];
778
+ return scope.page.tree.add(REUSABLE_INSTANCE_COMPONENT_ID, _extends({
779
+ [AI_INSTANCE_REF_PROP]: declared.id
780
+ }, Object.keys(values).length ? {
781
+ propValues: values
782
+ } : {}), null, null, 'instance');
783
+ }
784
+ function textProps(props) {
785
+ return Object.entries(props).filter(([, type])=>type === 'text' || type === 'richText').map(([name])=>name);
786
+ }
787
+ /** An item's words as the props of the component that draws it. */ function instanceValues(props, item, facts) {
788
+ var _texts_find, _texts_find1;
789
+ const texts = textProps(props);
790
+ const titleProp = (_texts_find = texts.find((name)=>/title|name|heading|label|question|figure|value/i.test(name))) != null ? _texts_find : texts[0];
791
+ const textProp = (_texts_find1 = texts.find((name)=>name !== titleProp && /text|description|body|summary|copy|answer|detail|caption/i.test(name))) != null ? _texts_find1 : texts.find((name)=>name !== titleProp);
792
+ const values = {};
793
+ if (titleProp && item.title.trim()) values[titleProp] = aiLayoutWords(item.title, 'itemTitle', facts);
794
+ if (textProp && item.text.trim()) values[textProp] = aiLayoutWords(item.text, 'itemText', facts);
795
+ const first = titleProp != null ? titleProp : textProp;
796
+ if (!Object.values(values).some(Boolean) && first) values[first] = aiLayoutWords(item.title || item.text, 'itemTitle', facts);
797
+ return values;
798
+ }
799
+ // ── Groups ────────────────────────────────────────────────────────────────
800
+ /** How many items sit side by side in a room. */ function across(count, room, kind) {
801
+ if (room === 'narrow') return 1;
802
+ if (room === 'half') return count >= 2 && kind === 'stats' ? 2 : 1;
803
+ if (count <= 3) return count;
804
+ if (count === 4) return 4;
805
+ if (count === 7) return 4;
806
+ return 3;
807
+ }
808
+ function itemSize(perRow) {
809
+ if (perRow === 2) return 'xs:12 sm:6';
810
+ if (perRow === 3) return 'xs:12 md:4';
811
+ return 'xs:12 sm:6 md:3';
812
+ }
813
+ /** Items laid out side by side as a Grid of sized items, or stacked where they sit one to a row. */ function layOut(scope, items, perRow, spacing, role) {
814
+ const tree = scope.page.tree;
815
+ if (items.length === 1) return items[0];
816
+ if (perRow <= 1) {
817
+ return tree.add('muiStack', {
818
+ spacing
819
+ }, null, items, role);
820
+ }
821
+ const size = itemSize(perRow);
822
+ const cells = items.map((id)=>tree.add('muiGrid', {
823
+ size
824
+ }, null, [
825
+ id
826
+ ], 'cell'));
827
+ return tree.add('muiGrid', {
828
+ container: true,
829
+ spacing
830
+ }, null, cells, role);
831
+ }
832
+ /**
833
+ * Whether repeats must be components here (rule 1): the workspace keeps
834
+ * them. Rule 1 counts like blocks across the whole page, so where it holds
835
+ * every group the plan places no component for is drawn compact, however
836
+ * few its items — two sections of two cards are four like cards.
837
+ */ function rule1(scope) {
838
+ return scope.page.options.reusableComponents;
839
+ }
840
+ /** The most pictures this page carries: two where rule 1 counts three like frames as a repeat. */ function maxImages(page) {
841
+ return page.options.reusableComponents ? 2 : AI_LAYOUT_MAX_IMAGES;
842
+ }
843
+ /**
844
+ * The items a group may still show in its section (rule 8): seven like items
845
+ * a section, across all its groups, since eight are a list typed by hand.
846
+ */ /** Whether an item has words left once they are cleaned and fitted: an item with none is no item. */ function speaks(scope, item) {
847
+ const facts = scope.page.targets.facts;
848
+ return !!(aiLayoutWords(item.title, 'itemTitle', facts) || aiLayoutWords(item.text, 'itemText', facts));
849
+ }
850
+ /** A group's items with every part that has no words left once cleaned emptied, and wordless items left out. */ function cleanItems(scope, items) {
851
+ const facts = scope.page.targets.facts;
852
+ return items.map((item)=>_extends({}, item, {
853
+ title: aiLayoutWords(item.title, 'itemTitle', facts) ? item.title : '',
854
+ text: aiLayoutWords(item.text, 'itemText', facts) ? item.text : ''
855
+ })).filter((item)=>speaks(scope, item));
856
+ }
857
+ function takeItems(scope, items) {
858
+ const kept = items.slice(0, Math.max(0, scope.itemsLeft));
859
+ if (kept.length < items.length) {
860
+ scope.page.settled.push({
861
+ at: scope.at,
862
+ what: `${items.length - kept.length} items past the section's ${AI_LAYOUT_MAX_ITEMS}; left out`
863
+ });
864
+ }
865
+ scope.itemsLeft -= kept.length;
866
+ return kept;
867
+ }
868
+ /** `takeItems` on a list it shortens where it stands. */ function takeItemsInPlace(scope, items) {
869
+ const kept = takeItems(scope, items);
870
+ items.length = kept.length;
871
+ }
872
+ function group(scope, block, room) {
873
+ var _block_items;
874
+ const items = takeItems(scope, cleanItems(scope, (_block_items = block.items) != null ? _block_items : []));
875
+ if (!items.length) return null;
876
+ const perRow = across(items.length, room, block.kind);
877
+ const placed = componentOf(scope.page.targets, block.to);
878
+ if (placed) return instances(scope, placed, items, perRow);
879
+ if (rule1(scope)) return compactGroup(scope, block, items, perRow);
880
+ switch(block.kind){
881
+ case 'steps':
882
+ return layOut(scope, items.map((item, position)=>step(scope, item, position)), perRow, '4', 'steps');
883
+ case 'stats':
884
+ return layOut(scope, items.map((item)=>stat(scope, item)), perRow, '4', 'stats');
885
+ case 'quotes':
886
+ return layOut(scope, items.map((item)=>quote(scope, item)), perRow, '3', 'quotes');
887
+ default:
888
+ return layOut(scope, items.map((item)=>card(scope, block, item)), perRow, '3', 'cards');
889
+ }
890
+ }
891
+ function instances(scope, placed, items, perRow) {
892
+ const tree = scope.page.tree;
893
+ const ids = items.map((item)=>{
894
+ const values = instanceValues(placed.props, item, scope.page.targets.facts);
895
+ return tree.add(REUSABLE_INSTANCE_COMPONENT_ID, _extends({
896
+ [AI_INSTANCE_REF_PROP]: placed.id
897
+ }, Object.keys(values).length ? {
898
+ propValues: values
899
+ } : {}), null, null, 'instance');
900
+ });
901
+ return layOut(scope, ids, perRow, '3', 'instances');
902
+ }
903
+ /**
904
+ * A group in its compact form, a title over its text: two elements an item,
905
+ * under the three a block must have before rule 1 asks for a component.
906
+ */ function compactGroup(scope, block, items, perRow) {
907
+ const tree = scope.page.tree;
908
+ const facts = scope.page.targets.facts;
909
+ const pairs = items.map((item, position)=>{
910
+ const title = block.kind === 'quotes' ? aiLayoutQuoteGap(item.text || item.title) : block.kind === 'stats' ? aiLayoutWords(item.title, 'stat', facts) : `${block.kind === 'steps' ? `${position + 1}. ` : ''}${aiLayoutWords(item.title, 'itemTitle', facts)}`;
911
+ const text = block.kind === 'quotes' ? '[Customer name]' : aiLayoutWords(item.text, block.kind === 'stats' ? 'statLabel' : 'itemText', facts);
912
+ return tree.add('muiListItemText', _extends({
913
+ primary: title
914
+ }, text ? {
915
+ secondary: text
916
+ } : {}), null, null, 'pair');
917
+ });
918
+ return layOut(scope, pairs, perRow, '3', 'compact');
919
+ }
920
+ /** A card: an optional icon, its title one level under the section's heading, and its words. */ function card(scope, block, item) {
921
+ var _aiIconOfWord;
922
+ const tree = scope.page.tree;
923
+ const facts = scope.page.targets.facts;
924
+ const icon = (_aiIconOfWord = aiIconOfWord(item.icon)) != null ? _aiIconOfWord : aiIconOfWord(block.icon);
925
+ const children = [
926
+ icon ? tree.add(AI_ICON_COMPONENT_ID, {
927
+ iconId: icon.id,
928
+ size: '32'
929
+ }, {
930
+ color: 'primary.main'
931
+ }, null, 'icon') : null,
932
+ item.title.trim() ? tree.add('muiTypography', {
933
+ children: aiLayoutWords(item.title, 'itemTitle', facts),
934
+ variant: 'h5',
935
+ component: itemElement(scope)
936
+ }, null, null, 'title') : null,
937
+ item.text.trim() ? tree.add('muiTypography', {
938
+ children: aiLayoutWords(item.text, 'itemText', facts),
939
+ variant: 'body1'
940
+ }, {
941
+ color: 'text.secondary'
942
+ }, null, 'text') : null
943
+ ];
944
+ const stack = tree.add('muiStack', {
945
+ spacing: '1.5'
946
+ }, null, children, 'cardStack');
947
+ if (block.style === 'quiet') return stack;
948
+ const content = tree.add('muiCardContent', null, {
949
+ p: 3
950
+ }, [
951
+ stack
952
+ ], 'cardContent');
953
+ return tree.add('muiCard', block.style === 'primary' || block.style === 'large' ? {
954
+ variant: 'elevation',
955
+ elevation: '2'
956
+ } : {
957
+ variant: 'outlined'
958
+ }, {
959
+ height: '100%'
960
+ }, [
961
+ content
962
+ ], 'card');
963
+ }
964
+ /** A numbered step: its number in the brand color, its title and its words. */ function step(scope, item, position) {
965
+ const tree = scope.page.tree;
966
+ const facts = scope.page.targets.facts;
967
+ return tree.add('muiStack', {
968
+ spacing: '1'
969
+ }, null, [
970
+ tree.add('muiTypography', {
971
+ children: String(position + 1).padStart(2, '0'),
972
+ variant: 'h3',
973
+ component: 'p'
974
+ }, accent(scope), null, 'number'),
975
+ item.title.trim() ? tree.add('muiTypography', {
976
+ children: aiLayoutWords(item.title, 'itemTitle', facts),
977
+ variant: 'h5',
978
+ component: itemElement(scope)
979
+ }, null, null, 'title') : null,
980
+ item.text.trim() ? tree.add('muiTypography', {
981
+ children: aiLayoutWords(item.text, 'itemText', facts),
982
+ variant: 'body1'
983
+ }, muted(scope), null, 'text') : null
984
+ ], 'step');
985
+ }
986
+ /** A figure and its label. A figure the brief did not give is the model's bracketed gap. */ function stat(scope, item) {
987
+ const tree = scope.page.tree;
988
+ const facts = scope.page.targets.facts;
989
+ return tree.add('muiStack', _extends({
990
+ spacing: '0.5'
991
+ }, scope.centered ? {
992
+ alignItems: 'center'
993
+ } : {}), null, [
994
+ tree.add('muiTypography', _extends({
995
+ children: aiLayoutWords(item.title, 'stat', facts) || '[figure]',
996
+ variant: 'h2',
997
+ component: 'p'
998
+ }, align(scope)), accent(scope), null, 'figure'),
999
+ item.text.trim() ? tree.add('muiTypography', _extends({
1000
+ children: aiLayoutWords(item.text, 'statLabel', facts),
1001
+ variant: 'body2'
1002
+ }, align(scope)), muted(scope), null, 'label') : null
1003
+ ], 'stat');
1004
+ }
1005
+ /** A quote slot: what a customer should be quoted saying, as the gap the owner fills. */ function quote(scope, item) {
1006
+ const tree = scope.page.tree;
1007
+ const words = aiLayoutQuoteGap(item.text || item.title);
1008
+ const who = item.text && item.title ? aiLayoutFitText(item.title, 'statLabel') : '';
1009
+ const stack = tree.add('muiStack', {
1010
+ spacing: '2'
1011
+ }, null, [
1012
+ tree.add(AI_ICON_COMPONENT_ID, {
1013
+ iconId: AI_ICON_LIBRARY.quote.id,
1014
+ size: '32'
1015
+ }, {
1016
+ color: 'primary.main'
1017
+ }, null, 'quoteMark'),
1018
+ tree.add('muiTypography', {
1019
+ children: words,
1020
+ variant: 'body1'
1021
+ }, null, null, 'quote'),
1022
+ tree.add('muiTypography', {
1023
+ children: aiLayoutFitText(who ? `[Customer name], ${who.replace(/^\[|\]$/g, '')}` : '', 'note') || '[Customer name]',
1024
+ variant: 'subtitle2',
1025
+ component: 'p'
1026
+ }, null, null, 'attribution')
1027
+ ], 'quoteStack');
1028
+ const content = tree.add('muiCardContent', null, {
1029
+ p: 3
1030
+ }, [
1031
+ stack
1032
+ ], 'quoteContent');
1033
+ return tree.add('muiCard', {
1034
+ variant: 'outlined'
1035
+ }, {
1036
+ height: '100%'
1037
+ }, [
1038
+ content
1039
+ ], 'quoteCard');
1040
+ }
1041
+ /** A list: check-marked lines, or plain lines where rule 1 holds and the list is long. */ function list(scope, block) {
1042
+ var _block_items, _block_items1, _aiIconOfWord;
1043
+ const tree = scope.page.tree;
1044
+ const facts = scope.page.targets.facts;
1045
+ // A list whose lines go somewhere is a list of links: each line that
1046
+ // resolves is a Page Link, and one that does not is left out (rule 10).
1047
+ if (((_block_items = block.items) != null ? _block_items : []).some((item)=>item.to)) {
1048
+ var _block_items2;
1049
+ const links = ((_block_items2 = block.items) != null ? _block_items2 : []).flatMap((item)=>{
1050
+ const label = aiLayoutFitText(item.title || item.text, 'label');
1051
+ const destination = label ? aiLayoutResolveLink(item.to, label, scope.link, scope.page.targets) : null;
1052
+ if (!destination) return [];
1053
+ const id = tree.add('muiScreenLink', _extends({
1054
+ children: label,
1055
+ renderAs: 'link',
1056
+ color: 'inherit'
1057
+ }, destinationProps(destination)), null, null, 'link');
1058
+ linkTo(scope, id, destination);
1059
+ return [
1060
+ id
1061
+ ];
1062
+ });
1063
+ return links.length ? tree.add('muiStack', {
1064
+ spacing: '1'
1065
+ }, null, links, 'links') : null;
1066
+ }
1067
+ const lines = cleanItems(scope, (_block_items1 = block.items) != null ? _block_items1 : []).map((item)=>aiLayoutWords([
1068
+ item.title,
1069
+ item.text
1070
+ ].filter((part)=>part.trim()).join(' — '), 'listItem', facts)).filter(Boolean);
1071
+ takeItemsInPlace(scope, lines);
1072
+ if (!lines.length) return null;
1073
+ if (rule1(scope)) {
1074
+ const rows = lines.map((line)=>tree.add('muiListItem', {
1075
+ disableGutters: true
1076
+ }, null, [
1077
+ tree.add('muiListItemText', {
1078
+ primary: line
1079
+ }, null, null, 'line')
1080
+ ], 'row'));
1081
+ return tree.add('muiList', {
1082
+ disablePadding: true
1083
+ }, null, rows, 'list');
1084
+ }
1085
+ const check = (_aiIconOfWord = aiIconOfWord(block.icon)) != null ? _aiIconOfWord : AI_ICON_LIBRARY.check;
1086
+ const rows = lines.map((line)=>tree.add('muiStack', {
1087
+ direction: 'row',
1088
+ spacing: '1.5',
1089
+ alignItems: 'flex-start'
1090
+ }, null, [
1091
+ tree.add(AI_ICON_COMPONENT_ID, {
1092
+ iconId: check.id,
1093
+ size: '22'
1094
+ }, accent(scope), null, 'check'),
1095
+ tree.add('muiTypography', {
1096
+ children: line,
1097
+ variant: 'body1'
1098
+ }, null, null, 'line')
1099
+ ], 'row'));
1100
+ return tree.add('muiStack', {
1101
+ spacing: '1.5'
1102
+ }, null, rows, 'list');
1103
+ }
1104
+ /** Questions and answers: an accordion each, or question-over-answer pairs where rule 1 holds. */ function faq(scope, block) {
1105
+ var _block_items;
1106
+ const tree = scope.page.tree;
1107
+ const facts = scope.page.targets.facts;
1108
+ const items = takeItems(scope, cleanItems(scope, (_block_items = block.items) != null ? _block_items : []).filter((item)=>!!aiLayoutWords(item.title, 'question', facts)));
1109
+ if (!items.length) return null;
1110
+ if (rule1(scope)) {
1111
+ const rows = items.map((item)=>tree.add('muiListItem', {
1112
+ disableGutters: true,
1113
+ divider: true
1114
+ }, null, [
1115
+ tree.add('muiListItemText', _extends({
1116
+ primary: aiLayoutWords(item.title, 'question', facts)
1117
+ }, item.text.trim() ? {
1118
+ secondary: aiLayoutWords(item.text, 'answer', facts)
1119
+ } : {}), null, null, 'qa')
1120
+ ], 'row'));
1121
+ return tree.add('muiList', {
1122
+ disablePadding: true
1123
+ }, null, rows, 'faq');
1124
+ }
1125
+ const panels = items.map((item, position)=>tree.add('muiAccordion', _extends({
1126
+ disableGutters: true
1127
+ }, position === 0 ? {
1128
+ defaultExpanded: true
1129
+ } : {}), null, [
1130
+ tree.add('muiAccordionSummary', {
1131
+ children: aiLayoutWords(item.title, 'question', facts)
1132
+ }, null, null, 'question'),
1133
+ item.text.trim() ? tree.add('muiAccordionDetails', null, null, [
1134
+ tree.add('muiTypography', {
1135
+ children: aiLayoutWords(item.text, 'answer', facts),
1136
+ variant: 'body1'
1137
+ }, {
1138
+ color: 'text.secondary'
1139
+ }, null, 'answer')
1140
+ ], 'details') : null
1141
+ ], 'panel'));
1142
+ return tree.add('muiStack', {
1143
+ spacing: '1.5'
1144
+ }, null, panels, 'faq');
1145
+ }
1146
+ /** The id the compiled page's root is stored under. */ export const AI_LAYOUT_PAGE_ROOT_ID = CANVAS_ROOT_ELEMENT_ID;
1147
+
1148
+ //# sourceMappingURL=ai-layout-compiler.js.map