@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
@@ -22,7 +22,7 @@ import {
22
22
  fileUploadAccept,
23
23
  filesFromClipboard,
24
24
  fileUploadPaths,
25
- formatBytes,
25
+ fileManagerSize,
26
26
  insertUploadedFile,
27
27
  moveRepeaterItem,
28
28
  requestJson,
@@ -43,7 +43,7 @@ import {
43
43
  } from '@lucide/vue'
44
44
  import { computed, ref, shallowRef, watch } from 'vue'
45
45
  import { useStore } from '../../composables/use-store'
46
- import { useChoice, usePanel, useT } from '../../context'
46
+ import { useChoice, useFormatter, usePanel, useT } from '../../context'
47
47
  import { cn } from '../../lib/utils'
48
48
  import { useField, useFormStore } from '../form/form-context'
49
49
  import FieldWrapper from '../schema/FieldWrapper.vue'
@@ -59,6 +59,7 @@ interface LocalFile extends UploadedFile {
59
59
 
60
60
  const props = defineProps<{ component: FileUploadSchema }>()
61
61
  const t = useT()
62
+ const formatter = useFormatter()
62
63
  const choice = useChoice()
63
64
  const panel = usePanel()
64
65
  const {
@@ -424,7 +425,9 @@ const onItemDrop = (event: DragEvent, index: number) => {
424
425
  const hints = computed(() =>
425
426
  [
426
427
  props.component.acceptedFileTypes?.join(', '),
427
- props.component.maxSize ? `≤ ${formatBytes(props.component.maxSize * 1024, 0)}` : null,
428
+ props.component.maxSize
429
+ ? `≤ ${fileManagerSize(props.component.maxSize * 1024, formatter.value)}`
430
+ : null,
428
431
  props.component.minFiles
429
432
  ? choice(
430
433
  'form.min_files',
@@ -491,7 +494,7 @@ function cssLength(value: number | string): string {
491
494
  type="button"
492
495
  variant="ghost"
493
496
  size="icon-xs"
494
- :aria-label="t('remove', {}, 'Remove')"
497
+ :aria-label="t('file_upload.remove', { name: file.name }, 'Remove :name')"
495
498
  @click="removeEntry(file)"
496
499
  ><XIcon
497
500
  /></Button>
@@ -525,7 +528,7 @@ function cssLength(value: number | string): string {
525
528
  : file.progress !== undefined && !file.error
526
529
  ? (props.component.uploadingMessage ?? t('form.uploading', {}, 'Uploading…'))
527
530
  : file.size
528
- ? formatBytes(file.size)
531
+ ? fileManagerSize(file.size, formatter)
529
532
  : file.temporary
530
533
  ? t('form.uploading', {}, 'Pending')
531
534
  : '')
@@ -541,7 +544,7 @@ function cssLength(value: number | string): string {
541
544
  type="button"
542
545
  variant="ghost"
543
546
  size="icon-xs"
544
- :aria-label="t('form.move_up', {}, 'Move up')"
547
+ :aria-label="t('file_upload.move_up', { name: file.name }, 'Move :name up')"
545
548
  :disabled="index === 0"
546
549
  @click="move(index, index - 1)"
547
550
  ><ChevronUpIcon
@@ -550,7 +553,7 @@ function cssLength(value: number | string): string {
550
553
  type="button"
551
554
  variant="ghost"
552
555
  size="icon-xs"
553
- :aria-label="t('form.move_down', {}, 'Move down')"
556
+ :aria-label="t('file_upload.move_down', { name: file.name }, 'Move :name down')"
554
557
  :disabled="index === files.length - 1"
555
558
  @click="move(index, index + 1)"
556
559
  ><ChevronDownIcon
@@ -562,7 +565,7 @@ function cssLength(value: number | string): string {
562
565
  :variant="circle ? 'secondary' : 'ghost'"
563
566
  size="icon-xs"
564
567
  :class="cn(circle && 'rounded-full shadow')"
565
- :aria-label="t('image_editor.title', {}, 'Edit image')"
568
+ :aria-label="t('file_upload.edit', { name: file.name }, 'Edit :name')"
566
569
  :title="t('image_editor.title', {}, 'Edit image')"
567
570
  data-action="edit-image"
568
571
  @click="void editExisting(file)"
@@ -579,7 +582,7 @@ function cssLength(value: number | string): string {
579
582
  :href="uploadedFileLinks(file).open"
580
583
  target="_blank"
581
584
  rel="noopener noreferrer"
582
- :aria-label="`${t('open', {}, 'Open')} ${t('opens_in_new_tab', {}, '(opens in a new tab)')}`"
585
+ :aria-label="`${t('file_upload.open', { name: file.name }, 'Open :name')} ${t('opens_in_new_tab', {}, '(opens in a new tab)')}`"
583
586
  ><ExternalLinkIcon
584
587
  /></a>
585
588
  </Button>
@@ -593,7 +596,7 @@ function cssLength(value: number | string): string {
593
596
  <a
594
597
  :href="uploadedFileLinks(file).download"
595
598
  download
596
- :aria-label="t('download', {}, 'Download')"
599
+ :aria-label="t('file_upload.download', { name: file.name }, 'Download :name')"
597
600
  ><DownloadIcon
598
601
  /></a>
599
602
  </Button>
@@ -603,7 +606,7 @@ function cssLength(value: number | string): string {
603
606
  :variant="circle ? 'secondary' : 'ghost'"
604
607
  size="icon-xs"
605
608
  :class="cn(circle && 'rounded-full shadow')"
606
- :aria-label="t('remove', {}, 'Remove')"
609
+ :aria-label="t('file_upload.remove', { name: file.name }, 'Remove :name')"
607
610
  @click="removeEntry(file)"
608
611
  ><XIcon
609
612
  /></Button>
@@ -11,7 +11,7 @@ import type {
11
11
  ImageEditorDragMode,
12
12
  ImageEditorState,
13
13
  } from '@alfakit/core'
14
- import { ImageEditor, loadEditorImage } from '@alfakit/core'
14
+ import { ImageEditor, imageEditorOptionsKey, loadEditorImage } from '@alfakit/core'
15
15
  import {
16
16
  FlipHorizontal2Icon,
17
17
  FlipVertical2Icon,
@@ -81,11 +81,15 @@ const release = () => {
81
81
  state.value = null
82
82
  }
83
83
 
84
+ // Restart only for another image or other settings: the schema object itself is new on
85
+ // every render of a template item (a new builder block), which kept restarting the load.
84
86
  watch(
85
- () => [props.request, props.options] as const,
86
- ([request, options], _previous, onCleanup) => {
87
+ [() => props.request, () => imageEditorOptionsKey(props.options)],
88
+ ([request], _previous, onCleanup) => {
87
89
  if (!request) return
88
90
 
91
+ const options = props.options
92
+
89
93
  let cancelled = false
90
94
 
91
95
  loadEditorImage(request.file)
@@ -5,6 +5,7 @@ import {
5
5
  reorderedItemKeys,
6
6
  resolveItemAction,
7
7
  type KeyValueSchema,
8
+ itemActionIcon,
8
9
  } from '@alfakit/core'
9
10
  import { ChevronDownIcon, ChevronUpIcon } from '@lucide/vue'
10
11
  import { computed, ref } from 'vue'
@@ -60,13 +61,13 @@ const addAction = computed(() =>
60
61
  const deleteAction = computed(() =>
61
62
  resolveItemAction('delete', props.component, undefined, {
62
63
  label: t('form.remove_row', {}, 'Remove row'),
63
- icon: 'trash-2',
64
+ icon: itemActionIcon('key-value', 'delete', 'trash-2'),
64
65
  }),
65
66
  )
66
67
  const reorderAction = computed(() =>
67
68
  resolveItemAction('reorder', props.component, undefined, {
68
69
  label: t('form.reorder_item', {}, 'Reorder'),
69
- icon: 'grip-vertical',
70
+ icon: itemActionIcon('key-value', 'reorder', 'grip-vertical'),
70
71
  }),
71
72
  )
72
73
  const deletable = computed(
@@ -15,7 +15,7 @@ import {
15
15
  SearchIcon,
16
16
  } from '@lucide/vue'
17
17
  import { computed, onScopeDispose, ref, watch } from 'vue'
18
- import { useChoice, useT } from '../../context'
18
+ import { useChoice, useFormatter, useT } from '../../context'
19
19
  import { cn } from '../../lib/utils'
20
20
  import { useFormStore } from '../form/form-context'
21
21
  import TableCellContent from '../table/TableCellContent.vue'
@@ -43,6 +43,7 @@ const emit = defineEmits<{
43
43
  confirm: [keys: string[], labels: Record<string, string>]
44
44
  }>()
45
45
  const t = useT()
46
+ const format = useFormatter()
46
47
  const choice = useChoice()
47
48
  const form = useFormStore()
48
49
  const multiple = computed(() => Boolean(props.component.multiple))
@@ -314,7 +315,11 @@ const confirm = () =>
314
315
  paging.total !== undefined
315
316
  ? t(
316
317
  'table.showing',
317
- { first: paging.from, last: paging.to, total: paging.total },
318
+ {
319
+ first: format.number(paging.from),
320
+ last: format.number(paging.to),
321
+ total: format.number(paging.total),
322
+ },
318
323
  'Showing :first–:last of :total',
319
324
  )
320
325
  : `${paging.from}–${paging.to}`
@@ -43,7 +43,6 @@ const onInput = (event: Event) => {
43
43
  inputmode="numeric"
44
44
  autocomplete="one-time-code"
45
45
  pattern="[0-9]*"
46
- :maxlength="props.component.length"
47
46
  :model-value="value ?? ''"
48
47
  :placeholder="props.component.placeholder"
49
48
  :disabled="disabled"
@@ -54,6 +53,7 @@ const onInput = (event: Event) => {
54
53
  :aria-describedby="aria['aria-describedby']"
55
54
  :aria-required="aria['aria-required']"
56
55
  data-slot="one-time-code-input"
56
+ data-input=""
57
57
  class="max-w-56 text-center font-mono text-lg tracking-[0.5em] tabular-nums"
58
58
  v-bind="props.component.extraInputAttributes"
59
59
  @input="onInput"
@@ -13,7 +13,7 @@ import {
13
13
  removeIndexedState,
14
14
  removeRepeaterItem,
15
15
  reorderedItemKeys,
16
- replacePlaceholder,
16
+ templateForIndex,
17
17
  resolveItemAction,
18
18
  virtualizeOptions,
19
19
  type ItemActionName,
@@ -82,8 +82,7 @@ const virtual = useVirtualList(
82
82
  useScrollToErroredItem(virtual, () => props.component.statePath)
83
83
 
84
84
  const schemaFor = (index: number): SchemaComponent[] =>
85
- props.component.items[index]?.schema ??
86
- replacePlaceholder(props.component.template, '__INDEX__', String(index))
85
+ props.component.items[index]?.schema ?? templateForIndex(props.component.template, index)
87
86
  const isCollapsed = (index: number) => collapsed.value[index] ?? props.component.collapsed ?? false
88
87
 
89
88
  const canAdd = computed(
@@ -32,6 +32,7 @@ import {
32
32
  toolbarCommands,
33
33
  panelUploadOptions,
34
34
  uploadTemporaryFile,
35
+ documentNonce,
35
36
  } from '@alfakit/core'
36
37
  import { EraserIcon } from '@lucide/vue'
37
38
  import Image from '@tiptap/extension-image'
@@ -230,6 +231,8 @@ onBeforeUnmount(() => {
230
231
  })
231
232
 
232
233
  const editor = useEditor({
234
+ // TipTap injects its base CSS; with the page's CSP nonce a nonce-based policy allows it.
235
+ injectNonce: documentNonce(),
233
236
  extensions: [
234
237
  StarterKit.configure({ link: false }),
235
238
  Link.configure(linkExtensionOptions(props.component.linkProtocols)),
@@ -62,7 +62,7 @@ const plainLabel = (label: string): string =>
62
62
  @blur="blur"
63
63
  >
64
64
  <option v-if="props.component.selectablePlaceholder" value="">
65
- {{ props.component.placeholder ?? '' }}
65
+ {{ props.component.placeholder ?? t('select_option', {}, 'Select an option') }}
66
66
  </option>
67
67
  <template
68
68
  v-for="option in props.component.options"
@@ -97,7 +97,9 @@ const plainLabel = (label: string): string =>
97
97
  :aria-readonly="readOnly || undefined"
98
98
  class="w-full"
99
99
  >
100
- <SelectValue :placeholder="props.component.placeholder ?? ''" />
100
+ <SelectValue
101
+ :placeholder="props.component.placeholder ?? t('select_option', {}, 'Select an option')"
102
+ />
101
103
  </SelectTrigger>
102
104
  <SelectContent>
103
105
  <SelectItem
@@ -5,6 +5,11 @@ import { cn } from '../../lib/utils'
5
5
 
6
6
  /** Header cells shared by the Repeater and RepeatableEntry tables. */
7
7
  const props = defineProps<{ columns: TableColumnSchema[] }>()
8
+
9
+ // A fixed `width()` (`9rem`, `120px`) is also the column's minimum, so the table scrolls
10
+ // sideways instead of squeezing its fields; percentages stay flexible.
11
+ const widthStyle = (width?: string | null) =>
12
+ !width ? undefined : width.trim().endsWith('%') ? { width } : { width, minWidth: width }
8
13
  </script>
9
14
 
10
15
  <template>
@@ -12,7 +17,7 @@ const props = defineProps<{ columns: TableColumnSchema[] }>()
12
17
  v-for="(column, index) in props.columns"
13
18
  :key="`${column.name ?? 'column'}-${index}`"
14
19
  scope="col"
15
- :style="column.width ? { width: column.width } : undefined"
20
+ :style="widthStyle(column.width)"
16
21
  :class="
17
22
  cn(
18
23
  'text-muted-foreground px-3 py-2 text-xs font-medium',
@@ -4,23 +4,44 @@ import type {
4
4
  ItemActionName,
5
5
  ItemActionSchema,
6
6
  } from '@alfakit/core'
7
- import { ItemMoveTracker, itemActionContext } from '@alfakit/core'
7
+ import { ItemMoveTracker, itemActionContext, itemActionIcon } from '@alfakit/core'
8
8
  import { nextTick, ref, toValue, watch, type MaybeRefOrGetter } from 'vue'
9
9
  import { useActionRunner, useT } from '../../context'
10
10
 
11
- /** Default looks of the built-in item actions, for payloads without `itemActions`. */
12
- export function useItemActionFallbacks(): Record<ItemActionName, ItemActionFallback> {
11
+ /** Default looks of the built-in item actions, for payloads without `itemActions` (icons follow their `alfakit::` aliases). */
12
+ export function useItemActionFallbacks(
13
+ kind: 'repeater' | 'builder' = 'repeater',
14
+ ): Record<ItemActionName, ItemActionFallback> {
13
15
  const t = useT()
14
16
 
15
17
  return {
16
18
  add: { label: '', icon: 'plus', variant: 'outline' },
17
- delete: { label: t('form.remove_item', {}, 'Remove'), icon: 'trash-2', color: 'danger' },
18
- clone: { label: t('form.clone', {}, 'Clone'), icon: 'copy' },
19
- reorder: { label: t('form.reorder_item', {}, 'Reorder'), icon: 'grip-vertical' },
20
- moveUp: { label: t('form.move_up', {}, 'Move up'), icon: 'chevron-up' },
21
- moveDown: { label: t('form.move_down', {}, 'Move down'), icon: 'chevron-down' },
22
- collapse: { label: t('form.collapse_item', {}, 'Collapse'), icon: 'chevron-up' },
23
- expand: { label: t('form.expand_item', {}, 'Expand'), icon: 'chevron-down' },
19
+ delete: {
20
+ label: t('form.remove_item', {}, 'Remove'),
21
+ icon: itemActionIcon(kind, 'delete', 'trash-2'),
22
+ color: 'danger',
23
+ },
24
+ clone: { label: t('form.clone', {}, 'Clone'), icon: itemActionIcon(kind, 'clone', 'copy') },
25
+ reorder: {
26
+ label: t('form.reorder_item', {}, 'Reorder'),
27
+ icon: itemActionIcon(kind, 'reorder', 'grip-vertical'),
28
+ },
29
+ moveUp: {
30
+ label: t('form.move_up', {}, 'Move up'),
31
+ icon: itemActionIcon(kind, 'move-up', 'chevron-up'),
32
+ },
33
+ moveDown: {
34
+ label: t('form.move_down', {}, 'Move down'),
35
+ icon: itemActionIcon(kind, 'move-down', 'chevron-down'),
36
+ },
37
+ collapse: {
38
+ label: t('form.collapse_item', {}, 'Collapse'),
39
+ icon: itemActionIcon(kind, 'collapse', 'chevron-up'),
40
+ },
41
+ expand: {
42
+ label: t('form.expand_item', {}, 'Expand'),
43
+ icon: itemActionIcon(kind, 'expand', 'chevron-down'),
44
+ },
24
45
  collapseAll: {
25
46
  label: t('form.collapse_all', {}, 'Collapse all'),
26
47
  icon: 'chevrons-down-up',
@@ -436,7 +436,7 @@ const onPreviewKeyDown = (event: KeyboardEvent) => {
436
436
  </label>
437
437
  <nav
438
438
  :aria-label="tt('breadcrumb', {}, 'Folder path')"
439
- class="min-w-0 flex-1"
439
+ class="min-w-0 flex-[1_1_12rem]"
440
440
  data-slot="file-manager-breadcrumb"
441
441
  >
442
442
  <ol class="flex min-w-0 flex-wrap items-center gap-1 text-sm">
@@ -14,6 +14,7 @@ import {
14
14
  registerFormSubmitter,
15
15
  registerPageForm,
16
16
  resolvePartialProps,
17
+ shouldResyncForm,
17
18
  wizardProgressStore,
18
19
  } from '@alfakit/core'
19
20
  import { router } from '@inertiajs/vue3'
@@ -102,6 +103,10 @@ watch(token, (value) => store.setToken(value))
102
103
  // block may arrive before or after Inertia's `success` event, so handle both orders.
103
104
  let submittedBlock: FormBlockSchema | null = null
104
105
  let refillPending = false
106
+ // Another action succeeded and its new block has not arrived yet.
107
+ let resyncPending = false
108
+ // The block when the latest non-GET visit started, to tell whether its response arrived.
109
+ let visitBlock: FormBlockSchema | null = null
105
110
 
106
111
  watch(
107
112
  () => props.block,
@@ -110,6 +115,12 @@ watch(
110
115
  refillPending = false
111
116
  store.fill(block)
112
117
  }
118
+
119
+ if (resyncPending) {
120
+ resyncPending = false
121
+
122
+ if (!store.isDirty) store.fill(block)
123
+ }
113
124
  },
114
125
  )
115
126
 
@@ -140,7 +151,8 @@ const trigger = async (action: ActionSchema, ctx: ActionContext) => {
140
151
  submitting = true
141
152
  submittedBlock = props.block
142
153
  store.setProcessing(true)
143
- runner.execute(action, ctx, store.state.values)
154
+ // A click that blurred a live field started a refresh: send the state it returns.
155
+ store.whenSettled(() => runner.execute(action, ctx, store.state.values))
144
156
  }
145
157
 
146
158
  // Track this form's own submit visit so unrelated reloads finishing meanwhile (polling,
@@ -153,11 +165,24 @@ const offStart = router.on('start', (event) => {
153
165
  if (submitting && !submitVisit && visit.method !== 'get') {
154
166
  submitVisit = visit.id
155
167
  }
168
+
169
+ if (visit.method !== 'get') visitBlock = props.block
156
170
  })
157
171
 
158
172
  const offSuccess = router.on('success', (event) => {
159
173
  const id = submitVisit
160
174
 
175
+ // Another action changed the record: show the server's new form unless it holds edits.
176
+ if (!id && shouldResyncForm(pageFlash(event.detail.page), store)) {
177
+ if (props.block !== visitBlock) {
178
+ store.fill(props.block)
179
+ } else {
180
+ resyncPending = true
181
+ }
182
+
183
+ return
184
+ }
185
+
161
186
  if (!id || (event.detail.visitId ?? id) !== id) return
162
187
 
163
188
  // A halted action (rate limit, `halt()`) saved nothing: keep what the user typed.
@@ -1,5 +1,5 @@
1
1
  import type { BaseField, FieldAriaAttributes, FormState, FormStore } from '@alfakit/core'
2
- import { fieldAria } from '@alfakit/core'
2
+ import { fieldAria, fieldDomId, fieldError } from '@alfakit/core'
3
3
  import {
4
4
  computed,
5
5
  inject,
@@ -70,12 +70,12 @@ export function useField<T = unknown>(field: MaybeRefOrGetter<BaseField>): Field
70
70
  return current as T
71
71
  })
72
72
 
73
- const error = computed(() => state.value.errors[path]?.[0])
73
+ const error = computed(() => fieldError(state.value.errors, path))
74
74
  // Fields stay enabled during a live refresh: the store keeps edits made while the request
75
75
  // is in flight, so locking inputs would only swallow keystrokes.
76
76
  const disabled = computed(() => Boolean(toValue(field).disabled))
77
77
  const readOnly = computed(() => Boolean(toValue(field).readOnly))
78
- const id = toValue(field).id ?? `alfakit-${path.replace(/[^a-zA-Z0-9_-]/g, '-')}`
78
+ const id = toValue(field).id ?? fieldDomId(store.idPrefix, path)
79
79
  const aria = computed(() => fieldAria(id, toValue(field), error.value))
80
80
 
81
81
  return {
@@ -122,9 +122,21 @@ const template = computed(() =>
122
122
  .join(' '),
123
123
  )
124
124
 
125
- const setCard = (key: string) => (element: unknown) => {
126
- if (element instanceof HTMLElement) cards.set(key, element)
127
- else cards.delete(key)
125
+ // A card moved to another column is mounted there before its old element is unmounted, so
126
+ // an unmount only forgets the element it registered itself (else the moved card would lose
127
+ // its entry and the keyboard focus).
128
+ const setCard = (key: string) => {
129
+ let own: HTMLElement | null = null
130
+
131
+ return (element: unknown) => {
132
+ if (element instanceof HTMLElement) {
133
+ own = element
134
+ cards.set(key, element)
135
+ } else if (own !== null) {
136
+ if (cards.get(key) === own) cards.delete(key)
137
+ own = null
138
+ }
139
+ }
128
140
  }
129
141
 
130
142
  const focus = (key: string | undefined) => {
@@ -3,7 +3,7 @@ import type { KanbanColumnSchema } from '@alfakit/core'
3
3
  import { kanbanWipState } from '@alfakit/core'
4
4
  import { ChevronsLeftRightIcon, ChevronsRightLeftIcon, PlusIcon } from '@lucide/vue'
5
5
  import { computed } from 'vue'
6
- import { useT } from '../../context'
6
+ import { useChoice, useT } from '../../context'
7
7
  import { cssColor } from '../../lib/colors'
8
8
  import { Icon } from '../../lib/icons'
9
9
  import { cn } from '../../lib/utils'
@@ -19,6 +19,7 @@ const props = defineProps<{
19
19
  }>()
20
20
  const emit = defineEmits<{ toggle: []; create: [] }>()
21
21
  const t = useT()
22
+ const choice = useChoice()
22
23
 
23
24
  const wip = computed(() => kanbanWipState(props.column))
24
25
  const shown = computed(() =>
@@ -41,7 +42,7 @@ const countLabel = computed(() => {
41
42
  { shown: column.total, count: column.count },
42
43
  ':shown of :count cards',
43
44
  )
44
- : t('kanban.count', { count: column.count }, ':count cards')
45
+ : choice('kanban.count', column.count, {}, '{1} :count card|[0,*] :count cards')
45
46
  })
46
47
  const style = computed(() =>
47
48
  props.column.color ? { borderTopColor: cssColor(props.column.color) } : undefined,
@@ -147,10 +148,11 @@ const addLabel = computed(() =>
147
148
  </p>
148
149
  <p v-if="wip === 'over'" class="text-destructive text-xs">
149
150
  {{
150
- t(
151
+ choice(
151
152
  'kanban.wip_over',
153
+ props.column.wipLimit ?? 0,
152
154
  { limit: props.column.wipLimit ?? 0 },
153
- 'Over the limit of :limit cards',
155
+ '{1} Over the limit of :limit card|[0,*] Over the limit of :limit cards',
154
156
  )
155
157
  }}
156
158
  </p>
@@ -40,6 +40,7 @@ const errors = computed(() =>
40
40
  <span
41
41
  v-if="props.component.label"
42
42
  :id="labelId"
43
+ data-slot="label"
43
44
  class="text-sm leading-none font-medium select-none"
44
45
  >
45
46
  {{ props.component.label }}
@@ -87,11 +87,14 @@ const t = useT()
87
87
  <component
88
88
  :is="heading"
89
89
  v-if="props.component.heading"
90
- class="text-base leading-6 font-semibold"
90
+ class="text-base leading-6 font-semibold break-words"
91
91
  >
92
92
  {{ props.component.heading }}
93
93
  </component>
94
- <p v-if="props.component.description" class="text-muted-foreground mt-1 text-sm">
94
+ <p
95
+ v-if="props.component.description"
96
+ class="text-muted-foreground mt-1 text-sm break-words"
97
+ >
95
98
  {{ props.component.description }}
96
99
  </p>
97
100
  </div>
@@ -188,11 +191,14 @@ const t = useT()
188
191
  <component
189
192
  :is="heading"
190
193
  v-if="props.component.heading"
191
- class="text-base leading-6 font-semibold"
194
+ class="text-base leading-6 font-semibold break-words"
192
195
  >
193
196
  {{ props.component.heading }}
194
197
  </component>
195
- <p v-if="props.component.description" class="text-muted-foreground mt-1 text-sm">
198
+ <p
199
+ v-if="props.component.description"
200
+ class="text-muted-foreground mt-1 text-sm break-words"
201
+ >
196
202
  {{ props.component.description }}
197
203
  </p>
198
204
  </div>
@@ -1,10 +1,21 @@
1
1
  <script setup lang="ts">
2
2
  import type { TabsSchema } from '@alfakit/core'
3
- import { readPersisted, schemaGapClass, writePersisted } from '@alfakit/core'
3
+ import {
4
+ componentHasErrors,
5
+ readPersisted,
6
+ schemaGapClass,
7
+ tabFromQuery,
8
+ tabQueryValue,
9
+ tabToReveal,
10
+ writePersisted,
11
+ } from '@alfakit/core'
4
12
  import { usePage } from '@inertiajs/vue3'
5
13
  import { computed, onMounted, ref, watch } from 'vue'
14
+ import { useStoreSelector } from '../../composables/use-store'
15
+ import { useT } from '../../context'
6
16
  import { Icon } from '../../lib/icons'
7
17
  import { cn } from '../../lib/utils'
18
+ import { useOptionalFormStore } from '../form/form-context'
8
19
  import SchemaRenderer from '../schema/SchemaRenderer.vue'
9
20
  import Tabs from '../ui/Tabs.vue'
10
21
  import TabsContent from '../ui/TabsContent.vue'
@@ -17,11 +28,15 @@ const props = defineProps<{ component: TabsSchema }>()
17
28
  const tabs = computed(() => props.component.schema ?? [])
18
29
  // The page URL (not `window.location`) so the server renders the same tab as the browser.
19
30
  const page = usePage()
31
+ // The tab's readable value (`?tab=billing-address`), or its key in links from older versions.
20
32
  const fromQuery = props.component.queryStringKey
21
- ? new URL(page.url, 'http://localhost').searchParams.get(props.component.queryStringKey)
33
+ ? tabFromQuery(
34
+ tabs.value,
35
+ new URL(page.url, 'http://localhost').searchParams.get(props.component.queryStringKey),
36
+ )
22
37
  : null
23
38
  const active = ref<string>(
24
- tabs.value.find((tab) => tab.key === fromQuery)?.key ??
39
+ fromQuery ??
25
40
  tabs.value[Math.max(0, props.component.activeTab - 1)]?.key ??
26
41
  tabs.value[0]?.key ??
27
42
  '',
@@ -39,6 +54,36 @@ onMounted(() => {
39
54
  if (stored && tabs.value.some((tab) => tab.key === stored)) active.value = stored
40
55
  })
41
56
 
57
+ // Tabs holding a field with a validation error are marked, and when a submit brings new
58
+ // errors while the open tab has none, the first tab with an error opens.
59
+ const TAB_INVALID_CLASSES =
60
+ 'text-destructive data-[state=active]:text-destructive dark:text-destructive dark:data-[state=active]:text-destructive'
61
+ const t = useT()
62
+ const store = useOptionalFormStore()
63
+ const errors = useStoreSelector(
64
+ store?.store ?? {
65
+ get: () => ({ errors: {} as Record<string, string[]> }),
66
+ subscribe: () => () => {},
67
+ },
68
+ (state) => state.errors,
69
+ )
70
+ const invalidTabs = computed(
71
+ () =>
72
+ new Set(
73
+ tabs.value.filter((tab) => componentHasErrors(tab, errors.value)).map((tab) => tab.key),
74
+ ),
75
+ )
76
+
77
+ watch(
78
+ errors,
79
+ (next, previous) => {
80
+ const reveal = tabToReveal(tabs.value, active.value, previous ?? {}, next)
81
+
82
+ if (reveal !== null) active.value = reveal
83
+ },
84
+ { immediate: true },
85
+ )
86
+
42
87
  function changeTab(value: string) {
43
88
  active.value = value
44
89
 
@@ -52,8 +97,9 @@ watch(
52
97
  (value) => {
53
98
  if (!props.component.queryStringKey || typeof window === 'undefined') return
54
99
 
100
+ const tab = tabs.value.find((item) => item.key === value)
55
101
  const url = new URL(window.location.href)
56
- url.searchParams.set(props.component.queryStringKey, value)
102
+ url.searchParams.set(props.component.queryStringKey, tab ? tabQueryValue(tab) : value)
57
103
  window.history.replaceState(window.history.state, '', url)
58
104
  },
59
105
  { immediate: true },
@@ -87,11 +133,21 @@ watch(
87
133
  )
88
134
  "
89
135
  >
90
- <TabsTrigger v-for="tab in tabs" :key="tab.key" :value="tab.key">
136
+ <TabsTrigger
137
+ v-for="tab in tabs"
138
+ :key="tab.key"
139
+ :value="tab.key"
140
+ :data-invalid="invalidTabs.has(tab.key) || undefined"
141
+ :class="invalidTabs.has(tab.key) ? TAB_INVALID_CLASSES : undefined"
142
+ >
91
143
  <Icon v-if="tab.icon && tab.iconPosition !== 'after'" :name="tab.icon" />
92
144
  {{ tab.label }}
93
145
  <Icon v-if="tab.icon && tab.iconPosition === 'after'" :name="tab.icon" />
94
146
  <TabBadge :tab="tab" />
147
+ <template v-if="invalidTabs.has(tab.key)">
148
+ <span aria-hidden="true" class="bg-destructive size-1.5 shrink-0 rounded-full"></span>
149
+ <span class="sr-only">({{ t('translatable.has_errors') }})</span>
150
+ </template>
95
151
  </TabsTrigger>
96
152
  </TabsList>
97
153
  <TabsContent