@alfakit/vue 0.1.2 → 0.1.6

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 (281) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/AlfakitRoot.js.map +1 -1
  3. package/dist/AlfakitRoot.vue.d.ts.map +1 -1
  4. package/dist/AlfakitRoot.vue_vue_type_script_setup_true_lang.js +3 -1
  5. package/dist/AlfakitRoot.vue_vue_type_script_setup_true_lang.js.map +1 -1
  6. package/dist/components/actions/ActionGroupMenu.js.map +1 -1
  7. package/dist/components/actions/ActionGroupMenu.vue.d.ts.map +1 -1
  8. package/dist/components/actions/ActionGroupMenu.vue_vue_type_script_setup_true_lang.js +69 -65
  9. package/dist/components/actions/ActionGroupMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  10. package/dist/components/actions/ActionModal.js.map +1 -1
  11. package/dist/components/actions/ActionModal.vue.d.ts.map +1 -1
  12. package/dist/components/actions/ActionModal.vue_vue_type_script_setup_true_lang.js +17 -15
  13. package/dist/components/actions/ActionModal.vue_vue_type_script_setup_true_lang.js.map +1 -1
  14. package/dist/components/ai/AiCopilot.js.map +1 -1
  15. package/dist/components/ai/AiCopilot.vue.d.ts +2 -0
  16. package/dist/components/ai/AiCopilot.vue.d.ts.map +1 -1
  17. package/dist/components/ai/AiCopilot.vue_vue_type_script_setup_true_lang.js +7 -2
  18. package/dist/components/ai/AiCopilot.vue_vue_type_script_setup_true_lang.js.map +1 -1
  19. package/dist/components/cms/CmsPage.vue_vue_type_script_setup_true_lang.js +19 -19
  20. package/dist/components/cms/CmsPage.vue_vue_type_script_setup_true_lang.js.map +1 -1
  21. package/dist/components/cms/LivePreview.js.map +1 -1
  22. package/dist/components/cms/LivePreview.vue.d.ts.map +1 -1
  23. package/dist/components/cms/LivePreview.vue_vue_type_script_setup_true_lang.js +83 -83
  24. package/dist/components/cms/LivePreview.vue_vue_type_script_setup_true_lang.js.map +1 -1
  25. package/dist/components/fields/BuilderField.js.map +1 -1
  26. package/dist/components/fields/BuilderField.vue.d.ts.map +1 -1
  27. package/dist/components/fields/BuilderField.vue_vue_type_script_setup_true_lang.js +162 -157
  28. package/dist/components/fields/BuilderField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  29. package/dist/components/fields/ImageEditorDialog.js.map +1 -1
  30. package/dist/components/fields/ImageEditorDialog.vue.d.ts.map +1 -1
  31. package/dist/components/fields/ImageEditorDialog.vue_vue_type_script_setup_true_lang.js +46 -46
  32. package/dist/components/fields/ImageEditorDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  33. package/dist/components/fields/KeyValueField.js.map +1 -1
  34. package/dist/components/fields/KeyValueField.vue.d.ts.map +1 -1
  35. package/dist/components/fields/KeyValueField.vue_vue_type_script_setup_true_lang.js +66 -66
  36. package/dist/components/fields/KeyValueField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  37. package/dist/components/fields/ModalTablePicker.js.map +1 -1
  38. package/dist/components/fields/ModalTablePicker.vue.d.ts.map +1 -1
  39. package/dist/components/fields/ModalTablePicker.vue_vue_type_script_setup_true_lang.js +113 -113
  40. package/dist/components/fields/ModalTablePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  41. package/dist/components/fields/RepeaterField.js.map +1 -1
  42. package/dist/components/fields/RepeaterField.vue.d.ts.map +1 -1
  43. package/dist/components/fields/RepeaterField.vue_vue_type_script_setup_true_lang.js +12 -12
  44. package/dist/components/fields/RepeaterField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  45. package/dist/components/fields/RichEditorInput.js.map +1 -1
  46. package/dist/components/fields/RichEditorInput.vue.d.ts.map +1 -1
  47. package/dist/components/fields/RichEditorInput.vue_vue_type_script_setup_true_lang.js +166 -165
  48. package/dist/components/fields/RichEditorInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  49. package/dist/components/fields/SliderField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  50. package/dist/components/fields/item-actions.d.ts +2 -2
  51. package/dist/components/fields/item-actions.d.ts.map +1 -1
  52. package/dist/components/fields/item-actions.js +31 -31
  53. package/dist/components/fields/item-actions.js.map +1 -1
  54. package/dist/components/form/FormBlock.js.map +1 -1
  55. package/dist/components/form/FormBlock.vue.d.ts.map +1 -1
  56. package/dist/components/form/FormBlock.vue_vue_type_script_setup_true_lang.js +1 -1
  57. package/dist/components/form/FormBlock.vue_vue_type_script_setup_true_lang.js.map +1 -1
  58. package/dist/components/form/form-context.js +25 -25
  59. package/dist/components/form/form-context.js.map +1 -1
  60. package/dist/components/kanban/KanbanBoard.js.map +1 -1
  61. package/dist/components/kanban/KanbanBoard.vue.d.ts.map +1 -1
  62. package/dist/components/kanban/KanbanBoard.vue_vue_type_script_setup_true_lang.js +5 -2
  63. package/dist/components/kanban/KanbanBoard.vue_vue_type_script_setup_true_lang.js.map +1 -1
  64. package/dist/components/kanban/KanbanColumnHeader.js.map +1 -1
  65. package/dist/components/kanban/KanbanColumnHeader.vue.d.ts.map +1 -1
  66. package/dist/components/kanban/KanbanColumnHeader.vue_vue_type_script_setup_true_lang.js +64 -64
  67. package/dist/components/kanban/KanbanColumnHeader.vue_vue_type_script_setup_true_lang.js.map +1 -1
  68. package/dist/components/layout/SectionComponent.js.map +1 -1
  69. package/dist/components/layout/SectionComponent.vue.d.ts.map +1 -1
  70. package/dist/components/layout/SectionComponent.vue_vue_type_script_setup_true_lang.js +23 -23
  71. package/dist/components/layout/SectionComponent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  72. package/dist/components/panel/DebugPanel.vue_vue_type_script_setup_true_lang.js +8 -8
  73. package/dist/components/panel/DebugPanel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  74. package/dist/components/panel/GlobalSearchPalette.js.map +1 -1
  75. package/dist/components/panel/GlobalSearchPalette.vue.d.ts.map +1 -1
  76. package/dist/components/panel/GlobalSearchPalette.vue_vue_type_script_setup_true_lang.js +102 -96
  77. package/dist/components/panel/GlobalSearchPalette.vue_vue_type_script_setup_true_lang.js.map +1 -1
  78. package/dist/components/panel/NavGroup.vue_vue_type_script_setup_true_lang.js +10 -10
  79. package/dist/components/panel/NavGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  80. package/dist/components/panel/NavGroupFlyout.vue_vue_type_script_setup_true_lang.js +9 -9
  81. package/dist/components/panel/NavGroupFlyout.vue_vue_type_script_setup_true_lang.js.map +1 -1
  82. package/dist/components/panel/NavItem.vue_vue_type_script_setup_true_lang.js +16 -16
  83. package/dist/components/panel/NavItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  84. package/dist/components/panel/NavSubItem.vue_vue_type_script_setup_true_lang.js +10 -10
  85. package/dist/components/panel/NavSubItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  86. package/dist/components/panel/TenantMenu.vue_vue_type_script_setup_true_lang.js +35 -35
  87. package/dist/components/panel/TenantMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  88. package/dist/components/panel/Topbar.vue_vue_type_script_setup_true_lang.js +11 -11
  89. package/dist/components/panel/Topbar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  90. package/dist/components/realtime/use-live-updates.d.ts.map +1 -1
  91. package/dist/components/realtime/use-live-updates.js +24 -23
  92. package/dist/components/realtime/use-live-updates.js.map +1 -1
  93. package/dist/components/table/BooleanCell.vue_vue_type_script_setup_true_lang.js +2 -1
  94. package/dist/components/table/BooleanCell.vue_vue_type_script_setup_true_lang.js.map +1 -1
  95. package/dist/components/table/ColumnHeader.js.map +1 -1
  96. package/dist/components/table/ColumnHeader.vue.d.ts.map +1 -1
  97. package/dist/components/table/ColumnHeader.vue_vue_type_script_setup_true_lang.js +55 -49
  98. package/dist/components/table/ColumnHeader.vue_vue_type_script_setup_true_lang.js.map +1 -1
  99. package/dist/components/table/ColumnManager.js.map +1 -1
  100. package/dist/components/table/ColumnManager.vue.d.ts.map +1 -1
  101. package/dist/components/table/ColumnManager.vue_vue_type_script_setup_true_lang.js +5 -4
  102. package/dist/components/table/ColumnManager.vue_vue_type_script_setup_true_lang.js.map +1 -1
  103. package/dist/components/table/ContentLayoutSort.js.map +1 -1
  104. package/dist/components/table/ContentLayoutSort.vue.d.ts.map +1 -1
  105. package/dist/components/table/ContentLayoutSort.vue_vue_type_script_setup_true_lang.js +5 -5
  106. package/dist/components/table/ContentLayoutSort.vue_vue_type_script_setup_true_lang.js.map +1 -1
  107. package/dist/components/table/SelectCell.vue_vue_type_script_setup_true_lang.js +2 -1
  108. package/dist/components/table/SelectCell.vue_vue_type_script_setup_true_lang.js.map +1 -1
  109. package/dist/components/table/SelectComboboxCell.vue_vue_type_script_setup_true_lang.js +2 -1
  110. package/dist/components/table/SelectComboboxCell.vue_vue_type_script_setup_true_lang.js.map +1 -1
  111. package/dist/components/table/TableCellContent.js.map +1 -1
  112. package/dist/components/table/TableCellContent.vue.d.ts.map +1 -1
  113. package/dist/components/table/TableCellContent.vue_vue_type_script_setup_true_lang.js +4 -3
  114. package/dist/components/table/TableCellContent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  115. package/dist/components/table/TablePagination.js.map +1 -1
  116. package/dist/components/table/TablePagination.vue.d.ts.map +1 -1
  117. package/dist/components/table/TablePagination.vue_vue_type_script_setup_true_lang.js +87 -87
  118. package/dist/components/table/TablePagination.vue_vue_type_script_setup_true_lang.js.map +1 -1
  119. package/dist/components/table/TextInputCell.vue_vue_type_script_setup_true_lang.js +2 -1
  120. package/dist/components/table/TextInputCell.vue_vue_type_script_setup_true_lang.js.map +1 -1
  121. package/dist/components/table/cell-update.d.ts +6 -0
  122. package/dist/components/table/cell-update.d.ts.map +1 -1
  123. package/dist/components/table/cell-update.js.map +1 -1
  124. package/dist/components/translation-manager/TranslationManagerView.vue_vue_type_script_setup_true_lang.js +1 -1
  125. package/dist/components/translation-manager/TranslationManagerView.vue_vue_type_script_setup_true_lang.js.map +1 -1
  126. package/dist/components/ui/CommandAutoHighlight.js +7 -0
  127. package/dist/components/ui/CommandAutoHighlight.js.map +1 -0
  128. package/dist/components/ui/CommandAutoHighlight.vue.d.ts +21 -0
  129. package/dist/components/ui/CommandAutoHighlight.vue.d.ts.map +1 -0
  130. package/dist/components/ui/CommandAutoHighlight.vue_vue_type_script_setup_true_lang.js +18 -0
  131. package/dist/components/ui/CommandAutoHighlight.vue_vue_type_script_setup_true_lang.js.map +1 -0
  132. package/dist/components/ui/DialogContent.js.map +1 -1
  133. package/dist/components/ui/DialogContent.vue.d.ts.map +1 -1
  134. package/dist/components/ui/DialogContent.vue_vue_type_script_setup_true_lang.js +13 -12
  135. package/dist/components/ui/DialogContent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  136. package/dist/components/ui/PopoverContent.js.map +1 -1
  137. package/dist/components/ui/PopoverContent.vue.d.ts.map +1 -1
  138. package/dist/components/ui/PopoverContent.vue_vue_type_script_setup_true_lang.js +9 -8
  139. package/dist/components/ui/PopoverContent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  140. package/dist/components/ui/SheetContent.js.map +1 -1
  141. package/dist/components/ui/SheetContent.vue.d.ts.map +1 -1
  142. package/dist/components/ui/SheetContent.vue_vue_type_script_setup_true_lang.js +13 -12
  143. package/dist/components/ui/SheetContent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  144. package/dist/components/ui/TooltipContent.js.map +1 -1
  145. package/dist/components/ui/TooltipContent.vue.d.ts.map +1 -1
  146. package/dist/components/ui/TooltipContent.vue_vue_type_script_setup_true_lang.js +9 -8
  147. package/dist/components/ui/TooltipContent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  148. package/dist/context.d.ts +7 -0
  149. package/dist/context.d.ts.map +1 -1
  150. package/dist/context.js +29 -26
  151. package/dist/context.js.map +1 -1
  152. package/dist/create-alfakit.d.ts.map +1 -1
  153. package/dist/create-alfakit.js +33 -31
  154. package/dist/create-alfakit.js.map +1 -1
  155. package/dist/eject-manifest.json +11 -2
  156. package/dist/index.d.ts +1 -0
  157. package/dist/index.d.ts.map +1 -1
  158. package/dist/index.js +219 -217
  159. package/dist/layouts/AppLayout.vue_vue_type_script_setup_true_lang.js +8 -8
  160. package/dist/layouts/AppLayout.vue_vue_type_script_setup_true_lang.js.map +1 -1
  161. package/dist/layouts/AuthLayout.vue_vue_type_script_setup_true_lang.js +9 -9
  162. package/dist/layouts/FullscreenLayout.vue_vue_type_script_setup_true_lang.js +8 -8
  163. package/dist/layouts/FullscreenLayout.vue_vue_type_script_setup_true_lang.js.map +1 -1
  164. package/dist/layouts/TopNavLayout.vue_vue_type_script_setup_true_lang.js +15 -15
  165. package/dist/layouts/TopNavLayout.vue_vue_type_script_setup_true_lang.js.map +1 -1
  166. package/dist/layouts/lazy-layouts.d.ts +10 -0
  167. package/dist/layouts/lazy-layouts.d.ts.map +1 -0
  168. package/dist/layouts/lazy-layouts.js +8 -0
  169. package/dist/layouts/lazy-layouts.js.map +1 -0
  170. package/dist/layouts/panel-layouts.d.ts +8 -0
  171. package/dist/layouts/panel-layouts.d.ts.map +1 -0
  172. package/dist/layouts/panel-layouts.js +15 -0
  173. package/dist/layouts/panel-layouts.js.map +1 -0
  174. package/dist/lib/lazy.d.ts.map +1 -1
  175. package/dist/lib/lazy.js +2 -2
  176. package/dist/lib/lazy.js.map +1 -1
  177. package/dist/pages/PageShell.js.map +1 -1
  178. package/dist/pages/PageShell.vue.d.ts.map +1 -1
  179. package/dist/pages/PageShell.vue_vue_type_script_setup_true_lang.js +39 -42
  180. package/dist/pages/PageShell.vue_vue_type_script_setup_true_lang.js.map +1 -1
  181. package/dist/standalone/AlfakitComponent.js.map +1 -1
  182. package/dist/standalone/AlfakitComponent.vue.d.ts.map +1 -1
  183. package/dist/standalone/AlfakitComponent.vue_vue_type_script_setup_true_lang.js +56 -52
  184. package/dist/standalone/AlfakitComponent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  185. package/dist/standalone.css +7 -0
  186. package/dist/starter-kit/AlfakitStarterKitRoot.js.map +1 -1
  187. package/dist/starter-kit/AlfakitStarterKitRoot.vue.d.ts +2 -2
  188. package/dist/starter-kit/AlfakitStarterKitRoot.vue.d.ts.map +1 -1
  189. package/dist/starter-kit/AlfakitStarterKitRoot.vue_vue_type_script_setup_true_lang.js +17 -12
  190. package/dist/starter-kit/AlfakitStarterKitRoot.vue_vue_type_script_setup_true_lang.js.map +1 -1
  191. package/dist/starter-kit/dashboard-widgets.d.ts +54 -0
  192. package/dist/starter-kit/dashboard-widgets.d.ts.map +1 -0
  193. package/dist/starter-kit/dashboard-widgets.js +54 -0
  194. package/dist/starter-kit/dashboard-widgets.js.map +1 -0
  195. package/dist/starter-kit/index.d.ts +2 -1
  196. package/dist/starter-kit/index.d.ts.map +1 -1
  197. package/dist/starter-kit/index.js +5 -4
  198. package/dist/starter-kit/runtime.d.ts +6 -0
  199. package/dist/starter-kit/runtime.d.ts.map +1 -1
  200. package/dist/starter-kit/runtime.js +19 -15
  201. package/dist/starter-kit/runtime.js.map +1 -1
  202. package/dist/starter-kit/starter-kit.d.ts.map +1 -1
  203. package/dist/starter-kit/starter-kit.js +8 -8
  204. package/dist/starter-kit/starter-kit.js.map +1 -1
  205. package/dist/starter-kit/widgets/CopilotTrigger.js +7 -0
  206. package/dist/starter-kit/widgets/CopilotTrigger.js.map +1 -0
  207. package/dist/starter-kit/widgets/CopilotTrigger.vue.d.ts +12 -0
  208. package/dist/starter-kit/widgets/CopilotTrigger.vue.d.ts.map +1 -0
  209. package/dist/starter-kit/widgets/CopilotTrigger.vue_vue_type_script_setup_true_lang.js +23 -0
  210. package/dist/starter-kit/widgets/CopilotTrigger.vue_vue_type_script_setup_true_lang.js.map +1 -0
  211. package/dist/starter-kit/widgets/LoadedCopilot.js +7 -0
  212. package/dist/starter-kit/widgets/LoadedCopilot.js.map +1 -0
  213. package/dist/starter-kit/widgets/LoadedCopilot.vue.d.ts +8 -0
  214. package/dist/starter-kit/widgets/LoadedCopilot.vue.d.ts.map +1 -0
  215. package/dist/starter-kit/widgets/LoadedCopilot.vue_vue_type_script_setup_true_lang.js +31 -0
  216. package/dist/starter-kit/widgets/LoadedCopilot.vue_vue_type_script_setup_true_lang.js.map +1 -0
  217. package/dist/starter-kit/widgets/StarterKitImpersonationBanner.js +7 -0
  218. package/dist/starter-kit/widgets/StarterKitImpersonationBanner.js.map +1 -0
  219. package/dist/starter-kit/widgets/StarterKitImpersonationBanner.vue.d.ts +8 -0
  220. package/dist/starter-kit/widgets/StarterKitImpersonationBanner.vue.d.ts.map +1 -0
  221. package/dist/starter-kit/widgets/StarterKitImpersonationBanner.vue_vue_type_script_setup_true_lang.js +34 -0
  222. package/dist/starter-kit/widgets/StarterKitImpersonationBanner.vue_vue_type_script_setup_true_lang.js.map +1 -0
  223. package/dist/starter-kit/widgets/index.d.ts +40 -9
  224. package/dist/starter-kit/widgets/index.d.ts.map +1 -1
  225. package/dist/starter-kit/widgets/index.js +21 -18
  226. package/dist/starter-kit/widgets/index.js.map +1 -1
  227. package/dist/starter-kit/widgets/loaded.d.ts +10 -0
  228. package/dist/starter-kit/widgets/loaded.d.ts.map +1 -0
  229. package/dist/starter-kit/widgets/loaded.js +5 -0
  230. package/dist/styles.css +9 -2
  231. package/dist/themes.css +6 -1
  232. package/package.json +2 -2
  233. package/src/AlfakitRoot.vue +9 -1
  234. package/src/components/actions/ActionGroupMenu.vue +13 -1
  235. package/src/components/actions/ActionModal.vue +9 -0
  236. package/src/components/ai/AiCopilot.vue +7 -1
  237. package/src/components/cms/LivePreview.vue +8 -2
  238. package/src/components/fields/BuilderField.vue +15 -2
  239. package/src/components/fields/ImageEditorDialog.vue +7 -3
  240. package/src/components/fields/KeyValueField.vue +3 -2
  241. package/src/components/fields/ModalTablePicker.vue +7 -2
  242. package/src/components/fields/RepeaterField.vue +2 -3
  243. package/src/components/fields/RichEditorInput.vue +3 -0
  244. package/src/components/fields/item-actions.ts +31 -10
  245. package/src/components/form/FormBlock.vue +2 -1
  246. package/src/components/form/form-context.ts +2 -2
  247. package/src/components/kanban/KanbanBoard.vue +15 -3
  248. package/src/components/kanban/KanbanColumnHeader.vue +6 -4
  249. package/src/components/layout/SectionComponent.vue +10 -4
  250. package/src/components/panel/GlobalSearchPalette.vue +2 -0
  251. package/src/components/realtime/use-live-updates.ts +3 -1
  252. package/src/components/table/ColumnHeader.vue +23 -12
  253. package/src/components/table/ColumnManager.vue +12 -8
  254. package/src/components/table/ContentLayoutSort.vue +7 -1
  255. package/src/components/table/TableCellContent.vue +4 -2
  256. package/src/components/table/TablePagination.vue +12 -7
  257. package/src/components/table/cell-update.ts +6 -0
  258. package/src/components/ui/CommandAutoHighlight.vue +27 -0
  259. package/src/components/ui/DialogContent.vue +5 -1
  260. package/src/components/ui/PopoverContent.vue +5 -1
  261. package/src/components/ui/SheetContent.vue +5 -1
  262. package/src/components/ui/TooltipContent.vue +5 -1
  263. package/src/context.ts +10 -0
  264. package/src/create-alfakit.ts +5 -0
  265. package/src/index.ts +2 -0
  266. package/src/layouts/lazy-layouts.ts +14 -0
  267. package/src/layouts/panel-layouts.ts +17 -0
  268. package/src/lib/lazy.ts +11 -1
  269. package/src/pages/PageShell.vue +5 -6
  270. package/src/standalone/AlfakitComponent.vue +17 -6
  271. package/src/starter-kit/AlfakitStarterKitRoot.vue +12 -3
  272. package/src/starter-kit/dashboard-widgets.ts +93 -0
  273. package/src/starter-kit/index.ts +7 -1
  274. package/src/starter-kit/runtime.ts +17 -1
  275. package/src/starter-kit/starter-kit.ts +2 -1
  276. package/src/starter-kit/widgets/CopilotTrigger.vue +58 -0
  277. package/src/starter-kit/widgets/LoadedCopilot.vue +29 -0
  278. package/src/starter-kit/widgets/StarterKitImpersonationBanner.vue +57 -0
  279. package/src/starter-kit/widgets/index.ts +56 -11
  280. package/src/starter-kit/widgets/loaded.ts +9 -0
  281. package/src/styles.css +9 -2
@@ -97,30 +97,32 @@ var ke = ["data-alfakit-modal"], Ae = { class: "flex flex-col gap-1.5" }, je = [
97
97
  };
98
98
  Ee(() => void E(We)), M(() => I.hidden, () => void E(We), { flush: "post" });
99
99
  let Ge = v(() => Be[xe(H.value)]), Ke = v(() => xe(H.value) === "end" ? "sm:me-auto" : void 0), qe = v(() => we(H.value.slideOverPosition, Ve.value)), Je = U ? ee(Te(U)) : null, q = v(() => be(H.value, Je?.value)), J = De(""), Ye = v(() => I.modal.errors[me]?.[0]), Xe = Se(V, B), Ze = (e) => {
100
+ U ? U.whenSettled(() => Qe(e)) : Qe(e);
101
+ }, Qe = (e) => {
100
102
  let t = U?.state.values ?? {}, n = {
101
103
  ...H.value.passwordConfirmation ? { password: J.value } : {},
102
104
  ...e ? { createAnother: !0 } : {}
103
105
  };
104
106
  Object.keys(n).length > 0 ? L.execute(B, V, t, n) : L.execute(B, V, t);
105
- }, Y = () => Ze(!1), X = () => Ze(!0);
107
+ }, Y = () => Ze(!1), $e = () => Ze(!0);
106
108
  M(() => H.value.form, (e, t) => {
107
109
  e && e !== t && U?.fill(e);
108
110
  }), M(() => I.modal.refocus, (e, t, n) => {
109
111
  let r = H.value.form?.components;
110
112
  e && r && n(Ce(() => document.getElementById(`action-form-${B.name}`), r));
111
113
  });
112
- let Qe = () => L.cancelModal(B.name), $e = z("unsaved_changes_close", {}, "You have unsaved changes. Close anyway?"), Z = () => {
113
- _e(H.value, U, $e) && Qe();
114
+ let et = () => L.cancelModal(B.name), X = z("unsaved_changes_close", {}, "You have unsaved changes. Close anyway?"), Z = () => {
115
+ _e(H.value, U, X) && et();
114
116
  };
115
- O(ye(H.value, U, $e));
116
- let et = v(() => H.value.cancelColor ? a(s, H.value.cancelColor) : ""), tt = v(() => H.value.createAnotherColor ? a(s, H.value.createAnotherColor) : ""), Q = v(() => H.value.heading ?? B.label ?? z("actions", {}, "Actions")), nt = (e) => {
117
+ O(ye(H.value, U, X));
118
+ let tt = v(() => H.value.cancelColor ? a(s, H.value.cancelColor) : ""), nt = v(() => H.value.createAnotherColor ? a(s, H.value.createAnotherColor) : ""), Q = v(() => H.value.heading ?? B.label ?? z("actions", {}, "Actions")), rt = (e) => {
117
119
  !e && !I.modal.processing && Z();
118
- }, $ = v(() => !!(H.value.submitLabel || H.value.cancelLabel || H.value.extraFooterActions?.length)), rt = v(() => !!(H.value.content || U || H.value.contentFooter || H.value.passwordConfirmation));
120
+ }, $ = v(() => !!(H.value.submitLabel || H.value.cancelLabel || H.value.extraFooterActions?.length)), it = v(() => !!(H.value.content || U || H.value.contentFooter || H.value.passwordConfirmation));
119
121
  return (e, t) => H.value.slideOver ? (k(), y(se, {
120
122
  key: 0,
121
123
  open: !I.hidden,
122
124
  modal: !H.value.clickThrough,
123
- "onUpdate:open": nt
125
+ "onUpdate:open": rt
124
126
  }, {
125
127
  default: N(() => [w(ce, {
126
128
  side: qe.value,
@@ -210,7 +212,7 @@ var ke = ["data-alfakit-modal"], Ae = { class: "flex flex-col gap-1.5" }, je = [
210
212
  key: 1,
211
213
  type: "button",
212
214
  variant: "outline",
213
- class: D(et.value),
215
+ class: D(tt.value),
214
216
  disabled: I.modal.processing,
215
217
  onClick: Z
216
218
  }, {
@@ -222,9 +224,9 @@ var ke = ["data-alfakit-modal"], Ae = { class: "flex flex-col gap-1.5" }, je = [
222
224
  type: "button",
223
225
  variant: "outline",
224
226
  "data-slot": "create-another",
225
- class: D(tt.value),
227
+ class: D(nt.value),
226
228
  disabled: I.modal.processing,
227
- onClick: X
229
+ onClick: $e
228
230
  }, {
229
231
  default: N(() => [H.value.createAnotherIcon ? (k(), y(j(l), {
230
232
  key: 0,
@@ -265,7 +267,7 @@ var ke = ["data-alfakit-modal"], Ae = { class: "flex flex-col gap-1.5" }, je = [
265
267
  key: 1,
266
268
  open: !I.hidden,
267
269
  modal: !H.value.clickThrough,
268
- "onUpdate:open": nt
270
+ "onUpdate:open": rt
269
271
  }, {
270
272
  default: N(() => [w(ie, {
271
273
  class: D(j(i)("max-h-[calc(100vh-2rem)] overflow-y-auto", F[H.value.width] ?? "sm:max-w-lg", G.value)),
@@ -300,7 +302,7 @@ var ke = ["data-alfakit-modal"], Ae = { class: "flex flex-col gap-1.5" }, je = [
300
302
  }))])], 2)]),
301
303
  _: 1
302
304
  }, 8, ["class"]),
303
- rt.value ? (k(), x("div", Re, [
305
+ it.value ? (k(), x("div", Re, [
304
306
  H.value.content ? (k(), y(p, {
305
307
  key: 0,
306
308
  components: H.value.content
@@ -354,7 +356,7 @@ var ke = ["data-alfakit-modal"], Ae = { class: "flex flex-col gap-1.5" }, je = [
354
356
  key: 1,
355
357
  type: "button",
356
358
  variant: "outline",
357
- class: D(et.value),
359
+ class: D(tt.value),
358
360
  disabled: I.modal.processing,
359
361
  onClick: Z
360
362
  }, {
@@ -366,9 +368,9 @@ var ke = ["data-alfakit-modal"], Ae = { class: "flex flex-col gap-1.5" }, je = [
366
368
  type: "button",
367
369
  variant: "outline",
368
370
  "data-slot": "create-another",
369
- class: D(tt.value),
371
+ class: D(nt.value),
370
372
  disabled: I.modal.processing,
371
- onClick: X
373
+ onClick: $e
372
374
  }, {
373
375
  default: N(() => [H.value.createAnotherIcon ? (k(), y(j(l), {
374
376
  key: 0,
@@ -1 +1 @@
1
- {"version":3,"file":"ActionModal.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createBlock","Sheet","_withCtx","_createVNode","SheetContent","_normalizeClass","_unref","_createElementVNode","SheetHeader","_createElementBlock","Icon","_createCommentVNode","SheetTitle","_createTextVNode","_toDisplayString","SheetDescription","SchemaRenderer","Slot","_withModifiers","ActionModalPassword","SheetFooter","ActionList","Button","Spinner","Dialog","DialogContent","DialogHeader","DialogTitle","DialogDescription","DialogFooter","Icon_default","Button_default","Spinner_default","ActionList_default","SchemaRenderer_default","Slot_default","Dialog_default","DialogContent_default","DialogDescription_default","DialogHeader_default","DialogTitle_default","Sheet_default","SheetContent_default","SheetDescription_default","SheetHeader_default","SheetTitle_default","DialogFooter_default","SheetFooter_default","ActionModalPassword_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_6","_hoisted_7","_hoisted_8","_hoisted_9","_hoisted_10","_hoisted_11","ActionModal_vue_vue_type_script_setup_true_lang_default","WIDTHS","FOOTER_JUSTIFY","props","__props","runner","useActionRunner","panel","usePanel","direction","useDirection","t","useT","action","context","schema","computed","form","FormStore","actionFormComponent","formIdPrefix","notifications","showToast","n","actionFormParams","provideForm","formState","useStore","watch","errors","onScopeDispose","windowClass","windowAttributes","_class","rest","modalId","useId","setAttributes","name","value","attributes","element","applyOverlayAttributes","overlay","onMounted","nextTick","footerJustify","modalFooterAlignment","footerActionsClass","side","slideOverSide","progress","wizardProgressStore","submitVisible","isModalSubmitVisible","password","ref","passwordError","PASSWORD_CONFIRMATION_INPUT","footerContext","nestedActionContext","run","values","options","createAnother","submit","submitAnother","payload","previous","components","refocus","onCleanup","scheduleAutofocus","close","unsavedMessage","requestClose","confirmModalClose","guardModalUnload","cancelClass","colorClass","outlineButtonColorClasses","createAnotherClass","title","onOpenChange","open","hasFooter","hasBody","openBlock","createBlock","withCtx","createVNode","normalizeClass","unref","cn","_cache","event","createElementVNode","createElementBlock","iconBackgroundColorClasses","createCommentVNode","createTextVNode","toDisplayString","withModifiers","$event","solidButtonColorClasses"],"sources":["../../../src/components/actions/ActionModal.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { OpenModal } from '@alfakit/core'\nimport {\n actionFormComponent,\n formIdPrefix,\n actionFormParams,\n confirmModalClose,\n FormStore,\n guardModalUnload,\n isModalSubmitVisible,\n modalFooterAlignment,\n nestedActionContext,\n PASSWORD_CONFIRMATION_INPUT,\n scheduleAutofocus,\n slideOverSide,\n wizardProgressStore,\n} from '@alfakit/core'\nimport { computed, nextTick, onMounted, onScopeDispose, ref, useId, watch } from 'vue'\nimport { useStore } from '../../composables/use-store'\nimport { useActionRunner, useDirection, usePanel, useT } from '../../context'\nimport {\n colorClass,\n iconBackgroundColorClasses,\n outlineButtonColorClasses,\n solidButtonColorClasses,\n} from '../../lib/colors'\nimport { Icon } from '../../lib/icons'\nimport { cn } from '../../lib/utils'\nimport { provideForm } from '../form/form-context'\nimport Slot from '../panel/Slot.vue'\nimport SchemaRenderer from '../schema/SchemaRenderer.vue'\nimport Button from '../ui/Button.vue'\nimport Dialog from '../ui/Dialog.vue'\nimport DialogContent from '../ui/DialogContent.vue'\nimport DialogDescription from '../ui/DialogDescription.vue'\nimport DialogFooter from '../ui/DialogFooter.vue'\nimport DialogHeader from '../ui/DialogHeader.vue'\nimport DialogTitle from '../ui/DialogTitle.vue'\nimport Sheet from '../ui/Sheet.vue'\nimport SheetContent from '../ui/SheetContent.vue'\nimport SheetDescription from '../ui/SheetDescription.vue'\nimport SheetFooter from '../ui/SheetFooter.vue'\nimport SheetHeader from '../ui/SheetHeader.vue'\nimport SheetTitle from '../ui/SheetTitle.vue'\nimport Spinner from '../ui/Spinner.vue'\nimport ActionList from './ActionList.vue'\nimport ActionModalPassword from './ActionModalPassword.vue'\nimport { showToast } from '../notifications/flash-toasts'\n\nconst WIDTHS: Record<string, string> = {\n '3xs': 'sm:max-w-3xs',\n '2xs': 'sm:max-w-2xs',\n xs: 'sm:max-w-xs',\n sm: 'sm:max-w-sm',\n md: 'sm:max-w-md',\n lg: 'sm:max-w-lg',\n xl: 'sm:max-w-xl',\n '2xl': 'sm:max-w-2xl',\n '3xl': 'sm:max-w-3xl',\n '4xl': 'sm:max-w-4xl',\n '5xl': 'sm:max-w-5xl',\n '6xl': 'sm:max-w-6xl',\n '7xl': 'sm:max-w-7xl',\n none: 'sm:max-w-none',\n min: 'sm:max-w-min',\n max: 'sm:max-w-max',\n fit: 'sm:max-w-fit',\n prose: 'sm:max-w-prose',\n container: 'sm:container',\n 'screen-sm': 'sm:max-w-(--breakpoint-sm)',\n 'screen-md': 'sm:max-w-(--breakpoint-md)',\n 'screen-lg': 'sm:max-w-(--breakpoint-lg)',\n 'screen-xl': 'sm:max-w-(--breakpoint-xl)',\n 'screen-2xl': 'sm:max-w-(--breakpoint-2xl)',\n full: 'sm:max-w-[calc(100%-2rem)]',\n screen: 'sm:max-w-[calc(100%-2rem)] h-[calc(100%-2rem)]',\n}\n\nconst FOOTER_JUSTIFY: Record<string, string> = {\n start: 'sm:justify-start',\n center: 'sm:justify-center',\n end: 'sm:justify-end',\n between: 'sm:justify-between',\n}\n\nconst props = withDefaults(defineProps<{ modal: OpenModal; hidden?: boolean }>(), {\n hidden: false,\n})\n\nconst runner = useActionRunner()\nconst panel = usePanel()\nconst direction = useDirection()\nconst t = useT()\n\nconst action = props.modal.action\nconst context = props.modal.context\nconst schema = computed(() => props.modal.modal)\n\nconst form = (() => {\n if (!schema.value.form) {\n return null\n }\n\n return new FormStore(schema.value.form, {\n token: context.token,\n component: actionFormComponent(action, context),\n // Own field ids: the modal opens over a form whose fields may share names.\n idPrefix: formIdPrefix(actionFormComponent(action, context)),\n record: context.record ?? null,\n refreshUrl: panel.value.endpoints.schemaRefresh,\n optionsUrl: panel.value.endpoints.schemaOptions,\n validateUrl: panel.value.endpoints.schemaValidate,\n // A halted wizard step shows what its hook sent.\n onNotifications: (notifications) => notifications.forEach((n) => showToast(n)),\n params: actionFormParams(context),\n })\n})()\n\nif (form) {\n provideForm(form)\n}\n\nconst formState = form ? useStore(form.store) : null\n\nwatch(\n () => props.modal.errors,\n (errors) => form?.setErrors(errors),\n { immediate: true },\n)\n\nonScopeDispose(() => form?.destroy())\n\n// Nested actions read this form (`$mountedActions`, `getRawData()`) and write into it\n// (`fillData()`).\nif (form) {\n onScopeDispose(runner.registerModalForm(action, context, form))\n}\n\n// `extraModalWindowAttributes()`: `class` joins the window's classes.\nconst windowClass = computed(() => schema.value.windowAttributes?.class as string | undefined)\nconst windowAttributes = computed(() => {\n const { class: _class, ...rest } = schema.value.windowAttributes ?? {}\n\n return rest\n})\n\n// `extraModalOverlayAttributes()`: the backdrop is the content's previous sibling.\nconst modalId = useId()\n\n// A marker inside the content finds the window and its backdrop (the dialog primitives\n// render through a portal and don't pass other attributes on).\nconst setAttributes = (element: Element, attributes: Record<string, unknown>) => {\n for (const [name, value] of Object.entries(attributes)) {\n if (value === null || value === undefined || value === false) continue\n\n if (name === 'class') {\n element.classList.add(...String(value).split(/\\s+/).filter(Boolean))\n } else {\n element.setAttribute(name, value === true ? '' : String(value))\n }\n }\n}\n\nconst applyOverlayAttributes = () => {\n if (props.hidden || typeof document === 'undefined') return\n\n const element = document\n .querySelector(`[data-alfakit-modal=\"${modalId}\"]`)\n ?.closest('[role=\"dialog\"]')\n const overlay = element?.previousElementSibling\n\n if (element) setAttributes(element, windowAttributes.value)\n\n if (overlay?.getAttribute('data-slot')?.endsWith('-overlay') && schema.value.overlayAttributes) {\n setAttributes(overlay, schema.value.overlayAttributes)\n }\n}\n\nonMounted(() => void nextTick(applyOverlayAttributes))\nwatch(\n () => props.hidden,\n () => void nextTick(applyOverlayAttributes),\n { flush: 'post' },\n)\n\nconst footerJustify = computed(() => FOOTER_JUSTIFY[modalFooterAlignment(schema.value)])\nconst footerActionsClass = computed(() =>\n modalFooterAlignment(schema.value) === 'end' ? 'sm:me-auto' : undefined,\n)\nconst side = computed(() => slideOverSide(schema.value.slideOverPosition, direction.value))\n\n// A wizard form reports its step, so the submit button waits for the last one.\nconst progress = form ? useStore(wizardProgressStore(form)) : null\nconst submitVisible = computed(() => isModalSubmitVisible(schema.value, progress?.value))\n\nconst password = ref('')\nconst passwordError = computed(() => props.modal.errors[PASSWORD_CONFIRMATION_INPUT]?.[0])\nconst footerContext = nestedActionContext(context, action)\n\nconst run = (createAnother: boolean) => {\n const values = form?.state.values ?? {}\n const options = {\n ...(schema.value.passwordConfirmation ? { password: password.value } : {}),\n ...(createAnother ? { createAnother: true } : {}),\n }\n\n if (Object.keys(options).length > 0) {\n runner.execute(action, context, values, options)\n } else {\n runner.execute(action, context, values)\n }\n}\nconst submit = () => run(false)\n// \"Create & create another\": the runner reloads the modal, and its fresh form fills this one.\nconst submitAnother = () => run(true)\n\nwatch(\n () => schema.value.form,\n (payload, previous) => {\n if (payload && payload !== previous) form?.fill(payload)\n },\n)\n\n// \"Create & create another\": back to the `autofocus()` field of the fresh form.\nwatch(\n () => props.modal.refocus,\n (refocus, _previous, onCleanup) => {\n const components = schema.value.form?.components\n\n if (!refocus || !components) return\n\n onCleanup(\n scheduleAutofocus(() => document.getElementById(`action-form-${action.name}`), components),\n )\n },\n)\n\n// Dismissing the modal (not submitting it): `cancelParentActionsOnClose()` applies.\nconst close = () => runner.cancelModal(action.name)\nconst unsavedMessage = t('unsaved_changes_close', {}, 'You have unsaved changes. Close anyway?')\n// Cancel, Escape, clicking away and the close button ask first when the form changed.\nconst requestClose = () => {\n if (confirmModalClose(schema.value, form, unsavedMessage)) close()\n}\nonScopeDispose(guardModalUnload(schema.value, form, unsavedMessage))\nconst cancelClass = computed(() =>\n schema.value.cancelColor ? colorClass(outlineButtonColorClasses, schema.value.cancelColor) : '',\n)\n// `createAnotherAction()`: the \"Create & create another\" button's colour.\nconst createAnotherClass = computed(() =>\n schema.value.createAnotherColor\n ? colorClass(outlineButtonColorClasses, schema.value.createAnotherColor)\n : '',\n)\n// Every dialog needs an accessible name: without a heading it stays visually hidden.\nconst title = computed(() => schema.value.heading ?? action.label ?? t('actions', {}, 'Actions'))\n\nconst onOpenChange = (open: boolean) => {\n if (!open && !props.modal.processing) {\n requestClose()\n }\n}\n\nconst hasFooter = computed(() =>\n Boolean(\n schema.value.submitLabel || schema.value.cancelLabel || schema.value.extraFooterActions?.length,\n ),\n)\nconst hasBody = computed(() =>\n Boolean(\n schema.value.content || form || schema.value.contentFooter || schema.value.passwordConfirmation,\n ),\n)\n</script>\n\n<template>\n <Sheet\n v-if=\"schema.slideOver\"\n :open=\"!props.hidden\"\n :modal=\"!schema.clickThrough\"\n @update:open=\"onOpenChange\"\n >\n <SheetContent\n :side=\"side\"\n :class=\"\n cn('flex w-full flex-col gap-0 p-0', WIDTHS[schema.width] ?? 'sm:max-w-md', windowClass)\n \"\n :show-close-button=\"schema.closeButton\"\n @interact-outside=\"(event) => !schema.closeByClickingAway && event.preventDefault()\"\n @escape-key-down=\"(event) => !schema.closeByEscaping && event.preventDefault()\"\n >\n <span :data-alfakit-modal=\"modalId\" hidden />\n <SheetHeader class=\"border-b\">\n <div\n :class=\"\n cn('flex gap-4', schema.alignment === 'center' && 'flex-col items-center text-center')\n \"\n >\n <div\n v-if=\"schema.icon\"\n :class=\"\n cn(\n 'flex size-10 shrink-0 items-center justify-center rounded-full',\n colorClass(iconBackgroundColorClasses, schema.iconColor, 'primary'),\n )\n \"\n >\n <Icon :name=\"schema.icon\" class=\"size-5\" />\n </div>\n <div class=\"flex flex-col gap-1.5\">\n <SheetTitle :class=\"cn(!schema.heading && 'sr-only')\">{{ title }}</SheetTitle>\n <SheetDescription v-if=\"schema.description\"\n ><span v-html=\"schema.description\"\n /></SheetDescription>\n <SheetDescription v-else class=\"sr-only\">{{ title }}</SheetDescription>\n </div>\n </div>\n </SheetHeader>\n <div class=\"flex-1 overflow-y-auto p-4\">\n <div class=\"flex flex-col gap-6\">\n <SchemaRenderer v-if=\"schema.content\" :components=\"schema.content\" />\n <Slot\n v-if=\"form && formState\"\n name=\"modal.schema.before\"\n :data=\"{ action: action.name }\"\n />\n <form\n v-if=\"form && formState\"\n :id=\"`action-form-${action.name}`\"\n @submit.prevent=\"submit\"\n >\n <SchemaRenderer :components=\"formState.components\" :columns=\"formState.columns\" />\n </form>\n <Slot\n v-if=\"form && formState\"\n name=\"modal.schema.after\"\n :data=\"{ action: action.name }\"\n />\n <SchemaRenderer v-if=\"schema.contentFooter\" :components=\"schema.contentFooter\" />\n <ActionModalPassword\n v-if=\"schema.passwordConfirmation\"\n v-model=\"password\"\n :error=\"passwordError\"\n @submit=\"submit\"\n />\n </div>\n </div>\n <SheetFooter\n v-if=\"hasFooter\"\n :class=\"cn('border-t', schema.stickyFooter && 'bg-background sticky bottom-0')\"\n >\n <div\n :class=\"\n cn('flex w-full flex-col-reverse gap-2 sm:flex-row sm:items-center', footerJustify)\n \"\n >\n <ActionList\n v-if=\"schema.extraFooterActions\"\n :actions=\"schema.extraFooterActions\"\n :context=\"footerContext\"\n :class=\"footerActionsClass\"\n />\n <Button\n v-if=\"schema.cancelLabel\"\n type=\"button\"\n variant=\"outline\"\n :class=\"cancelClass\"\n :disabled=\"props.modal.processing\"\n @click=\"requestClose\"\n >{{ schema.cancelLabel }}</Button\n >\n <Button\n v-if=\"schema.createAnotherLabel && schema.submitLabel && submitVisible\"\n type=\"button\"\n variant=\"outline\"\n data-slot=\"create-another\"\n :class=\"createAnotherClass\"\n :disabled=\"props.modal.processing\"\n @click=\"submitAnother\"\n ><Icon v-if=\"schema.createAnotherIcon\" :name=\"schema.createAnotherIcon\" />{{\n schema.createAnotherLabel\n }}</Button\n >\n <Button\n v-if=\"schema.submitLabel && submitVisible\"\n type=\"button\"\n :class=\"colorClass(solidButtonColorClasses, schema.submitColor, 'primary')\"\n :disabled=\"props.modal.processing\"\n :autofocus=\"schema.autofocus && !form\"\n @click=\"submit\"\n >\n <Spinner v-if=\"props.modal.processing\" />\n <Icon v-else-if=\"schema.submitIcon\" :name=\"schema.submitIcon\" />\n {{ schema.submitLabel }}\n </Button>\n </div>\n </SheetFooter>\n </SheetContent>\n </Sheet>\n <Dialog v-else :open=\"!props.hidden\" :modal=\"!schema.clickThrough\" @update:open=\"onOpenChange\">\n <DialogContent\n :class=\"\n cn(\n 'max-h-[calc(100vh-2rem)] overflow-y-auto',\n WIDTHS[schema.width] ?? 'sm:max-w-lg',\n windowClass,\n )\n \"\n :show-close-button=\"schema.closeButton\"\n @interact-outside=\"(event) => !schema.closeByClickingAway && event.preventDefault()\"\n @escape-key-down=\"(event) => !schema.closeByEscaping && event.preventDefault()\"\n >\n <span :data-alfakit-modal=\"modalId\" hidden />\n <!-- A sticky header stays pinned to the top of the scrolling dialog, edge to edge. -->\n <DialogHeader\n :class=\"\n cn(\n schema.stickyHeader &&\n 'bg-background sticky -top-6 z-10 -mx-6 -mt-6 rounded-t-lg border-b px-6 pt-6 pb-4',\n )\n \"\n >\n <div\n :class=\"\n cn('flex gap-4', schema.alignment === 'center' && 'flex-col items-center text-center')\n \"\n >\n <div\n v-if=\"schema.icon\"\n :class=\"\n cn(\n 'flex size-10 shrink-0 items-center justify-center rounded-full',\n colorClass(iconBackgroundColorClasses, schema.iconColor, 'primary'),\n )\n \"\n >\n <Icon :name=\"schema.icon\" class=\"size-5\" />\n </div>\n <div class=\"flex flex-col gap-1.5\">\n <DialogTitle :class=\"cn(!schema.heading && 'sr-only')\">{{ title }}</DialogTitle>\n <DialogDescription v-if=\"schema.description\"\n ><span v-html=\"schema.description\"\n /></DialogDescription>\n <DialogDescription v-else class=\"sr-only\">{{ title }}</DialogDescription>\n </div>\n </div>\n </DialogHeader>\n <div v-if=\"hasBody\" class=\"flex flex-col gap-6\">\n <SchemaRenderer v-if=\"schema.content\" :components=\"schema.content\" />\n <Slot v-if=\"form && formState\" name=\"modal.schema.before\" :data=\"{ action: action.name }\" />\n <form v-if=\"form && formState\" :id=\"`action-form-${action.name}`\" @submit.prevent=\"submit\">\n <SchemaRenderer :components=\"formState.components\" :columns=\"formState.columns\" />\n </form>\n <Slot v-if=\"form && formState\" name=\"modal.schema.after\" :data=\"{ action: action.name }\" />\n <SchemaRenderer v-if=\"schema.contentFooter\" :components=\"schema.contentFooter\" />\n <ActionModalPassword\n v-if=\"schema.passwordConfirmation\"\n v-model=\"password\"\n :error=\"passwordError\"\n @submit=\"submit\"\n />\n </div>\n <!-- A sticky footer stays pinned to the bottom of the scrolling dialog, edge to edge. -->\n <DialogFooter\n v-if=\"hasFooter\"\n :class=\"\n cn(\n schema.stickyFooter &&\n 'bg-background sticky bottom-0 -mx-6 -mb-6 rounded-b-lg border-t px-6 py-4',\n )\n \"\n >\n <div\n :class=\"\n cn('flex w-full flex-col-reverse gap-2 sm:flex-row sm:items-center', footerJustify)\n \"\n >\n <ActionList\n v-if=\"schema.extraFooterActions\"\n :actions=\"schema.extraFooterActions\"\n :context=\"footerContext\"\n :class=\"footerActionsClass\"\n />\n <Button\n v-if=\"schema.cancelLabel\"\n type=\"button\"\n variant=\"outline\"\n :class=\"cancelClass\"\n :disabled=\"props.modal.processing\"\n @click=\"requestClose\"\n >{{ schema.cancelLabel }}</Button\n >\n <Button\n v-if=\"schema.createAnotherLabel && schema.submitLabel && submitVisible\"\n type=\"button\"\n variant=\"outline\"\n data-slot=\"create-another\"\n :class=\"createAnotherClass\"\n :disabled=\"props.modal.processing\"\n @click=\"submitAnother\"\n ><Icon v-if=\"schema.createAnotherIcon\" :name=\"schema.createAnotherIcon\" />{{\n schema.createAnotherLabel\n }}</Button\n >\n <Button\n v-if=\"schema.submitLabel && submitVisible\"\n type=\"button\"\n :class=\"colorClass(solidButtonColorClasses, schema.submitColor, 'primary')\"\n :disabled=\"props.modal.processing\"\n :autofocus=\"schema.autofocus && !form\"\n @click=\"submit\"\n >\n <Spinner v-if=\"props.modal.processing\" />\n <Icon v-else-if=\"schema.submitIcon\" :name=\"schema.submitIcon\" />\n {{ schema.submitLabel }}\n </Button>\n </div>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"ActionModal.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createBlock","Sheet","_withCtx","_createVNode","SheetContent","_normalizeClass","_unref","_createElementVNode","SheetHeader","_createElementBlock","Icon","_createCommentVNode","SheetTitle","_createTextVNode","_toDisplayString","SheetDescription","SchemaRenderer","Slot","_withModifiers","ActionModalPassword","SheetFooter","ActionList","Button","Spinner","Dialog","DialogContent","DialogHeader","DialogTitle","DialogDescription","DialogFooter","Icon_default","Button_default","Spinner_default","ActionList_default","SchemaRenderer_default","Slot_default","Dialog_default","DialogContent_default","DialogDescription_default","DialogHeader_default","DialogTitle_default","Sheet_default","SheetContent_default","SheetDescription_default","SheetHeader_default","SheetTitle_default","DialogFooter_default","SheetFooter_default","ActionModalPassword_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_6","_hoisted_7","_hoisted_8","_hoisted_9","_hoisted_10","_hoisted_11","ActionModal_vue_vue_type_script_setup_true_lang_default","WIDTHS","FOOTER_JUSTIFY","props","__props","runner","useActionRunner","panel","usePanel","direction","useDirection","t","useT","action","context","schema","computed","form","FormStore","actionFormComponent","formIdPrefix","notifications","showToast","n","actionFormParams","provideForm","formState","useStore","watch","errors","onScopeDispose","windowClass","windowAttributes","_class","rest","modalId","useId","setAttributes","name","value","attributes","element","applyOverlayAttributes","overlay","onMounted","nextTick","footerJustify","modalFooterAlignment","footerActionsClass","side","slideOverSide","progress","wizardProgressStore","submitVisible","isModalSubmitVisible","password","ref","passwordError","PASSWORD_CONFIRMATION_INPUT","footerContext","nestedActionContext","run","execute","createAnother","values","options","submit","submitAnother","payload","previous","components","refocus","onCleanup","scheduleAutofocus","close","unsavedMessage","requestClose","confirmModalClose","guardModalUnload","cancelClass","colorClass","outlineButtonColorClasses","createAnotherClass","title","onOpenChange","open","hasFooter","hasBody","openBlock","createBlock","withCtx","createVNode","normalizeClass","unref","cn","_cache","event","createElementVNode","createElementBlock","iconBackgroundColorClasses","createCommentVNode","createTextVNode","toDisplayString","withModifiers","$event","solidButtonColorClasses"],"sources":["../../../src/components/actions/ActionModal.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { OpenModal } from '@alfakit/core'\nimport {\n actionFormComponent,\n formIdPrefix,\n actionFormParams,\n confirmModalClose,\n FormStore,\n guardModalUnload,\n isModalSubmitVisible,\n modalFooterAlignment,\n nestedActionContext,\n PASSWORD_CONFIRMATION_INPUT,\n scheduleAutofocus,\n slideOverSide,\n wizardProgressStore,\n} from '@alfakit/core'\nimport { computed, nextTick, onMounted, onScopeDispose, ref, useId, watch } from 'vue'\nimport { useStore } from '../../composables/use-store'\nimport { useActionRunner, useDirection, usePanel, useT } from '../../context'\nimport {\n colorClass,\n iconBackgroundColorClasses,\n outlineButtonColorClasses,\n solidButtonColorClasses,\n} from '../../lib/colors'\nimport { Icon } from '../../lib/icons'\nimport { cn } from '../../lib/utils'\nimport { provideForm } from '../form/form-context'\nimport Slot from '../panel/Slot.vue'\nimport SchemaRenderer from '../schema/SchemaRenderer.vue'\nimport Button from '../ui/Button.vue'\nimport Dialog from '../ui/Dialog.vue'\nimport DialogContent from '../ui/DialogContent.vue'\nimport DialogDescription from '../ui/DialogDescription.vue'\nimport DialogFooter from '../ui/DialogFooter.vue'\nimport DialogHeader from '../ui/DialogHeader.vue'\nimport DialogTitle from '../ui/DialogTitle.vue'\nimport Sheet from '../ui/Sheet.vue'\nimport SheetContent from '../ui/SheetContent.vue'\nimport SheetDescription from '../ui/SheetDescription.vue'\nimport SheetFooter from '../ui/SheetFooter.vue'\nimport SheetHeader from '../ui/SheetHeader.vue'\nimport SheetTitle from '../ui/SheetTitle.vue'\nimport Spinner from '../ui/Spinner.vue'\nimport ActionList from './ActionList.vue'\nimport ActionModalPassword from './ActionModalPassword.vue'\nimport { showToast } from '../notifications/flash-toasts'\n\nconst WIDTHS: Record<string, string> = {\n '3xs': 'sm:max-w-3xs',\n '2xs': 'sm:max-w-2xs',\n xs: 'sm:max-w-xs',\n sm: 'sm:max-w-sm',\n md: 'sm:max-w-md',\n lg: 'sm:max-w-lg',\n xl: 'sm:max-w-xl',\n '2xl': 'sm:max-w-2xl',\n '3xl': 'sm:max-w-3xl',\n '4xl': 'sm:max-w-4xl',\n '5xl': 'sm:max-w-5xl',\n '6xl': 'sm:max-w-6xl',\n '7xl': 'sm:max-w-7xl',\n none: 'sm:max-w-none',\n min: 'sm:max-w-min',\n max: 'sm:max-w-max',\n fit: 'sm:max-w-fit',\n prose: 'sm:max-w-prose',\n container: 'sm:container',\n 'screen-sm': 'sm:max-w-(--breakpoint-sm)',\n 'screen-md': 'sm:max-w-(--breakpoint-md)',\n 'screen-lg': 'sm:max-w-(--breakpoint-lg)',\n 'screen-xl': 'sm:max-w-(--breakpoint-xl)',\n 'screen-2xl': 'sm:max-w-(--breakpoint-2xl)',\n full: 'sm:max-w-[calc(100%-2rem)]',\n screen: 'sm:max-w-[calc(100%-2rem)] h-[calc(100%-2rem)]',\n}\n\nconst FOOTER_JUSTIFY: Record<string, string> = {\n start: 'sm:justify-start',\n center: 'sm:justify-center',\n end: 'sm:justify-end',\n between: 'sm:justify-between',\n}\n\nconst props = withDefaults(defineProps<{ modal: OpenModal; hidden?: boolean }>(), {\n hidden: false,\n})\n\nconst runner = useActionRunner()\nconst panel = usePanel()\nconst direction = useDirection()\nconst t = useT()\n\nconst action = props.modal.action\nconst context = props.modal.context\nconst schema = computed(() => props.modal.modal)\n\nconst form = (() => {\n if (!schema.value.form) {\n return null\n }\n\n return new FormStore(schema.value.form, {\n token: context.token,\n component: actionFormComponent(action, context),\n // Own field ids: the modal opens over a form whose fields may share names.\n idPrefix: formIdPrefix(actionFormComponent(action, context)),\n record: context.record ?? null,\n refreshUrl: panel.value.endpoints.schemaRefresh,\n optionsUrl: panel.value.endpoints.schemaOptions,\n validateUrl: panel.value.endpoints.schemaValidate,\n // A halted wizard step shows what its hook sent.\n onNotifications: (notifications) => notifications.forEach((n) => showToast(n)),\n params: actionFormParams(context),\n })\n})()\n\nif (form) {\n provideForm(form)\n}\n\nconst formState = form ? useStore(form.store) : null\n\nwatch(\n () => props.modal.errors,\n (errors) => form?.setErrors(errors),\n { immediate: true },\n)\n\nonScopeDispose(() => form?.destroy())\n\n// Nested actions read this form (`$mountedActions`, `getRawData()`) and write into it\n// (`fillData()`).\nif (form) {\n onScopeDispose(runner.registerModalForm(action, context, form))\n}\n\n// `extraModalWindowAttributes()`: `class` joins the window's classes.\nconst windowClass = computed(() => schema.value.windowAttributes?.class as string | undefined)\nconst windowAttributes = computed(() => {\n const { class: _class, ...rest } = schema.value.windowAttributes ?? {}\n\n return rest\n})\n\n// `extraModalOverlayAttributes()`: the backdrop is the content's previous sibling.\nconst modalId = useId()\n\n// A marker inside the content finds the window and its backdrop (the dialog primitives\n// render through a portal and don't pass other attributes on).\nconst setAttributes = (element: Element, attributes: Record<string, unknown>) => {\n for (const [name, value] of Object.entries(attributes)) {\n if (value === null || value === undefined || value === false) continue\n\n if (name === 'class') {\n element.classList.add(...String(value).split(/\\s+/).filter(Boolean))\n } else {\n element.setAttribute(name, value === true ? '' : String(value))\n }\n }\n}\n\nconst applyOverlayAttributes = () => {\n if (props.hidden || typeof document === 'undefined') return\n\n const element = document\n .querySelector(`[data-alfakit-modal=\"${modalId}\"]`)\n ?.closest('[role=\"dialog\"]')\n const overlay = element?.previousElementSibling\n\n if (element) setAttributes(element, windowAttributes.value)\n\n if (overlay?.getAttribute('data-slot')?.endsWith('-overlay') && schema.value.overlayAttributes) {\n setAttributes(overlay, schema.value.overlayAttributes)\n }\n}\n\nonMounted(() => void nextTick(applyOverlayAttributes))\nwatch(\n () => props.hidden,\n () => void nextTick(applyOverlayAttributes),\n { flush: 'post' },\n)\n\nconst footerJustify = computed(() => FOOTER_JUSTIFY[modalFooterAlignment(schema.value)])\nconst footerActionsClass = computed(() =>\n modalFooterAlignment(schema.value) === 'end' ? 'sm:me-auto' : undefined,\n)\nconst side = computed(() => slideOverSide(schema.value.slideOverPosition, direction.value))\n\n// A wizard form reports its step, so the submit button waits for the last one.\nconst progress = form ? useStore(wizardProgressStore(form)) : null\nconst submitVisible = computed(() => isModalSubmitVisible(schema.value, progress?.value))\n\nconst password = ref('')\nconst passwordError = computed(() => props.modal.errors[PASSWORD_CONFIRMATION_INPUT]?.[0])\nconst footerContext = nestedActionContext(context, action)\n\nconst run = (createAnother: boolean) => {\n // A click that blurred a live field started a refresh: send the state it returns.\n if (form) {\n form.whenSettled(() => execute(createAnother))\n } else {\n execute(createAnother)\n }\n}\n\nconst execute = (createAnother: boolean) => {\n const values = form?.state.values ?? {}\n const options = {\n ...(schema.value.passwordConfirmation ? { password: password.value } : {}),\n ...(createAnother ? { createAnother: true } : {}),\n }\n\n if (Object.keys(options).length > 0) {\n runner.execute(action, context, values, options)\n } else {\n runner.execute(action, context, values)\n }\n}\nconst submit = () => run(false)\n// \"Create & create another\": the runner reloads the modal, and its fresh form fills this one.\nconst submitAnother = () => run(true)\n\nwatch(\n () => schema.value.form,\n (payload, previous) => {\n if (payload && payload !== previous) form?.fill(payload)\n },\n)\n\n// \"Create & create another\": back to the `autofocus()` field of the fresh form.\nwatch(\n () => props.modal.refocus,\n (refocus, _previous, onCleanup) => {\n const components = schema.value.form?.components\n\n if (!refocus || !components) return\n\n onCleanup(\n scheduleAutofocus(() => document.getElementById(`action-form-${action.name}`), components),\n )\n },\n)\n\n// Dismissing the modal (not submitting it): `cancelParentActionsOnClose()` applies.\nconst close = () => runner.cancelModal(action.name)\nconst unsavedMessage = t('unsaved_changes_close', {}, 'You have unsaved changes. Close anyway?')\n// Cancel, Escape, clicking away and the close button ask first when the form changed.\nconst requestClose = () => {\n if (confirmModalClose(schema.value, form, unsavedMessage)) close()\n}\nonScopeDispose(guardModalUnload(schema.value, form, unsavedMessage))\nconst cancelClass = computed(() =>\n schema.value.cancelColor ? colorClass(outlineButtonColorClasses, schema.value.cancelColor) : '',\n)\n// `createAnotherAction()`: the \"Create & create another\" button's colour.\nconst createAnotherClass = computed(() =>\n schema.value.createAnotherColor\n ? colorClass(outlineButtonColorClasses, schema.value.createAnotherColor)\n : '',\n)\n// Every dialog needs an accessible name: without a heading it stays visually hidden.\nconst title = computed(() => schema.value.heading ?? action.label ?? t('actions', {}, 'Actions'))\n\nconst onOpenChange = (open: boolean) => {\n if (!open && !props.modal.processing) {\n requestClose()\n }\n}\n\nconst hasFooter = computed(() =>\n Boolean(\n schema.value.submitLabel || schema.value.cancelLabel || schema.value.extraFooterActions?.length,\n ),\n)\nconst hasBody = computed(() =>\n Boolean(\n schema.value.content || form || schema.value.contentFooter || schema.value.passwordConfirmation,\n ),\n)\n</script>\n\n<template>\n <Sheet\n v-if=\"schema.slideOver\"\n :open=\"!props.hidden\"\n :modal=\"!schema.clickThrough\"\n @update:open=\"onOpenChange\"\n >\n <SheetContent\n :side=\"side\"\n :class=\"\n cn('flex w-full flex-col gap-0 p-0', WIDTHS[schema.width] ?? 'sm:max-w-md', windowClass)\n \"\n :show-close-button=\"schema.closeButton\"\n @interact-outside=\"(event) => !schema.closeByClickingAway && event.preventDefault()\"\n @escape-key-down=\"(event) => !schema.closeByEscaping && event.preventDefault()\"\n >\n <span :data-alfakit-modal=\"modalId\" hidden />\n <SheetHeader class=\"border-b\">\n <div\n :class=\"\n cn('flex gap-4', schema.alignment === 'center' && 'flex-col items-center text-center')\n \"\n >\n <div\n v-if=\"schema.icon\"\n :class=\"\n cn(\n 'flex size-10 shrink-0 items-center justify-center rounded-full',\n colorClass(iconBackgroundColorClasses, schema.iconColor, 'primary'),\n )\n \"\n >\n <Icon :name=\"schema.icon\" class=\"size-5\" />\n </div>\n <div class=\"flex flex-col gap-1.5\">\n <SheetTitle :class=\"cn(!schema.heading && 'sr-only')\">{{ title }}</SheetTitle>\n <SheetDescription v-if=\"schema.description\"\n ><span v-html=\"schema.description\"\n /></SheetDescription>\n <SheetDescription v-else class=\"sr-only\">{{ title }}</SheetDescription>\n </div>\n </div>\n </SheetHeader>\n <div class=\"flex-1 overflow-y-auto p-4\">\n <div class=\"flex flex-col gap-6\">\n <SchemaRenderer v-if=\"schema.content\" :components=\"schema.content\" />\n <Slot\n v-if=\"form && formState\"\n name=\"modal.schema.before\"\n :data=\"{ action: action.name }\"\n />\n <form\n v-if=\"form && formState\"\n :id=\"`action-form-${action.name}`\"\n @submit.prevent=\"submit\"\n >\n <SchemaRenderer :components=\"formState.components\" :columns=\"formState.columns\" />\n </form>\n <Slot\n v-if=\"form && formState\"\n name=\"modal.schema.after\"\n :data=\"{ action: action.name }\"\n />\n <SchemaRenderer v-if=\"schema.contentFooter\" :components=\"schema.contentFooter\" />\n <ActionModalPassword\n v-if=\"schema.passwordConfirmation\"\n v-model=\"password\"\n :error=\"passwordError\"\n @submit=\"submit\"\n />\n </div>\n </div>\n <SheetFooter\n v-if=\"hasFooter\"\n :class=\"cn('border-t', schema.stickyFooter && 'bg-background sticky bottom-0')\"\n >\n <div\n :class=\"\n cn('flex w-full flex-col-reverse gap-2 sm:flex-row sm:items-center', footerJustify)\n \"\n >\n <ActionList\n v-if=\"schema.extraFooterActions\"\n :actions=\"schema.extraFooterActions\"\n :context=\"footerContext\"\n :class=\"footerActionsClass\"\n />\n <Button\n v-if=\"schema.cancelLabel\"\n type=\"button\"\n variant=\"outline\"\n :class=\"cancelClass\"\n :disabled=\"props.modal.processing\"\n @click=\"requestClose\"\n >{{ schema.cancelLabel }}</Button\n >\n <Button\n v-if=\"schema.createAnotherLabel && schema.submitLabel && submitVisible\"\n type=\"button\"\n variant=\"outline\"\n data-slot=\"create-another\"\n :class=\"createAnotherClass\"\n :disabled=\"props.modal.processing\"\n @click=\"submitAnother\"\n ><Icon v-if=\"schema.createAnotherIcon\" :name=\"schema.createAnotherIcon\" />{{\n schema.createAnotherLabel\n }}</Button\n >\n <Button\n v-if=\"schema.submitLabel && submitVisible\"\n type=\"button\"\n :class=\"colorClass(solidButtonColorClasses, schema.submitColor, 'primary')\"\n :disabled=\"props.modal.processing\"\n :autofocus=\"schema.autofocus && !form\"\n @click=\"submit\"\n >\n <Spinner v-if=\"props.modal.processing\" />\n <Icon v-else-if=\"schema.submitIcon\" :name=\"schema.submitIcon\" />\n {{ schema.submitLabel }}\n </Button>\n </div>\n </SheetFooter>\n </SheetContent>\n </Sheet>\n <Dialog v-else :open=\"!props.hidden\" :modal=\"!schema.clickThrough\" @update:open=\"onOpenChange\">\n <DialogContent\n :class=\"\n cn(\n 'max-h-[calc(100vh-2rem)] overflow-y-auto',\n WIDTHS[schema.width] ?? 'sm:max-w-lg',\n windowClass,\n )\n \"\n :show-close-button=\"schema.closeButton\"\n @interact-outside=\"(event) => !schema.closeByClickingAway && event.preventDefault()\"\n @escape-key-down=\"(event) => !schema.closeByEscaping && event.preventDefault()\"\n >\n <span :data-alfakit-modal=\"modalId\" hidden />\n <!-- A sticky header stays pinned to the top of the scrolling dialog, edge to edge. -->\n <DialogHeader\n :class=\"\n cn(\n schema.stickyHeader &&\n 'bg-background sticky -top-6 z-10 -mx-6 -mt-6 rounded-t-lg border-b px-6 pt-6 pb-4',\n )\n \"\n >\n <div\n :class=\"\n cn('flex gap-4', schema.alignment === 'center' && 'flex-col items-center text-center')\n \"\n >\n <div\n v-if=\"schema.icon\"\n :class=\"\n cn(\n 'flex size-10 shrink-0 items-center justify-center rounded-full',\n colorClass(iconBackgroundColorClasses, schema.iconColor, 'primary'),\n )\n \"\n >\n <Icon :name=\"schema.icon\" class=\"size-5\" />\n </div>\n <div class=\"flex flex-col gap-1.5\">\n <DialogTitle :class=\"cn(!schema.heading && 'sr-only')\">{{ title }}</DialogTitle>\n <DialogDescription v-if=\"schema.description\"\n ><span v-html=\"schema.description\"\n /></DialogDescription>\n <DialogDescription v-else class=\"sr-only\">{{ title }}</DialogDescription>\n </div>\n </div>\n </DialogHeader>\n <div v-if=\"hasBody\" class=\"flex flex-col gap-6\">\n <SchemaRenderer v-if=\"schema.content\" :components=\"schema.content\" />\n <Slot v-if=\"form && formState\" name=\"modal.schema.before\" :data=\"{ action: action.name }\" />\n <form v-if=\"form && formState\" :id=\"`action-form-${action.name}`\" @submit.prevent=\"submit\">\n <SchemaRenderer :components=\"formState.components\" :columns=\"formState.columns\" />\n </form>\n <Slot v-if=\"form && formState\" name=\"modal.schema.after\" :data=\"{ action: action.name }\" />\n <SchemaRenderer v-if=\"schema.contentFooter\" :components=\"schema.contentFooter\" />\n <ActionModalPassword\n v-if=\"schema.passwordConfirmation\"\n v-model=\"password\"\n :error=\"passwordError\"\n @submit=\"submit\"\n />\n </div>\n <!-- A sticky footer stays pinned to the bottom of the scrolling dialog, edge to edge. -->\n <DialogFooter\n v-if=\"hasFooter\"\n :class=\"\n cn(\n schema.stickyFooter &&\n 'bg-background sticky bottom-0 -mx-6 -mb-6 rounded-b-lg border-t px-6 py-4',\n )\n \"\n >\n <div\n :class=\"\n cn('flex w-full flex-col-reverse gap-2 sm:flex-row sm:items-center', footerJustify)\n \"\n >\n <ActionList\n v-if=\"schema.extraFooterActions\"\n :actions=\"schema.extraFooterActions\"\n :context=\"footerContext\"\n :class=\"footerActionsClass\"\n />\n <Button\n v-if=\"schema.cancelLabel\"\n type=\"button\"\n variant=\"outline\"\n :class=\"cancelClass\"\n :disabled=\"props.modal.processing\"\n @click=\"requestClose\"\n >{{ schema.cancelLabel }}</Button\n >\n <Button\n v-if=\"schema.createAnotherLabel && schema.submitLabel && submitVisible\"\n type=\"button\"\n variant=\"outline\"\n data-slot=\"create-another\"\n :class=\"createAnotherClass\"\n :disabled=\"props.modal.processing\"\n @click=\"submitAnother\"\n ><Icon v-if=\"schema.createAnotherIcon\" :name=\"schema.createAnotherIcon\" />{{\n schema.createAnotherLabel\n }}</Button\n >\n <Button\n v-if=\"schema.submitLabel && submitVisible\"\n type=\"button\"\n :class=\"colorClass(solidButtonColorClasses, schema.submitColor, 'primary')\"\n :disabled=\"props.modal.processing\"\n :autofocus=\"schema.autofocus && !form\"\n @click=\"submit\"\n >\n <Spinner v-if=\"props.modal.processing\" />\n <Icon v-else-if=\"schema.submitIcon\" :name=\"schema.submitIcon\" />\n {{ schema.submitLabel }}\n </Button>\n </div>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n</template>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"AiCopilot.js","names":["_sfc_main","AiCopilot_vue_vue_type_script_setup_true_lang_default","AiCopilot_default"],"sources":["../../../src/components/ai/AiCopilot.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { type AiCopilotSchema, CopilotController, shortcuts } from '@alfakit/core'\nimport { SparklesIcon } from '@lucide/vue'\nimport { computed, onBeforeUnmount, ref, shallowRef, watch } from 'vue'\nimport { useT } from '../../context'\nimport Button from '../ui/Button.vue'\nimport { CopilotPanel, preloadCopilotPanel } from './copilot-lazy'\n\n/**\n * The copilot of alfasix/alfakit-ai (`ai:copilot`): a topbar button (and `mod+j`) opening\n * a chat slide-over. Questions, tools and actions run on the server; proposed actions\n * run only when the user confirms them in the chat.\n */\nconst props = defineProps<{ component: AiCopilotSchema }>()\nconst t = useT()\n// One controller per panel: Inertia visits pass new props objects.\nconst controller = new CopilotController(props.component)\nconst state = shallowRef(controller.state)\nconst mounted = ref(false)\nconst label = computed(() => t('ai.open', {}, 'Open AI copilot'))\n\nconst unsubscribe = controller.subscribe((next) => {\n state.value = next\n\n if (next.open) mounted.value = true\n})\n\nlet unregister: (() => void) | undefined\n\nwatch(\n () => [JSON.stringify(props.component.keyBindings ?? []), label.value] as const,\n ([keys, text]) => {\n unregister?.()\n unregister = undefined\n\n const bindings = JSON.parse(keys) as string[]\n\n if (bindings.length === 0) return\n\n unregister = shortcuts.register({\n id: 'ai.copilot',\n keys: bindings,\n label: text,\n group: 'general',\n allowInInputs: true,\n handler: () => controller.toggle(),\n })\n },\n { immediate: true },\n)\n\nonBeforeUnmount(() => {\n unsubscribe()\n unregister?.()\n})\n</script>\n\n<template>\n <div v-if=\"props.component.canUse !== false\" data-slot=\"ai-copilot\" class=\"contents\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n data-slot=\"ai-copilot-trigger\"\n :aria-label=\"label\"\n :aria-expanded=\"state.open\"\n aria-haspopup=\"dialog\"\n :title=\"label\"\n @click=\"controller.open()\"\n @pointerenter=\"preloadCopilotPanel()\"\n @focus=\"preloadCopilotPanel()\"\n >\n <SparklesIcon aria-hidden=\"true\" />\n </Button>\n <CopilotPanel v-if=\"mounted\" :controller=\"controller\" />\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"AiCopilot.js","names":["_sfc_main","AiCopilot_vue_vue_type_script_setup_true_lang_default","AiCopilot_default"],"sources":["../../../src/components/ai/AiCopilot.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { type AiCopilotSchema, CopilotController, shortcuts } from '@alfakit/core'\nimport { SparklesIcon } from '@lucide/vue'\nimport { computed, onBeforeUnmount, ref, shallowRef, watch } from 'vue'\nimport { useT } from '../../context'\nimport Button from '../ui/Button.vue'\nimport { CopilotPanel, preloadCopilotPanel } from './copilot-lazy'\n\n/**\n * The copilot of alfasix/alfakit-ai (`ai:copilot`): a topbar button (and `mod+j`) opening\n * a chat slide-over. Questions, tools and actions run on the server; proposed actions\n * run only when the user confirms them in the chat.\n */\nconst props = defineProps<{\n component: AiCopilotSchema\n /** Open once mounted (starter kit header: clicked or `mod+j` before its code loaded). */\n autoOpen?: boolean\n}>()\nconst t = useT()\n// One controller per panel: Inertia visits pass new props objects.\nconst controller = new CopilotController(props.component)\nconst state = shallowRef(controller.state)\nconst mounted = ref(false)\nconst label = computed(() => t('ai.open', {}, 'Open AI copilot'))\n\nconst unsubscribe = controller.subscribe((next) => {\n state.value = next\n\n if (next.open) mounted.value = true\n})\n\nif (props.autoOpen && props.component.canUse !== false) controller.open()\n\nlet unregister: (() => void) | undefined\n\nwatch(\n () => [JSON.stringify(props.component.keyBindings ?? []), label.value] as const,\n ([keys, text]) => {\n unregister?.()\n unregister = undefined\n\n const bindings = JSON.parse(keys) as string[]\n\n if (bindings.length === 0) return\n\n unregister = shortcuts.register({\n id: 'ai.copilot',\n keys: bindings,\n label: text,\n group: 'general',\n allowInInputs: true,\n handler: () => controller.toggle(),\n })\n },\n { immediate: true },\n)\n\nonBeforeUnmount(() => {\n unsubscribe()\n unregister?.()\n})\n</script>\n\n<template>\n <div v-if=\"props.component.canUse !== false\" data-slot=\"ai-copilot\" class=\"contents\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n data-slot=\"ai-copilot-trigger\"\n :aria-label=\"label\"\n :aria-expanded=\"state.open\"\n aria-haspopup=\"dialog\"\n :title=\"label\"\n @click=\"controller.open()\"\n @pointerenter=\"preloadCopilotPanel()\"\n @focus=\"preloadCopilotPanel()\"\n >\n <SparklesIcon aria-hidden=\"true\" />\n </Button>\n <CopilotPanel v-if=\"mounted\" :controller=\"controller\" />\n </div>\n</template>\n"],"mappings":""}
@@ -6,6 +6,8 @@ import { type AiCopilotSchema } from '@alfakit/core';
6
6
  */
7
7
  type __VLS_Props = {
8
8
  component: AiCopilotSchema;
9
+ /** Open once mounted (starter kit header: clicked or `mod+j` before its code loaded). */
10
+ autoOpen?: boolean;
9
11
  };
10
12
  declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
11
13
  export default _default;
@@ -1 +1 @@
1
- {"version":3,"file":"AiCopilot.vue.d.ts","sourceRoot":"","sources":["../../../src/components/ai/AiCopilot.vue"],"names":[],"mappings":"AA+EA,OAAO,EAAE,KAAK,eAAe,EAAgC,MAAM,eAAe,CAAA;AAOlF;;;;GAIG;AACH,KAAK,WAAW,GAAG;IAAE,SAAS,EAAE,eAAe,CAAA;CAAE,CAAC;;AA0JlD,wBAMG"}
1
+ {"version":3,"file":"AiCopilot.vue.d.ts","sourceRoot":"","sources":["../../../src/components/ai/AiCopilot.vue"],"names":[],"mappings":"AAqFA,OAAO,EAAE,KAAK,eAAe,EAAgC,MAAM,eAAe,CAAA;AAOlF;;;;GAIG;AACH,KAAK,WAAW,GAAG;IACjB,SAAS,EAAE,eAAe,CAAA;IAC1B,yFAAyF;IACzF,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAC;;AA4JF,wBAMG"}
@@ -11,11 +11,16 @@ var b = {
11
11
  class: "contents"
12
12
  }, x = /*@__PURE__*/ d({
13
13
  __name: "AiCopilot",
14
- props: { component: {} },
14
+ props: {
15
+ component: {},
16
+ autoOpen: { type: Boolean }
17
+ },
15
18
  setup(d) {
16
19
  let x = d, S = e(), C = new i(x.component), w = h(C.state), T = m(!1), E = o(() => S("ai.open", {}, "Open AI copilot")), D = C.subscribe((e) => {
17
20
  w.value = e, e.open && (T.value = !0);
18
- }), O;
21
+ });
22
+ x.autoOpen && x.component.canUse !== !1 && C.open();
23
+ let O;
19
24
  return _(() => [JSON.stringify(x.component.keyBindings ?? []), E.value], ([e, t]) => {
20
25
  O?.(), O = void 0;
21
26
  let n = JSON.parse(e);
@@ -1 +1 @@
1
- {"version":3,"file":"AiCopilot.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_createVNode","Button","_unref","_withCtx","_createBlock","_createCommentVNode","Button_default","_hoisted_1","AiCopilot_vue_vue_type_script_setup_true_lang_default","props","__props","t","useT","controller","CopilotController","state","shallowRef","mounted","ref","label","computed","unsubscribe","next","unregister","watch","keys","text","bindings","shortcuts","onBeforeUnmount","createCommentVNode","openBlock","createElementBlock","createVNode","_cache","unref","preloadCopilotPanel","withCtx","SparklesIcon","createBlock","CopilotPanel"],"sources":["../../../src/components/ai/AiCopilot.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { type AiCopilotSchema, CopilotController, shortcuts } from '@alfakit/core'\nimport { SparklesIcon } from '@lucide/vue'\nimport { computed, onBeforeUnmount, ref, shallowRef, watch } from 'vue'\nimport { useT } from '../../context'\nimport Button from '../ui/Button.vue'\nimport { CopilotPanel, preloadCopilotPanel } from './copilot-lazy'\n\n/**\n * The copilot of alfasix/alfakit-ai (`ai:copilot`): a topbar button (and `mod+j`) opening\n * a chat slide-over. Questions, tools and actions run on the server; proposed actions\n * run only when the user confirms them in the chat.\n */\nconst props = defineProps<{ component: AiCopilotSchema }>()\nconst t = useT()\n// One controller per panel: Inertia visits pass new props objects.\nconst controller = new CopilotController(props.component)\nconst state = shallowRef(controller.state)\nconst mounted = ref(false)\nconst label = computed(() => t('ai.open', {}, 'Open AI copilot'))\n\nconst unsubscribe = controller.subscribe((next) => {\n state.value = next\n\n if (next.open) mounted.value = true\n})\n\nlet unregister: (() => void) | undefined\n\nwatch(\n () => [JSON.stringify(props.component.keyBindings ?? []), label.value] as const,\n ([keys, text]) => {\n unregister?.()\n unregister = undefined\n\n const bindings = JSON.parse(keys) as string[]\n\n if (bindings.length === 0) return\n\n unregister = shortcuts.register({\n id: 'ai.copilot',\n keys: bindings,\n label: text,\n group: 'general',\n allowInInputs: true,\n handler: () => controller.toggle(),\n })\n },\n { immediate: true },\n)\n\nonBeforeUnmount(() => {\n unsubscribe()\n unregister?.()\n})\n</script>\n\n<template>\n <div v-if=\"props.component.canUse !== false\" data-slot=\"ai-copilot\" class=\"contents\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n data-slot=\"ai-copilot-trigger\"\n :aria-label=\"label\"\n :aria-expanded=\"state.open\"\n aria-haspopup=\"dialog\"\n :title=\"label\"\n @click=\"controller.open()\"\n @pointerenter=\"preloadCopilotPanel()\"\n @focus=\"preloadCopilotPanel()\"\n >\n <SparklesIcon aria-hidden=\"true\" />\n </Button>\n <CopilotPanel v-if=\"mounted\" :controller=\"controller\" />\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;EAaA,IAAMW,IAAQC,GACRC,IAAIC,EAAK,GAETC,IAAa,IAAIC,EAAkBL,EAAM,SAAS,GAClDM,IAAQC,EAAWH,EAAW,KAAK,GACnCI,IAAUC,EAAI,EAAK,GACnBC,IAAQC,QAAeT,EAAE,WAAW,CAAC,GAAG,iBAAiB,CAAC,GAE1DU,IAAcR,EAAW,WAAW,MAAS;GAGjD,AAFA,EAAM,QAAQS,GAEVA,EAAK,SAAM,EAAQ,QAAQ;EACjC,CAAC,GAEGC;SAEJC,QACQ,CAAC,KAAK,UAAUf,EAAM,UAAU,eAAe,CAAC,CAAC,GAAGU,EAAM,KAAK,IACpE,CAACM,GAAMC,OAAU;GAEhB,AADAH,IAAa,GACb,IAAa,KAAA;GAEb,IAAMI,IAAW,KAAK,MAAMF,CAAI;GAEhC,AAAIE,EAAS,WAAW,MAExB,IAAaC,EAAU,SAAS;IAC9B,IAAI;IACJ,MAAMD;IACN,OAAOD;IACP,OAAO;IACP,eAAe;IACf,eAAeb,EAAW,OAAO;GACnC,CAAC;EACH,GACA,EAAE,WAAW,GAAK,CACpB,GAEAgB,QAAsB;GAEpB,AADAR,EAAY,GACZE,IAAa;EACf,CAAC,aAIYd,EAAM,UAAU,WAAM,kBAAjCX,EAAA,GAAAC,EAiBM,OAjBNQ,GAiBM,CAhBJP,EAcSC,GAAA;GAbP,MAAK;GACL,SAAQ;GACR,MAAK;GACL,aAAU;GACT,cAAYkB,EAAA;GACZ,iBAAeJ,EAAA,MAAM;GACtB,iBAAc;GACb,OAAOI,EAAA;GACP,SAAK,AAAAe,EAAA,QAAA,MAAEhC,EAAAW,CAAA,CAAU,CAAC,KAAI;GACtB,gBAAY,AAAAqB,EAAA,QAAA,MAAEhC,EAAAkC,CAAA,CAAmB,CAAA;GACjC,SAAK,AAAAF,EAAA,QAAA,MAAEhC,EAAAkC,CAAA,CAAmB,CAAA;;GAE3B,SAAAjC,QAAmC,CAAnCH,EAAmCE,EAAAoC,CAAA,GAAA,EAArB,eAAY,OAAM,CAAA,CAAA,CAAA;;;;;;EAEd,CAAA,GAAArB,EAAA,SAApBnB,EAAA,GAAAM,EAAwDF,EAAAsC,CAAA,GAAA;;GAA1B,YAAYtC,EAAAW,CAAA"}
1
+ {"version":3,"file":"AiCopilot.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_createVNode","Button","_unref","_withCtx","_createBlock","_createCommentVNode","Button_default","_hoisted_1","AiCopilot_vue_vue_type_script_setup_true_lang_default","props","__props","t","useT","controller","CopilotController","state","shallowRef","mounted","ref","label","computed","unsubscribe","next","unregister","watch","keys","text","bindings","shortcuts","onBeforeUnmount","createCommentVNode","openBlock","createElementBlock","createVNode","_cache","unref","preloadCopilotPanel","withCtx","SparklesIcon","createBlock","CopilotPanel"],"sources":["../../../src/components/ai/AiCopilot.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { type AiCopilotSchema, CopilotController, shortcuts } from '@alfakit/core'\nimport { SparklesIcon } from '@lucide/vue'\nimport { computed, onBeforeUnmount, ref, shallowRef, watch } from 'vue'\nimport { useT } from '../../context'\nimport Button from '../ui/Button.vue'\nimport { CopilotPanel, preloadCopilotPanel } from './copilot-lazy'\n\n/**\n * The copilot of alfasix/alfakit-ai (`ai:copilot`): a topbar button (and `mod+j`) opening\n * a chat slide-over. Questions, tools and actions run on the server; proposed actions\n * run only when the user confirms them in the chat.\n */\nconst props = defineProps<{\n component: AiCopilotSchema\n /** Open once mounted (starter kit header: clicked or `mod+j` before its code loaded). */\n autoOpen?: boolean\n}>()\nconst t = useT()\n// One controller per panel: Inertia visits pass new props objects.\nconst controller = new CopilotController(props.component)\nconst state = shallowRef(controller.state)\nconst mounted = ref(false)\nconst label = computed(() => t('ai.open', {}, 'Open AI copilot'))\n\nconst unsubscribe = controller.subscribe((next) => {\n state.value = next\n\n if (next.open) mounted.value = true\n})\n\nif (props.autoOpen && props.component.canUse !== false) controller.open()\n\nlet unregister: (() => void) | undefined\n\nwatch(\n () => [JSON.stringify(props.component.keyBindings ?? []), label.value] as const,\n ([keys, text]) => {\n unregister?.()\n unregister = undefined\n\n const bindings = JSON.parse(keys) as string[]\n\n if (bindings.length === 0) return\n\n unregister = shortcuts.register({\n id: 'ai.copilot',\n keys: bindings,\n label: text,\n group: 'general',\n allowInInputs: true,\n handler: () => controller.toggle(),\n })\n },\n { immediate: true },\n)\n\nonBeforeUnmount(() => {\n unsubscribe()\n unregister?.()\n})\n</script>\n\n<template>\n <div v-if=\"props.component.canUse !== false\" data-slot=\"ai-copilot\" class=\"contents\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n data-slot=\"ai-copilot-trigger\"\n :aria-label=\"label\"\n :aria-expanded=\"state.open\"\n aria-haspopup=\"dialog\"\n :title=\"label\"\n @click=\"controller.open()\"\n @pointerenter=\"preloadCopilotPanel()\"\n @focus=\"preloadCopilotPanel()\"\n >\n <SparklesIcon aria-hidden=\"true\" />\n </Button>\n <CopilotPanel v-if=\"mounted\" :controller=\"controller\" />\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;EAaA,IAAMW,IAAQC,GAKRC,IAAIC,EAAK,GAETC,IAAa,IAAIC,EAAkBL,EAAM,SAAS,GAClDM,IAAQC,EAAWH,EAAW,KAAK,GACnCI,IAAUC,EAAI,EAAK,GACnBC,IAAQC,QAAeT,EAAE,WAAW,CAAC,GAAG,iBAAiB,CAAC,GAE1DU,IAAcR,EAAW,WAAW,MAAS;GAGjD,AAFA,EAAM,QAAQS,GAEVA,EAAK,SAAM,EAAQ,QAAQ;EACjC,CAAC;EAED,AAAIb,EAAM,YAAYA,EAAM,UAAU,WAAW,MAAOI,EAAW,KAAK;EAExE,IAAIU;SAEJC,QACQ,CAAC,KAAK,UAAUf,EAAM,UAAU,eAAe,CAAC,CAAC,GAAGU,EAAM,KAAK,IACpE,CAACM,GAAMC,OAAU;GAEhB,AADAH,IAAa,GACb,IAAa,KAAA;GAEb,IAAMI,IAAW,KAAK,MAAMF,CAAI;GAEhC,AAAIE,EAAS,WAAW,MAExB,IAAaC,EAAU,SAAS;IAC9B,IAAI;IACJ,MAAMD;IACN,OAAOD;IACP,OAAO;IACP,eAAe;IACf,eAAeb,EAAW,OAAO;GACnC,CAAC;EACH,GACA,EAAE,WAAW,GAAK,CACpB,GAEAgB,QAAsB;GAEpB,AADAR,EAAY,GACZE,IAAa;EACf,CAAC,aAIYd,EAAM,UAAU,WAAM,kBAAjCX,EAAA,GAAAC,EAiBM,OAjBNQ,GAiBM,CAhBJP,EAcSC,GAAA;GAbP,MAAK;GACL,SAAQ;GACR,MAAK;GACL,aAAU;GACT,cAAYkB,EAAA;GACZ,iBAAeJ,EAAA,MAAM;GACtB,iBAAc;GACb,OAAOI,EAAA;GACP,SAAK,AAAAe,EAAA,QAAA,MAAEhC,EAAAW,CAAA,CAAU,CAAC,KAAI;GACtB,gBAAY,AAAAqB,EAAA,QAAA,MAAEhC,EAAAkC,CAAA,CAAmB,CAAA;GACjC,SAAK,AAAAF,EAAA,QAAA,MAAEhC,EAAAkC,CAAA,CAAmB,CAAA;;GAE3B,SAAAjC,QAAmC,CAAnCH,EAAmCE,EAAAoC,CAAA,GAAA,EAArB,eAAY,OAAM,CAAA,CAAA,CAAA;;;;;;EAEd,CAAA,GAAArB,EAAA,SAApBnB,EAAA,GAAAM,EAAwDF,EAAAsC,CAAA,GAAA;;GAA1B,YAAYtC,EAAAW,CAAA"}
@@ -1,15 +1,15 @@
1
1
  import { useOptionalRegistry as e } from "../../context.js";
2
- import t from "../ui/Breadcrumb.js";
3
- import n from "../ui/BreadcrumbItem.js";
4
- import r from "../ui/BreadcrumbLink.js";
5
- import i from "../ui/BreadcrumbList.js";
6
- import a from "../ui/BreadcrumbPage.js";
7
- import o from "../ui/BreadcrumbSeparator.js";
8
- import { provideCms as s } from "./context.js";
9
- import c from "./CmsBlocks.js";
10
- import l from "./CmsFooter.js";
11
- import u from "./CmsHead.js";
12
- import d from "./CmsHeader.js";
2
+ import { provideCms as t } from "./context.js";
3
+ import n from "./CmsBlocks.js";
4
+ import r from "./CmsFooter.js";
5
+ import i from "./CmsHead.js";
6
+ import a from "./CmsHeader.js";
7
+ import o from "../ui/Breadcrumb.js";
8
+ import s from "../ui/BreadcrumbItem.js";
9
+ import c from "../ui/BreadcrumbLink.js";
10
+ import l from "../ui/BreadcrumbList.js";
11
+ import u from "../ui/BreadcrumbPage.js";
12
+ import d from "../ui/BreadcrumbSeparator.js";
13
13
  import { CMS_FOOTER_KEY as f, CMS_HEADER_KEY as p, cmsPayload as m } from "@alfakit/core";
14
14
  import { usePage as h } from "@inertiajs/vue3";
15
15
  import { Fragment as g, computed as _, createBlock as v, createCommentVNode as y, createElementBlock as b, createElementVNode as x, createTextVNode as S, createVNode as C, defineAsyncComponent as w, defineComponent as T, openBlock as E, renderList as D, renderSlot as O, resolveDynamicComponent as k, toDisplayString as A, unref as j, watchEffect as M, withCtx as N } from "vue";
@@ -51,10 +51,10 @@ var F = [
51
51
  return () => null;
52
52
  }
53
53
  }
54
- let W = U(), G = _(() => H.cms ?? m(W())), K = s(() => G.value, () => H.components), q = e(), J = _(() => q?.resolve(p) ?? d), Y = _(() => q?.resolve(f) ?? l), X = (e, t) => K.value.t(e, {}, t), Z = w(() => import("./AdminBar.js"));
54
+ let W = U(), G = _(() => H.cms ?? m(W())), K = t(() => G.value, () => H.components), q = e(), J = _(() => q?.resolve(p) ?? a), Y = _(() => q?.resolve(f) ?? r), X = (e, t) => K.value.t(e, {}, t), Z = w(() => import("./AdminBar.js"));
55
55
  return M(() => {
56
56
  typeof document < "u" && G.value && (document.documentElement.lang = G.value.site.tag, document.documentElement.dir = G.value.site.direction);
57
- }), (e, s) => G.value ? (E(), b(g, { key: 0 }, [C(u, { seo: G.value.page.seo }, null, 8, ["seo"]), x("div", {
57
+ }), (e, t) => G.value ? (E(), b(g, { key: 0 }, [C(i, { seo: G.value.page.seo }, null, 8, ["seo"]), x("div", {
58
58
  dir: G.value.site.direction,
59
59
  lang: G.value.site.tag,
60
60
  "data-slot": "cms-page",
@@ -67,17 +67,17 @@ var F = [
67
67
  "aria-hidden": "true"
68
68
  }), x("span", null, [x("strong", R, A(X("cms.preview", "Preview")), 1), S(" · " + A(X("cms.preview_notice", "This is a preview. Visitors don't see unpublished changes.")), 1)])])) : y("", !0),
69
69
  (E(), v(k(J.value), { cms: G.value }, null, 8, ["cms"])),
70
- x("main", z, [G.value.page.breadcrumbs.length > 1 ? (E(), v(t, {
70
+ x("main", z, [G.value.page.breadcrumbs.length > 1 ? (E(), v(o, {
71
71
  key: 0,
72
72
  "aria-label": X("cms.breadcrumbs", "Breadcrumbs"),
73
73
  class: "mx-auto max-w-6xl px-4 pt-6 sm:px-6 lg:px-8"
74
74
  }, {
75
- default: N(() => [C(i, null, {
76
- default: N(() => [(E(!0), b(g, null, D(G.value.page.breadcrumbs, (e, t) => (E(), b(g, { key: e.url }, [t > 0 ? (E(), v(o, { key: 0 })) : y("", !0), C(n, null, {
77
- default: N(() => [t === G.value.page.breadcrumbs.length - 1 ? (E(), v(a, { key: 0 }, {
75
+ default: N(() => [C(l, null, {
76
+ default: N(() => [(E(!0), b(g, null, D(G.value.page.breadcrumbs, (e, t) => (E(), b(g, { key: e.url }, [t > 0 ? (E(), v(d, { key: 0 })) : y("", !0), C(s, null, {
77
+ default: N(() => [t === G.value.page.breadcrumbs.length - 1 ? (E(), v(u, { key: 0 }, {
78
78
  default: N(() => [S(A(e.label), 1)]),
79
79
  _: 2
80
- }, 1024)) : (E(), v(r, {
80
+ }, 1024)) : (E(), v(c, {
81
81
  key: 1,
82
82
  href: e.url
83
83
  }, {
@@ -89,7 +89,7 @@ var F = [
89
89
  _: 1
90
90
  })]),
91
91
  _: 1
92
- }, 8, ["aria-label"])) : y("", !0), O(e.$slots, "default", { cms: G.value }, () => [G.value.page.blocks.length > 0 ? (E(), v(c, {
92
+ }, 8, ["aria-label"])) : y("", !0), O(e.$slots, "default", { cms: G.value }, () => [G.value.page.blocks.length > 0 ? (E(), v(n, {
93
93
  key: 0,
94
94
  blocks: G.value.page.blocks
95
95
  }, null, 8, ["blocks"])) : (E(), b("p", B, A(X("cms.empty_page", "This page has no content yet.")), 1))])]),
@@ -1 +1 @@
1
- {"version":3,"file":"CmsPage.vue_vue_type_script_setup_true_lang.js","names":["CmsHeader","CmsFooter","_openBlock","_createElementBlock","_Fragment","_createVNode","CmsHead","_createElementVNode","_toDisplayString","_unref","_createTextVNode","_createCommentVNode","_createBlock","_resolveDynamicComponent","Breadcrumb","_withCtx","BreadcrumbList","_renderList","BreadcrumbSeparator","BreadcrumbItem","BreadcrumbPage","BreadcrumbLink","_renderSlot","CmsBlocks","Breadcrumb_default","BreadcrumbItem_default","BreadcrumbLink_default","BreadcrumbList_default","BreadcrumbPage_default","BreadcrumbSeparator_default","CmsBlocks_default","CmsFooter_default","CmsHead_default","CmsHeader_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_6","_hoisted_7","CmsPage_vue_vue_type_script_setup_true_lang_default","props","__props","usePageProps","page","usePage","pageProps","cms","computed","cmsPayload","context","provideCms","registry","useOptionalRegistry","header","CMS_HEADER_KEY","footer","CMS_FOOTER_KEY","t","key","fallback","CmsAdminBar","defineAsyncComponent","watchEffect","openBlock","createElementBlock","Fragment","createVNode","createElementVNode","toDisplayString","unref","EyeIcon","createTextVNode","createCommentVNode","createBlock","resolveDynamicComponent","withCtx","renderList","crumb","index","renderSlot","_ctx"],"sources":["../../../src/components/cms/CmsPage.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { CMS_FOOTER_KEY, CMS_HEADER_KEY, cmsPayload, type CmsPayload } from '@alfakit/core'\nimport { usePage } from '@inertiajs/vue3'\nimport { EyeIcon } from '@lucide/vue'\nimport { computed, defineAsyncComponent, watchEffect } from 'vue'\nimport { useOptionalRegistry, type AnyComponent } from '../../context'\nimport Breadcrumb from '../ui/Breadcrumb.vue'\nimport BreadcrumbItem from '../ui/BreadcrumbItem.vue'\nimport BreadcrumbLink from '../ui/BreadcrumbLink.vue'\nimport BreadcrumbList from '../ui/BreadcrumbList.vue'\nimport BreadcrumbPage from '../ui/BreadcrumbPage.vue'\nimport BreadcrumbSeparator from '../ui/BreadcrumbSeparator.vue'\nimport CmsBlocks from './CmsBlocks.vue'\nimport CmsFooter from './CmsFooter.vue'\nimport CmsHead from './CmsHead.vue'\nimport CmsHeader from './CmsHeader.vue'\nimport { provideCms } from './context'\n\n/**\n * The `Alfakit/CmsPage` Inertia page (public CMS pages and previews). Register it in your\n * public site's Inertia app: `createAlfakit({ pages: { 'Alfakit/CmsPage': CmsPage } })`.\n *\n * Replace the header or footer with `cms:header` / `cms:footer` registry components, a\n * block with `cms:block:{type}`, or build your own page from `CmsBlocks` and `CmsHead`.\n */\nconst props = defineProps<{ cms?: CmsPayload; components?: Record<string, AnyComponent> }>()\n\nfunction usePageProps(): () => unknown {\n try {\n const page = usePage()\n\n return () => page.props\n } catch {\n return () => null\n }\n}\n\nconst pageProps = usePageProps()\nconst cms = computed(() => props.cms ?? cmsPayload(pageProps()))\nconst context = provideCms(\n () => cms.value,\n () => props.components,\n)\nconst registry = useOptionalRegistry()\nconst header = computed<AnyComponent>(() => registry?.resolve(CMS_HEADER_KEY) ?? CmsHeader)\nconst footer = computed<AnyComponent>(() => registry?.resolve(CMS_FOOTER_KEY) ?? CmsFooter)\n\nconst t = (key: string, fallback: string) => context.value.t(key, {}, fallback)\n\n// The admin bar loads only for signed-in editors (the server sends `cms.admin` to them alone).\nconst CmsAdminBar = defineAsyncComponent(() => import('./AdminBar.vue'))\n\nwatchEffect(() => {\n if (typeof document === 'undefined' || !cms.value) return\n\n document.documentElement.lang = cms.value.site.tag\n document.documentElement.dir = cms.value.site.direction\n})\n</script>\n\n<template>\n <template v-if=\"cms\">\n <CmsHead :seo=\"cms.page.seo\" />\n <div\n :dir=\"cms.site.direction\"\n :lang=\"cms.site.tag\"\n data-slot=\"cms-page\"\n :data-layout=\"cms.page.layout ?? undefined\"\n class=\"bg-background text-foreground flex min-h-svh flex-col\"\n >\n <a\n href=\"#cms-content\"\n class=\"bg-background focus-visible:ring-ring/50 sr-only z-50 rounded-md px-4 py-2 focus:not-sr-only focus:absolute focus:start-4 focus:top-4 focus-visible:ring-[3px]\"\n >\n {{ t('cms.skip_to_content', 'Skip to content') }}\n </a>\n <div\n v-if=\"cms.preview\"\n role=\"status\"\n data-slot=\"cms-preview-banner\"\n class=\"flex items-center justify-center gap-2 bg-amber-100 px-4 py-2 text-sm text-amber-950 dark:bg-amber-950 dark:text-amber-100\"\n >\n <EyeIcon class=\"size-4 shrink-0\" aria-hidden=\"true\" />\n <span>\n <strong class=\"font-semibold\">{{ t('cms.preview', 'Preview') }}</strong> ·\n {{\n t('cms.preview_notice', \"This is a preview. Visitors don't see unpublished changes.\")\n }}\n </span>\n </div>\n <component :is=\"header\" :cms=\"cms\" />\n <main id=\"cms-content\" tabindex=\"-1\" class=\"flex-1 outline-none\" data-slot=\"cms-content\">\n <Breadcrumb\n v-if=\"cms.page.breadcrumbs.length > 1\"\n :aria-label=\"t('cms.breadcrumbs', 'Breadcrumbs')\"\n class=\"mx-auto max-w-6xl px-4 pt-6 sm:px-6 lg:px-8\"\n >\n <BreadcrumbList>\n <template v-for=\"(crumb, index) in cms.page.breadcrumbs\" :key=\"crumb.url\">\n <BreadcrumbSeparator v-if=\"index > 0\" />\n <BreadcrumbItem>\n <BreadcrumbPage v-if=\"index === cms.page.breadcrumbs.length - 1\">{{\n crumb.label\n }}</BreadcrumbPage>\n <BreadcrumbLink v-else :href=\"crumb.url\">{{ crumb.label }}</BreadcrumbLink>\n </BreadcrumbItem>\n </template>\n </BreadcrumbList>\n </Breadcrumb>\n <slot :cms=\"cms\">\n <CmsBlocks v-if=\"cms.page.blocks.length > 0\" :blocks=\"cms.page.blocks\" />\n <p v-else class=\"text-muted-foreground mx-auto max-w-3xl px-4 py-24 text-center\">\n {{ t('cms.empty_page', 'This page has no content yet.') }}\n </p>\n </slot>\n </main>\n <component :is=\"footer\" :cms=\"cms\" />\n <!-- eslint-disable-next-line vue/no-v-html -- built on the server (Credit::poweredBy) -->\n <div v-if=\"cms.poweredBy\" data-slot=\"cms-powered-by\" v-html=\"cms.poweredBy\" />\n <CmsAdminBar v-if=\"cms.admin\" :admin=\"cms.admin\" />\n </div>\n </template>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"CmsPage.vue_vue_type_script_setup_true_lang.js","names":["CmsHeader","CmsFooter","_openBlock","_createElementBlock","_Fragment","_createVNode","CmsHead","_createElementVNode","_toDisplayString","_unref","_createTextVNode","_createCommentVNode","_createBlock","_resolveDynamicComponent","Breadcrumb","_withCtx","BreadcrumbList","_renderList","BreadcrumbSeparator","BreadcrumbItem","BreadcrumbPage","BreadcrumbLink","_renderSlot","CmsBlocks","CmsBlocks_default","CmsFooter_default","CmsHead_default","CmsHeader_default","Breadcrumb_default","BreadcrumbItem_default","BreadcrumbLink_default","BreadcrumbList_default","BreadcrumbPage_default","BreadcrumbSeparator_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_6","_hoisted_7","CmsPage_vue_vue_type_script_setup_true_lang_default","props","__props","usePageProps","page","usePage","pageProps","cms","computed","cmsPayload","context","provideCms","registry","useOptionalRegistry","header","CMS_HEADER_KEY","footer","CMS_FOOTER_KEY","t","key","fallback","CmsAdminBar","defineAsyncComponent","watchEffect","openBlock","createElementBlock","Fragment","createVNode","createElementVNode","toDisplayString","unref","EyeIcon","createTextVNode","createCommentVNode","createBlock","resolveDynamicComponent","withCtx","renderList","crumb","index","renderSlot","_ctx"],"sources":["../../../src/components/cms/CmsPage.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { CMS_FOOTER_KEY, CMS_HEADER_KEY, cmsPayload, type CmsPayload } from '@alfakit/core'\nimport { usePage } from '@inertiajs/vue3'\nimport { EyeIcon } from '@lucide/vue'\nimport { computed, defineAsyncComponent, watchEffect } from 'vue'\nimport { useOptionalRegistry, type AnyComponent } from '../../context'\nimport Breadcrumb from '../ui/Breadcrumb.vue'\nimport BreadcrumbItem from '../ui/BreadcrumbItem.vue'\nimport BreadcrumbLink from '../ui/BreadcrumbLink.vue'\nimport BreadcrumbList from '../ui/BreadcrumbList.vue'\nimport BreadcrumbPage from '../ui/BreadcrumbPage.vue'\nimport BreadcrumbSeparator from '../ui/BreadcrumbSeparator.vue'\nimport CmsBlocks from './CmsBlocks.vue'\nimport CmsFooter from './CmsFooter.vue'\nimport CmsHead from './CmsHead.vue'\nimport CmsHeader from './CmsHeader.vue'\nimport { provideCms } from './context'\n\n/**\n * The `Alfakit/CmsPage` Inertia page (public CMS pages and previews). Register it in your\n * public site's Inertia app: `createAlfakit({ pages: { 'Alfakit/CmsPage': CmsPage } })`.\n *\n * Replace the header or footer with `cms:header` / `cms:footer` registry components, a\n * block with `cms:block:{type}`, or build your own page from `CmsBlocks` and `CmsHead`.\n */\nconst props = defineProps<{ cms?: CmsPayload; components?: Record<string, AnyComponent> }>()\n\nfunction usePageProps(): () => unknown {\n try {\n const page = usePage()\n\n return () => page.props\n } catch {\n return () => null\n }\n}\n\nconst pageProps = usePageProps()\nconst cms = computed(() => props.cms ?? cmsPayload(pageProps()))\nconst context = provideCms(\n () => cms.value,\n () => props.components,\n)\nconst registry = useOptionalRegistry()\nconst header = computed<AnyComponent>(() => registry?.resolve(CMS_HEADER_KEY) ?? CmsHeader)\nconst footer = computed<AnyComponent>(() => registry?.resolve(CMS_FOOTER_KEY) ?? CmsFooter)\n\nconst t = (key: string, fallback: string) => context.value.t(key, {}, fallback)\n\n// The admin bar loads only for signed-in editors (the server sends `cms.admin` to them alone).\nconst CmsAdminBar = defineAsyncComponent(() => import('./AdminBar.vue'))\n\nwatchEffect(() => {\n if (typeof document === 'undefined' || !cms.value) return\n\n document.documentElement.lang = cms.value.site.tag\n document.documentElement.dir = cms.value.site.direction\n})\n</script>\n\n<template>\n <template v-if=\"cms\">\n <CmsHead :seo=\"cms.page.seo\" />\n <div\n :dir=\"cms.site.direction\"\n :lang=\"cms.site.tag\"\n data-slot=\"cms-page\"\n :data-layout=\"cms.page.layout ?? undefined\"\n class=\"bg-background text-foreground flex min-h-svh flex-col\"\n >\n <a\n href=\"#cms-content\"\n class=\"bg-background focus-visible:ring-ring/50 sr-only z-50 rounded-md px-4 py-2 focus:not-sr-only focus:absolute focus:start-4 focus:top-4 focus-visible:ring-[3px]\"\n >\n {{ t('cms.skip_to_content', 'Skip to content') }}\n </a>\n <div\n v-if=\"cms.preview\"\n role=\"status\"\n data-slot=\"cms-preview-banner\"\n class=\"flex items-center justify-center gap-2 bg-amber-100 px-4 py-2 text-sm text-amber-950 dark:bg-amber-950 dark:text-amber-100\"\n >\n <EyeIcon class=\"size-4 shrink-0\" aria-hidden=\"true\" />\n <span>\n <strong class=\"font-semibold\">{{ t('cms.preview', 'Preview') }}</strong> ·\n {{\n t('cms.preview_notice', \"This is a preview. Visitors don't see unpublished changes.\")\n }}\n </span>\n </div>\n <component :is=\"header\" :cms=\"cms\" />\n <main id=\"cms-content\" tabindex=\"-1\" class=\"flex-1 outline-none\" data-slot=\"cms-content\">\n <Breadcrumb\n v-if=\"cms.page.breadcrumbs.length > 1\"\n :aria-label=\"t('cms.breadcrumbs', 'Breadcrumbs')\"\n class=\"mx-auto max-w-6xl px-4 pt-6 sm:px-6 lg:px-8\"\n >\n <BreadcrumbList>\n <template v-for=\"(crumb, index) in cms.page.breadcrumbs\" :key=\"crumb.url\">\n <BreadcrumbSeparator v-if=\"index > 0\" />\n <BreadcrumbItem>\n <BreadcrumbPage v-if=\"index === cms.page.breadcrumbs.length - 1\">{{\n crumb.label\n }}</BreadcrumbPage>\n <BreadcrumbLink v-else :href=\"crumb.url\">{{ crumb.label }}</BreadcrumbLink>\n </BreadcrumbItem>\n </template>\n </BreadcrumbList>\n </Breadcrumb>\n <slot :cms=\"cms\">\n <CmsBlocks v-if=\"cms.page.blocks.length > 0\" :blocks=\"cms.page.blocks\" />\n <p v-else class=\"text-muted-foreground mx-auto max-w-3xl px-4 py-24 text-center\">\n {{ t('cms.empty_page', 'This page has no content yet.') }}\n </p>\n </slot>\n </main>\n <component :is=\"footer\" :cms=\"cms\" />\n <!-- eslint-disable-next-line vue/no-v-html -- built on the server (Credit::poweredBy) -->\n <div v-if=\"cms.poweredBy\" data-slot=\"cms-powered-by\" v-html=\"cms.poweredBy\" />\n <CmsAdminBar v-if=\"cms.admin\" :admin=\"cms.admin\" />\n </div>\n </template>\n</template>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"LivePreview.js","names":["_sfc_main","LivePreview_vue_vue_type_script_setup_true_lang_default","LivePreview_default"],"sources":["../../../src/components/cms/LivePreview.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n CMS_PREVIEW_DEVICES,\n CmsAutosave,\n callCmsAutosave,\n cmsPreviewFitsBeside,\n cmsPreviewOpensOnLoad,\n rememberedCmsPreview,\n resolveStickyOffset,\n reserveCmsPreviewSpace,\n type CmsAutosaveSnapshot,\n type CmsLivePreviewSchema,\n type CmsPreviewDevice,\n} from '@alfakit/core'\nimport {\n CheckIcon,\n CircleAlertIcon,\n EyeIcon,\n LoaderCircleIcon,\n Maximize2Icon,\n Minimize2Icon,\n MonitorIcon,\n SmartphoneIcon,\n TabletIcon,\n XIcon,\n} from '@lucide/vue'\nimport { computed, onBeforeUnmount, onMounted, ref, shallowRef, watch } from 'vue'\nimport { usePageSchema, usePanel, useT } from '../../context'\nimport { cn } from '../../lib/utils'\nimport { useOptionalFormStore } from '../form/form-context'\nimport ActionList from '../actions/ActionList.vue'\nimport Badge from '../ui/Badge.vue'\nimport Button from '../ui/Button.vue'\n\n/**\n * The page editor's autosave status and live preview (schema type `CmsLivePreview`).\n * Changes are autosaved as a draft a moment after typing stops; the preview pane shows\n * the signed preview of that draft beside the form, full screen, or at tablet and phone\n * widths.\n */\nconst props = defineProps<{ component: CmsLivePreviewSchema }>()\n\nconst t = useT()\nconst form = useOptionalFormStore()\nconst page = usePageSchema()\nconst panel = usePanel()\nconst root = ref<HTMLElement | null>(null)\nconst open = ref(false)\nconst fullScreen = ref(false)\n// Too narrow for the form beside the pane (e.g. 1280px with the sidebar): full-screen overlay.\nconst overlay = ref(false)\nconst expanded = computed(() => fullScreen.value || overlay.value)\nconst device = ref<CmsPreviewDevice>('desktop')\nconst snapshot = shallowRef<CmsAutosaveSnapshot>({\n status: props.component.savedAt ? 'saved' : 'idle',\n savedAt: props.component.savedAt ?? null,\n previewUrl: props.component.previewUrl,\n version: 0,\n hasChanges: props.component.hasChanges ?? false,\n})\nconst top = ref('0px')\nconst actionContext = computed(() => ({ token: page.value?.token ?? '', component: 'page' }))\nconst status = computed(() =>\n snapshot.value.hasChanges && props.component.changedStatus\n ? props.component.changedStatus\n : props.component.status,\n)\n/** Badge colours of the status (the server's `PageState` colours). */\nconst STATUS_COLORS: Record<string, string> = {\n gray: 'border-border bg-muted text-foreground',\n success: 'border-emerald-600/30 bg-emerald-500/10 text-emerald-700 dark:text-emerald-300',\n warning: 'border-amber-600/30 bg-amber-500/10 text-amber-700 dark:text-amber-300',\n info: 'border-sky-600/30 bg-sky-500/10 text-sky-700 dark:text-sky-300',\n danger: 'border-red-600/30 bg-red-500/10 text-red-700 dark:text-red-300',\n}\n\nconst devices = Object.keys(CMS_PREVIEW_DEVICES) as CmsPreviewDevice[]\nconst icons = { desktop: MonitorIcon, tablet: TabletIcon, phone: SmartphoneIcon }\nconst labels = { desktop: 'Desktop', tablet: 'Tablet', phone: 'Phone' }\nconst width = computed(() => CMS_PREVIEW_DEVICES[device.value])\n\nconst statusLabel = computed(() => {\n switch (snapshot.value.status) {\n case 'saving':\n return t('cms.saving', {}, 'Saving…')\n case 'saved':\n return t('cms.saved', {}, 'Draft saved automatically')\n case 'pending':\n return t('cms.unsaved', {}, 'Unsaved changes')\n case 'error':\n return t(\n 'cms.save_failed',\n {},\n \"Your latest changes couldn't be saved. They will be tried again.\",\n )\n default:\n return ''\n }\n})\n\nlet autosave: CmsAutosave | null = null\nlet unsubscribe: (() => void) | null = null\nlet release: () => void = () => {}\n\nfunction onKey(event: KeyboardEvent) {\n if (event.key !== 'Escape' || !open.value) return\n if (fullScreen.value && !overlay.value) fullScreen.value = false\n else setOpen(false)\n}\n\n/** Open or collapse the pane, remembering the choice for the next visit. */\nfunction setOpen(next: boolean) {\n open.value = next\n rememberedCmsPreview(next ? 'open' : 'closed')\n}\n\nfunction measure() {\n if (open.value) overlay.value = !cmsPreviewFitsBeside(root.value)\n}\n\nonMounted(() => {\n window.addEventListener('keydown', onKey)\n window.addEventListener('resize', measure)\n // Stick right under the panel's topbar when it sticks too.\n top.value = resolveStickyOffset(null)\n // Wide screens open the pane beside the form; the viewer's last choice wins.\n if (props.component.previewUrl && cmsPreviewOpensOnLoad(root.value)) open.value = true\n\n if (!form) return\n\n autosave = new CmsAutosave({\n debounce: props.component.debounce,\n previewUrl: props.component.previewUrl,\n savedAt: props.component.savedAt,\n hasChanges: props.component.hasChanges,\n save: (state) =>\n callCmsAutosave(props.component.autosaveMethod, state, {\n token: page.value?.token ?? '',\n endpoint: panel.value?.endpoints?.pageCall ?? '',\n }),\n onChange: (next) => (snapshot.value = next),\n })\n\n let values = form.state.values\n unsubscribe = form.subscribe((state) => {\n if (state.values !== values) {\n values = state.values\n autosave?.schedule(state.values)\n }\n })\n})\n\n// Side by side, the form makes room for the pane.\nwatch(open, measure)\nwatch([open, expanded], ([isOpen, isFull]) => {\n release()\n release = isOpen && !isFull ? reserveCmsPreviewSpace(root.value, 'min(50vw, 56rem)') : () => {}\n})\n\nonBeforeUnmount(() => {\n window.removeEventListener('keydown', onKey)\n window.removeEventListener('resize', measure)\n unsubscribe?.()\n release()\n const current = autosave\n void current?.flush().finally(() => current.dispose())\n})\n</script>\n\n<template>\n <div\n ref=\"root\"\n data-slot=\"cms-live-preview\"\n :style=\"{ top }\"\n class=\"bg-background sticky z-20 flex flex-wrap items-center gap-x-4 gap-y-2 rounded-xl border px-3 py-2.5 shadow-sm\"\n >\n <div class=\"flex min-w-0 flex-1 basis-64 flex-col gap-0.5\">\n <p\n v-if=\"status\"\n class=\"flex flex-wrap items-center gap-x-2 gap-y-1 text-sm\"\n data-slot=\"cms-editor-status\"\n >\n <Badge\n variant=\"outline\"\n :data-color=\"status.color\"\n :class=\"STATUS_COLORS[status.color] ?? ''\"\n >{{ status.label }}</Badge\n >\n <span class=\"text-muted-foreground\">{{ status.description }}</span>\n </p>\n <p\n class=\"text-muted-foreground flex min-h-4 items-center gap-1.5 text-xs\"\n role=\"status\"\n aria-live=\"polite\"\n >\n <LoaderCircleIcon\n v-if=\"snapshot.status === 'saving'\"\n class=\"size-4 animate-spin\"\n aria-hidden=\"true\"\n />\n <CircleAlertIcon\n v-else-if=\"snapshot.status === 'error'\"\n class=\"text-destructive size-4\"\n aria-hidden=\"true\"\n />\n <CheckIcon v-else-if=\"snapshot.status === 'saved'\" class=\"size-4\" aria-hidden=\"true\" />\n {{ statusLabel }}\n </p>\n </div>\n <div class=\"flex flex-wrap items-center gap-2\">\n <Button\n v-if=\"snapshot.previewUrl\"\n type=\"button\"\n :variant=\"open ? 'secondary' : 'outline'\"\n size=\"sm\"\n :aria-pressed=\"open\"\n :title=\"\n t('cms.live_preview_help', {}, 'See the page as visitors will, updated as you type.')\n \"\n data-slot=\"cms-live-preview-toggle\"\n @click=\"setOpen(!open)\"\n >\n <EyeIcon aria-hidden=\"true\" />\n {{\n open\n ? t('cms.hide_preview', {}, 'Hide preview')\n : t('cms.live_preview', {}, 'Live preview')\n }}\n </Button>\n <div v-if=\"props.component.actions?.length\" @pointerdown.capture=\"autosave?.flush()\">\n <ActionList :actions=\"props.component.actions\" :context=\"actionContext\" size=\"sm\" />\n </div>\n </div>\n <section\n v-if=\"open && snapshot.previewUrl\"\n :aria-label=\"t('cms.live_preview', {}, 'Live preview')\"\n data-slot=\"cms-live-preview-pane\"\n :data-full-screen=\"expanded || undefined\"\n :style=\"{ top: expanded ? '0px' : top }\"\n :class=\"\n cn(\n 'bg-background fixed end-0 bottom-0 z-50 flex flex-col border-s shadow-xl',\n expanded ? 'inset-x-0 border-s-0' : 'w-full lg:w-[min(50vw,56rem)]',\n )\n \"\n >\n <header class=\"flex items-center justify-between gap-2 border-b px-3 py-2\">\n <div\n class=\"flex items-center gap-1\"\n role=\"group\"\n :aria-label=\"t('cms.preview_width', {}, 'Preview width')\"\n >\n <Button\n v-for=\"name in devices\"\n :key=\"name\"\n type=\"button\"\n :variant=\"device === name ? 'secondary' : 'ghost'\"\n size=\"icon-sm\"\n :aria-pressed=\"device === name\"\n @click=\"device = name\"\n >\n <component :is=\"icons[name]\" aria-hidden=\"true\" />\n <span class=\"sr-only\">{{ t(`cms.device_${name}`, {}, labels[name]) }}</span>\n </Button>\n </div>\n <p class=\"text-muted-foreground hidden truncate text-xs sm:block\">{{ statusLabel }}</p>\n <div class=\"flex items-center gap-1\">\n <Button\n v-if=\"!overlay\"\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n :aria-pressed=\"fullScreen\"\n @click=\"fullScreen = !fullScreen\"\n >\n <Minimize2Icon v-if=\"fullScreen\" aria-hidden=\"true\" />\n <Maximize2Icon v-else aria-hidden=\"true\" />\n <span class=\"sr-only\">{{\n fullScreen\n ? t('cms.exit_full_screen', {}, 'Exit full screen')\n : t('cms.full_screen', {}, 'Full screen')\n }}</span>\n </Button>\n <Button type=\"button\" variant=\"ghost\" size=\"icon-sm\" @click=\"setOpen(false)\">\n <XIcon aria-hidden=\"true\" />\n <span class=\"sr-only\">{{ t('cms.close_preview', {}, 'Close preview') }}</span>\n </Button>\n </div>\n </header>\n <div class=\"bg-muted/40 flex flex-1 justify-center overflow-auto p-3\">\n <iframe\n :key=\"snapshot.version\"\n :src=\"snapshot.previewUrl\"\n :title=\"t('cms.preview_frame', {}, 'Page preview')\"\n class=\"bg-background h-full rounded-md border shadow-sm\"\n :style=\"{ width: width === null ? '100%' : `${width}px`, maxWidth: '100%' }\"\n />\n </div>\n </section>\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"LivePreview.js","names":["_sfc_main","LivePreview_vue_vue_type_script_setup_true_lang_default","LivePreview_default"],"sources":["../../../src/components/cms/LivePreview.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n CMS_PREVIEW_DEVICES,\n CmsAutosave,\n callCmsAutosave,\n cmsPreviewFitsBeside,\n cmsPreviewOpensOnLoad,\n rememberedCmsPreview,\n resolveStickyOffset,\n reserveCmsPreviewSpace,\n type CmsAutosaveSnapshot,\n type CmsLivePreviewSchema,\n type CmsPreviewDevice,\n} from '@alfakit/core'\nimport {\n CheckIcon,\n CircleAlertIcon,\n EyeIcon,\n LoaderCircleIcon,\n Maximize2Icon,\n Minimize2Icon,\n MonitorIcon,\n SmartphoneIcon,\n TabletIcon,\n XIcon,\n} from '@lucide/vue'\nimport { computed, onBeforeUnmount, onMounted, ref, shallowRef, watch } from 'vue'\nimport { usePageSchema, usePanel, useT } from '../../context'\nimport { cn } from '../../lib/utils'\nimport { useOptionalFormStore } from '../form/form-context'\nimport ActionList from '../actions/ActionList.vue'\nimport Badge from '../ui/Badge.vue'\nimport Button from '../ui/Button.vue'\n\n/**\n * The page editor's autosave status and live preview (schema type `CmsLivePreview`).\n * Changes are autosaved as a draft a moment after typing stops; the preview pane shows\n * the signed preview of that draft beside the form, full screen, or at tablet and phone\n * widths.\n */\nconst props = defineProps<{ component: CmsLivePreviewSchema }>()\n\nconst t = useT()\nconst form = useOptionalFormStore()\nconst page = usePageSchema()\nconst panel = usePanel()\nconst root = ref<HTMLElement | null>(null)\nconst open = ref(false)\nconst fullScreen = ref(false)\n// Too narrow for the form beside the pane (e.g. 1280px with the sidebar): full-screen overlay.\nconst overlay = ref(false)\nconst expanded = computed(() => fullScreen.value || overlay.value)\nconst device = ref<CmsPreviewDevice>('desktop')\nconst snapshot = shallowRef<CmsAutosaveSnapshot>({\n status: props.component.savedAt ? 'saved' : 'idle',\n savedAt: props.component.savedAt ?? null,\n previewUrl: props.component.previewUrl,\n version: 0,\n hasChanges: props.component.hasChanges ?? false,\n})\nconst top = ref('0px')\nconst actionContext = computed(() => ({ token: page.value?.token ?? '', component: 'page' }))\nconst status = computed(() =>\n snapshot.value.hasChanges && props.component.changedStatus\n ? props.component.changedStatus\n : props.component.status,\n)\n// \"Publish changes\" appears as soon as an autosave makes the draft differ.\nconst actions = computed(() =>\n snapshot.value.hasChanges && props.component.changedActions\n ? props.component.changedActions\n : props.component.actions,\n)\n/** Badge colours of the status (the server's `PageState` colours). */\nconst STATUS_COLORS: Record<string, string> = {\n gray: 'border-border bg-muted text-foreground',\n success: 'border-emerald-600/30 bg-emerald-500/10 text-emerald-700 dark:text-emerald-300',\n warning: 'border-amber-600/30 bg-amber-500/10 text-amber-700 dark:text-amber-300',\n info: 'border-sky-600/30 bg-sky-500/10 text-sky-700 dark:text-sky-300',\n danger: 'border-red-600/30 bg-red-500/10 text-red-700 dark:text-red-300',\n}\n\nconst devices = Object.keys(CMS_PREVIEW_DEVICES) as CmsPreviewDevice[]\nconst icons = { desktop: MonitorIcon, tablet: TabletIcon, phone: SmartphoneIcon }\nconst labels = { desktop: 'Desktop', tablet: 'Tablet', phone: 'Phone' }\nconst width = computed(() => CMS_PREVIEW_DEVICES[device.value])\n\nconst statusLabel = computed(() => {\n switch (snapshot.value.status) {\n case 'saving':\n return t('cms.saving', {}, 'Saving…')\n case 'saved':\n return t('cms.saved', {}, 'Draft saved automatically')\n case 'pending':\n return t('cms.unsaved', {}, 'Unsaved changes')\n case 'error':\n return t(\n 'cms.save_failed',\n {},\n \"Your latest changes couldn't be saved. They will be tried again.\",\n )\n default:\n return ''\n }\n})\n\nlet autosave: CmsAutosave | null = null\nlet unsubscribe: (() => void) | null = null\nlet release: () => void = () => {}\n\nfunction onKey(event: KeyboardEvent) {\n if (event.key !== 'Escape' || !open.value) return\n if (fullScreen.value && !overlay.value) fullScreen.value = false\n else setOpen(false)\n}\n\n/** Open or collapse the pane, remembering the choice for the next visit. */\nfunction setOpen(next: boolean) {\n open.value = next\n rememberedCmsPreview(next ? 'open' : 'closed')\n}\n\nfunction measure() {\n if (open.value) overlay.value = !cmsPreviewFitsBeside(root.value)\n}\n\nonMounted(() => {\n window.addEventListener('keydown', onKey)\n window.addEventListener('resize', measure)\n // Stick right under the panel's topbar when it sticks too.\n top.value = resolveStickyOffset(null)\n // Wide screens open the pane beside the form; the viewer's last choice wins.\n if (props.component.previewUrl && cmsPreviewOpensOnLoad(root.value)) open.value = true\n\n if (!form) return\n\n autosave = new CmsAutosave({\n debounce: props.component.debounce,\n previewUrl: props.component.previewUrl,\n savedAt: props.component.savedAt,\n hasChanges: props.component.hasChanges,\n save: (state) =>\n callCmsAutosave(props.component.autosaveMethod, state, {\n token: page.value?.token ?? '',\n endpoint: panel.value?.endpoints?.pageCall ?? '',\n }),\n onChange: (next) => (snapshot.value = next),\n })\n\n let values = form.state.values\n unsubscribe = form.subscribe((state) => {\n if (state.values !== values) {\n values = state.values\n autosave?.schedule(state.values)\n }\n })\n})\n\n// Side by side, the form makes room for the pane.\nwatch(open, measure)\nwatch([open, expanded], ([isOpen, isFull]) => {\n release()\n release = isOpen && !isFull ? reserveCmsPreviewSpace(root.value, 'min(50vw, 56rem)') : () => {}\n})\n\nonBeforeUnmount(() => {\n window.removeEventListener('keydown', onKey)\n window.removeEventListener('resize', measure)\n unsubscribe?.()\n release()\n const current = autosave\n void current?.flush().finally(() => current.dispose())\n})\n</script>\n\n<template>\n <div\n ref=\"root\"\n data-slot=\"cms-live-preview\"\n :style=\"{ top }\"\n class=\"bg-background sticky z-20 flex flex-wrap items-center gap-x-4 gap-y-2 rounded-xl border px-3 py-2.5 shadow-sm\"\n >\n <div class=\"flex min-w-0 flex-1 basis-64 flex-col gap-0.5\">\n <p\n v-if=\"status\"\n class=\"flex flex-wrap items-center gap-x-2 gap-y-1 text-sm\"\n data-slot=\"cms-editor-status\"\n >\n <Badge\n variant=\"outline\"\n :data-color=\"status.color\"\n :class=\"STATUS_COLORS[status.color] ?? ''\"\n >{{ status.label }}</Badge\n >\n <span class=\"text-muted-foreground\">{{ status.description }}</span>\n </p>\n <p\n class=\"text-muted-foreground flex min-h-4 items-center gap-1.5 text-xs\"\n role=\"status\"\n aria-live=\"polite\"\n >\n <LoaderCircleIcon\n v-if=\"snapshot.status === 'saving'\"\n class=\"size-4 animate-spin\"\n aria-hidden=\"true\"\n />\n <CircleAlertIcon\n v-else-if=\"snapshot.status === 'error'\"\n class=\"text-destructive size-4\"\n aria-hidden=\"true\"\n />\n <CheckIcon v-else-if=\"snapshot.status === 'saved'\" class=\"size-4\" aria-hidden=\"true\" />\n {{ statusLabel }}\n </p>\n </div>\n <div class=\"flex flex-wrap items-center gap-2\">\n <Button\n v-if=\"snapshot.previewUrl\"\n type=\"button\"\n :variant=\"open ? 'secondary' : 'outline'\"\n size=\"sm\"\n :aria-pressed=\"open\"\n :title=\"\n t('cms.live_preview_help', {}, 'See the page as visitors will, updated as you type.')\n \"\n data-slot=\"cms-live-preview-toggle\"\n @click=\"setOpen(!open)\"\n >\n <EyeIcon aria-hidden=\"true\" />\n {{\n open\n ? t('cms.hide_preview', {}, 'Hide preview')\n : t('cms.live_preview', {}, 'Live preview')\n }}\n </Button>\n <div v-if=\"actions?.length\" @pointerdown.capture=\"autosave?.flush()\">\n <ActionList :actions=\"actions\" :context=\"actionContext\" size=\"sm\" />\n </div>\n </div>\n <section\n v-if=\"open && snapshot.previewUrl\"\n :aria-label=\"t('cms.live_preview', {}, 'Live preview')\"\n data-slot=\"cms-live-preview-pane\"\n :data-full-screen=\"expanded || undefined\"\n :style=\"{ top: expanded ? '0px' : top }\"\n :class=\"\n cn(\n 'bg-background fixed end-0 bottom-0 z-50 flex flex-col border-s shadow-xl',\n expanded ? 'inset-x-0 border-s-0' : 'w-full lg:w-[min(50vw,56rem)]',\n )\n \"\n >\n <header class=\"flex items-center justify-between gap-2 border-b px-3 py-2\">\n <div\n class=\"flex items-center gap-1\"\n role=\"group\"\n :aria-label=\"t('cms.preview_width', {}, 'Preview width')\"\n >\n <Button\n v-for=\"name in devices\"\n :key=\"name\"\n type=\"button\"\n :variant=\"device === name ? 'secondary' : 'ghost'\"\n size=\"icon-sm\"\n :aria-pressed=\"device === name\"\n @click=\"device = name\"\n >\n <component :is=\"icons[name]\" aria-hidden=\"true\" />\n <span class=\"sr-only\">{{ t(`cms.device_${name}`, {}, labels[name]) }}</span>\n </Button>\n </div>\n <p class=\"text-muted-foreground hidden truncate text-xs sm:block\">{{ statusLabel }}</p>\n <div class=\"flex items-center gap-1\">\n <Button\n v-if=\"!overlay\"\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n :aria-pressed=\"fullScreen\"\n @click=\"fullScreen = !fullScreen\"\n >\n <Minimize2Icon v-if=\"fullScreen\" aria-hidden=\"true\" />\n <Maximize2Icon v-else aria-hidden=\"true\" />\n <span class=\"sr-only\">{{\n fullScreen\n ? t('cms.exit_full_screen', {}, 'Exit full screen')\n : t('cms.full_screen', {}, 'Full screen')\n }}</span>\n </Button>\n <Button type=\"button\" variant=\"ghost\" size=\"icon-sm\" @click=\"setOpen(false)\">\n <XIcon aria-hidden=\"true\" />\n <span class=\"sr-only\">{{ t('cms.close_preview', {}, 'Close preview') }}</span>\n </Button>\n </div>\n </header>\n <div class=\"bg-muted/40 flex flex-1 justify-center overflow-auto p-3\">\n <iframe\n :key=\"snapshot.version\"\n :src=\"snapshot.previewUrl\"\n :title=\"t('cms.preview_frame', {}, 'Page preview')\"\n class=\"bg-background h-full rounded-md border shadow-sm\"\n :style=\"{ width: width === null ? '100%' : `${width}px`, maxWidth: '100%' }\"\n />\n </div>\n </section>\n </div>\n</template>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"LivePreview.vue.d.ts","sourceRoot":"","sources":["../../../src/components/cms/LivePreview.vue"],"names":[],"mappings":"AA+SA,OAAO,EAUL,KAAK,oBAAoB,EAE1B,MAAM,eAAe,CAAA;AAqBtB;;;;;GAKG;AACH,KAAK,WAAW,GAAG;IAAE,SAAS,EAAE,oBAAoB,CAAA;CAAE,CAAC;;AA8kBvD,wBAMG"}
1
+ {"version":3,"file":"LivePreview.vue.d.ts","sourceRoot":"","sources":["../../../src/components/cms/LivePreview.vue"],"names":[],"mappings":"AAqTA,OAAO,EAUL,KAAK,oBAAoB,EAE1B,MAAM,eAAe,CAAA;AAqBtB;;;;;GAKG;AACH,KAAK,WAAW,GAAG;IAAE,SAAS,EAAE,oBAAoB,CAAA;CAAE,CAAC;;AAqlBvD,wBAMG"}