@alfakit/vue 0.1.1 → 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 (372) hide show
  1. package/CHANGELOG.md +16 -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/ActionButton.js.map +1 -1
  7. package/dist/components/actions/ActionButton.vue.d.ts.map +1 -1
  8. package/dist/components/actions/ActionButton.vue_vue_type_script_setup_true_lang.js +160 -159
  9. package/dist/components/actions/ActionButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  10. package/dist/components/actions/ActionGroupMenu.js.map +1 -1
  11. package/dist/components/actions/ActionGroupMenu.vue.d.ts.map +1 -1
  12. package/dist/components/actions/ActionGroupMenu.vue_vue_type_script_setup_true_lang.js +69 -65
  13. package/dist/components/actions/ActionGroupMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  14. package/dist/components/actions/ActionModal.js.map +1 -1
  15. package/dist/components/actions/ActionModal.vue.d.ts.map +1 -1
  16. package/dist/components/actions/ActionModal.vue_vue_type_script_setup_true_lang.js +221 -219
  17. package/dist/components/actions/ActionModal.vue_vue_type_script_setup_true_lang.js.map +1 -1
  18. package/dist/components/ai/AiCopilot.js.map +1 -1
  19. package/dist/components/ai/AiCopilot.vue.d.ts +2 -0
  20. package/dist/components/ai/AiCopilot.vue.d.ts.map +1 -1
  21. package/dist/components/ai/AiCopilot.vue_vue_type_script_setup_true_lang.js +7 -2
  22. package/dist/components/ai/AiCopilot.vue_vue_type_script_setup_true_lang.js.map +1 -1
  23. package/dist/components/cms/CmsPage.vue_vue_type_script_setup_true_lang.js +19 -19
  24. package/dist/components/cms/CmsPage.vue_vue_type_script_setup_true_lang.js.map +1 -1
  25. package/dist/components/cms/LivePreview.js.map +1 -1
  26. package/dist/components/cms/LivePreview.vue.d.ts.map +1 -1
  27. package/dist/components/cms/LivePreview.vue_vue_type_script_setup_true_lang.js +83 -83
  28. package/dist/components/cms/LivePreview.vue_vue_type_script_setup_true_lang.js.map +1 -1
  29. package/dist/components/fields/BuilderField.js.map +1 -1
  30. package/dist/components/fields/BuilderField.vue.d.ts.map +1 -1
  31. package/dist/components/fields/BuilderField.vue_vue_type_script_setup_true_lang.js +162 -157
  32. package/dist/components/fields/BuilderField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  33. package/dist/components/fields/ColorPickerField.js.map +1 -1
  34. package/dist/components/fields/ColorPickerField.vue.d.ts.map +1 -1
  35. package/dist/components/fields/ColorPickerField.vue_vue_type_script_setup_true_lang.js +1 -0
  36. package/dist/components/fields/ColorPickerField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  37. package/dist/components/fields/ComboboxSelect.js.map +1 -1
  38. package/dist/components/fields/ComboboxSelect.vue.d.ts.map +1 -1
  39. package/dist/components/fields/ComboboxSelect.vue_vue_type_script_setup_true_lang.js +1 -1
  40. package/dist/components/fields/ComboboxSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  41. package/dist/components/fields/FileUploadField.js.map +1 -1
  42. package/dist/components/fields/FileUploadField.vue.d.ts.map +1 -1
  43. package/dist/components/fields/FileUploadField.vue_vue_type_script_setup_true_lang.js +183 -183
  44. package/dist/components/fields/FileUploadField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  45. package/dist/components/fields/ImageEditorDialog.js.map +1 -1
  46. package/dist/components/fields/ImageEditorDialog.vue.d.ts.map +1 -1
  47. package/dist/components/fields/ImageEditorDialog.vue_vue_type_script_setup_true_lang.js +46 -46
  48. package/dist/components/fields/ImageEditorDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  49. package/dist/components/fields/KeyValueField.js.map +1 -1
  50. package/dist/components/fields/KeyValueField.vue.d.ts.map +1 -1
  51. package/dist/components/fields/KeyValueField.vue_vue_type_script_setup_true_lang.js +66 -66
  52. package/dist/components/fields/KeyValueField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  53. package/dist/components/fields/ModalTablePicker.js.map +1 -1
  54. package/dist/components/fields/ModalTablePicker.vue.d.ts.map +1 -1
  55. package/dist/components/fields/ModalTablePicker.vue_vue_type_script_setup_true_lang.js +113 -113
  56. package/dist/components/fields/ModalTablePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  57. package/dist/components/fields/OneTimeCodeInputField.js.map +1 -1
  58. package/dist/components/fields/OneTimeCodeInputField.vue_vue_type_script_setup_true_lang.js +1 -2
  59. package/dist/components/fields/OneTimeCodeInputField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  60. package/dist/components/fields/RepeaterField.js.map +1 -1
  61. package/dist/components/fields/RepeaterField.vue.d.ts.map +1 -1
  62. package/dist/components/fields/RepeaterField.vue_vue_type_script_setup_true_lang.js +12 -12
  63. package/dist/components/fields/RepeaterField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  64. package/dist/components/fields/RichEditorInput.js.map +1 -1
  65. package/dist/components/fields/RichEditorInput.vue.d.ts.map +1 -1
  66. package/dist/components/fields/RichEditorInput.vue_vue_type_script_setup_true_lang.js +166 -165
  67. package/dist/components/fields/RichEditorInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  68. package/dist/components/fields/SelectField.js.map +1 -1
  69. package/dist/components/fields/SelectField.vue.d.ts.map +1 -1
  70. package/dist/components/fields/SelectField.vue_vue_type_script_setup_true_lang.js +2 -2
  71. package/dist/components/fields/SelectField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  72. package/dist/components/fields/SliderField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  73. package/dist/components/fields/TableColumnHeaders.js.map +1 -1
  74. package/dist/components/fields/TableColumnHeaders.vue.d.ts.map +1 -1
  75. package/dist/components/fields/TableColumnHeaders.vue_vue_type_script_setup_true_lang.js +6 -3
  76. package/dist/components/fields/TableColumnHeaders.vue_vue_type_script_setup_true_lang.js.map +1 -1
  77. package/dist/components/fields/item-actions.d.ts +2 -2
  78. package/dist/components/fields/item-actions.d.ts.map +1 -1
  79. package/dist/components/fields/item-actions.js +31 -31
  80. package/dist/components/fields/item-actions.js.map +1 -1
  81. package/dist/components/file-manager/FileManagerView.js.map +1 -1
  82. package/dist/components/file-manager/FileManagerView.vue_vue_type_script_setup_true_lang.js +1 -1
  83. package/dist/components/file-manager/FileManagerView.vue_vue_type_script_setup_true_lang.js.map +1 -1
  84. package/dist/components/form/FormBlock.js.map +1 -1
  85. package/dist/components/form/FormBlock.vue.d.ts.map +1 -1
  86. package/dist/components/form/FormBlock.vue_vue_type_script_setup_true_lang.js +81 -77
  87. package/dist/components/form/FormBlock.vue_vue_type_script_setup_true_lang.js.map +1 -1
  88. package/dist/components/form/form-context.js +25 -25
  89. package/dist/components/form/form-context.js.map +1 -1
  90. package/dist/components/kanban/KanbanBoard.js.map +1 -1
  91. package/dist/components/kanban/KanbanBoard.vue.d.ts.map +1 -1
  92. package/dist/components/kanban/KanbanBoard.vue_vue_type_script_setup_true_lang.js +5 -2
  93. package/dist/components/kanban/KanbanBoard.vue_vue_type_script_setup_true_lang.js.map +1 -1
  94. package/dist/components/kanban/KanbanColumnHeader.js.map +1 -1
  95. package/dist/components/kanban/KanbanColumnHeader.vue.d.ts.map +1 -1
  96. package/dist/components/kanban/KanbanColumnHeader.vue_vue_type_script_setup_true_lang.js +64 -64
  97. package/dist/components/kanban/KanbanColumnHeader.vue_vue_type_script_setup_true_lang.js.map +1 -1
  98. package/dist/components/layout/FusedGroupComponent.js.map +1 -1
  99. package/dist/components/layout/FusedGroupComponent.vue.d.ts.map +1 -1
  100. package/dist/components/layout/FusedGroupComponent.vue_vue_type_script_setup_true_lang.js +1 -0
  101. package/dist/components/layout/FusedGroupComponent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  102. package/dist/components/layout/SectionComponent.js.map +1 -1
  103. package/dist/components/layout/SectionComponent.vue.d.ts.map +1 -1
  104. package/dist/components/layout/SectionComponent.vue_vue_type_script_setup_true_lang.js +23 -23
  105. package/dist/components/layout/SectionComponent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  106. package/dist/components/layout/TabsComponent.js.map +1 -1
  107. package/dist/components/layout/TabsComponent.vue.d.ts.map +1 -1
  108. package/dist/components/layout/TabsComponent.vue_vue_type_script_setup_true_lang.js +76 -55
  109. package/dist/components/layout/TabsComponent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  110. package/dist/components/notifications/NotificationsMenu.js.map +1 -1
  111. package/dist/components/notifications/NotificationsMenu.vue.d.ts.map +1 -1
  112. package/dist/components/notifications/NotificationsMenu.vue_vue_type_script_setup_true_lang.js +44 -42
  113. package/dist/components/notifications/NotificationsMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  114. package/dist/components/panel/DebugPanel.vue_vue_type_script_setup_true_lang.js +8 -8
  115. package/dist/components/panel/DebugPanel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  116. package/dist/components/panel/GlobalSearch.js.map +1 -1
  117. package/dist/components/panel/GlobalSearch.vue.d.ts.map +1 -1
  118. package/dist/components/panel/GlobalSearch.vue_vue_type_script_setup_true_lang.js +1 -0
  119. package/dist/components/panel/GlobalSearch.vue_vue_type_script_setup_true_lang.js.map +1 -1
  120. package/dist/components/panel/GlobalSearchPalette.js.map +1 -1
  121. package/dist/components/panel/GlobalSearchPalette.vue.d.ts.map +1 -1
  122. package/dist/components/panel/GlobalSearchPalette.vue_vue_type_script_setup_true_lang.js +102 -96
  123. package/dist/components/panel/GlobalSearchPalette.vue_vue_type_script_setup_true_lang.js.map +1 -1
  124. package/dist/components/panel/NavGroup.vue_vue_type_script_setup_true_lang.js +10 -10
  125. package/dist/components/panel/NavGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  126. package/dist/components/panel/NavGroupFlyout.vue_vue_type_script_setup_true_lang.js +9 -9
  127. package/dist/components/panel/NavGroupFlyout.vue_vue_type_script_setup_true_lang.js.map +1 -1
  128. package/dist/components/panel/NavItem.vue_vue_type_script_setup_true_lang.js +16 -16
  129. package/dist/components/panel/NavItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  130. package/dist/components/panel/NavSubItem.vue_vue_type_script_setup_true_lang.js +10 -10
  131. package/dist/components/panel/NavSubItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  132. package/dist/components/panel/ShortcutKeys.js.map +1 -1
  133. package/dist/components/panel/ShortcutKeys.vue.d.ts.map +1 -1
  134. package/dist/components/panel/ShortcutKeys.vue_vue_type_script_setup_true_lang.js +4 -1
  135. package/dist/components/panel/ShortcutKeys.vue_vue_type_script_setup_true_lang.js.map +1 -1
  136. package/dist/components/panel/TenantMenu.js.map +1 -1
  137. package/dist/components/panel/TenantMenu.vue_vue_type_script_setup_true_lang.js +37 -37
  138. package/dist/components/panel/TenantMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  139. package/dist/components/panel/Topbar.vue_vue_type_script_setup_true_lang.js +11 -11
  140. package/dist/components/panel/Topbar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  141. package/dist/components/realtime/use-live-updates.d.ts.map +1 -1
  142. package/dist/components/realtime/use-live-updates.js +24 -23
  143. package/dist/components/realtime/use-live-updates.js.map +1 -1
  144. package/dist/components/table/BooleanCell.vue_vue_type_script_setup_true_lang.js +2 -1
  145. package/dist/components/table/BooleanCell.vue_vue_type_script_setup_true_lang.js.map +1 -1
  146. package/dist/components/table/ColumnHeader.js.map +1 -1
  147. package/dist/components/table/ColumnHeader.vue.d.ts.map +1 -1
  148. package/dist/components/table/ColumnHeader.vue_vue_type_script_setup_true_lang.js +55 -49
  149. package/dist/components/table/ColumnHeader.vue_vue_type_script_setup_true_lang.js.map +1 -1
  150. package/dist/components/table/ColumnManager.js.map +1 -1
  151. package/dist/components/table/ColumnManager.vue.d.ts.map +1 -1
  152. package/dist/components/table/ColumnManager.vue_vue_type_script_setup_true_lang.js +5 -4
  153. package/dist/components/table/ColumnManager.vue_vue_type_script_setup_true_lang.js.map +1 -1
  154. package/dist/components/table/ContentLayoutSort.js.map +1 -1
  155. package/dist/components/table/ContentLayoutSort.vue.d.ts.map +1 -1
  156. package/dist/components/table/ContentLayoutSort.vue_vue_type_script_setup_true_lang.js +5 -5
  157. package/dist/components/table/ContentLayoutSort.vue_vue_type_script_setup_true_lang.js.map +1 -1
  158. package/dist/components/table/GroupHeaderRow.js.map +1 -1
  159. package/dist/components/table/GroupHeaderRow.vue.d.ts.map +1 -1
  160. package/dist/components/table/GroupHeaderRow.vue_vue_type_script_setup_true_lang.js +55 -34
  161. package/dist/components/table/GroupHeaderRow.vue_vue_type_script_setup_true_lang.js.map +1 -1
  162. package/dist/components/table/SelectCell.js.map +1 -1
  163. package/dist/components/table/SelectCell.vue.d.ts.map +1 -1
  164. package/dist/components/table/SelectCell.vue_vue_type_script_setup_true_lang.js +26 -20
  165. package/dist/components/table/SelectCell.vue_vue_type_script_setup_true_lang.js.map +1 -1
  166. package/dist/components/table/SelectComboboxCell.vue_vue_type_script_setup_true_lang.js +2 -1
  167. package/dist/components/table/SelectComboboxCell.vue_vue_type_script_setup_true_lang.js.map +1 -1
  168. package/dist/components/table/TableCellContent.js.map +1 -1
  169. package/dist/components/table/TableCellContent.vue.d.ts.map +1 -1
  170. package/dist/components/table/TableCellContent.vue_vue_type_script_setup_true_lang.js +4 -3
  171. package/dist/components/table/TableCellContent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  172. package/dist/components/table/TablePagination.js.map +1 -1
  173. package/dist/components/table/TablePagination.vue.d.ts.map +1 -1
  174. package/dist/components/table/TablePagination.vue_vue_type_script_setup_true_lang.js +87 -87
  175. package/dist/components/table/TablePagination.vue_vue_type_script_setup_true_lang.js.map +1 -1
  176. package/dist/components/table/TextInputCell.js.map +1 -1
  177. package/dist/components/table/TextInputCell.vue.d.ts.map +1 -1
  178. package/dist/components/table/TextInputCell.vue_vue_type_script_setup_true_lang.js +40 -34
  179. package/dist/components/table/TextInputCell.vue_vue_type_script_setup_true_lang.js.map +1 -1
  180. package/dist/components/table/cell-update.d.ts +6 -0
  181. package/dist/components/table/cell-update.d.ts.map +1 -1
  182. package/dist/components/table/cell-update.js.map +1 -1
  183. package/dist/components/translation-manager/TranslationManagerView.vue_vue_type_script_setup_true_lang.js +1 -1
  184. package/dist/components/translation-manager/TranslationManagerView.vue_vue_type_script_setup_true_lang.js.map +1 -1
  185. package/dist/components/ui/CommandAutoHighlight.js +7 -0
  186. package/dist/components/ui/CommandAutoHighlight.js.map +1 -0
  187. package/dist/components/ui/CommandAutoHighlight.vue.d.ts +21 -0
  188. package/dist/components/ui/CommandAutoHighlight.vue.d.ts.map +1 -0
  189. package/dist/components/ui/CommandAutoHighlight.vue_vue_type_script_setup_true_lang.js +18 -0
  190. package/dist/components/ui/CommandAutoHighlight.vue_vue_type_script_setup_true_lang.js.map +1 -0
  191. package/dist/components/ui/DialogContent.js.map +1 -1
  192. package/dist/components/ui/DialogContent.vue.d.ts.map +1 -1
  193. package/dist/components/ui/DialogContent.vue_vue_type_script_setup_true_lang.js +13 -12
  194. package/dist/components/ui/DialogContent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  195. package/dist/components/ui/PopoverContent.js.map +1 -1
  196. package/dist/components/ui/PopoverContent.vue.d.ts.map +1 -1
  197. package/dist/components/ui/PopoverContent.vue_vue_type_script_setup_true_lang.js +9 -8
  198. package/dist/components/ui/PopoverContent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  199. package/dist/components/ui/SheetContent.js.map +1 -1
  200. package/dist/components/ui/SheetContent.vue.d.ts.map +1 -1
  201. package/dist/components/ui/SheetContent.vue_vue_type_script_setup_true_lang.js +13 -12
  202. package/dist/components/ui/SheetContent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  203. package/dist/components/ui/TooltipContent.js.map +1 -1
  204. package/dist/components/ui/TooltipContent.vue.d.ts.map +1 -1
  205. package/dist/components/ui/TooltipContent.vue_vue_type_script_setup_true_lang.js +9 -8
  206. package/dist/components/ui/TooltipContent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  207. package/dist/components.css +347 -0
  208. package/dist/context.d.ts +7 -0
  209. package/dist/context.d.ts.map +1 -1
  210. package/dist/context.js +29 -26
  211. package/dist/context.js.map +1 -1
  212. package/dist/create-alfakit.d.ts.map +1 -1
  213. package/dist/create-alfakit.js +33 -31
  214. package/dist/create-alfakit.js.map +1 -1
  215. package/dist/eject-manifest.json +11 -2
  216. package/dist/index.d.ts +1 -0
  217. package/dist/index.d.ts.map +1 -1
  218. package/dist/index.js +219 -217
  219. package/dist/layouts/AppLayout.vue_vue_type_script_setup_true_lang.js +8 -8
  220. package/dist/layouts/AppLayout.vue_vue_type_script_setup_true_lang.js.map +1 -1
  221. package/dist/layouts/AuthLayout.vue_vue_type_script_setup_true_lang.js +9 -9
  222. package/dist/layouts/FullscreenLayout.vue_vue_type_script_setup_true_lang.js +8 -8
  223. package/dist/layouts/FullscreenLayout.vue_vue_type_script_setup_true_lang.js.map +1 -1
  224. package/dist/layouts/TopNavLayout.vue_vue_type_script_setup_true_lang.js +15 -15
  225. package/dist/layouts/TopNavLayout.vue_vue_type_script_setup_true_lang.js.map +1 -1
  226. package/dist/layouts/lazy-layouts.d.ts +10 -0
  227. package/dist/layouts/lazy-layouts.d.ts.map +1 -0
  228. package/dist/layouts/lazy-layouts.js +8 -0
  229. package/dist/layouts/lazy-layouts.js.map +1 -0
  230. package/dist/layouts/panel-layouts.d.ts +8 -0
  231. package/dist/layouts/panel-layouts.d.ts.map +1 -0
  232. package/dist/layouts/panel-layouts.js +15 -0
  233. package/dist/layouts/panel-layouts.js.map +1 -0
  234. package/dist/lib/lazy.d.ts.map +1 -1
  235. package/dist/lib/lazy.js +2 -2
  236. package/dist/lib/lazy.js.map +1 -1
  237. package/dist/pages/PageShell.js.map +1 -1
  238. package/dist/pages/PageShell.vue.d.ts.map +1 -1
  239. package/dist/pages/PageShell.vue_vue_type_script_setup_true_lang.js +39 -42
  240. package/dist/pages/PageShell.vue_vue_type_script_setup_true_lang.js.map +1 -1
  241. package/dist/standalone/AlfakitComponent.js.map +1 -1
  242. package/dist/standalone/AlfakitComponent.vue.d.ts.map +1 -1
  243. package/dist/standalone/AlfakitComponent.vue_vue_type_script_setup_true_lang.js +56 -52
  244. package/dist/standalone/AlfakitComponent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  245. package/dist/standalone/AlfakitToaster.js.map +1 -1
  246. package/dist/standalone/AlfakitToaster.vue.d.ts.map +1 -1
  247. package/dist/standalone/AlfakitToaster.vue_vue_type_script_setup_true_lang.js +23 -15
  248. package/dist/standalone/AlfakitToaster.vue_vue_type_script_setup_true_lang.js.map +1 -1
  249. package/dist/standalone.css +54 -0
  250. package/dist/starter-kit/AlfakitStarterKitRoot.js.map +1 -1
  251. package/dist/starter-kit/AlfakitStarterKitRoot.vue.d.ts +2 -2
  252. package/dist/starter-kit/AlfakitStarterKitRoot.vue.d.ts.map +1 -1
  253. package/dist/starter-kit/AlfakitStarterKitRoot.vue_vue_type_script_setup_true_lang.js +17 -12
  254. package/dist/starter-kit/AlfakitStarterKitRoot.vue_vue_type_script_setup_true_lang.js.map +1 -1
  255. package/dist/starter-kit/dashboard-widgets.d.ts +54 -0
  256. package/dist/starter-kit/dashboard-widgets.d.ts.map +1 -0
  257. package/dist/starter-kit/dashboard-widgets.js +54 -0
  258. package/dist/starter-kit/dashboard-widgets.js.map +1 -0
  259. package/dist/starter-kit/index.d.ts +2 -1
  260. package/dist/starter-kit/index.d.ts.map +1 -1
  261. package/dist/starter-kit/index.js +5 -4
  262. package/dist/starter-kit/runtime.d.ts +6 -0
  263. package/dist/starter-kit/runtime.d.ts.map +1 -1
  264. package/dist/starter-kit/runtime.js +19 -15
  265. package/dist/starter-kit/runtime.js.map +1 -1
  266. package/dist/starter-kit/starter-kit.d.ts.map +1 -1
  267. package/dist/starter-kit/starter-kit.js +8 -8
  268. package/dist/starter-kit/starter-kit.js.map +1 -1
  269. package/dist/starter-kit/widgets/CopilotTrigger.js +7 -0
  270. package/dist/starter-kit/widgets/CopilotTrigger.js.map +1 -0
  271. package/dist/starter-kit/widgets/CopilotTrigger.vue.d.ts +12 -0
  272. package/dist/starter-kit/widgets/CopilotTrigger.vue.d.ts.map +1 -0
  273. package/dist/starter-kit/widgets/CopilotTrigger.vue_vue_type_script_setup_true_lang.js +23 -0
  274. package/dist/starter-kit/widgets/CopilotTrigger.vue_vue_type_script_setup_true_lang.js.map +1 -0
  275. package/dist/starter-kit/widgets/LoadedCopilot.js +7 -0
  276. package/dist/starter-kit/widgets/LoadedCopilot.js.map +1 -0
  277. package/dist/starter-kit/widgets/LoadedCopilot.vue.d.ts +8 -0
  278. package/dist/starter-kit/widgets/LoadedCopilot.vue.d.ts.map +1 -0
  279. package/dist/starter-kit/widgets/LoadedCopilot.vue_vue_type_script_setup_true_lang.js +31 -0
  280. package/dist/starter-kit/widgets/LoadedCopilot.vue_vue_type_script_setup_true_lang.js.map +1 -0
  281. package/dist/starter-kit/widgets/SearchTrigger.js.map +1 -1
  282. package/dist/starter-kit/widgets/SearchTrigger.vue.d.ts.map +1 -1
  283. package/dist/starter-kit/widgets/SearchTrigger.vue_vue_type_script_setup_true_lang.js +1 -0
  284. package/dist/starter-kit/widgets/SearchTrigger.vue_vue_type_script_setup_true_lang.js.map +1 -1
  285. package/dist/starter-kit/widgets/StarterKitImpersonationBanner.js +7 -0
  286. package/dist/starter-kit/widgets/StarterKitImpersonationBanner.js.map +1 -0
  287. package/dist/starter-kit/widgets/StarterKitImpersonationBanner.vue.d.ts +8 -0
  288. package/dist/starter-kit/widgets/StarterKitImpersonationBanner.vue.d.ts.map +1 -0
  289. package/dist/starter-kit/widgets/StarterKitImpersonationBanner.vue_vue_type_script_setup_true_lang.js +34 -0
  290. package/dist/starter-kit/widgets/StarterKitImpersonationBanner.vue_vue_type_script_setup_true_lang.js.map +1 -0
  291. package/dist/starter-kit/widgets/TenantChooser.js.map +1 -1
  292. package/dist/starter-kit/widgets/TenantChooser.vue_vue_type_script_setup_true_lang.js +1 -1
  293. package/dist/starter-kit/widgets/TenantChooser.vue_vue_type_script_setup_true_lang.js.map +1 -1
  294. package/dist/starter-kit/widgets/index.d.ts +40 -9
  295. package/dist/starter-kit/widgets/index.d.ts.map +1 -1
  296. package/dist/starter-kit/widgets/index.js +21 -18
  297. package/dist/starter-kit/widgets/index.js.map +1 -1
  298. package/dist/starter-kit/widgets/loaded.d.ts +10 -0
  299. package/dist/starter-kit/widgets/loaded.d.ts.map +1 -0
  300. package/dist/starter-kit/widgets/loaded.js +5 -0
  301. package/dist/styles.css +9 -2
  302. package/dist/themes.css +8 -335
  303. package/package.json +3 -3
  304. package/src/AlfakitRoot.vue +9 -1
  305. package/src/components/actions/ActionButton.vue +14 -6
  306. package/src/components/actions/ActionGroupMenu.vue +13 -1
  307. package/src/components/actions/ActionModal.vue +12 -1
  308. package/src/components/ai/AiCopilot.vue +7 -1
  309. package/src/components/cms/LivePreview.vue +8 -2
  310. package/src/components/fields/BuilderField.vue +15 -2
  311. package/src/components/fields/ColorPickerField.vue +1 -0
  312. package/src/components/fields/ComboboxSelect.vue +1 -1
  313. package/src/components/fields/FileUploadField.vue +14 -11
  314. package/src/components/fields/ImageEditorDialog.vue +7 -3
  315. package/src/components/fields/KeyValueField.vue +3 -2
  316. package/src/components/fields/ModalTablePicker.vue +7 -2
  317. package/src/components/fields/OneTimeCodeInputField.vue +1 -1
  318. package/src/components/fields/RepeaterField.vue +2 -3
  319. package/src/components/fields/RichEditorInput.vue +3 -0
  320. package/src/components/fields/SelectField.vue +4 -2
  321. package/src/components/fields/TableColumnHeaders.vue +6 -1
  322. package/src/components/fields/item-actions.ts +31 -10
  323. package/src/components/file-manager/FileManagerView.vue +1 -1
  324. package/src/components/form/FormBlock.vue +26 -1
  325. package/src/components/form/form-context.ts +3 -3
  326. package/src/components/kanban/KanbanBoard.vue +15 -3
  327. package/src/components/kanban/KanbanColumnHeader.vue +6 -4
  328. package/src/components/layout/FusedGroupComponent.vue +1 -0
  329. package/src/components/layout/SectionComponent.vue +10 -4
  330. package/src/components/layout/TabsComponent.vue +61 -5
  331. package/src/components/notifications/NotificationsMenu.vue +11 -0
  332. package/src/components/panel/GlobalSearch.vue +1 -0
  333. package/src/components/panel/GlobalSearchPalette.vue +2 -0
  334. package/src/components/panel/ShortcutKeys.vue +1 -0
  335. package/src/components/panel/TenantMenu.vue +2 -2
  336. package/src/components/realtime/use-live-updates.ts +3 -1
  337. package/src/components/table/ColumnHeader.vue +23 -12
  338. package/src/components/table/ColumnManager.vue +12 -8
  339. package/src/components/table/ContentLayoutSort.vue +7 -1
  340. package/src/components/table/GroupHeaderRow.vue +27 -0
  341. package/src/components/table/SelectCell.vue +5 -2
  342. package/src/components/table/TableCellContent.vue +4 -2
  343. package/src/components/table/TablePagination.vue +12 -7
  344. package/src/components/table/TextInputCell.vue +11 -5
  345. package/src/components/table/cell-update.ts +6 -0
  346. package/src/components/ui/CommandAutoHighlight.vue +27 -0
  347. package/src/components/ui/DialogContent.vue +5 -1
  348. package/src/components/ui/PopoverContent.vue +5 -1
  349. package/src/components/ui/SheetContent.vue +5 -1
  350. package/src/components/ui/TooltipContent.vue +5 -1
  351. package/src/context.ts +10 -0
  352. package/src/create-alfakit.ts +5 -0
  353. package/src/index.ts +2 -0
  354. package/src/layouts/lazy-layouts.ts +14 -0
  355. package/src/layouts/panel-layouts.ts +17 -0
  356. package/src/lib/lazy.ts +11 -1
  357. package/src/pages/PageShell.vue +5 -6
  358. package/src/standalone/AlfakitComponent.vue +17 -6
  359. package/src/standalone/AlfakitToaster.vue +12 -2
  360. package/src/starter-kit/AlfakitStarterKitRoot.vue +12 -3
  361. package/src/starter-kit/dashboard-widgets.ts +93 -0
  362. package/src/starter-kit/index.ts +7 -1
  363. package/src/starter-kit/runtime.ts +17 -1
  364. package/src/starter-kit/starter-kit.ts +2 -1
  365. package/src/starter-kit/widgets/CopilotTrigger.vue +58 -0
  366. package/src/starter-kit/widgets/LoadedCopilot.vue +29 -0
  367. package/src/starter-kit/widgets/SearchTrigger.vue +1 -0
  368. package/src/starter-kit/widgets/StarterKitImpersonationBanner.vue +57 -0
  369. package/src/starter-kit/widgets/TenantChooser.vue +1 -1
  370. package/src/starter-kit/widgets/index.ts +56 -11
  371. package/src/starter-kit/widgets/loaded.ts +9 -0
  372. package/src/styles.css +9 -2
@@ -1 +1 @@
1
- {"version":3,"file":"RichEditorInput.js","names":["_sfc_main","RichEditorInput_vue_vue_type_script_setup_true_lang_default","RichEditorInput_default"],"sources":["../../../src/components/fields/RichEditorInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { LoadedRichEditorExtensions, RichEditorPanel, RichEditorSchema } from '@alfakit/core'\nimport {\n allToolbarButtons,\n attachToolbarKeyboard,\n focusToolbar,\n isToolbarShortcut,\n detailsNodeConfigs,\n gridNodeConfigs,\n leadExtensionConfig,\n linkExtensionOptions,\n smallMarkConfig,\n EditorAttachments,\n fieldIds,\n fileAttachmentError,\n floatingToolbarStyle,\n highlightMarkConfig,\n htmlToMarkdown,\n resizableImageAttributes,\n resizableImageOptions,\n resolveFloatingToolbar,\n resolveStickyOffset,\n setTextColor,\n showsTableToolbar,\n subscriptMarkConfig,\n superscriptMarkConfig,\n TABLE_TOOLBAR_BUTTONS,\n textAlignExtensionConfig,\n textColorMarkConfig,\n toEditorDocument,\n toolbarButtonLabel,\n toolbarCommands,\n panelUploadOptions,\n uploadTemporaryFile,\n} from '@alfakit/core'\nimport { EraserIcon } from '@lucide/vue'\nimport Image from '@tiptap/extension-image'\nimport Link from '@tiptap/extension-link'\nimport Placeholder from '@tiptap/extension-placeholder'\nimport { TableKit } from '@tiptap/extension-table'\nimport StarterKit from '@tiptap/starter-kit'\nimport {\n EditorContent,\n Extension,\n Mark,\n Node,\n useEditor,\n type Editor,\n type Extensions,\n} from '@tiptap/vue-3'\nimport { computed, onBeforeUnmount, onMounted, ref, shallowRef, watch } from 'vue'\nimport { useActionRunner, usePanel, useT } from '../../context'\nimport { cn } from '../../lib/utils'\nimport { useField } from '../form/form-context'\nimport FieldWrapper from '../schema/FieldWrapper.vue'\nimport Button from '../ui/Button.vue'\nimport { useRichEditorExtensions } from './rich-editor-extensions'\nimport RichEditorSidePanel from './RichEditorSidePanel.vue'\nimport RichEditorSuggestions from './RichEditorSuggestions.vue'\nimport RichEditorToolbarEntries from './RichEditorToolbarEntries.vue'\n\ntype MarkConfig = Parameters<typeof Mark.create>[0]\ntype NodeConfig = Parameters<typeof Node.create>[0]\ntype ExtensionConfig = Parameters<typeof Extension.create>[0]\n\n/**\n * Resize handles of `resizableImages()` (Tiptap's node view adds bare `data-resize-handle`\n * elements): round dots on the corners, shown on hover and while the image is selected.\n */\nconst RESIZE_HANDLE_CLASSES =\n '[&_[data-resize-handle]]:z-10 [&_[data-resize-handle]]:size-3 [&_[data-resize-handle]]:rounded-full [&_[data-resize-handle]]:border-2 [&_[data-resize-handle]]:border-background [&_[data-resize-handle]]:bg-primary [&_[data-resize-handle]]:opacity-0 [&_[data-resize-container]:hover_[data-resize-handle]]:opacity-100 [&_.ProseMirror-selectednode_[data-resize-handle]]:opacity-100 [&_[data-resize-handle=bottom-right]]:cursor-nwse-resize [&_[data-resize-handle=top-left]]:cursor-nwse-resize [&_[data-resize-handle=bottom-left]]:cursor-nesw-resize [&_[data-resize-handle=top-right]]:cursor-nesw-resize'\n\n/** The image extension, with drag handles for `resizableImages()`. */\nfunction imageExtension(resizable: boolean) {\n if (!resizable) return Image\n\n return Image.extend({\n addAttributes() {\n return resizableImageAttributes(this.parent?.() ?? {})\n },\n }).configure(resizableImageOptions())\n}\n\n/** Extensions for the extra toolbar buttons (only those the toolbar uses are loaded). */\nfunction toolbarExtensions(buttons: string[], markdown: boolean): Extensions {\n const has = (...names: string[]) => names.some((name) => buttons.includes(name))\n const extensions: Extensions = []\n\n if (has('table')) extensions.push(TableKit.configure({ table: { resizable: false } }))\n // Markdown has no syntax for these.\n if (markdown) return extensions\n\n if (has('highlight')) extensions.push(Mark.create(highlightMarkConfig() as MarkConfig))\n if (has('subscript')) extensions.push(Mark.create(subscriptMarkConfig() as MarkConfig))\n if (has('superscript')) extensions.push(Mark.create(superscriptMarkConfig() as MarkConfig))\n if (has('textColor')) extensions.push(Mark.create(textColorMarkConfig() as MarkConfig))\n if (has('alignStart', 'alignCenter', 'alignEnd', 'alignJustify')) {\n extensions.push(Extension.create(textAlignExtensionConfig() as ExtensionConfig))\n }\n if (has('details')) {\n extensions.push(...detailsNodeConfigs().map((config) => Node.create(config as NodeConfig)))\n }\n if (has('small')) extensions.push(Mark.create(smallMarkConfig() as MarkConfig))\n if (has('lead')) extensions.push(Extension.create(leadExtensionConfig() as ExtensionConfig))\n if (has('grid', 'gridDelete', 'gridAddColumnBefore', 'gridAddColumnAfter', 'gridDeleteColumn')) {\n extensions.push(...gridNodeConfigs().map((config) => Node.create(config as NodeConfig)))\n }\n\n return extensions\n}\n\nconst props = defineProps<{ component: RichEditorSchema; plugins: LoadedRichEditorExtensions }>()\nconst t = useT()\nconst panel = usePanel()\nconst runner = useActionRunner()\nconst { value, setValue, blur, error, id, disabled, readOnly, aria } = useField<unknown>(\n () => props.component,\n)\nconst fileInput = ref<HTMLInputElement | null>(null)\nconst isMarkdown = computed(() => props.component.type === 'MarkdownEditor')\nconst editable = computed(() => !disabled.value && !readOnly.value)\n// Uploaded images preview from a local URL but are stored by their `tmp:` key.\nconst attachments = new EditorAttachments()\nconst isJson = computed(() => Boolean(props.component.json) && !isMarkdown.value)\n// The editor's live instance, for the custom block node views and suggestions.\nconst liveEditor = shallowRef<Editor | undefined>()\nconst rich = useRichEditorExtensions(() => props.component, liveEditor)\n// The open toolbar panel (the text colour palette).\nconst openPanel = ref<'textColor' | null>(null)\n// The open side panel (custom blocks or merge tags).\nconst initialSidePanel = (): RichEditorPanel | null => {\n const initial = props.component.activePanel ?? null\n\n if (initial === 'customBlocks') return props.component.customBlocks?.length ? initial : null\n if (initial === 'mergeTags') return props.component.mergeTags?.length ? initial : null\n\n return null\n}\nconst sidePanel = ref<RichEditorPanel | null>(initialSidePanel())\nconst attachmentError = ref<string | null>(null)\n// Bumped on every transaction so active states and the table row follow the cursor.\nconst selectionTick = ref(0)\nconst stickyTop = ref<string | null>(null)\nconst sticky = computed(() =>\n Boolean(props.component.stickyToolbar || props.component.stickyPanels),\n)\n\nconst updateStickyTop = () => {\n stickyTop.value = sticky.value ? resolveStickyOffset(props.component.stickyOffset) : null\n}\n\nonMounted(updateStickyTop)\nwatch([sticky, () => props.component.stickyOffset], updateStickyTop)\n\n// Built-in buttons, plugin tools and commands of plugin JavaScript extensions.\nconst commands = computed(() =>\n toolbarCommands(\n props.component.editorTools,\n {\n runAction: (tool, args) =>\n tool.action\n ? runner.runField(tool.action, { ...rich.context.value, arguments: args })\n : Promise.resolve(undefined),\n editor: () => liveEditor.value ?? null,\n },\n props.plugins.commands,\n ),\n)\n\n// Field state ↔ editor content: HTML, Markdown (loaded from the server's HTML) or a\n// Tiptap JSON document. `tmp:` upload keys become local preview URLs and back.\nconst stateToContent = (state: unknown): string | Record<string, unknown> => {\n if (isJson.value) {\n const document = toEditorDocument(state)\n\n return document ? JSON.parse(attachments.toEditor(JSON.stringify(document))) : ''\n }\n\n return attachments.toEditor(\n ((isMarkdown.value\n ? typeof props.component.html === 'string'\n ? props.component.html\n : null\n : state) as string | null) ?? '',\n )\n}\nconst editorToState = (instance: Pick<Editor, 'isEmpty' | 'getJSON' | 'getHTML'>): unknown => {\n if (instance.isEmpty) return null\n if (isJson.value) return JSON.parse(attachments.toState(JSON.stringify(instance.getJSON())))\n\n const html = instance.getHTML()\n\n return attachments.toState(isMarkdown.value ? htmlToMarkdown(html) : html)\n}\n\nonBeforeUnmount(() => attachments.destroy())\n\n// Keyboard access to the toolbars (roving tabindex, arrows, Escape, Alt+F10).\ntype ToolbarSlot = 'main' | 'table' | 'floating'\nconst toolbarElements: Record<ToolbarSlot, { element: HTMLElement; detach: () => void } | null> = {\n main: null,\n table: null,\n floating: null,\n}\nconst toolbars = () => [\n toolbarElements.floating?.element,\n toolbarElements.main?.element,\n toolbarElements.table?.element,\n]\nconst setToolbar = (slot: ToolbarSlot, element: unknown) => {\n const current = toolbarElements[slot]\n\n if (current?.element === element) return\n\n current?.detach()\n toolbarElements[slot] =\n element instanceof HTMLElement\n ? {\n element,\n detach: attachToolbarKeyboard(element, {\n onEscape: () => liveEditor.value?.commands.focus(),\n toolbars,\n }),\n }\n : null\n}\n\nonBeforeUnmount(() => {\n for (const slot of ['main', 'table', 'floating'] as const) setToolbar(slot, null)\n})\n\nconst editor = useEditor({\n extensions: [\n StarterKit.configure({ link: false }),\n Link.configure(linkExtensionOptions(props.component.linkProtocols)),\n imageExtension(Boolean(props.component.resizableImages) && !isMarkdown.value),\n Placeholder.configure({ placeholder: props.component.placeholder ?? '' }),\n ...toolbarExtensions(allToolbarButtons(props.component), isMarkdown.value),\n ...(isMarkdown.value ? [] : rich.extensions),\n ...(isMarkdown.value ? [] : (props.plugins.extensions as Extensions)),\n ],\n // Markdown is loaded from the server's HTML rendering of it, never parsed as HTML.\n content: stateToContent(value.value),\n editable: editable.value,\n editorProps: {\n // The mention / merge tag popup takes the arrow, Enter, Tab and Escape keys.\n handleKeyDown: (_view, event) => {\n // Alt+F10: into the floating toolbar, else the main one.\n if (isToolbarShortcut(event)) return focusToolbar(toolbars())\n\n return liveEditor.value ? rich.suggestions.handleKeyDown(event, liveEditor.value) : false\n },\n // ProseMirror reads its DOM attributes on every view update, so they follow `aria`.\n attributes: () => ({\n class: cn(\n 'alfakit-prose min-h-32 px-3 py-2 text-sm outline-none',\n props.component.resizableImages && RESIZE_HANDLE_CLASSES,\n ),\n // Runtime sizes cannot be Tailwind classes (they would never be generated).\n ...(props.component.minHeight ? { style: `min-height: ${props.component.minHeight}px` } : {}),\n id,\n // Each paragraph follows its own script, so Arabic and English mix correctly.\n dir: 'auto',\n role: 'textbox',\n 'aria-multiline': 'true',\n ...(props.component.label ? { 'aria-labelledby': fieldIds(id).label } : {}),\n ...Object.fromEntries(\n Object.entries(aria.value).map(([name, attribute]) => [name, String(attribute)]),\n ),\n }),\n },\n onUpdate: ({ editor: instance }) => {\n setValue(editorToState(instance))\n },\n onTransaction: ({ editor: instance }) => {\n rich.suggestions.update(instance)\n selectionTick.value++\n },\n onBlur: () => {\n rich.suggestions.close()\n blur()\n },\n})\n\nwatch(\n editor,\n (instance) => {\n liveEditor.value = instance\n },\n { immediate: true },\n)\n\n// Keep editor in sync when the server refreshes the state.\nwatch(value, (next) => {\n const instance = editor.value\n\n if (!instance) return\n\n const current = editorToState(instance)\n const same = isJson.value\n ? JSON.stringify(toEditorDocument(next)) === JSON.stringify(current)\n : (next ?? '') === (current ?? '')\n\n if (!same) {\n instance.commands.setContent(stateToContent(next), { emitUpdate: false })\n }\n})\n\nwatch(editable, (isEditable) => {\n editor.value?.setEditable(isEditable)\n})\n\n// Re-apply the editable element's attributes when the error or description changes.\nwatch(aria, () => {\n if (editor.value && !editor.value.isDestroyed) {\n editor.value.view.setProps({})\n }\n})\n\n// A floating toolbar follows its selection while the page scrolls.\nwatch(\n () => Boolean(props.component.floatingToolbars),\n (hasFloatingToolbars, _previous, onCleanup) => {\n if (!hasFloatingToolbars || typeof window === 'undefined') return\n\n const onScroll = () => selectionTick.value++\n\n window.addEventListener('scroll', onScroll, { capture: true, passive: true })\n onCleanup(() => window.removeEventListener('scroll', onScroll, { capture: true }))\n },\n { immediate: true },\n)\n\nconst pickImage = () => fileInput.value?.click()\n\nconst uploadImage = async (file: File) => {\n if (!panel.value.endpoints.upload || !editor.value) return\n\n // The server checks again when the form is saved.\n const problem = fileAttachmentError(file, props.component.fileAttachments)\n\n if (problem) {\n attachmentError.value =\n problem === 'too_large'\n ? t('form.file_too_large', {}, 'This file is too large.')\n : t('form.file_invalid_type', {}, 'This file type is not allowed.')\n\n return\n }\n\n attachmentError.value = null\n\n let response: { key: string }\n\n try {\n // Large attachments go in resumable chunks.\n response = await uploadTemporaryFile(\n panel.value.endpoints.upload,\n file,\n panelUploadOptions(panel.value, props.component.fileAttachments.uploadPolicy),\n )\n } catch (error) {\n attachmentError.value =\n (error as { errors?: Record<string, string[]> }).errors?.file?.[0] ??\n t('form.upload_failed', {}, 'The file could not be uploaded.')\n\n return\n }\n\n const src = attachments.add(response.key, file)\n\n editor.value.chain().focus().setImage({ src, alt: file.name }).run()\n}\n\nconst onFilePicked = (event: Event) => {\n const file = (event.target as HTMLInputElement).files?.[0]\n\n if (file) void uploadImage(file)\n}\n\nconst accept = computed(() =>\n (props.component.fileAttachments.acceptedFileTypes ?? ['image/*']).join(','),\n)\n\nconst translate = (key: string, fallback: string) => t(key, {}, fallback)\n\nconst runCommand = (name: string) => {\n const button = commands.value[name]\n\n if (!button || !editor.value) return\n\n button.run(editor.value, {\n // Messages arrive translated (`form.link_prompt`, `editor.grid_columns`).\n prompt: (message) => window.prompt(message),\n pickImage,\n togglePanel: (target) => {\n openPanel.value = openPanel.value === target ? null : target\n },\n t: translate,\n })\n}\n\nconst toggleSidePanel = (target: RichEditorPanel) => {\n sidePanel.value = sidePanel.value === target ? null : target\n}\n\nconst insertMergeTag = (tagId: string) => {\n editor.value\n ?.chain()\n .focus()\n .insertContent({ type: 'mergeTag', attrs: { id: tagId } })\n .run()\n}\n\nconst currentTextColor = () => {\n void selectionTick.value\n\n return editor.value?.getAttributes('textColor').color\n}\n\n// A `table` floating toolbar replaces the table row of buttons.\nconst showTableToolbar = () => {\n void selectionTick.value\n\n return Boolean(\n editor.value &&\n editable.value &&\n !props.component.floatingToolbars?.table &&\n showsTableToolbar(allToolbarButtons(props.component), editor.value),\n )\n}\n\nconst floating = computed(() => {\n void selectionTick.value\n\n return editable.value\n ? resolveFloatingToolbar(editor.value ?? null, props.component.floatingToolbars)\n : null\n})\n\nconst applyColor = (color: string | null, close = true) => {\n if (!editor.value) return\n\n setTextColor(editor.value, color)\n\n if (close) openPanel.value = null\n}\n</script>\n\n<template>\n <FieldWrapper :field=\"props.component\" :html-for=\"id\" :error=\"error\">\n <div\n :class=\"\n cn(\n 'border-input dark:bg-input/30 focus-within:border-ring focus-within:ring-ring/50 rounded-md border shadow-xs focus-within:ring-[3px]',\n error && 'border-destructive',\n disabled && 'opacity-60',\n )\n \"\n >\n <!-- The sticky offset is a runtime value: no Tailwind class can hold it. -->\n <div\n v-if=\"props.component.toolbarButtons.length > 0 && editor\"\n :ref=\"(element) => setToolbar('main', element)\"\n role=\"toolbar\"\n :aria-label=\"t('editor.toolbar', {}, 'Formatting')\"\n aria-keyshortcuts=\"Alt+F10\"\n data-slot=\"rich-editor-toolbar\"\n :class=\"\n cn(\n 'flex flex-wrap items-center gap-0.5 border-b p-1',\n props.component.stickyToolbar && 'bg-background sticky z-10 rounded-t-md',\n )\n \"\n :style=\"props.component.stickyToolbar ? { top: stickyTop ?? '0px' } : undefined\"\n >\n <RichEditorToolbarEntries\n :names=\"props.component.toolbarButtons\"\n :component=\"props.component\"\n :editor=\"editor\"\n :editable=\"editable\"\n :commands=\"commands\"\n :tick=\"selectionTick\"\n :open-panel=\"openPanel\"\n :side-panel=\"sidePanel\"\n @run=\"runCommand\"\n @toggle-panel=\"toggleSidePanel\"\n />\n </div>\n <div\n v-if=\"editor && openPanel === 'textColor'\"\n role=\"group\"\n :aria-label=\"toolbarButtonLabel('textColor', translate)\"\n class=\"flex flex-wrap items-center gap-1 border-b p-1\"\n data-slot=\"rich-editor-text-colors\"\n >\n <!-- Palette colours are runtime values: no Tailwind class can hold them. -->\n <button\n v-for=\"color in props.component.textColors ?? []\"\n :key=\"color.value\"\n type=\"button\"\n :title=\"color.label\"\n :aria-label=\"color.label\"\n :aria-pressed=\"currentTextColor() === color.value ? 'true' : 'false'\"\n class=\"focus-visible:ring-ring/50 size-6 rounded-full border shadow-xs outline-none focus-visible:ring-[3px] aria-pressed:ring-2\"\n :style=\"{ backgroundColor: color.value }\"\n @mousedown.prevent\n @click=\"applyColor(color.value)\"\n />\n <input\n v-if=\"props.component.customTextColors\"\n type=\"color\"\n :aria-label=\"t('editor.custom_color', {}, 'Custom color')\"\n :title=\"t('editor.custom_color', {}, 'Custom color')\"\n class=\"size-6 cursor-pointer rounded border bg-transparent p-0\"\n @input=\"applyColor(($event.target as HTMLInputElement).value, false)\"\n />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n :aria-label=\"t('editor.remove_color', {}, 'Remove color')\"\n :title=\"t('editor.remove_color', {}, 'Remove color')\"\n @mousedown.prevent\n @click=\"applyColor(null)\"\n >\n <EraserIcon />\n </Button>\n </div>\n <div\n v-if=\"editor && showTableToolbar()\"\n :ref=\"(element) => setToolbar('table', element)\"\n role=\"toolbar\"\n :aria-label=\"toolbarButtonLabel('table', translate)\"\n class=\"flex flex-wrap items-center gap-0.5 border-b p-1\"\n data-slot=\"rich-editor-table-toolbar\"\n >\n <RichEditorToolbarEntries\n :names=\"TABLE_TOOLBAR_BUTTONS\"\n :component=\"props.component\"\n :editor=\"editor\"\n :editable=\"editable\"\n :commands=\"commands\"\n :tick=\"selectionTick\"\n :open-panel=\"openPanel\"\n :side-panel=\"sidePanel\"\n @run=\"runCommand\"\n @toggle-panel=\"toggleSidePanel\"\n />\n </div>\n <div class=\"@container\">\n <div class=\"flex flex-col-reverse @2xl:flex-row\">\n <EditorContent\n :editor=\"editor\"\n class=\"min-w-0 flex-1\"\n :style=\"\n props.component.maxHeight\n ? { maxHeight: `${props.component.maxHeight}px`, overflowY: 'auto' }\n : undefined\n \"\n />\n <RichEditorSidePanel\n v-if=\"editor && sidePanel\"\n :panel=\"sidePanel\"\n :component=\"props.component\"\n :editable=\"editable\"\n :sticky=\"props.component.stickyPanels ? (stickyTop ?? '0px') : null\"\n @insert-block=\"(blockId: string) => void rich.insertBlock(blockId)\"\n @insert-merge-tag=\"insertMergeTag\"\n @close=\"sidePanel = null\"\n />\n </div>\n </div>\n <!-- Runtime coordinates cannot be Tailwind classes. -->\n <div\n v-if=\"editor && floating && floating.buttons.length > 0\"\n :ref=\"(element) => setToolbar('floating', element)\"\n role=\"toolbar\"\n :aria-label=\"t('editor.floating_toolbar', {}, 'Selection formatting')\"\n data-slot=\"rich-editor-floating-toolbar\"\n :data-node=\"floating.node\"\n class=\"bg-popover text-popover-foreground fixed z-50 flex items-center gap-0.5 rounded-md border p-1 shadow-md\"\n :style=\"floatingToolbarStyle(floating.coords)\"\n >\n <RichEditorToolbarEntries\n :names=\"floating.buttons\"\n :component=\"props.component\"\n :editor=\"editor\"\n :editable=\"editable\"\n :commands=\"commands\"\n :tick=\"selectionTick\"\n :open-panel=\"openPanel\"\n :side-panel=\"sidePanel\"\n @run=\"runCommand\"\n @toggle-panel=\"toggleSidePanel\"\n />\n </div>\n <RichEditorSuggestions\n :id=\"`${id}-suggestions`\"\n :suggestions=\"rich.suggestions\"\n :editor=\"editor\"\n />\n <p v-if=\"attachmentError\" role=\"alert\" class=\"text-destructive px-3 pb-2 text-xs\">\n {{ attachmentError }}\n </p>\n <input\n ref=\"fileInput\"\n type=\"file\"\n :accept=\"accept\"\n class=\"sr-only\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n @change=\"onFilePicked\"\n />\n </div>\n </FieldWrapper>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"RichEditorInput.js","names":["_sfc_main","RichEditorInput_vue_vue_type_script_setup_true_lang_default","RichEditorInput_default"],"sources":["../../../src/components/fields/RichEditorInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { LoadedRichEditorExtensions, RichEditorPanel, RichEditorSchema } from '@alfakit/core'\nimport {\n allToolbarButtons,\n attachToolbarKeyboard,\n focusToolbar,\n isToolbarShortcut,\n detailsNodeConfigs,\n gridNodeConfigs,\n leadExtensionConfig,\n linkExtensionOptions,\n smallMarkConfig,\n EditorAttachments,\n fieldIds,\n fileAttachmentError,\n floatingToolbarStyle,\n highlightMarkConfig,\n htmlToMarkdown,\n resizableImageAttributes,\n resizableImageOptions,\n resolveFloatingToolbar,\n resolveStickyOffset,\n setTextColor,\n showsTableToolbar,\n subscriptMarkConfig,\n superscriptMarkConfig,\n TABLE_TOOLBAR_BUTTONS,\n textAlignExtensionConfig,\n textColorMarkConfig,\n toEditorDocument,\n toolbarButtonLabel,\n toolbarCommands,\n panelUploadOptions,\n uploadTemporaryFile,\n documentNonce,\n} from '@alfakit/core'\nimport { EraserIcon } from '@lucide/vue'\nimport Image from '@tiptap/extension-image'\nimport Link from '@tiptap/extension-link'\nimport Placeholder from '@tiptap/extension-placeholder'\nimport { TableKit } from '@tiptap/extension-table'\nimport StarterKit from '@tiptap/starter-kit'\nimport {\n EditorContent,\n Extension,\n Mark,\n Node,\n useEditor,\n type Editor,\n type Extensions,\n} from '@tiptap/vue-3'\nimport { computed, onBeforeUnmount, onMounted, ref, shallowRef, watch } from 'vue'\nimport { useActionRunner, usePanel, useT } from '../../context'\nimport { cn } from '../../lib/utils'\nimport { useField } from '../form/form-context'\nimport FieldWrapper from '../schema/FieldWrapper.vue'\nimport Button from '../ui/Button.vue'\nimport { useRichEditorExtensions } from './rich-editor-extensions'\nimport RichEditorSidePanel from './RichEditorSidePanel.vue'\nimport RichEditorSuggestions from './RichEditorSuggestions.vue'\nimport RichEditorToolbarEntries from './RichEditorToolbarEntries.vue'\n\ntype MarkConfig = Parameters<typeof Mark.create>[0]\ntype NodeConfig = Parameters<typeof Node.create>[0]\ntype ExtensionConfig = Parameters<typeof Extension.create>[0]\n\n/**\n * Resize handles of `resizableImages()` (Tiptap's node view adds bare `data-resize-handle`\n * elements): round dots on the corners, shown on hover and while the image is selected.\n */\nconst RESIZE_HANDLE_CLASSES =\n '[&_[data-resize-handle]]:z-10 [&_[data-resize-handle]]:size-3 [&_[data-resize-handle]]:rounded-full [&_[data-resize-handle]]:border-2 [&_[data-resize-handle]]:border-background [&_[data-resize-handle]]:bg-primary [&_[data-resize-handle]]:opacity-0 [&_[data-resize-container]:hover_[data-resize-handle]]:opacity-100 [&_.ProseMirror-selectednode_[data-resize-handle]]:opacity-100 [&_[data-resize-handle=bottom-right]]:cursor-nwse-resize [&_[data-resize-handle=top-left]]:cursor-nwse-resize [&_[data-resize-handle=bottom-left]]:cursor-nesw-resize [&_[data-resize-handle=top-right]]:cursor-nesw-resize'\n\n/** The image extension, with drag handles for `resizableImages()`. */\nfunction imageExtension(resizable: boolean) {\n if (!resizable) return Image\n\n return Image.extend({\n addAttributes() {\n return resizableImageAttributes(this.parent?.() ?? {})\n },\n }).configure(resizableImageOptions())\n}\n\n/** Extensions for the extra toolbar buttons (only those the toolbar uses are loaded). */\nfunction toolbarExtensions(buttons: string[], markdown: boolean): Extensions {\n const has = (...names: string[]) => names.some((name) => buttons.includes(name))\n const extensions: Extensions = []\n\n if (has('table')) extensions.push(TableKit.configure({ table: { resizable: false } }))\n // Markdown has no syntax for these.\n if (markdown) return extensions\n\n if (has('highlight')) extensions.push(Mark.create(highlightMarkConfig() as MarkConfig))\n if (has('subscript')) extensions.push(Mark.create(subscriptMarkConfig() as MarkConfig))\n if (has('superscript')) extensions.push(Mark.create(superscriptMarkConfig() as MarkConfig))\n if (has('textColor')) extensions.push(Mark.create(textColorMarkConfig() as MarkConfig))\n if (has('alignStart', 'alignCenter', 'alignEnd', 'alignJustify')) {\n extensions.push(Extension.create(textAlignExtensionConfig() as ExtensionConfig))\n }\n if (has('details')) {\n extensions.push(...detailsNodeConfigs().map((config) => Node.create(config as NodeConfig)))\n }\n if (has('small')) extensions.push(Mark.create(smallMarkConfig() as MarkConfig))\n if (has('lead')) extensions.push(Extension.create(leadExtensionConfig() as ExtensionConfig))\n if (has('grid', 'gridDelete', 'gridAddColumnBefore', 'gridAddColumnAfter', 'gridDeleteColumn')) {\n extensions.push(...gridNodeConfigs().map((config) => Node.create(config as NodeConfig)))\n }\n\n return extensions\n}\n\nconst props = defineProps<{ component: RichEditorSchema; plugins: LoadedRichEditorExtensions }>()\nconst t = useT()\nconst panel = usePanel()\nconst runner = useActionRunner()\nconst { value, setValue, blur, error, id, disabled, readOnly, aria } = useField<unknown>(\n () => props.component,\n)\nconst fileInput = ref<HTMLInputElement | null>(null)\nconst isMarkdown = computed(() => props.component.type === 'MarkdownEditor')\nconst editable = computed(() => !disabled.value && !readOnly.value)\n// Uploaded images preview from a local URL but are stored by their `tmp:` key.\nconst attachments = new EditorAttachments()\nconst isJson = computed(() => Boolean(props.component.json) && !isMarkdown.value)\n// The editor's live instance, for the custom block node views and suggestions.\nconst liveEditor = shallowRef<Editor | undefined>()\nconst rich = useRichEditorExtensions(() => props.component, liveEditor)\n// The open toolbar panel (the text colour palette).\nconst openPanel = ref<'textColor' | null>(null)\n// The open side panel (custom blocks or merge tags).\nconst initialSidePanel = (): RichEditorPanel | null => {\n const initial = props.component.activePanel ?? null\n\n if (initial === 'customBlocks') return props.component.customBlocks?.length ? initial : null\n if (initial === 'mergeTags') return props.component.mergeTags?.length ? initial : null\n\n return null\n}\nconst sidePanel = ref<RichEditorPanel | null>(initialSidePanel())\nconst attachmentError = ref<string | null>(null)\n// Bumped on every transaction so active states and the table row follow the cursor.\nconst selectionTick = ref(0)\nconst stickyTop = ref<string | null>(null)\nconst sticky = computed(() =>\n Boolean(props.component.stickyToolbar || props.component.stickyPanels),\n)\n\nconst updateStickyTop = () => {\n stickyTop.value = sticky.value ? resolveStickyOffset(props.component.stickyOffset) : null\n}\n\nonMounted(updateStickyTop)\nwatch([sticky, () => props.component.stickyOffset], updateStickyTop)\n\n// Built-in buttons, plugin tools and commands of plugin JavaScript extensions.\nconst commands = computed(() =>\n toolbarCommands(\n props.component.editorTools,\n {\n runAction: (tool, args) =>\n tool.action\n ? runner.runField(tool.action, { ...rich.context.value, arguments: args })\n : Promise.resolve(undefined),\n editor: () => liveEditor.value ?? null,\n },\n props.plugins.commands,\n ),\n)\n\n// Field state ↔ editor content: HTML, Markdown (loaded from the server's HTML) or a\n// Tiptap JSON document. `tmp:` upload keys become local preview URLs and back.\nconst stateToContent = (state: unknown): string | Record<string, unknown> => {\n if (isJson.value) {\n const document = toEditorDocument(state)\n\n return document ? JSON.parse(attachments.toEditor(JSON.stringify(document))) : ''\n }\n\n return attachments.toEditor(\n ((isMarkdown.value\n ? typeof props.component.html === 'string'\n ? props.component.html\n : null\n : state) as string | null) ?? '',\n )\n}\nconst editorToState = (instance: Pick<Editor, 'isEmpty' | 'getJSON' | 'getHTML'>): unknown => {\n if (instance.isEmpty) return null\n if (isJson.value) return JSON.parse(attachments.toState(JSON.stringify(instance.getJSON())))\n\n const html = instance.getHTML()\n\n return attachments.toState(isMarkdown.value ? htmlToMarkdown(html) : html)\n}\n\nonBeforeUnmount(() => attachments.destroy())\n\n// Keyboard access to the toolbars (roving tabindex, arrows, Escape, Alt+F10).\ntype ToolbarSlot = 'main' | 'table' | 'floating'\nconst toolbarElements: Record<ToolbarSlot, { element: HTMLElement; detach: () => void } | null> = {\n main: null,\n table: null,\n floating: null,\n}\nconst toolbars = () => [\n toolbarElements.floating?.element,\n toolbarElements.main?.element,\n toolbarElements.table?.element,\n]\nconst setToolbar = (slot: ToolbarSlot, element: unknown) => {\n const current = toolbarElements[slot]\n\n if (current?.element === element) return\n\n current?.detach()\n toolbarElements[slot] =\n element instanceof HTMLElement\n ? {\n element,\n detach: attachToolbarKeyboard(element, {\n onEscape: () => liveEditor.value?.commands.focus(),\n toolbars,\n }),\n }\n : null\n}\n\nonBeforeUnmount(() => {\n for (const slot of ['main', 'table', 'floating'] as const) setToolbar(slot, null)\n})\n\nconst editor = useEditor({\n // TipTap injects its base CSS; with the page's CSP nonce a nonce-based policy allows it.\n injectNonce: documentNonce(),\n extensions: [\n StarterKit.configure({ link: false }),\n Link.configure(linkExtensionOptions(props.component.linkProtocols)),\n imageExtension(Boolean(props.component.resizableImages) && !isMarkdown.value),\n Placeholder.configure({ placeholder: props.component.placeholder ?? '' }),\n ...toolbarExtensions(allToolbarButtons(props.component), isMarkdown.value),\n ...(isMarkdown.value ? [] : rich.extensions),\n ...(isMarkdown.value ? [] : (props.plugins.extensions as Extensions)),\n ],\n // Markdown is loaded from the server's HTML rendering of it, never parsed as HTML.\n content: stateToContent(value.value),\n editable: editable.value,\n editorProps: {\n // The mention / merge tag popup takes the arrow, Enter, Tab and Escape keys.\n handleKeyDown: (_view, event) => {\n // Alt+F10: into the floating toolbar, else the main one.\n if (isToolbarShortcut(event)) return focusToolbar(toolbars())\n\n return liveEditor.value ? rich.suggestions.handleKeyDown(event, liveEditor.value) : false\n },\n // ProseMirror reads its DOM attributes on every view update, so they follow `aria`.\n attributes: () => ({\n class: cn(\n 'alfakit-prose min-h-32 px-3 py-2 text-sm outline-none',\n props.component.resizableImages && RESIZE_HANDLE_CLASSES,\n ),\n // Runtime sizes cannot be Tailwind classes (they would never be generated).\n ...(props.component.minHeight ? { style: `min-height: ${props.component.minHeight}px` } : {}),\n id,\n // Each paragraph follows its own script, so Arabic and English mix correctly.\n dir: 'auto',\n role: 'textbox',\n 'aria-multiline': 'true',\n ...(props.component.label ? { 'aria-labelledby': fieldIds(id).label } : {}),\n ...Object.fromEntries(\n Object.entries(aria.value).map(([name, attribute]) => [name, String(attribute)]),\n ),\n }),\n },\n onUpdate: ({ editor: instance }) => {\n setValue(editorToState(instance))\n },\n onTransaction: ({ editor: instance }) => {\n rich.suggestions.update(instance)\n selectionTick.value++\n },\n onBlur: () => {\n rich.suggestions.close()\n blur()\n },\n})\n\nwatch(\n editor,\n (instance) => {\n liveEditor.value = instance\n },\n { immediate: true },\n)\n\n// Keep editor in sync when the server refreshes the state.\nwatch(value, (next) => {\n const instance = editor.value\n\n if (!instance) return\n\n const current = editorToState(instance)\n const same = isJson.value\n ? JSON.stringify(toEditorDocument(next)) === JSON.stringify(current)\n : (next ?? '') === (current ?? '')\n\n if (!same) {\n instance.commands.setContent(stateToContent(next), { emitUpdate: false })\n }\n})\n\nwatch(editable, (isEditable) => {\n editor.value?.setEditable(isEditable)\n})\n\n// Re-apply the editable element's attributes when the error or description changes.\nwatch(aria, () => {\n if (editor.value && !editor.value.isDestroyed) {\n editor.value.view.setProps({})\n }\n})\n\n// A floating toolbar follows its selection while the page scrolls.\nwatch(\n () => Boolean(props.component.floatingToolbars),\n (hasFloatingToolbars, _previous, onCleanup) => {\n if (!hasFloatingToolbars || typeof window === 'undefined') return\n\n const onScroll = () => selectionTick.value++\n\n window.addEventListener('scroll', onScroll, { capture: true, passive: true })\n onCleanup(() => window.removeEventListener('scroll', onScroll, { capture: true }))\n },\n { immediate: true },\n)\n\nconst pickImage = () => fileInput.value?.click()\n\nconst uploadImage = async (file: File) => {\n if (!panel.value.endpoints.upload || !editor.value) return\n\n // The server checks again when the form is saved.\n const problem = fileAttachmentError(file, props.component.fileAttachments)\n\n if (problem) {\n attachmentError.value =\n problem === 'too_large'\n ? t('form.file_too_large', {}, 'This file is too large.')\n : t('form.file_invalid_type', {}, 'This file type is not allowed.')\n\n return\n }\n\n attachmentError.value = null\n\n let response: { key: string }\n\n try {\n // Large attachments go in resumable chunks.\n response = await uploadTemporaryFile(\n panel.value.endpoints.upload,\n file,\n panelUploadOptions(panel.value, props.component.fileAttachments.uploadPolicy),\n )\n } catch (error) {\n attachmentError.value =\n (error as { errors?: Record<string, string[]> }).errors?.file?.[0] ??\n t('form.upload_failed', {}, 'The file could not be uploaded.')\n\n return\n }\n\n const src = attachments.add(response.key, file)\n\n editor.value.chain().focus().setImage({ src, alt: file.name }).run()\n}\n\nconst onFilePicked = (event: Event) => {\n const file = (event.target as HTMLInputElement).files?.[0]\n\n if (file) void uploadImage(file)\n}\n\nconst accept = computed(() =>\n (props.component.fileAttachments.acceptedFileTypes ?? ['image/*']).join(','),\n)\n\nconst translate = (key: string, fallback: string) => t(key, {}, fallback)\n\nconst runCommand = (name: string) => {\n const button = commands.value[name]\n\n if (!button || !editor.value) return\n\n button.run(editor.value, {\n // Messages arrive translated (`form.link_prompt`, `editor.grid_columns`).\n prompt: (message) => window.prompt(message),\n pickImage,\n togglePanel: (target) => {\n openPanel.value = openPanel.value === target ? null : target\n },\n t: translate,\n })\n}\n\nconst toggleSidePanel = (target: RichEditorPanel) => {\n sidePanel.value = sidePanel.value === target ? null : target\n}\n\nconst insertMergeTag = (tagId: string) => {\n editor.value\n ?.chain()\n .focus()\n .insertContent({ type: 'mergeTag', attrs: { id: tagId } })\n .run()\n}\n\nconst currentTextColor = () => {\n void selectionTick.value\n\n return editor.value?.getAttributes('textColor').color\n}\n\n// A `table` floating toolbar replaces the table row of buttons.\nconst showTableToolbar = () => {\n void selectionTick.value\n\n return Boolean(\n editor.value &&\n editable.value &&\n !props.component.floatingToolbars?.table &&\n showsTableToolbar(allToolbarButtons(props.component), editor.value),\n )\n}\n\nconst floating = computed(() => {\n void selectionTick.value\n\n return editable.value\n ? resolveFloatingToolbar(editor.value ?? null, props.component.floatingToolbars)\n : null\n})\n\nconst applyColor = (color: string | null, close = true) => {\n if (!editor.value) return\n\n setTextColor(editor.value, color)\n\n if (close) openPanel.value = null\n}\n</script>\n\n<template>\n <FieldWrapper :field=\"props.component\" :html-for=\"id\" :error=\"error\">\n <div\n :class=\"\n cn(\n 'border-input dark:bg-input/30 focus-within:border-ring focus-within:ring-ring/50 rounded-md border shadow-xs focus-within:ring-[3px]',\n error && 'border-destructive',\n disabled && 'opacity-60',\n )\n \"\n >\n <!-- The sticky offset is a runtime value: no Tailwind class can hold it. -->\n <div\n v-if=\"props.component.toolbarButtons.length > 0 && editor\"\n :ref=\"(element) => setToolbar('main', element)\"\n role=\"toolbar\"\n :aria-label=\"t('editor.toolbar', {}, 'Formatting')\"\n aria-keyshortcuts=\"Alt+F10\"\n data-slot=\"rich-editor-toolbar\"\n :class=\"\n cn(\n 'flex flex-wrap items-center gap-0.5 border-b p-1',\n props.component.stickyToolbar && 'bg-background sticky z-10 rounded-t-md',\n )\n \"\n :style=\"props.component.stickyToolbar ? { top: stickyTop ?? '0px' } : undefined\"\n >\n <RichEditorToolbarEntries\n :names=\"props.component.toolbarButtons\"\n :component=\"props.component\"\n :editor=\"editor\"\n :editable=\"editable\"\n :commands=\"commands\"\n :tick=\"selectionTick\"\n :open-panel=\"openPanel\"\n :side-panel=\"sidePanel\"\n @run=\"runCommand\"\n @toggle-panel=\"toggleSidePanel\"\n />\n </div>\n <div\n v-if=\"editor && openPanel === 'textColor'\"\n role=\"group\"\n :aria-label=\"toolbarButtonLabel('textColor', translate)\"\n class=\"flex flex-wrap items-center gap-1 border-b p-1\"\n data-slot=\"rich-editor-text-colors\"\n >\n <!-- Palette colours are runtime values: no Tailwind class can hold them. -->\n <button\n v-for=\"color in props.component.textColors ?? []\"\n :key=\"color.value\"\n type=\"button\"\n :title=\"color.label\"\n :aria-label=\"color.label\"\n :aria-pressed=\"currentTextColor() === color.value ? 'true' : 'false'\"\n class=\"focus-visible:ring-ring/50 size-6 rounded-full border shadow-xs outline-none focus-visible:ring-[3px] aria-pressed:ring-2\"\n :style=\"{ backgroundColor: color.value }\"\n @mousedown.prevent\n @click=\"applyColor(color.value)\"\n />\n <input\n v-if=\"props.component.customTextColors\"\n type=\"color\"\n :aria-label=\"t('editor.custom_color', {}, 'Custom color')\"\n :title=\"t('editor.custom_color', {}, 'Custom color')\"\n class=\"size-6 cursor-pointer rounded border bg-transparent p-0\"\n @input=\"applyColor(($event.target as HTMLInputElement).value, false)\"\n />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-sm\"\n :aria-label=\"t('editor.remove_color', {}, 'Remove color')\"\n :title=\"t('editor.remove_color', {}, 'Remove color')\"\n @mousedown.prevent\n @click=\"applyColor(null)\"\n >\n <EraserIcon />\n </Button>\n </div>\n <div\n v-if=\"editor && showTableToolbar()\"\n :ref=\"(element) => setToolbar('table', element)\"\n role=\"toolbar\"\n :aria-label=\"toolbarButtonLabel('table', translate)\"\n class=\"flex flex-wrap items-center gap-0.5 border-b p-1\"\n data-slot=\"rich-editor-table-toolbar\"\n >\n <RichEditorToolbarEntries\n :names=\"TABLE_TOOLBAR_BUTTONS\"\n :component=\"props.component\"\n :editor=\"editor\"\n :editable=\"editable\"\n :commands=\"commands\"\n :tick=\"selectionTick\"\n :open-panel=\"openPanel\"\n :side-panel=\"sidePanel\"\n @run=\"runCommand\"\n @toggle-panel=\"toggleSidePanel\"\n />\n </div>\n <div class=\"@container\">\n <div class=\"flex flex-col-reverse @2xl:flex-row\">\n <EditorContent\n :editor=\"editor\"\n class=\"min-w-0 flex-1\"\n :style=\"\n props.component.maxHeight\n ? { maxHeight: `${props.component.maxHeight}px`, overflowY: 'auto' }\n : undefined\n \"\n />\n <RichEditorSidePanel\n v-if=\"editor && sidePanel\"\n :panel=\"sidePanel\"\n :component=\"props.component\"\n :editable=\"editable\"\n :sticky=\"props.component.stickyPanels ? (stickyTop ?? '0px') : null\"\n @insert-block=\"(blockId: string) => void rich.insertBlock(blockId)\"\n @insert-merge-tag=\"insertMergeTag\"\n @close=\"sidePanel = null\"\n />\n </div>\n </div>\n <!-- Runtime coordinates cannot be Tailwind classes. -->\n <div\n v-if=\"editor && floating && floating.buttons.length > 0\"\n :ref=\"(element) => setToolbar('floating', element)\"\n role=\"toolbar\"\n :aria-label=\"t('editor.floating_toolbar', {}, 'Selection formatting')\"\n data-slot=\"rich-editor-floating-toolbar\"\n :data-node=\"floating.node\"\n class=\"bg-popover text-popover-foreground fixed z-50 flex items-center gap-0.5 rounded-md border p-1 shadow-md\"\n :style=\"floatingToolbarStyle(floating.coords)\"\n >\n <RichEditorToolbarEntries\n :names=\"floating.buttons\"\n :component=\"props.component\"\n :editor=\"editor\"\n :editable=\"editable\"\n :commands=\"commands\"\n :tick=\"selectionTick\"\n :open-panel=\"openPanel\"\n :side-panel=\"sidePanel\"\n @run=\"runCommand\"\n @toggle-panel=\"toggleSidePanel\"\n />\n </div>\n <RichEditorSuggestions\n :id=\"`${id}-suggestions`\"\n :suggestions=\"rich.suggestions\"\n :editor=\"editor\"\n />\n <p v-if=\"attachmentError\" role=\"alert\" class=\"text-destructive px-3 pb-2 text-xs\">\n {{ attachmentError }}\n </p>\n <input\n ref=\"fileInput\"\n type=\"file\"\n :accept=\"accept\"\n class=\"sr-only\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n @change=\"onFilePicked\"\n />\n </div>\n </FieldWrapper>\n</template>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"RichEditorInput.vue.d.ts","sourceRoot":"","sources":["../../../src/components/fields/RichEditorInput.vue"],"names":[],"mappings":"AA2mBA,OAAO,KAAK,EAAE,0BAA0B,EAAmB,gBAAgB,EAAE,MAAM,eAAe,CAAA;AA8GlG,KAAK,WAAW,GAAG;IAAE,SAAS,EAAE,gBAAgB,CAAC;IAAC,OAAO,EAAE,0BAA0B,CAAA;CAAE,CAAC;;AA2wBxF,wBAMG"}
1
+ {"version":3,"file":"RichEditorInput.vue.d.ts","sourceRoot":"","sources":["../../../src/components/fields/RichEditorInput.vue"],"names":[],"mappings":"AA8mBA,OAAO,KAAK,EAAE,0BAA0B,EAAmB,gBAAgB,EAAE,MAAM,eAAe,CAAA;AA+GlG,KAAK,WAAW,GAAG;IAAE,SAAS,EAAE,gBAAgB,CAAC;IAAC,OAAO,EAAE,0BAA0B,CAAA;CAAE,CAAC;;AA6wBxF,wBAMG"}