@alfakit/vue 0.1.2 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (281) hide show
  1. package/CHANGELOG.md +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/ActionGroupMenu.js.map +1 -1
  7. package/dist/components/actions/ActionGroupMenu.vue.d.ts.map +1 -1
  8. package/dist/components/actions/ActionGroupMenu.vue_vue_type_script_setup_true_lang.js +69 -65
  9. package/dist/components/actions/ActionGroupMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  10. package/dist/components/actions/ActionModal.js.map +1 -1
  11. package/dist/components/actions/ActionModal.vue.d.ts.map +1 -1
  12. package/dist/components/actions/ActionModal.vue_vue_type_script_setup_true_lang.js +17 -15
  13. package/dist/components/actions/ActionModal.vue_vue_type_script_setup_true_lang.js.map +1 -1
  14. package/dist/components/ai/AiCopilot.js.map +1 -1
  15. package/dist/components/ai/AiCopilot.vue.d.ts +2 -0
  16. package/dist/components/ai/AiCopilot.vue.d.ts.map +1 -1
  17. package/dist/components/ai/AiCopilot.vue_vue_type_script_setup_true_lang.js +7 -2
  18. package/dist/components/ai/AiCopilot.vue_vue_type_script_setup_true_lang.js.map +1 -1
  19. package/dist/components/cms/CmsPage.vue_vue_type_script_setup_true_lang.js +19 -19
  20. package/dist/components/cms/CmsPage.vue_vue_type_script_setup_true_lang.js.map +1 -1
  21. package/dist/components/cms/LivePreview.js.map +1 -1
  22. package/dist/components/cms/LivePreview.vue.d.ts.map +1 -1
  23. package/dist/components/cms/LivePreview.vue_vue_type_script_setup_true_lang.js +83 -83
  24. package/dist/components/cms/LivePreview.vue_vue_type_script_setup_true_lang.js.map +1 -1
  25. package/dist/components/fields/BuilderField.js.map +1 -1
  26. package/dist/components/fields/BuilderField.vue.d.ts.map +1 -1
  27. package/dist/components/fields/BuilderField.vue_vue_type_script_setup_true_lang.js +162 -157
  28. package/dist/components/fields/BuilderField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  29. package/dist/components/fields/ImageEditorDialog.js.map +1 -1
  30. package/dist/components/fields/ImageEditorDialog.vue.d.ts.map +1 -1
  31. package/dist/components/fields/ImageEditorDialog.vue_vue_type_script_setup_true_lang.js +46 -46
  32. package/dist/components/fields/ImageEditorDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  33. package/dist/components/fields/KeyValueField.js.map +1 -1
  34. package/dist/components/fields/KeyValueField.vue.d.ts.map +1 -1
  35. package/dist/components/fields/KeyValueField.vue_vue_type_script_setup_true_lang.js +66 -66
  36. package/dist/components/fields/KeyValueField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  37. package/dist/components/fields/ModalTablePicker.js.map +1 -1
  38. package/dist/components/fields/ModalTablePicker.vue.d.ts.map +1 -1
  39. package/dist/components/fields/ModalTablePicker.vue_vue_type_script_setup_true_lang.js +113 -113
  40. package/dist/components/fields/ModalTablePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  41. package/dist/components/fields/RepeaterField.js.map +1 -1
  42. package/dist/components/fields/RepeaterField.vue.d.ts.map +1 -1
  43. package/dist/components/fields/RepeaterField.vue_vue_type_script_setup_true_lang.js +12 -12
  44. package/dist/components/fields/RepeaterField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  45. package/dist/components/fields/RichEditorInput.js.map +1 -1
  46. package/dist/components/fields/RichEditorInput.vue.d.ts.map +1 -1
  47. package/dist/components/fields/RichEditorInput.vue_vue_type_script_setup_true_lang.js +166 -165
  48. package/dist/components/fields/RichEditorInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  49. package/dist/components/fields/SliderField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  50. package/dist/components/fields/item-actions.d.ts +2 -2
  51. package/dist/components/fields/item-actions.d.ts.map +1 -1
  52. package/dist/components/fields/item-actions.js +31 -31
  53. package/dist/components/fields/item-actions.js.map +1 -1
  54. package/dist/components/form/FormBlock.js.map +1 -1
  55. package/dist/components/form/FormBlock.vue.d.ts.map +1 -1
  56. package/dist/components/form/FormBlock.vue_vue_type_script_setup_true_lang.js +1 -1
  57. package/dist/components/form/FormBlock.vue_vue_type_script_setup_true_lang.js.map +1 -1
  58. package/dist/components/form/form-context.js +25 -25
  59. package/dist/components/form/form-context.js.map +1 -1
  60. package/dist/components/kanban/KanbanBoard.js.map +1 -1
  61. package/dist/components/kanban/KanbanBoard.vue.d.ts.map +1 -1
  62. package/dist/components/kanban/KanbanBoard.vue_vue_type_script_setup_true_lang.js +5 -2
  63. package/dist/components/kanban/KanbanBoard.vue_vue_type_script_setup_true_lang.js.map +1 -1
  64. package/dist/components/kanban/KanbanColumnHeader.js.map +1 -1
  65. package/dist/components/kanban/KanbanColumnHeader.vue.d.ts.map +1 -1
  66. package/dist/components/kanban/KanbanColumnHeader.vue_vue_type_script_setup_true_lang.js +64 -64
  67. package/dist/components/kanban/KanbanColumnHeader.vue_vue_type_script_setup_true_lang.js.map +1 -1
  68. package/dist/components/layout/SectionComponent.js.map +1 -1
  69. package/dist/components/layout/SectionComponent.vue.d.ts.map +1 -1
  70. package/dist/components/layout/SectionComponent.vue_vue_type_script_setup_true_lang.js +23 -23
  71. package/dist/components/layout/SectionComponent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  72. package/dist/components/panel/DebugPanel.vue_vue_type_script_setup_true_lang.js +8 -8
  73. package/dist/components/panel/DebugPanel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  74. package/dist/components/panel/GlobalSearchPalette.js.map +1 -1
  75. package/dist/components/panel/GlobalSearchPalette.vue.d.ts.map +1 -1
  76. package/dist/components/panel/GlobalSearchPalette.vue_vue_type_script_setup_true_lang.js +102 -96
  77. package/dist/components/panel/GlobalSearchPalette.vue_vue_type_script_setup_true_lang.js.map +1 -1
  78. package/dist/components/panel/NavGroup.vue_vue_type_script_setup_true_lang.js +10 -10
  79. package/dist/components/panel/NavGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
  80. package/dist/components/panel/NavGroupFlyout.vue_vue_type_script_setup_true_lang.js +9 -9
  81. package/dist/components/panel/NavGroupFlyout.vue_vue_type_script_setup_true_lang.js.map +1 -1
  82. package/dist/components/panel/NavItem.vue_vue_type_script_setup_true_lang.js +16 -16
  83. package/dist/components/panel/NavItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  84. package/dist/components/panel/NavSubItem.vue_vue_type_script_setup_true_lang.js +10 -10
  85. package/dist/components/panel/NavSubItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  86. package/dist/components/panel/TenantMenu.vue_vue_type_script_setup_true_lang.js +35 -35
  87. package/dist/components/panel/TenantMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
  88. package/dist/components/panel/Topbar.vue_vue_type_script_setup_true_lang.js +11 -11
  89. package/dist/components/panel/Topbar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  90. package/dist/components/realtime/use-live-updates.d.ts.map +1 -1
  91. package/dist/components/realtime/use-live-updates.js +24 -23
  92. package/dist/components/realtime/use-live-updates.js.map +1 -1
  93. package/dist/components/table/BooleanCell.vue_vue_type_script_setup_true_lang.js +2 -1
  94. package/dist/components/table/BooleanCell.vue_vue_type_script_setup_true_lang.js.map +1 -1
  95. package/dist/components/table/ColumnHeader.js.map +1 -1
  96. package/dist/components/table/ColumnHeader.vue.d.ts.map +1 -1
  97. package/dist/components/table/ColumnHeader.vue_vue_type_script_setup_true_lang.js +55 -49
  98. package/dist/components/table/ColumnHeader.vue_vue_type_script_setup_true_lang.js.map +1 -1
  99. package/dist/components/table/ColumnManager.js.map +1 -1
  100. package/dist/components/table/ColumnManager.vue.d.ts.map +1 -1
  101. package/dist/components/table/ColumnManager.vue_vue_type_script_setup_true_lang.js +5 -4
  102. package/dist/components/table/ColumnManager.vue_vue_type_script_setup_true_lang.js.map +1 -1
  103. package/dist/components/table/ContentLayoutSort.js.map +1 -1
  104. package/dist/components/table/ContentLayoutSort.vue.d.ts.map +1 -1
  105. package/dist/components/table/ContentLayoutSort.vue_vue_type_script_setup_true_lang.js +5 -5
  106. package/dist/components/table/ContentLayoutSort.vue_vue_type_script_setup_true_lang.js.map +1 -1
  107. package/dist/components/table/SelectCell.vue_vue_type_script_setup_true_lang.js +2 -1
  108. package/dist/components/table/SelectCell.vue_vue_type_script_setup_true_lang.js.map +1 -1
  109. package/dist/components/table/SelectComboboxCell.vue_vue_type_script_setup_true_lang.js +2 -1
  110. package/dist/components/table/SelectComboboxCell.vue_vue_type_script_setup_true_lang.js.map +1 -1
  111. package/dist/components/table/TableCellContent.js.map +1 -1
  112. package/dist/components/table/TableCellContent.vue.d.ts.map +1 -1
  113. package/dist/components/table/TableCellContent.vue_vue_type_script_setup_true_lang.js +4 -3
  114. package/dist/components/table/TableCellContent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  115. package/dist/components/table/TablePagination.js.map +1 -1
  116. package/dist/components/table/TablePagination.vue.d.ts.map +1 -1
  117. package/dist/components/table/TablePagination.vue_vue_type_script_setup_true_lang.js +87 -87
  118. package/dist/components/table/TablePagination.vue_vue_type_script_setup_true_lang.js.map +1 -1
  119. package/dist/components/table/TextInputCell.vue_vue_type_script_setup_true_lang.js +2 -1
  120. package/dist/components/table/TextInputCell.vue_vue_type_script_setup_true_lang.js.map +1 -1
  121. package/dist/components/table/cell-update.d.ts +6 -0
  122. package/dist/components/table/cell-update.d.ts.map +1 -1
  123. package/dist/components/table/cell-update.js.map +1 -1
  124. package/dist/components/translation-manager/TranslationManagerView.vue_vue_type_script_setup_true_lang.js +1 -1
  125. package/dist/components/translation-manager/TranslationManagerView.vue_vue_type_script_setup_true_lang.js.map +1 -1
  126. package/dist/components/ui/CommandAutoHighlight.js +7 -0
  127. package/dist/components/ui/CommandAutoHighlight.js.map +1 -0
  128. package/dist/components/ui/CommandAutoHighlight.vue.d.ts +21 -0
  129. package/dist/components/ui/CommandAutoHighlight.vue.d.ts.map +1 -0
  130. package/dist/components/ui/CommandAutoHighlight.vue_vue_type_script_setup_true_lang.js +18 -0
  131. package/dist/components/ui/CommandAutoHighlight.vue_vue_type_script_setup_true_lang.js.map +1 -0
  132. package/dist/components/ui/DialogContent.js.map +1 -1
  133. package/dist/components/ui/DialogContent.vue.d.ts.map +1 -1
  134. package/dist/components/ui/DialogContent.vue_vue_type_script_setup_true_lang.js +13 -12
  135. package/dist/components/ui/DialogContent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  136. package/dist/components/ui/PopoverContent.js.map +1 -1
  137. package/dist/components/ui/PopoverContent.vue.d.ts.map +1 -1
  138. package/dist/components/ui/PopoverContent.vue_vue_type_script_setup_true_lang.js +9 -8
  139. package/dist/components/ui/PopoverContent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  140. package/dist/components/ui/SheetContent.js.map +1 -1
  141. package/dist/components/ui/SheetContent.vue.d.ts.map +1 -1
  142. package/dist/components/ui/SheetContent.vue_vue_type_script_setup_true_lang.js +13 -12
  143. package/dist/components/ui/SheetContent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  144. package/dist/components/ui/TooltipContent.js.map +1 -1
  145. package/dist/components/ui/TooltipContent.vue.d.ts.map +1 -1
  146. package/dist/components/ui/TooltipContent.vue_vue_type_script_setup_true_lang.js +9 -8
  147. package/dist/components/ui/TooltipContent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  148. package/dist/context.d.ts +7 -0
  149. package/dist/context.d.ts.map +1 -1
  150. package/dist/context.js +29 -26
  151. package/dist/context.js.map +1 -1
  152. package/dist/create-alfakit.d.ts.map +1 -1
  153. package/dist/create-alfakit.js +33 -31
  154. package/dist/create-alfakit.js.map +1 -1
  155. package/dist/eject-manifest.json +11 -2
  156. package/dist/index.d.ts +1 -0
  157. package/dist/index.d.ts.map +1 -1
  158. package/dist/index.js +219 -217
  159. package/dist/layouts/AppLayout.vue_vue_type_script_setup_true_lang.js +8 -8
  160. package/dist/layouts/AppLayout.vue_vue_type_script_setup_true_lang.js.map +1 -1
  161. package/dist/layouts/AuthLayout.vue_vue_type_script_setup_true_lang.js +9 -9
  162. package/dist/layouts/FullscreenLayout.vue_vue_type_script_setup_true_lang.js +8 -8
  163. package/dist/layouts/FullscreenLayout.vue_vue_type_script_setup_true_lang.js.map +1 -1
  164. package/dist/layouts/TopNavLayout.vue_vue_type_script_setup_true_lang.js +15 -15
  165. package/dist/layouts/TopNavLayout.vue_vue_type_script_setup_true_lang.js.map +1 -1
  166. package/dist/layouts/lazy-layouts.d.ts +10 -0
  167. package/dist/layouts/lazy-layouts.d.ts.map +1 -0
  168. package/dist/layouts/lazy-layouts.js +8 -0
  169. package/dist/layouts/lazy-layouts.js.map +1 -0
  170. package/dist/layouts/panel-layouts.d.ts +8 -0
  171. package/dist/layouts/panel-layouts.d.ts.map +1 -0
  172. package/dist/layouts/panel-layouts.js +15 -0
  173. package/dist/layouts/panel-layouts.js.map +1 -0
  174. package/dist/lib/lazy.d.ts.map +1 -1
  175. package/dist/lib/lazy.js +2 -2
  176. package/dist/lib/lazy.js.map +1 -1
  177. package/dist/pages/PageShell.js.map +1 -1
  178. package/dist/pages/PageShell.vue.d.ts.map +1 -1
  179. package/dist/pages/PageShell.vue_vue_type_script_setup_true_lang.js +39 -42
  180. package/dist/pages/PageShell.vue_vue_type_script_setup_true_lang.js.map +1 -1
  181. package/dist/standalone/AlfakitComponent.js.map +1 -1
  182. package/dist/standalone/AlfakitComponent.vue.d.ts.map +1 -1
  183. package/dist/standalone/AlfakitComponent.vue_vue_type_script_setup_true_lang.js +56 -52
  184. package/dist/standalone/AlfakitComponent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  185. package/dist/standalone.css +7 -0
  186. package/dist/starter-kit/AlfakitStarterKitRoot.js.map +1 -1
  187. package/dist/starter-kit/AlfakitStarterKitRoot.vue.d.ts +2 -2
  188. package/dist/starter-kit/AlfakitStarterKitRoot.vue.d.ts.map +1 -1
  189. package/dist/starter-kit/AlfakitStarterKitRoot.vue_vue_type_script_setup_true_lang.js +17 -12
  190. package/dist/starter-kit/AlfakitStarterKitRoot.vue_vue_type_script_setup_true_lang.js.map +1 -1
  191. package/dist/starter-kit/dashboard-widgets.d.ts +54 -0
  192. package/dist/starter-kit/dashboard-widgets.d.ts.map +1 -0
  193. package/dist/starter-kit/dashboard-widgets.js +54 -0
  194. package/dist/starter-kit/dashboard-widgets.js.map +1 -0
  195. package/dist/starter-kit/index.d.ts +2 -1
  196. package/dist/starter-kit/index.d.ts.map +1 -1
  197. package/dist/starter-kit/index.js +5 -4
  198. package/dist/starter-kit/runtime.d.ts +6 -0
  199. package/dist/starter-kit/runtime.d.ts.map +1 -1
  200. package/dist/starter-kit/runtime.js +19 -15
  201. package/dist/starter-kit/runtime.js.map +1 -1
  202. package/dist/starter-kit/starter-kit.d.ts.map +1 -1
  203. package/dist/starter-kit/starter-kit.js +8 -8
  204. package/dist/starter-kit/starter-kit.js.map +1 -1
  205. package/dist/starter-kit/widgets/CopilotTrigger.js +7 -0
  206. package/dist/starter-kit/widgets/CopilotTrigger.js.map +1 -0
  207. package/dist/starter-kit/widgets/CopilotTrigger.vue.d.ts +12 -0
  208. package/dist/starter-kit/widgets/CopilotTrigger.vue.d.ts.map +1 -0
  209. package/dist/starter-kit/widgets/CopilotTrigger.vue_vue_type_script_setup_true_lang.js +23 -0
  210. package/dist/starter-kit/widgets/CopilotTrigger.vue_vue_type_script_setup_true_lang.js.map +1 -0
  211. package/dist/starter-kit/widgets/LoadedCopilot.js +7 -0
  212. package/dist/starter-kit/widgets/LoadedCopilot.js.map +1 -0
  213. package/dist/starter-kit/widgets/LoadedCopilot.vue.d.ts +8 -0
  214. package/dist/starter-kit/widgets/LoadedCopilot.vue.d.ts.map +1 -0
  215. package/dist/starter-kit/widgets/LoadedCopilot.vue_vue_type_script_setup_true_lang.js +31 -0
  216. package/dist/starter-kit/widgets/LoadedCopilot.vue_vue_type_script_setup_true_lang.js.map +1 -0
  217. package/dist/starter-kit/widgets/StarterKitImpersonationBanner.js +7 -0
  218. package/dist/starter-kit/widgets/StarterKitImpersonationBanner.js.map +1 -0
  219. package/dist/starter-kit/widgets/StarterKitImpersonationBanner.vue.d.ts +8 -0
  220. package/dist/starter-kit/widgets/StarterKitImpersonationBanner.vue.d.ts.map +1 -0
  221. package/dist/starter-kit/widgets/StarterKitImpersonationBanner.vue_vue_type_script_setup_true_lang.js +34 -0
  222. package/dist/starter-kit/widgets/StarterKitImpersonationBanner.vue_vue_type_script_setup_true_lang.js.map +1 -0
  223. package/dist/starter-kit/widgets/index.d.ts +40 -9
  224. package/dist/starter-kit/widgets/index.d.ts.map +1 -1
  225. package/dist/starter-kit/widgets/index.js +21 -18
  226. package/dist/starter-kit/widgets/index.js.map +1 -1
  227. package/dist/starter-kit/widgets/loaded.d.ts +10 -0
  228. package/dist/starter-kit/widgets/loaded.d.ts.map +1 -0
  229. package/dist/starter-kit/widgets/loaded.js +5 -0
  230. package/dist/styles.css +9 -2
  231. package/dist/themes.css +6 -1
  232. package/package.json +2 -2
  233. package/src/AlfakitRoot.vue +9 -1
  234. package/src/components/actions/ActionGroupMenu.vue +13 -1
  235. package/src/components/actions/ActionModal.vue +9 -0
  236. package/src/components/ai/AiCopilot.vue +7 -1
  237. package/src/components/cms/LivePreview.vue +8 -2
  238. package/src/components/fields/BuilderField.vue +15 -2
  239. package/src/components/fields/ImageEditorDialog.vue +7 -3
  240. package/src/components/fields/KeyValueField.vue +3 -2
  241. package/src/components/fields/ModalTablePicker.vue +7 -2
  242. package/src/components/fields/RepeaterField.vue +2 -3
  243. package/src/components/fields/RichEditorInput.vue +3 -0
  244. package/src/components/fields/item-actions.ts +31 -10
  245. package/src/components/form/FormBlock.vue +2 -1
  246. package/src/components/form/form-context.ts +2 -2
  247. package/src/components/kanban/KanbanBoard.vue +15 -3
  248. package/src/components/kanban/KanbanColumnHeader.vue +6 -4
  249. package/src/components/layout/SectionComponent.vue +10 -4
  250. package/src/components/panel/GlobalSearchPalette.vue +2 -0
  251. package/src/components/realtime/use-live-updates.ts +3 -1
  252. package/src/components/table/ColumnHeader.vue +23 -12
  253. package/src/components/table/ColumnManager.vue +12 -8
  254. package/src/components/table/ContentLayoutSort.vue +7 -1
  255. package/src/components/table/TableCellContent.vue +4 -2
  256. package/src/components/table/TablePagination.vue +12 -7
  257. package/src/components/table/cell-update.ts +6 -0
  258. package/src/components/ui/CommandAutoHighlight.vue +27 -0
  259. package/src/components/ui/DialogContent.vue +5 -1
  260. package/src/components/ui/PopoverContent.vue +5 -1
  261. package/src/components/ui/SheetContent.vue +5 -1
  262. package/src/components/ui/TooltipContent.vue +5 -1
  263. package/src/context.ts +10 -0
  264. package/src/create-alfakit.ts +5 -0
  265. package/src/index.ts +2 -0
  266. package/src/layouts/lazy-layouts.ts +14 -0
  267. package/src/layouts/panel-layouts.ts +17 -0
  268. package/src/lib/lazy.ts +11 -1
  269. package/src/pages/PageShell.vue +5 -6
  270. package/src/standalone/AlfakitComponent.vue +17 -6
  271. package/src/starter-kit/AlfakitStarterKitRoot.vue +12 -3
  272. package/src/starter-kit/dashboard-widgets.ts +93 -0
  273. package/src/starter-kit/index.ts +7 -1
  274. package/src/starter-kit/runtime.ts +17 -1
  275. package/src/starter-kit/starter-kit.ts +2 -1
  276. package/src/starter-kit/widgets/CopilotTrigger.vue +58 -0
  277. package/src/starter-kit/widgets/LoadedCopilot.vue +29 -0
  278. package/src/starter-kit/widgets/StarterKitImpersonationBanner.vue +57 -0
  279. package/src/starter-kit/widgets/index.ts +56 -11
  280. package/src/starter-kit/widgets/loaded.ts +9 -0
  281. package/src/styles.css +9 -2
@@ -1 +1 @@
1
- {"version":3,"file":"ImageEditorDialog.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createBlock","Dialog","_withCtx","_createVNode","DialogContent","DialogHeader","DialogTitle","_createTextVNode","_toDisplayString","_unref","DialogDescription","_createElementVNode","_createElementBlock","_normalizeClass","_normalizeStyle","_Fragment","_renderList","Button","_resolveDynamicComponent","Input","_withKeys","_withModifiers","Spinner","DialogFooter","_createCommentVNode","Button_default","Spinner_default","Input_default","Dialog_default","DialogContent_default","DialogDescription_default","DialogHeader_default","DialogTitle_default","DialogFooter_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_6","_hoisted_7","_hoisted_8","_hoisted_9","_hoisted_10","_hoisted_11","_hoisted_12","_hoisted_13","ImageEditorDialog_vue_vue_type_script_setup_true_lang_default","HANDLES","NUMERIC_FIELDS","SCALES","props","__props","t","useT","loaded","shallowRef","state","saving","ref","hintId","useId","inputsId","canvas","frame","unsubscribe","stopObserving","release","watch","request","options","cancelled","loadEditorImage","bitmap","editor","ImageEditor","next","onCleanup","onScopeDispose","element","measure","observer","onWheel","rect","event","data","computed","commit","input","value","field","box","finish","file","save","current","start","mode","onKeydown","ratioLabel","ratio","tools","ZoomOutIcon","ZoomInIcon","RotateCcwIcon","RotateCwIcon","FlipHorizontal2Icon","FlipVertical2Icon","Undo2Icon","openBlock","createBlock","_cache","open","withCtx","createVNode","createTextVNode","toDisplayString","unref","createElementVNode","createElementBlock","$event","normalizeClass","cn","normalizeStyle","Fragment","renderList","handle","tool","resolveDynamicComponent","key","fallback","withKeys","withModifiers","axis","createCommentVNode"],"sources":["../../../src/components/fields/ImageEditorDialog.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * `FileUpload::imageEditor()`: crop, zoom, rotate and flip an image before it is uploaded\n * (or to replace an uploaded one). Resolves the request with the edited file, or null\n * when cancelled.\n */\nimport type {\n CropHandle,\n FileUploadImageEditorSchema,\n ImageEditorData,\n ImageEditorDragMode,\n ImageEditorState,\n} from '@alfakit/core'\nimport { ImageEditor, loadEditorImage } from '@alfakit/core'\nimport {\n FlipHorizontal2Icon,\n FlipVertical2Icon,\n RotateCcwIcon,\n RotateCwIcon,\n Undo2Icon,\n ZoomInIcon,\n ZoomOutIcon,\n} from '@lucide/vue'\nimport { computed, onScopeDispose, ref, shallowRef, useId, watch, type Component } from 'vue'\nimport { useT } from '../../context'\nimport { cn } from '../../lib/utils'\nimport Button from '../ui/Button.vue'\nimport Dialog from '../ui/Dialog.vue'\nimport DialogContent from '../ui/DialogContent.vue'\nimport DialogDescription from '../ui/DialogDescription.vue'\nimport DialogFooter from '../ui/DialogFooter.vue'\nimport DialogHeader from '../ui/DialogHeader.vue'\nimport DialogTitle from '../ui/DialogTitle.vue'\nimport Input from '../ui/Input.vue'\nimport Spinner from '../ui/Spinner.vue'\n\nexport interface ImageEditRequest {\n file: File\n resolve: (file: File | null) => void\n}\n\nconst HANDLES: CropHandle[] = ['nw', 'ne', 'sw', 'se']\n\n/** The numeric inputs, in the order Filament shows them. */\nconst NUMERIC_FIELDS = [\n ['x', 'image_editor.x', 'X'],\n ['y', 'image_editor.y', 'Y'],\n ['width', 'image_editor.width', 'Width'],\n ['height', 'image_editor.height', 'Height'],\n ['rotate', 'image_editor.rotation', 'Rotation'],\n] as const satisfies ReadonlyArray<readonly [keyof ImageEditorData, string, string]>\n\nconst SCALES = [\n ['x', 'image_editor.scale_x', 'Scale X'],\n ['y', 'image_editor.scale_y', 'Scale Y'],\n] as const\n\nconst props = defineProps<{\n request: ImageEditRequest | null\n options: FileUploadImageEditorSchema\n}>()\n\nconst t = useT()\nconst loaded = shallowRef<{ bitmap: ImageBitmap; editor: ImageEditor } | null>(null)\nconst state = shallowRef<ImageEditorState | null>(null)\nconst saving = ref(false)\nconst hintId = useId()\nconst inputsId = useId()\nconst canvas = ref<HTMLCanvasElement | null>(null)\nconst frame = ref<HTMLDivElement | null>(null)\nlet unsubscribe: (() => void) | null = null\nlet stopObserving: (() => void) | null = null\n\nconst release = () => {\n unsubscribe?.()\n unsubscribe = null\n stopObserving?.()\n stopObserving = null\n loaded.value?.bitmap.close()\n loaded.value = null\n state.value = null\n}\n\nwatch(\n () => [props.request, props.options] as const,\n ([request, options], _previous, onCleanup) => {\n if (!request) return\n\n let cancelled = false\n\n loadEditorImage(request.file)\n .then((bitmap) => {\n if (cancelled) return bitmap.close()\n\n const editor = new ImageEditor({\n width: bitmap.width,\n height: bitmap.height,\n aspectRatios: options.aspectRatios,\n circle: options.circle,\n mode: options.mode,\n emptyFillColor: options.emptyFillColor,\n viewportWidth: options.viewportWidth,\n viewportHeight: options.viewportHeight,\n })\n\n loaded.value = { bitmap, editor }\n state.value = editor.store.get()\n unsubscribe = editor.store.subscribe((next) => {\n state.value = next\n })\n })\n // Undecodable: upload the file as it is.\n .catch(() => !cancelled && request.resolve(request.file))\n\n onCleanup(() => {\n cancelled = true\n release()\n })\n },\n { immediate: true },\n)\n\nonScopeDispose(release)\n\n// Redraw on every change (crop, zoom, rotation, flips, container size).\nwatch(\n () => [canvas.value, state.value] as const,\n ([element]) => {\n if (element && loaded.value) {\n loaded.value.editor.drawPreview(\n element,\n loaded.value.bitmap,\n globalThis.devicePixelRatio || 1,\n )\n }\n },\n { flush: 'post' },\n)\n\n// Measure the container and follow its size; zoom with the wheel and trackpad pinch.\nwatch(\n () => [frame.value, loaded.value?.editor] as const,\n ([element, editor]) => {\n stopObserving?.()\n stopObserving = null\n\n if (!element || !editor) return\n\n const measure = () => editor.setContainer(element.clientWidth, element.clientHeight)\n measure()\n\n const observer = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(measure)\n observer?.observe(element)\n\n const onWheel = (event: WheelEvent) => {\n const rect = element.getBoundingClientRect()\n\n if (editor.wheel(event, { x: event.clientX - rect.left, y: event.clientY - rect.top })) {\n event.preventDefault()\n }\n }\n\n element.addEventListener('wheel', onWheel, { passive: false })\n\n stopObserving = () => {\n observer?.disconnect()\n element.removeEventListener('wheel', onWheel)\n }\n },\n { flush: 'post' },\n)\n\nconst data = computed<ImageEditorData | null>(() => {\n void state.value\n\n return loaded.value?.editor.getData() ?? null\n})\n\n// Numeric inputs apply on change (blur, Enter, spinner); invalid values snap back.\nconst commit = (field: keyof ImageEditorData, event: Event) => {\n const editor = loaded.value?.editor\n const input = event.target as HTMLInputElement | null\n\n if (!editor || !input) return\n\n const value = input.value.trim() === '' ? Number.NaN : Number(input.value)\n editor.setData({ [field]: value })\n input.value = String(editor.getData()[field])\n}\n\nconst box = computed(() => {\n void state.value\n\n return loaded.value?.editor.cropBox() ?? { left: 0, top: 0, width: 0, height: 0 }\n})\n\nconst finish = (file: File | null) => {\n props.request?.resolve(file)\n}\n\nconst save = async () => {\n const request = props.request\n const current = loaded.value\n\n if (!request || !current) return\n\n saving.value = true\n\n try {\n finish(await current.editor.export(current.bitmap, request.file))\n } catch {\n finish(request.file)\n } finally {\n saving.value = false\n }\n}\n\nconst start = (mode: ImageEditorDragMode, event: PointerEvent) => {\n const editor = loaded.value?.editor\n\n if (!editor) return\n\n event.preventDefault()\n event.stopPropagation()\n ;(event.currentTarget as HTMLElement | null)?.setPointerCapture?.(event.pointerId)\n editor.startDrag(mode, event.clientX, event.clientY, undefined, event.pointerId ?? 0)\n}\n\nconst onKeydown = (event: KeyboardEvent) => {\n if (loaded.value?.editor.handleKey(event)) event.preventDefault()\n}\n\nconst ratioLabel = (ratio: string | null) => ratio ?? t('image_editor.free', {}, 'Free')\n\nconst tools = computed<\n Array<{ label: string; icon: Component; run: () => void; disabled?: boolean }>\n>(() => [\n {\n label: t('image_editor.zoom_out', {}, 'Zoom out'),\n icon: ZoomOutIcon,\n run: () => loaded.value?.editor.zoomOut(),\n disabled: !(state.value && loaded.value?.editor.canZoomOut),\n },\n {\n label: t('image_editor.zoom_in', {}, 'Zoom in'),\n icon: ZoomInIcon,\n run: () => loaded.value?.editor.zoomIn(),\n disabled: !(state.value && loaded.value?.editor.canZoomIn),\n },\n {\n label: t('image_editor.rotate_left', {}, 'Rotate left'),\n icon: RotateCcwIcon,\n run: () => loaded.value?.editor.rotate(-1),\n },\n {\n label: t('image_editor.rotate_right', {}, 'Rotate right'),\n icon: RotateCwIcon,\n run: () => loaded.value?.editor.rotate(1),\n },\n {\n label: t('image_editor.flip_horizontal', {}, 'Flip horizontally'),\n icon: FlipHorizontal2Icon,\n run: () => loaded.value?.editor.flip('x'),\n },\n {\n label: t('image_editor.flip_vertical', {}, 'Flip vertically'),\n icon: FlipVertical2Icon,\n run: () => loaded.value?.editor.flip('y'),\n },\n {\n label: t('image_editor.reset', {}, 'Reset'),\n icon: Undo2Icon,\n run: () => loaded.value?.editor.reset(),\n },\n])\n</script>\n\n<template>\n <Dialog :open=\"props.request !== null\" @update:open=\"(open) => !open && finish(null)\">\n <DialogContent class=\"sm:max-w-3xl\" data-slot=\"image-editor\">\n <DialogHeader>\n <DialogTitle>{{ t('image_editor.title', {}, 'Edit image') }}</DialogTitle>\n <DialogDescription class=\"sr-only\">\n <span :id=\"hintId\"\n >{{\n t(\n 'image_editor.keyboard_hint',\n {},\n 'Arrow keys move the crop area. Shift and arrow keys resize it.',\n )\n }}\n {{ t('image_editor.zoom_hint', {}, 'Plus and minus keys zoom the image.') }}</span\n >\n </DialogDescription>\n </DialogHeader>\n <div v-if=\"loaded && state && data\" class=\"flex flex-col gap-4 md:flex-row\">\n <div class=\"flex min-w-0 flex-1 flex-col gap-3\">\n <!-- Image space: left is the image's left in every reading direction. -->\n <div\n ref=\"frame\"\n dir=\"ltr\"\n data-slot=\"image-editor-viewport\"\n class=\"bg-muted/40 relative h-72 w-full cursor-grab touch-none overflow-hidden rounded-md select-none sm:h-96\"\n @pointerdown=\"start('pan', $event)\"\n @pointermove=\"\n loaded.editor.dragTo($event.clientX, $event.clientY, $event.pointerId ?? 0)\n \"\n @pointerup=\"loaded.editor.endDrag($event.pointerId ?? 0)\"\n @pointercancel=\"loaded.editor.endDrag($event.pointerId ?? 0)\"\n >\n <canvas ref=\"canvas\" class=\"pointer-events-none absolute inset-0 block size-full\" />\n <!-- Runtime geometry: no Tailwind class can hold these values. -->\n <div\n role=\"group\"\n tabindex=\"0\"\n :aria-label=\"t('image_editor.crop_area', {}, 'Crop area')\"\n :aria-describedby=\"hintId\"\n data-slot=\"image-editor-crop\"\n :class=\"\n cn(\n 'ring-ring/50 absolute cursor-move border-2 border-white shadow-[0_0_0_9999px_rgb(0_0_0/0.5)] outline-none focus-visible:ring-[3px]',\n loaded.editor.circle && 'rounded-full',\n )\n \"\n :style=\"{\n left: `${box.left}%`,\n top: `${box.top}%`,\n width: `${box.width}%`,\n height: `${box.height}%`,\n }\"\n @pointerdown=\"start('move', $event)\"\n @keydown=\"onKeydown\"\n >\n <span\n v-for=\"handle in HANDLES\"\n :key=\"handle\"\n :data-handle=\"handle\"\n aria-hidden=\"true\"\n class=\"absolute size-3 -translate-x-1/2 -translate-y-1/2 rounded-sm border border-black/40 bg-white\"\n :style=\"{\n left: handle.endsWith('w') ? '0%' : '100%',\n top: handle.startsWith('n') ? '0%' : '100%',\n cursor: handle === 'nw' || handle === 'se' ? 'nwse-resize' : 'nesw-resize',\n }\"\n @pointerdown=\"start(handle, $event)\"\n />\n </div>\n </div>\n <div class=\"flex flex-wrap items-center justify-between gap-2\">\n <div\n v-if=\"loaded.editor.aspectRatios.length > 1\"\n role=\"group\"\n :aria-label=\"t('image_editor.aspect_ratio', {}, 'Aspect ratio')\"\n class=\"flex flex-wrap gap-1\"\n >\n <Button\n v-for=\"ratio in loaded.editor.aspectRatios\"\n :key=\"ratio ?? 'free'\"\n type=\"button\"\n size=\"sm\"\n :variant=\"state.aspectRatio === ratio ? 'default' : 'outline'\"\n :aria-pressed=\"String(state.aspectRatio === ratio)\"\n @click=\"loaded.editor.setAspectRatio(ratio)\"\n >\n {{ ratioLabel(ratio) }}\n </Button>\n </div>\n <span v-else />\n <div class=\"flex flex-wrap gap-1\">\n <Button\n v-for=\"tool in tools\"\n :key=\"tool.label\"\n type=\"button\"\n variant=\"outline\"\n size=\"icon-sm\"\n :aria-label=\"tool.label\"\n :title=\"tool.label\"\n :disabled=\"tool.disabled\"\n @click=\"tool.run()\"\n >\n <component :is=\"tool.icon\" />\n </Button>\n </div>\n </div>\n </div>\n <!-- Numeric inputs: beside the image from md up, under it on phones. -->\n <div\n role=\"group\"\n :aria-label=\"t('image_editor.inputs', {}, 'Position and size')\"\n data-slot=\"image-editor-inputs\"\n class=\"grid grid-cols-2 content-start gap-x-3 gap-y-2 sm:grid-cols-4 md:w-40 md:shrink-0 md:grid-cols-1\"\n >\n <div\n v-for=\"[field, key, fallback] in NUMERIC_FIELDS\"\n :key=\"field\"\n class=\"flex flex-col gap-1\"\n >\n <label :for=\"`${inputsId}-${field}`\" class=\"text-muted-foreground text-xs\">\n {{ t(key, {}, fallback) }}\n </label>\n <Input\n :id=\"`${inputsId}-${field}`\"\n type=\"number\"\n inputmode=\"decimal\"\n step=\"1\"\n :data-field=\"field\"\n class=\"h-8 tabular-nums\"\n :model-value=\"data[field]\"\n @change=\"commit(field, $event)\"\n @keydown.enter.prevent=\"commit(field, $event)\"\n />\n </div>\n <div class=\"col-span-2 flex gap-1 sm:col-span-4 md:col-span-1\">\n <Button\n v-for=\"[axis, key, fallback] in SCALES\"\n :key=\"axis\"\n type=\"button\"\n size=\"sm\"\n :variant=\"(axis === 'x' ? state.flipX : state.flipY) ? 'default' : 'outline'\"\n :aria-pressed=\"String(axis === 'x' ? state.flipX : state.flipY)\"\n :data-field=\"`scale${axis.toUpperCase()}`\"\n class=\"flex-1\"\n @click=\"loaded.editor.flip(axis)\"\n >\n {{ t(key, {}, fallback) }}\n </Button>\n </div>\n </div>\n </div>\n <div v-else class=\"flex h-48 items-center justify-center\">\n <Spinner />\n </div>\n <DialogFooter>\n <Button type=\"button\" variant=\"outline\" @click=\"finish(null)\">\n {{ t('image_editor.cancel', {}, 'Cancel') }}\n </Button>\n <Button type=\"button\" :disabled=\"!loaded || saving\" @click=\"void save()\">\n <Spinner v-if=\"saving\" />\n {{ t('image_editor.save', {}, 'Apply') }}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"ImageEditorDialog.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createBlock","Dialog","_withCtx","_createVNode","DialogContent","DialogHeader","DialogTitle","_createTextVNode","_toDisplayString","_unref","DialogDescription","_createElementVNode","_createElementBlock","_normalizeClass","_normalizeStyle","_Fragment","_renderList","Button","_resolveDynamicComponent","Input","_withKeys","_withModifiers","Spinner","DialogFooter","_createCommentVNode","Button_default","Spinner_default","Input_default","Dialog_default","DialogContent_default","DialogDescription_default","DialogHeader_default","DialogTitle_default","DialogFooter_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_6","_hoisted_7","_hoisted_8","_hoisted_9","_hoisted_10","_hoisted_11","_hoisted_12","_hoisted_13","ImageEditorDialog_vue_vue_type_script_setup_true_lang_default","HANDLES","NUMERIC_FIELDS","SCALES","props","__props","t","useT","loaded","shallowRef","state","saving","ref","hintId","useId","inputsId","canvas","frame","unsubscribe","stopObserving","release","watch","imageEditorOptionsKey","request","options","cancelled","loadEditorImage","bitmap","editor","ImageEditor","next","onCleanup","onScopeDispose","element","measure","observer","onWheel","rect","event","data","computed","commit","input","value","field","box","finish","file","save","current","start","mode","onKeydown","ratioLabel","ratio","tools","ZoomOutIcon","ZoomInIcon","RotateCcwIcon","RotateCwIcon","FlipHorizontal2Icon","FlipVertical2Icon","Undo2Icon","openBlock","createBlock","_cache","open","withCtx","createVNode","createTextVNode","toDisplayString","unref","createElementVNode","createElementBlock","$event","normalizeClass","cn","normalizeStyle","Fragment","renderList","handle","tool","resolveDynamicComponent","key","fallback","withKeys","withModifiers","axis","createCommentVNode"],"sources":["../../../src/components/fields/ImageEditorDialog.vue"],"sourcesContent":["<script setup lang=\"ts\">\n/**\n * `FileUpload::imageEditor()`: crop, zoom, rotate and flip an image before it is uploaded\n * (or to replace an uploaded one). Resolves the request with the edited file, or null\n * when cancelled.\n */\nimport type {\n CropHandle,\n FileUploadImageEditorSchema,\n ImageEditorData,\n ImageEditorDragMode,\n ImageEditorState,\n} from '@alfakit/core'\nimport { ImageEditor, imageEditorOptionsKey, loadEditorImage } from '@alfakit/core'\nimport {\n FlipHorizontal2Icon,\n FlipVertical2Icon,\n RotateCcwIcon,\n RotateCwIcon,\n Undo2Icon,\n ZoomInIcon,\n ZoomOutIcon,\n} from '@lucide/vue'\nimport { computed, onScopeDispose, ref, shallowRef, useId, watch, type Component } from 'vue'\nimport { useT } from '../../context'\nimport { cn } from '../../lib/utils'\nimport Button from '../ui/Button.vue'\nimport Dialog from '../ui/Dialog.vue'\nimport DialogContent from '../ui/DialogContent.vue'\nimport DialogDescription from '../ui/DialogDescription.vue'\nimport DialogFooter from '../ui/DialogFooter.vue'\nimport DialogHeader from '../ui/DialogHeader.vue'\nimport DialogTitle from '../ui/DialogTitle.vue'\nimport Input from '../ui/Input.vue'\nimport Spinner from '../ui/Spinner.vue'\n\nexport interface ImageEditRequest {\n file: File\n resolve: (file: File | null) => void\n}\n\nconst HANDLES: CropHandle[] = ['nw', 'ne', 'sw', 'se']\n\n/** The numeric inputs, in the order Filament shows them. */\nconst NUMERIC_FIELDS = [\n ['x', 'image_editor.x', 'X'],\n ['y', 'image_editor.y', 'Y'],\n ['width', 'image_editor.width', 'Width'],\n ['height', 'image_editor.height', 'Height'],\n ['rotate', 'image_editor.rotation', 'Rotation'],\n] as const satisfies ReadonlyArray<readonly [keyof ImageEditorData, string, string]>\n\nconst SCALES = [\n ['x', 'image_editor.scale_x', 'Scale X'],\n ['y', 'image_editor.scale_y', 'Scale Y'],\n] as const\n\nconst props = defineProps<{\n request: ImageEditRequest | null\n options: FileUploadImageEditorSchema\n}>()\n\nconst t = useT()\nconst loaded = shallowRef<{ bitmap: ImageBitmap; editor: ImageEditor } | null>(null)\nconst state = shallowRef<ImageEditorState | null>(null)\nconst saving = ref(false)\nconst hintId = useId()\nconst inputsId = useId()\nconst canvas = ref<HTMLCanvasElement | null>(null)\nconst frame = ref<HTMLDivElement | null>(null)\nlet unsubscribe: (() => void) | null = null\nlet stopObserving: (() => void) | null = null\n\nconst release = () => {\n unsubscribe?.()\n unsubscribe = null\n stopObserving?.()\n stopObserving = null\n loaded.value?.bitmap.close()\n loaded.value = null\n state.value = null\n}\n\n// Restart only for another image or other settings: the schema object itself is new on\n// every render of a template item (a new builder block), which kept restarting the load.\nwatch(\n [() => props.request, () => imageEditorOptionsKey(props.options)],\n ([request], _previous, onCleanup) => {\n if (!request) return\n\n const options = props.options\n\n let cancelled = false\n\n loadEditorImage(request.file)\n .then((bitmap) => {\n if (cancelled) return bitmap.close()\n\n const editor = new ImageEditor({\n width: bitmap.width,\n height: bitmap.height,\n aspectRatios: options.aspectRatios,\n circle: options.circle,\n mode: options.mode,\n emptyFillColor: options.emptyFillColor,\n viewportWidth: options.viewportWidth,\n viewportHeight: options.viewportHeight,\n })\n\n loaded.value = { bitmap, editor }\n state.value = editor.store.get()\n unsubscribe = editor.store.subscribe((next) => {\n state.value = next\n })\n })\n // Undecodable: upload the file as it is.\n .catch(() => !cancelled && request.resolve(request.file))\n\n onCleanup(() => {\n cancelled = true\n release()\n })\n },\n { immediate: true },\n)\n\nonScopeDispose(release)\n\n// Redraw on every change (crop, zoom, rotation, flips, container size).\nwatch(\n () => [canvas.value, state.value] as const,\n ([element]) => {\n if (element && loaded.value) {\n loaded.value.editor.drawPreview(\n element,\n loaded.value.bitmap,\n globalThis.devicePixelRatio || 1,\n )\n }\n },\n { flush: 'post' },\n)\n\n// Measure the container and follow its size; zoom with the wheel and trackpad pinch.\nwatch(\n () => [frame.value, loaded.value?.editor] as const,\n ([element, editor]) => {\n stopObserving?.()\n stopObserving = null\n\n if (!element || !editor) return\n\n const measure = () => editor.setContainer(element.clientWidth, element.clientHeight)\n measure()\n\n const observer = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(measure)\n observer?.observe(element)\n\n const onWheel = (event: WheelEvent) => {\n const rect = element.getBoundingClientRect()\n\n if (editor.wheel(event, { x: event.clientX - rect.left, y: event.clientY - rect.top })) {\n event.preventDefault()\n }\n }\n\n element.addEventListener('wheel', onWheel, { passive: false })\n\n stopObserving = () => {\n observer?.disconnect()\n element.removeEventListener('wheel', onWheel)\n }\n },\n { flush: 'post' },\n)\n\nconst data = computed<ImageEditorData | null>(() => {\n void state.value\n\n return loaded.value?.editor.getData() ?? null\n})\n\n// Numeric inputs apply on change (blur, Enter, spinner); invalid values snap back.\nconst commit = (field: keyof ImageEditorData, event: Event) => {\n const editor = loaded.value?.editor\n const input = event.target as HTMLInputElement | null\n\n if (!editor || !input) return\n\n const value = input.value.trim() === '' ? Number.NaN : Number(input.value)\n editor.setData({ [field]: value })\n input.value = String(editor.getData()[field])\n}\n\nconst box = computed(() => {\n void state.value\n\n return loaded.value?.editor.cropBox() ?? { left: 0, top: 0, width: 0, height: 0 }\n})\n\nconst finish = (file: File | null) => {\n props.request?.resolve(file)\n}\n\nconst save = async () => {\n const request = props.request\n const current = loaded.value\n\n if (!request || !current) return\n\n saving.value = true\n\n try {\n finish(await current.editor.export(current.bitmap, request.file))\n } catch {\n finish(request.file)\n } finally {\n saving.value = false\n }\n}\n\nconst start = (mode: ImageEditorDragMode, event: PointerEvent) => {\n const editor = loaded.value?.editor\n\n if (!editor) return\n\n event.preventDefault()\n event.stopPropagation()\n ;(event.currentTarget as HTMLElement | null)?.setPointerCapture?.(event.pointerId)\n editor.startDrag(mode, event.clientX, event.clientY, undefined, event.pointerId ?? 0)\n}\n\nconst onKeydown = (event: KeyboardEvent) => {\n if (loaded.value?.editor.handleKey(event)) event.preventDefault()\n}\n\nconst ratioLabel = (ratio: string | null) => ratio ?? t('image_editor.free', {}, 'Free')\n\nconst tools = computed<\n Array<{ label: string; icon: Component; run: () => void; disabled?: boolean }>\n>(() => [\n {\n label: t('image_editor.zoom_out', {}, 'Zoom out'),\n icon: ZoomOutIcon,\n run: () => loaded.value?.editor.zoomOut(),\n disabled: !(state.value && loaded.value?.editor.canZoomOut),\n },\n {\n label: t('image_editor.zoom_in', {}, 'Zoom in'),\n icon: ZoomInIcon,\n run: () => loaded.value?.editor.zoomIn(),\n disabled: !(state.value && loaded.value?.editor.canZoomIn),\n },\n {\n label: t('image_editor.rotate_left', {}, 'Rotate left'),\n icon: RotateCcwIcon,\n run: () => loaded.value?.editor.rotate(-1),\n },\n {\n label: t('image_editor.rotate_right', {}, 'Rotate right'),\n icon: RotateCwIcon,\n run: () => loaded.value?.editor.rotate(1),\n },\n {\n label: t('image_editor.flip_horizontal', {}, 'Flip horizontally'),\n icon: FlipHorizontal2Icon,\n run: () => loaded.value?.editor.flip('x'),\n },\n {\n label: t('image_editor.flip_vertical', {}, 'Flip vertically'),\n icon: FlipVertical2Icon,\n run: () => loaded.value?.editor.flip('y'),\n },\n {\n label: t('image_editor.reset', {}, 'Reset'),\n icon: Undo2Icon,\n run: () => loaded.value?.editor.reset(),\n },\n])\n</script>\n\n<template>\n <Dialog :open=\"props.request !== null\" @update:open=\"(open) => !open && finish(null)\">\n <DialogContent class=\"sm:max-w-3xl\" data-slot=\"image-editor\">\n <DialogHeader>\n <DialogTitle>{{ t('image_editor.title', {}, 'Edit image') }}</DialogTitle>\n <DialogDescription class=\"sr-only\">\n <span :id=\"hintId\"\n >{{\n t(\n 'image_editor.keyboard_hint',\n {},\n 'Arrow keys move the crop area. Shift and arrow keys resize it.',\n )\n }}\n {{ t('image_editor.zoom_hint', {}, 'Plus and minus keys zoom the image.') }}</span\n >\n </DialogDescription>\n </DialogHeader>\n <div v-if=\"loaded && state && data\" class=\"flex flex-col gap-4 md:flex-row\">\n <div class=\"flex min-w-0 flex-1 flex-col gap-3\">\n <!-- Image space: left is the image's left in every reading direction. -->\n <div\n ref=\"frame\"\n dir=\"ltr\"\n data-slot=\"image-editor-viewport\"\n class=\"bg-muted/40 relative h-72 w-full cursor-grab touch-none overflow-hidden rounded-md select-none sm:h-96\"\n @pointerdown=\"start('pan', $event)\"\n @pointermove=\"\n loaded.editor.dragTo($event.clientX, $event.clientY, $event.pointerId ?? 0)\n \"\n @pointerup=\"loaded.editor.endDrag($event.pointerId ?? 0)\"\n @pointercancel=\"loaded.editor.endDrag($event.pointerId ?? 0)\"\n >\n <canvas ref=\"canvas\" class=\"pointer-events-none absolute inset-0 block size-full\" />\n <!-- Runtime geometry: no Tailwind class can hold these values. -->\n <div\n role=\"group\"\n tabindex=\"0\"\n :aria-label=\"t('image_editor.crop_area', {}, 'Crop area')\"\n :aria-describedby=\"hintId\"\n data-slot=\"image-editor-crop\"\n :class=\"\n cn(\n 'ring-ring/50 absolute cursor-move border-2 border-white shadow-[0_0_0_9999px_rgb(0_0_0/0.5)] outline-none focus-visible:ring-[3px]',\n loaded.editor.circle && 'rounded-full',\n )\n \"\n :style=\"{\n left: `${box.left}%`,\n top: `${box.top}%`,\n width: `${box.width}%`,\n height: `${box.height}%`,\n }\"\n @pointerdown=\"start('move', $event)\"\n @keydown=\"onKeydown\"\n >\n <span\n v-for=\"handle in HANDLES\"\n :key=\"handle\"\n :data-handle=\"handle\"\n aria-hidden=\"true\"\n class=\"absolute size-3 -translate-x-1/2 -translate-y-1/2 rounded-sm border border-black/40 bg-white\"\n :style=\"{\n left: handle.endsWith('w') ? '0%' : '100%',\n top: handle.startsWith('n') ? '0%' : '100%',\n cursor: handle === 'nw' || handle === 'se' ? 'nwse-resize' : 'nesw-resize',\n }\"\n @pointerdown=\"start(handle, $event)\"\n />\n </div>\n </div>\n <div class=\"flex flex-wrap items-center justify-between gap-2\">\n <div\n v-if=\"loaded.editor.aspectRatios.length > 1\"\n role=\"group\"\n :aria-label=\"t('image_editor.aspect_ratio', {}, 'Aspect ratio')\"\n class=\"flex flex-wrap gap-1\"\n >\n <Button\n v-for=\"ratio in loaded.editor.aspectRatios\"\n :key=\"ratio ?? 'free'\"\n type=\"button\"\n size=\"sm\"\n :variant=\"state.aspectRatio === ratio ? 'default' : 'outline'\"\n :aria-pressed=\"String(state.aspectRatio === ratio)\"\n @click=\"loaded.editor.setAspectRatio(ratio)\"\n >\n {{ ratioLabel(ratio) }}\n </Button>\n </div>\n <span v-else />\n <div class=\"flex flex-wrap gap-1\">\n <Button\n v-for=\"tool in tools\"\n :key=\"tool.label\"\n type=\"button\"\n variant=\"outline\"\n size=\"icon-sm\"\n :aria-label=\"tool.label\"\n :title=\"tool.label\"\n :disabled=\"tool.disabled\"\n @click=\"tool.run()\"\n >\n <component :is=\"tool.icon\" />\n </Button>\n </div>\n </div>\n </div>\n <!-- Numeric inputs: beside the image from md up, under it on phones. -->\n <div\n role=\"group\"\n :aria-label=\"t('image_editor.inputs', {}, 'Position and size')\"\n data-slot=\"image-editor-inputs\"\n class=\"grid grid-cols-2 content-start gap-x-3 gap-y-2 sm:grid-cols-4 md:w-40 md:shrink-0 md:grid-cols-1\"\n >\n <div\n v-for=\"[field, key, fallback] in NUMERIC_FIELDS\"\n :key=\"field\"\n class=\"flex flex-col gap-1\"\n >\n <label :for=\"`${inputsId}-${field}`\" class=\"text-muted-foreground text-xs\">\n {{ t(key, {}, fallback) }}\n </label>\n <Input\n :id=\"`${inputsId}-${field}`\"\n type=\"number\"\n inputmode=\"decimal\"\n step=\"1\"\n :data-field=\"field\"\n class=\"h-8 tabular-nums\"\n :model-value=\"data[field]\"\n @change=\"commit(field, $event)\"\n @keydown.enter.prevent=\"commit(field, $event)\"\n />\n </div>\n <div class=\"col-span-2 flex gap-1 sm:col-span-4 md:col-span-1\">\n <Button\n v-for=\"[axis, key, fallback] in SCALES\"\n :key=\"axis\"\n type=\"button\"\n size=\"sm\"\n :variant=\"(axis === 'x' ? state.flipX : state.flipY) ? 'default' : 'outline'\"\n :aria-pressed=\"String(axis === 'x' ? state.flipX : state.flipY)\"\n :data-field=\"`scale${axis.toUpperCase()}`\"\n class=\"flex-1\"\n @click=\"loaded.editor.flip(axis)\"\n >\n {{ t(key, {}, fallback) }}\n </Button>\n </div>\n </div>\n </div>\n <div v-else class=\"flex h-48 items-center justify-center\">\n <Spinner />\n </div>\n <DialogFooter>\n <Button type=\"button\" variant=\"outline\" @click=\"finish(null)\">\n {{ t('image_editor.cancel', {}, 'Cancel') }}\n </Button>\n <Button type=\"button\" :disabled=\"!loaded || saving\" @click=\"void save()\">\n <Spinner v-if=\"saving\" />\n {{ t('image_editor.save', {}, 'Apply') }}\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n</template>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"KeyValueField.js","names":["_sfc_main","KeyValueField_vue_vue_type_script_setup_true_lang_default","KeyValueField_default"],"sources":["../../../src/components/fields/KeyValueField.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n fieldIds,\n moveRepeaterItem,\n reorderedItemKeys,\n resolveItemAction,\n type KeyValueSchema,\n} from '@alfakit/core'\nimport { ChevronDownIcon, ChevronUpIcon } from '@lucide/vue'\nimport { computed, ref } from 'vue'\nimport { cn } from '../../lib/utils'\nimport { useField } from '../form/form-context'\nimport { useFieldActionContext } from '../schema/field-actions'\nimport FieldWrapper from '../schema/FieldWrapper.vue'\nimport Button from '../ui/Button.vue'\nimport Input from '../ui/Input.vue'\nimport { useT } from '../../context'\nimport ItemActionButton from './ItemActionButton.vue'\nimport { useItemMoves, useRunItemAction } from './item-actions'\n\ntype Row = { key: string; value: string }\n\n/**\n * The server stores an object; while editing we keep an ordered list of rows so keys\n * can be typed freely (including temporarily duplicate or empty keys).\n */\nconst props = defineProps<{ component: KeyValueSchema }>()\nconst { value, setValue, blur, error, id, disabled, readOnly, aria } = useField<\n Record<string, unknown> | Row[] | null\n>(() => props.component)\n\nconst rows = computed<Row[]>(() => {\n if (Array.isArray(value.value)) {\n return value.value.map((row) => ({\n key: String(row.key ?? ''),\n value: row.value === null || row.value === undefined ? '' : String(row.value),\n }))\n }\n\n return Object.entries(value.value ?? {}).map(([key, rowValue]) => ({\n key,\n value: rowValue === null || rowValue === undefined ? '' : String(rowValue),\n }))\n})\n\nconst update = (next: Row[]) => setValue(next)\nconst patch = (index: number, change: Partial<Row>) =>\n update(rows.value.map((item, i) => (i === index ? { ...item, ...change } : item)))\nconst t = useT()\n\nconst context = useFieldActionContext(() => props.component)\nconst runItemAction = useRunItemAction(context)\nconst addAction = computed(() =>\n resolveItemAction('add', props.component, undefined, {\n label: props.component.addActionLabel,\n icon: 'plus',\n variant: 'ghost',\n }),\n)\nconst deleteAction = computed(() =>\n resolveItemAction('delete', props.component, undefined, {\n label: t('form.remove_row', {}, 'Remove row'),\n icon: 'trash-2',\n }),\n)\nconst reorderAction = computed(() =>\n resolveItemAction('reorder', props.component, undefined, {\n label: t('form.reorder_item', {}, 'Reorder'),\n icon: 'grip-vertical',\n }),\n)\nconst deletable = computed(\n () => props.component.deletable && !readOnly.value && deleteAction.value !== null,\n)\nconst reorderable = computed(\n () =>\n props.component.reorderable &&\n !readOnly.value &&\n !disabled.value &&\n reorderAction.value !== null,\n)\nconst dragIndex = ref<number | null>(null)\n// Moving runs the reorder action: in the browser, or on the server when customised.\nconst move = (from: number, to: number) =>\n runItemAction(\n reorderAction.value,\n { items: reorderedItemKeys(rows.value.length, from, to) },\n () => update(moveRepeaterItem(rows.value, from, to) as Row[]),\n )\n// Move buttons: announced, one at a time, focus kept on the moved row.\nconst moves = useItemMoves(\n value,\n move,\n (index) => rows.value[index]?.key || null,\n () => rows.value.length,\n)\nconst moveAnnouncement = moves.announcement\nconst moveContainer = moves.container\nconst onRowDrop = (index: number) => {\n if (dragIndex.value !== null && dragIndex.value !== index) move(dragIndex.value, index)\n dragIndex.value = null\n}\n</script>\n\n<template>\n <FieldWrapper :field=\"props.component\" :html-for=\"id\" :error=\"error\">\n <div ref=\"moveContainer\" class=\"overflow-hidden rounded-md border\">\n <span aria-live=\"polite\" aria-atomic=\"true\" class=\"sr-only\" data-slot=\"item-move-status\">{{\n moveAnnouncement\n }}</span>\n <table\n class=\"w-full text-sm\"\n :aria-labelledby=\"props.component.label ? fieldIds(id).label : undefined\"\n :aria-describedby=\"aria['aria-describedby']\"\n >\n <thead class=\"bg-muted/50 text-muted-foreground text-xs\">\n <tr>\n <th v-if=\"reorderable\" class=\"w-16\" />\n <th class=\"px-3 py-2 text-start font-medium\">{{ props.component.keyLabel }}</th>\n <th class=\"px-3 py-2 text-start font-medium\">{{ props.component.valueLabel }}</th>\n <th v-if=\"deletable\" class=\"w-10\" />\n </tr>\n </thead>\n <tbody>\n <tr\n v-for=\"(row, index) in rows\"\n :key=\"index\"\n :data-index=\"index\"\n :draggable=\"reorderable\"\n :class=\"cn('border-t', dragIndex === index && 'opacity-50')\"\n @dragstart=\"dragIndex = index\"\n @dragover=\"reorderable && $event.preventDefault()\"\n @drop=\"onRowDrop(index)\"\n @dragend=\"dragIndex = null\"\n >\n <td v-if=\"reorderable\" class=\"p-1.5\">\n <div class=\"flex items-center\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-xs\"\n :aria-label=\"t('form.move_up', {}, 'Move up')\"\n :disabled=\"index === 0\"\n data-item-move=\"up\"\n @click=\"moves.moveWithButton(index, index - 1)\"\n ><ChevronUpIcon\n /></Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-xs\"\n :aria-label=\"t('form.move_down', {}, 'Move down')\"\n :disabled=\"index === rows.length - 1\"\n data-item-move=\"down\"\n @click=\"moves.moveWithButton(index, index + 1)\"\n ><ChevronDownIcon\n /></Button>\n </div>\n </td>\n <td class=\"p-1.5\">\n <Input\n dir=\"auto\"\n :model-value=\"row.key\"\n :readonly=\"readOnly || !props.component.editableKeys\"\n :disabled=\"disabled\"\n :placeholder=\"props.component.keyPlaceholder\"\n :aria-label=\"props.component.keyLabel\"\n :aria-invalid=\"aria['aria-invalid']\"\n class=\"h-8\"\n @update:model-value=\"patch(index, { key: $event })\"\n @blur=\"blur\"\n />\n </td>\n <td class=\"p-1.5\">\n <Input\n dir=\"auto\"\n :model-value=\"row.value\"\n :readonly=\"readOnly || !props.component.editableValues\"\n :disabled=\"disabled\"\n :placeholder=\"props.component.valuePlaceholder\"\n :aria-label=\"props.component.valueLabel\"\n :aria-invalid=\"aria['aria-invalid']\"\n class=\"h-8\"\n @update:model-value=\"patch(index, { value: $event })\"\n @blur=\"blur\"\n />\n </td>\n <td v-if=\"deletable\" class=\"p-1.5\">\n <ItemActionButton\n :action=\"deleteAction\"\n :context=\"context\"\n :args=\"{ item: String(index) }\"\n size=\"sm\"\n :disabled=\"disabled\"\n class=\"text-muted-foreground\"\n @client=\"update(rows.filter((_, i) => i !== index))\"\n />\n </td>\n </tr>\n <tr v-if=\"rows.length === 0\" class=\"border-t\">\n <td\n :colspan=\"reorderable ? 4 : 3\"\n class=\"text-muted-foreground px-3 py-4 text-center text-xs\"\n >\n —\n </td>\n </tr>\n </tbody>\n </table>\n <div v-if=\"props.component.addable && !readOnly && addAction\" class=\"border-t p-1.5\">\n <ItemActionButton\n :action=\"addAction\"\n :context=\"context\"\n size=\"sm\"\n :disabled=\"disabled\"\n @client=\"update([...rows, { key: '', value: '' }])\"\n />\n </div>\n </div>\n </FieldWrapper>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"KeyValueField.js","names":["_sfc_main","KeyValueField_vue_vue_type_script_setup_true_lang_default","KeyValueField_default"],"sources":["../../../src/components/fields/KeyValueField.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n fieldIds,\n moveRepeaterItem,\n reorderedItemKeys,\n resolveItemAction,\n type KeyValueSchema,\n itemActionIcon,\n} from '@alfakit/core'\nimport { ChevronDownIcon, ChevronUpIcon } from '@lucide/vue'\nimport { computed, ref } from 'vue'\nimport { cn } from '../../lib/utils'\nimport { useField } from '../form/form-context'\nimport { useFieldActionContext } from '../schema/field-actions'\nimport FieldWrapper from '../schema/FieldWrapper.vue'\nimport Button from '../ui/Button.vue'\nimport Input from '../ui/Input.vue'\nimport { useT } from '../../context'\nimport ItemActionButton from './ItemActionButton.vue'\nimport { useItemMoves, useRunItemAction } from './item-actions'\n\ntype Row = { key: string; value: string }\n\n/**\n * The server stores an object; while editing we keep an ordered list of rows so keys\n * can be typed freely (including temporarily duplicate or empty keys).\n */\nconst props = defineProps<{ component: KeyValueSchema }>()\nconst { value, setValue, blur, error, id, disabled, readOnly, aria } = useField<\n Record<string, unknown> | Row[] | null\n>(() => props.component)\n\nconst rows = computed<Row[]>(() => {\n if (Array.isArray(value.value)) {\n return value.value.map((row) => ({\n key: String(row.key ?? ''),\n value: row.value === null || row.value === undefined ? '' : String(row.value),\n }))\n }\n\n return Object.entries(value.value ?? {}).map(([key, rowValue]) => ({\n key,\n value: rowValue === null || rowValue === undefined ? '' : String(rowValue),\n }))\n})\n\nconst update = (next: Row[]) => setValue(next)\nconst patch = (index: number, change: Partial<Row>) =>\n update(rows.value.map((item, i) => (i === index ? { ...item, ...change } : item)))\nconst t = useT()\n\nconst context = useFieldActionContext(() => props.component)\nconst runItemAction = useRunItemAction(context)\nconst addAction = computed(() =>\n resolveItemAction('add', props.component, undefined, {\n label: props.component.addActionLabel,\n icon: 'plus',\n variant: 'ghost',\n }),\n)\nconst deleteAction = computed(() =>\n resolveItemAction('delete', props.component, undefined, {\n label: t('form.remove_row', {}, 'Remove row'),\n icon: itemActionIcon('key-value', 'delete', 'trash-2'),\n }),\n)\nconst reorderAction = computed(() =>\n resolveItemAction('reorder', props.component, undefined, {\n label: t('form.reorder_item', {}, 'Reorder'),\n icon: itemActionIcon('key-value', 'reorder', 'grip-vertical'),\n }),\n)\nconst deletable = computed(\n () => props.component.deletable && !readOnly.value && deleteAction.value !== null,\n)\nconst reorderable = computed(\n () =>\n props.component.reorderable &&\n !readOnly.value &&\n !disabled.value &&\n reorderAction.value !== null,\n)\nconst dragIndex = ref<number | null>(null)\n// Moving runs the reorder action: in the browser, or on the server when customised.\nconst move = (from: number, to: number) =>\n runItemAction(\n reorderAction.value,\n { items: reorderedItemKeys(rows.value.length, from, to) },\n () => update(moveRepeaterItem(rows.value, from, to) as Row[]),\n )\n// Move buttons: announced, one at a time, focus kept on the moved row.\nconst moves = useItemMoves(\n value,\n move,\n (index) => rows.value[index]?.key || null,\n () => rows.value.length,\n)\nconst moveAnnouncement = moves.announcement\nconst moveContainer = moves.container\nconst onRowDrop = (index: number) => {\n if (dragIndex.value !== null && dragIndex.value !== index) move(dragIndex.value, index)\n dragIndex.value = null\n}\n</script>\n\n<template>\n <FieldWrapper :field=\"props.component\" :html-for=\"id\" :error=\"error\">\n <div ref=\"moveContainer\" class=\"overflow-hidden rounded-md border\">\n <span aria-live=\"polite\" aria-atomic=\"true\" class=\"sr-only\" data-slot=\"item-move-status\">{{\n moveAnnouncement\n }}</span>\n <table\n class=\"w-full text-sm\"\n :aria-labelledby=\"props.component.label ? fieldIds(id).label : undefined\"\n :aria-describedby=\"aria['aria-describedby']\"\n >\n <thead class=\"bg-muted/50 text-muted-foreground text-xs\">\n <tr>\n <th v-if=\"reorderable\" class=\"w-16\" />\n <th class=\"px-3 py-2 text-start font-medium\">{{ props.component.keyLabel }}</th>\n <th class=\"px-3 py-2 text-start font-medium\">{{ props.component.valueLabel }}</th>\n <th v-if=\"deletable\" class=\"w-10\" />\n </tr>\n </thead>\n <tbody>\n <tr\n v-for=\"(row, index) in rows\"\n :key=\"index\"\n :data-index=\"index\"\n :draggable=\"reorderable\"\n :class=\"cn('border-t', dragIndex === index && 'opacity-50')\"\n @dragstart=\"dragIndex = index\"\n @dragover=\"reorderable && $event.preventDefault()\"\n @drop=\"onRowDrop(index)\"\n @dragend=\"dragIndex = null\"\n >\n <td v-if=\"reorderable\" class=\"p-1.5\">\n <div class=\"flex items-center\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-xs\"\n :aria-label=\"t('form.move_up', {}, 'Move up')\"\n :disabled=\"index === 0\"\n data-item-move=\"up\"\n @click=\"moves.moveWithButton(index, index - 1)\"\n ><ChevronUpIcon\n /></Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-xs\"\n :aria-label=\"t('form.move_down', {}, 'Move down')\"\n :disabled=\"index === rows.length - 1\"\n data-item-move=\"down\"\n @click=\"moves.moveWithButton(index, index + 1)\"\n ><ChevronDownIcon\n /></Button>\n </div>\n </td>\n <td class=\"p-1.5\">\n <Input\n dir=\"auto\"\n :model-value=\"row.key\"\n :readonly=\"readOnly || !props.component.editableKeys\"\n :disabled=\"disabled\"\n :placeholder=\"props.component.keyPlaceholder\"\n :aria-label=\"props.component.keyLabel\"\n :aria-invalid=\"aria['aria-invalid']\"\n class=\"h-8\"\n @update:model-value=\"patch(index, { key: $event })\"\n @blur=\"blur\"\n />\n </td>\n <td class=\"p-1.5\">\n <Input\n dir=\"auto\"\n :model-value=\"row.value\"\n :readonly=\"readOnly || !props.component.editableValues\"\n :disabled=\"disabled\"\n :placeholder=\"props.component.valuePlaceholder\"\n :aria-label=\"props.component.valueLabel\"\n :aria-invalid=\"aria['aria-invalid']\"\n class=\"h-8\"\n @update:model-value=\"patch(index, { value: $event })\"\n @blur=\"blur\"\n />\n </td>\n <td v-if=\"deletable\" class=\"p-1.5\">\n <ItemActionButton\n :action=\"deleteAction\"\n :context=\"context\"\n :args=\"{ item: String(index) }\"\n size=\"sm\"\n :disabled=\"disabled\"\n class=\"text-muted-foreground\"\n @client=\"update(rows.filter((_, i) => i !== index))\"\n />\n </td>\n </tr>\n <tr v-if=\"rows.length === 0\" class=\"border-t\">\n <td\n :colspan=\"reorderable ? 4 : 3\"\n class=\"text-muted-foreground px-3 py-4 text-center text-xs\"\n >\n —\n </td>\n </tr>\n </tbody>\n </table>\n <div v-if=\"props.component.addable && !readOnly && addAction\" class=\"border-t p-1.5\">\n <ItemActionButton\n :action=\"addAction\"\n :context=\"context\"\n size=\"sm\"\n :disabled=\"disabled\"\n @client=\"update([...rows, { key: '', value: '' }])\"\n />\n </div>\n </div>\n </FieldWrapper>\n</template>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"KeyValueField.vue.d.ts","sourceRoot":"","sources":["../../../src/components/fields/KeyValueField.vue"],"names":[],"mappings":"AA+NA,OAAO,EAKL,KAAK,cAAc,EACpB,MAAM,eAAe,CAAA;AAetB;;;GAGG;AACH,KAAK,WAAW,GAAG;IAAE,SAAS,EAAE,cAAc,CAAA;CAAE,CAAC;;AAkejD,wBAMG"}
1
+ {"version":3,"file":"KeyValueField.vue.d.ts","sourceRoot":"","sources":["../../../src/components/fields/KeyValueField.vue"],"names":[],"mappings":"AAgOA,OAAO,EAKL,KAAK,cAAc,EAEpB,MAAM,eAAe,CAAA;AAetB;;;GAGG;AACH,KAAK,WAAW,GAAG;IAAE,SAAS,EAAE,cAAc,CAAA;CAAE,CAAC;;AAkejD,wBAMG"}
@@ -4,30 +4,30 @@ import n from "../ui/Button2.js";
4
4
  import { useField as r } from "../form/form-context.js";
5
5
  import i from "../ui/Input.js";
6
6
  import { useFieldActionContext as a } from "../schema/field-actions.js";
7
- import ee from "../schema/FieldWrapper.js";
8
- import o from "./ItemActionButton.js";
9
- import { useItemMoves as s, useRunItemAction as c } from "./item-actions.js";
10
- import { fieldIds as l, moveRepeaterItem as te, reorderedItemKeys as ne, resolveItemAction as u } from "@alfakit/core";
11
- import { Fragment as re, computed as d, createBlock as f, createCommentVNode as p, createElementBlock as m, createElementVNode as h, createVNode as g, defineComponent as _, normalizeClass as ie, openBlock as v, ref as ae, renderList as oe, toDisplayString as y, unref as b, withCtx as x } from "vue";
12
- import { ChevronDownIcon as S, ChevronUpIcon as C } from "@lucide/vue";
7
+ import o from "../schema/FieldWrapper.js";
8
+ import s from "./ItemActionButton.js";
9
+ import { useItemMoves as c, useRunItemAction as l } from "./item-actions.js";
10
+ import { fieldIds as ee, itemActionIcon as u, moveRepeaterItem as te, reorderedItemKeys as ne, resolveItemAction as d } from "@alfakit/core";
11
+ import { Fragment as re, computed as f, createBlock as p, createCommentVNode as m, createElementBlock as h, createElementVNode as g, createVNode as _, defineComponent as v, normalizeClass as ie, openBlock as y, ref as ae, renderList as oe, toDisplayString as b, unref as x, withCtx as S } from "vue";
12
+ import { ChevronDownIcon as C, ChevronUpIcon as w } from "@lucide/vue";
13
13
  //#region src/components/fields/KeyValueField.vue?vue&type=script&setup=true&lang.ts
14
- var w = {
14
+ var se = {
15
15
  "aria-live": "polite",
16
16
  "aria-atomic": "true",
17
17
  class: "sr-only",
18
18
  "data-slot": "item-move-status"
19
- }, se = ["aria-labelledby", "aria-describedby"], ce = { class: "bg-muted/50 text-muted-foreground text-xs" }, le = {
19
+ }, ce = ["aria-labelledby", "aria-describedby"], le = { class: "bg-muted/50 text-muted-foreground text-xs" }, ue = {
20
20
  key: 0,
21
21
  class: "w-16"
22
- }, ue = { class: "px-3 py-2 text-start font-medium" }, de = { class: "px-3 py-2 text-start font-medium" }, fe = {
22
+ }, de = { class: "px-3 py-2 text-start font-medium" }, fe = { class: "px-3 py-2 text-start font-medium" }, pe = {
23
23
  key: 1,
24
24
  class: "w-10"
25
- }, pe = [
25
+ }, me = [
26
26
  "data-index",
27
27
  "draggable",
28
28
  "onDragstart",
29
29
  "onDrop"
30
- ], me = {
30
+ ], he = {
31
31
  key: 0,
32
32
  class: "p-1.5"
33
33
  }, T = { class: "flex items-center" }, E = { class: "p-1.5" }, D = { class: "p-1.5" }, O = {
@@ -39,11 +39,11 @@ var w = {
39
39
  }, A = ["colspan"], j = {
40
40
  key: 0,
41
41
  class: "border-t p-1.5"
42
- }, M = /*@__PURE__*/ _({
42
+ }, M = /*@__PURE__*/ v({
43
43
  __name: "KeyValueField",
44
44
  props: { component: {} },
45
- setup(_) {
46
- let M = _, { value: N, setValue: P, blur: F, error: I, id: L, disabled: R, readOnly: z, aria: B } = r(() => M.component), V = d(() => Array.isArray(N.value) ? N.value.map((e) => ({
45
+ setup(v) {
46
+ let M = v, { value: N, setValue: P, blur: F, error: I, id: L, disabled: R, readOnly: z, aria: B } = r(() => M.component), V = f(() => Array.isArray(N.value) ? N.value.map((e) => ({
47
47
  key: String(e.key ?? ""),
48
48
  value: e.value === null || e.value === void 0 ? "" : String(e.value)
49
49
  })) : Object.entries(N.value ?? {}).map(([e, t]) => ({
@@ -52,91 +52,91 @@ var w = {
52
52
  }))), H = (e) => P(e), U = (e, t) => H(V.value.map((n, r) => r === e ? {
53
53
  ...n,
54
54
  ...t
55
- } : n)), W = e(), G = a(() => M.component), he = c(G), K = d(() => u("add", M.component, void 0, {
55
+ } : n)), W = e(), G = a(() => M.component), ge = l(G), K = f(() => d("add", M.component, void 0, {
56
56
  label: M.component.addActionLabel,
57
57
  icon: "plus",
58
58
  variant: "ghost"
59
- })), q = d(() => u("delete", M.component, void 0, {
59
+ })), q = f(() => d("delete", M.component, void 0, {
60
60
  label: W("form.remove_row", {}, "Remove row"),
61
- icon: "trash-2"
62
- })), J = d(() => u("reorder", M.component, void 0, {
61
+ icon: u("key-value", "delete", "trash-2")
62
+ })), J = f(() => d("reorder", M.component, void 0, {
63
63
  label: W("form.reorder_item", {}, "Reorder"),
64
- icon: "grip-vertical"
65
- })), Y = d(() => M.component.deletable && !z.value && q.value !== null), X = d(() => M.component.reorderable && !z.value && !R.value && J.value !== null), Z = ae(null), Q = (e, t) => he(J.value, { items: ne(V.value.length, e, t) }, () => H(te(V.value, e, t))), $ = s(N, Q, (e) => V.value[e]?.key || null, () => V.value.length), ge = $.announcement, _e = $.container, ve = (e) => {
64
+ icon: u("key-value", "reorder", "grip-vertical")
65
+ })), Y = f(() => M.component.deletable && !z.value && q.value !== null), X = f(() => M.component.reorderable && !z.value && !R.value && J.value !== null), Z = ae(null), Q = (e, t) => ge(J.value, { items: ne(V.value.length, e, t) }, () => H(te(V.value, e, t))), $ = c(N, Q, (e) => V.value[e]?.key || null, () => V.value.length), _e = $.announcement, ve = $.container, ye = (e) => {
66
66
  Z.value !== null && Z.value !== e && Q(Z.value, e), Z.value = null;
67
67
  };
68
- return (e, r) => (v(), f(ee, {
68
+ return (e, r) => (y(), p(o, {
69
69
  field: M.component,
70
- "html-for": b(L),
71
- error: b(I)
70
+ "html-for": x(L),
71
+ error: x(I)
72
72
  }, {
73
- default: x(() => [h("div", {
73
+ default: S(() => [g("div", {
74
74
  ref_key: "moveContainer",
75
- ref: _e,
75
+ ref: ve,
76
76
  class: "overflow-hidden rounded-md border"
77
77
  }, [
78
- h("span", w, y(b(ge)), 1),
79
- h("table", {
78
+ g("span", se, b(x(_e)), 1),
79
+ g("table", {
80
80
  class: "w-full text-sm",
81
- "aria-labelledby": M.component.label ? b(l)(b(L)).label : void 0,
82
- "aria-describedby": b(B)["aria-describedby"]
83
- }, [h("thead", ce, [h("tr", null, [
84
- X.value ? (v(), m("th", le)) : p("", !0),
85
- h("th", ue, y(M.component.keyLabel), 1),
86
- h("th", de, y(M.component.valueLabel), 1),
87
- Y.value ? (v(), m("th", fe)) : p("", !0)
88
- ])]), h("tbody", null, [(v(!0), m(re, null, oe(V.value, (e, a) => (v(), m("tr", {
81
+ "aria-labelledby": M.component.label ? x(ee)(x(L)).label : void 0,
82
+ "aria-describedby": x(B)["aria-describedby"]
83
+ }, [g("thead", le, [g("tr", null, [
84
+ X.value ? (y(), h("th", ue)) : m("", !0),
85
+ g("th", de, b(M.component.keyLabel), 1),
86
+ g("th", fe, b(M.component.valueLabel), 1),
87
+ Y.value ? (y(), h("th", pe)) : m("", !0)
88
+ ])]), g("tbody", null, [(y(!0), h(re, null, oe(V.value, (e, a) => (y(), h("tr", {
89
89
  key: a,
90
90
  "data-index": a,
91
91
  draggable: X.value,
92
- class: ie(b(t)("border-t", Z.value === a && "opacity-50")),
92
+ class: ie(x(t)("border-t", Z.value === a && "opacity-50")),
93
93
  onDragstart: (e) => Z.value = a,
94
94
  onDragover: r[0] ||= (e) => X.value && e.preventDefault(),
95
- onDrop: (e) => ve(a),
95
+ onDrop: (e) => ye(a),
96
96
  onDragend: r[1] ||= (e) => Z.value = null
97
97
  }, [
98
- X.value ? (v(), m("td", me, [h("div", T, [g(n, {
98
+ X.value ? (y(), h("td", he, [g("div", T, [_(n, {
99
99
  type: "button",
100
100
  variant: "ghost",
101
101
  size: "icon-xs",
102
- "aria-label": b(W)("form.move_up", {}, "Move up"),
102
+ "aria-label": x(W)("form.move_up", {}, "Move up"),
103
103
  disabled: a === 0,
104
104
  "data-item-move": "up",
105
- onClick: (e) => b($).moveWithButton(a, a - 1)
105
+ onClick: (e) => x($).moveWithButton(a, a - 1)
106
106
  }, {
107
- default: x(() => [g(b(C))]),
107
+ default: S(() => [_(x(w))]),
108
108
  _: 1
109
109
  }, 8, [
110
110
  "aria-label",
111
111
  "disabled",
112
112
  "onClick"
113
- ]), g(n, {
113
+ ]), _(n, {
114
114
  type: "button",
115
115
  variant: "ghost",
116
116
  size: "icon-xs",
117
- "aria-label": b(W)("form.move_down", {}, "Move down"),
117
+ "aria-label": x(W)("form.move_down", {}, "Move down"),
118
118
  disabled: a === V.value.length - 1,
119
119
  "data-item-move": "down",
120
- onClick: (e) => b($).moveWithButton(a, a + 1)
120
+ onClick: (e) => x($).moveWithButton(a, a + 1)
121
121
  }, {
122
- default: x(() => [g(b(S))]),
122
+ default: S(() => [_(x(C))]),
123
123
  _: 1
124
124
  }, 8, [
125
125
  "aria-label",
126
126
  "disabled",
127
127
  "onClick"
128
- ])])])) : p("", !0),
129
- h("td", E, [g(i, {
128
+ ])])])) : m("", !0),
129
+ g("td", E, [_(i, {
130
130
  dir: "auto",
131
131
  "model-value": e.key,
132
- readonly: b(z) || !M.component.editableKeys,
133
- disabled: b(R),
132
+ readonly: x(z) || !M.component.editableKeys,
133
+ disabled: x(R),
134
134
  placeholder: M.component.keyPlaceholder,
135
135
  "aria-label": M.component.keyLabel,
136
- "aria-invalid": b(B)["aria-invalid"],
136
+ "aria-invalid": x(B)["aria-invalid"],
137
137
  class: "h-8",
138
138
  "onUpdate:modelValue": (e) => U(a, { key: e }),
139
- onBlur: b(F)
139
+ onBlur: x(F)
140
140
  }, null, 8, [
141
141
  "model-value",
142
142
  "readonly",
@@ -147,17 +147,17 @@ var w = {
147
147
  "onUpdate:modelValue",
148
148
  "onBlur"
149
149
  ])]),
150
- h("td", D, [g(i, {
150
+ g("td", D, [_(i, {
151
151
  dir: "auto",
152
152
  "model-value": e.value,
153
- readonly: b(z) || !M.component.editableValues,
154
- disabled: b(R),
153
+ readonly: x(z) || !M.component.editableValues,
154
+ disabled: x(R),
155
155
  placeholder: M.component.valuePlaceholder,
156
156
  "aria-label": M.component.valueLabel,
157
- "aria-invalid": b(B)["aria-invalid"],
157
+ "aria-invalid": x(B)["aria-invalid"],
158
158
  class: "h-8",
159
159
  "onUpdate:modelValue": (e) => U(a, { value: e }),
160
- onBlur: b(F)
160
+ onBlur: x(F)
161
161
  }, null, 8, [
162
162
  "model-value",
163
163
  "readonly",
@@ -168,12 +168,12 @@ var w = {
168
168
  "onUpdate:modelValue",
169
169
  "onBlur"
170
170
  ])]),
171
- Y.value ? (v(), m("td", O, [g(o, {
171
+ Y.value ? (y(), h("td", O, [_(s, {
172
172
  action: q.value,
173
- context: b(G),
173
+ context: x(G),
174
174
  args: { item: String(a) },
175
175
  size: "sm",
176
- disabled: b(R),
176
+ disabled: x(R),
177
177
  class: "text-muted-foreground",
178
178
  onClient: (e) => H(V.value.filter((e, t) => t !== a))
179
179
  }, null, 8, [
@@ -182,16 +182,16 @@ var w = {
182
182
  "args",
183
183
  "disabled",
184
184
  "onClient"
185
- ])])) : p("", !0)
186
- ], 42, pe))), 128)), V.value.length === 0 ? (v(), m("tr", k, [h("td", {
185
+ ])])) : m("", !0)
186
+ ], 42, me))), 128)), V.value.length === 0 ? (y(), h("tr", k, [g("td", {
187
187
  colspan: X.value ? 4 : 3,
188
188
  class: "text-muted-foreground px-3 py-4 text-center text-xs"
189
- }, " — ", 8, A)])) : p("", !0)])], 8, se),
190
- M.component.addable && !b(z) && K.value ? (v(), m("div", j, [g(o, {
189
+ }, " — ", 8, A)])) : m("", !0)])], 8, ce),
190
+ M.component.addable && !x(z) && K.value ? (y(), h("div", j, [_(s, {
191
191
  action: K.value,
192
- context: b(G),
192
+ context: x(G),
193
193
  size: "sm",
194
- disabled: b(R),
194
+ disabled: x(R),
195
195
  onClient: r[2] ||= (e) => H([...V.value, {
196
196
  key: "",
197
197
  value: ""
@@ -200,7 +200,7 @@ var w = {
200
200
  "action",
201
201
  "context",
202
202
  "disabled"
203
- ])])) : p("", !0)
203
+ ])])) : m("", !0)
204
204
  ], 512)]),
205
205
  _: 1
206
206
  }, 8, [
@@ -1 +1 @@
1
- {"version":3,"file":"KeyValueField.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createBlock","FieldWrapper","_unref","_withCtx","_createElementVNode","_toDisplayString","_createElementBlock","_createCommentVNode","_Fragment","_renderList","_normalizeClass","_createVNode","Button","Input","ItemActionButton","Button_default","Input_default","FieldWrapper_default","ItemActionButton_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_6","_hoisted_7","_hoisted_8","_hoisted_9","_hoisted_10","_hoisted_11","_hoisted_12","_hoisted_13","_hoisted_14","_hoisted_15","_hoisted_16","KeyValueField_vue_vue_type_script_setup_true_lang_default","props","__props","useField","rows","computed","value","row","key","rowValue","update","setValue","next","patch","i","index","item","change","t","useT","context","useFieldActionContext","runItemAction","useRunItemAction","addAction","resolveItemAction","deleteAction","reorderAction","deletable","readOnly","reorderable","disabled","dragIndex","ref","move","reorderedItemKeys","from","to","moveRepeaterItem","moves","useItemMoves","moveAnnouncement","moveContainer","onRowDrop","openBlock","createBlock","unref","id","error","withCtx","createElementVNode","toDisplayString","fieldIds","aria","createElementBlock","createCommentVNode","Fragment","renderList","normalizeClass","cn","_cache","$event","createVNode","ChevronUpIcon","ChevronDownIcon","blur"],"sources":["../../../src/components/fields/KeyValueField.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n fieldIds,\n moveRepeaterItem,\n reorderedItemKeys,\n resolveItemAction,\n type KeyValueSchema,\n} from '@alfakit/core'\nimport { ChevronDownIcon, ChevronUpIcon } from '@lucide/vue'\nimport { computed, ref } from 'vue'\nimport { cn } from '../../lib/utils'\nimport { useField } from '../form/form-context'\nimport { useFieldActionContext } from '../schema/field-actions'\nimport FieldWrapper from '../schema/FieldWrapper.vue'\nimport Button from '../ui/Button.vue'\nimport Input from '../ui/Input.vue'\nimport { useT } from '../../context'\nimport ItemActionButton from './ItemActionButton.vue'\nimport { useItemMoves, useRunItemAction } from './item-actions'\n\ntype Row = { key: string; value: string }\n\n/**\n * The server stores an object; while editing we keep an ordered list of rows so keys\n * can be typed freely (including temporarily duplicate or empty keys).\n */\nconst props = defineProps<{ component: KeyValueSchema }>()\nconst { value, setValue, blur, error, id, disabled, readOnly, aria } = useField<\n Record<string, unknown> | Row[] | null\n>(() => props.component)\n\nconst rows = computed<Row[]>(() => {\n if (Array.isArray(value.value)) {\n return value.value.map((row) => ({\n key: String(row.key ?? ''),\n value: row.value === null || row.value === undefined ? '' : String(row.value),\n }))\n }\n\n return Object.entries(value.value ?? {}).map(([key, rowValue]) => ({\n key,\n value: rowValue === null || rowValue === undefined ? '' : String(rowValue),\n }))\n})\n\nconst update = (next: Row[]) => setValue(next)\nconst patch = (index: number, change: Partial<Row>) =>\n update(rows.value.map((item, i) => (i === index ? { ...item, ...change } : item)))\nconst t = useT()\n\nconst context = useFieldActionContext(() => props.component)\nconst runItemAction = useRunItemAction(context)\nconst addAction = computed(() =>\n resolveItemAction('add', props.component, undefined, {\n label: props.component.addActionLabel,\n icon: 'plus',\n variant: 'ghost',\n }),\n)\nconst deleteAction = computed(() =>\n resolveItemAction('delete', props.component, undefined, {\n label: t('form.remove_row', {}, 'Remove row'),\n icon: 'trash-2',\n }),\n)\nconst reorderAction = computed(() =>\n resolveItemAction('reorder', props.component, undefined, {\n label: t('form.reorder_item', {}, 'Reorder'),\n icon: 'grip-vertical',\n }),\n)\nconst deletable = computed(\n () => props.component.deletable && !readOnly.value && deleteAction.value !== null,\n)\nconst reorderable = computed(\n () =>\n props.component.reorderable &&\n !readOnly.value &&\n !disabled.value &&\n reorderAction.value !== null,\n)\nconst dragIndex = ref<number | null>(null)\n// Moving runs the reorder action: in the browser, or on the server when customised.\nconst move = (from: number, to: number) =>\n runItemAction(\n reorderAction.value,\n { items: reorderedItemKeys(rows.value.length, from, to) },\n () => update(moveRepeaterItem(rows.value, from, to) as Row[]),\n )\n// Move buttons: announced, one at a time, focus kept on the moved row.\nconst moves = useItemMoves(\n value,\n move,\n (index) => rows.value[index]?.key || null,\n () => rows.value.length,\n)\nconst moveAnnouncement = moves.announcement\nconst moveContainer = moves.container\nconst onRowDrop = (index: number) => {\n if (dragIndex.value !== null && dragIndex.value !== index) move(dragIndex.value, index)\n dragIndex.value = null\n}\n</script>\n\n<template>\n <FieldWrapper :field=\"props.component\" :html-for=\"id\" :error=\"error\">\n <div ref=\"moveContainer\" class=\"overflow-hidden rounded-md border\">\n <span aria-live=\"polite\" aria-atomic=\"true\" class=\"sr-only\" data-slot=\"item-move-status\">{{\n moveAnnouncement\n }}</span>\n <table\n class=\"w-full text-sm\"\n :aria-labelledby=\"props.component.label ? fieldIds(id).label : undefined\"\n :aria-describedby=\"aria['aria-describedby']\"\n >\n <thead class=\"bg-muted/50 text-muted-foreground text-xs\">\n <tr>\n <th v-if=\"reorderable\" class=\"w-16\" />\n <th class=\"px-3 py-2 text-start font-medium\">{{ props.component.keyLabel }}</th>\n <th class=\"px-3 py-2 text-start font-medium\">{{ props.component.valueLabel }}</th>\n <th v-if=\"deletable\" class=\"w-10\" />\n </tr>\n </thead>\n <tbody>\n <tr\n v-for=\"(row, index) in rows\"\n :key=\"index\"\n :data-index=\"index\"\n :draggable=\"reorderable\"\n :class=\"cn('border-t', dragIndex === index && 'opacity-50')\"\n @dragstart=\"dragIndex = index\"\n @dragover=\"reorderable && $event.preventDefault()\"\n @drop=\"onRowDrop(index)\"\n @dragend=\"dragIndex = null\"\n >\n <td v-if=\"reorderable\" class=\"p-1.5\">\n <div class=\"flex items-center\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-xs\"\n :aria-label=\"t('form.move_up', {}, 'Move up')\"\n :disabled=\"index === 0\"\n data-item-move=\"up\"\n @click=\"moves.moveWithButton(index, index - 1)\"\n ><ChevronUpIcon\n /></Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-xs\"\n :aria-label=\"t('form.move_down', {}, 'Move down')\"\n :disabled=\"index === rows.length - 1\"\n data-item-move=\"down\"\n @click=\"moves.moveWithButton(index, index + 1)\"\n ><ChevronDownIcon\n /></Button>\n </div>\n </td>\n <td class=\"p-1.5\">\n <Input\n dir=\"auto\"\n :model-value=\"row.key\"\n :readonly=\"readOnly || !props.component.editableKeys\"\n :disabled=\"disabled\"\n :placeholder=\"props.component.keyPlaceholder\"\n :aria-label=\"props.component.keyLabel\"\n :aria-invalid=\"aria['aria-invalid']\"\n class=\"h-8\"\n @update:model-value=\"patch(index, { key: $event })\"\n @blur=\"blur\"\n />\n </td>\n <td class=\"p-1.5\">\n <Input\n dir=\"auto\"\n :model-value=\"row.value\"\n :readonly=\"readOnly || !props.component.editableValues\"\n :disabled=\"disabled\"\n :placeholder=\"props.component.valuePlaceholder\"\n :aria-label=\"props.component.valueLabel\"\n :aria-invalid=\"aria['aria-invalid']\"\n class=\"h-8\"\n @update:model-value=\"patch(index, { value: $event })\"\n @blur=\"blur\"\n />\n </td>\n <td v-if=\"deletable\" class=\"p-1.5\">\n <ItemActionButton\n :action=\"deleteAction\"\n :context=\"context\"\n :args=\"{ item: String(index) }\"\n size=\"sm\"\n :disabled=\"disabled\"\n class=\"text-muted-foreground\"\n @client=\"update(rows.filter((_, i) => i !== index))\"\n />\n </td>\n </tr>\n <tr v-if=\"rows.length === 0\" class=\"border-t\">\n <td\n :colspan=\"reorderable ? 4 : 3\"\n class=\"text-muted-foreground px-3 py-4 text-center text-xs\"\n >\n —\n </td>\n </tr>\n </tbody>\n </table>\n <div v-if=\"props.component.addable && !readOnly && addAction\" class=\"border-t p-1.5\">\n <ItemActionButton\n :action=\"addAction\"\n :context=\"context\"\n size=\"sm\"\n :disabled=\"disabled\"\n @client=\"update([...rows, { key: '', value: '' }])\"\n />\n </div>\n </div>\n </FieldWrapper>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"KeyValueField.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createBlock","FieldWrapper","_unref","_withCtx","_createElementVNode","_toDisplayString","_createElementBlock","_createCommentVNode","_Fragment","_renderList","_normalizeClass","_createVNode","Button","Input","ItemActionButton","Button_default","Input_default","FieldWrapper_default","ItemActionButton_default","_hoisted_1","_hoisted_2","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_6","_hoisted_7","_hoisted_8","_hoisted_9","_hoisted_10","_hoisted_11","_hoisted_12","_hoisted_13","_hoisted_14","_hoisted_15","_hoisted_16","KeyValueField_vue_vue_type_script_setup_true_lang_default","props","__props","useField","rows","computed","value","row","key","rowValue","update","setValue","next","patch","i","index","item","change","t","useT","context","useFieldActionContext","runItemAction","useRunItemAction","addAction","resolveItemAction","deleteAction","itemActionIcon","reorderAction","deletable","readOnly","reorderable","disabled","dragIndex","ref","move","reorderedItemKeys","from","to","moveRepeaterItem","moves","useItemMoves","moveAnnouncement","moveContainer","onRowDrop","openBlock","createBlock","unref","id","error","withCtx","createElementVNode","toDisplayString","fieldIds","aria","createElementBlock","createCommentVNode","Fragment","renderList","normalizeClass","cn","_cache","$event","createVNode","ChevronUpIcon","ChevronDownIcon","blur"],"sources":["../../../src/components/fields/KeyValueField.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n fieldIds,\n moveRepeaterItem,\n reorderedItemKeys,\n resolveItemAction,\n type KeyValueSchema,\n itemActionIcon,\n} from '@alfakit/core'\nimport { ChevronDownIcon, ChevronUpIcon } from '@lucide/vue'\nimport { computed, ref } from 'vue'\nimport { cn } from '../../lib/utils'\nimport { useField } from '../form/form-context'\nimport { useFieldActionContext } from '../schema/field-actions'\nimport FieldWrapper from '../schema/FieldWrapper.vue'\nimport Button from '../ui/Button.vue'\nimport Input from '../ui/Input.vue'\nimport { useT } from '../../context'\nimport ItemActionButton from './ItemActionButton.vue'\nimport { useItemMoves, useRunItemAction } from './item-actions'\n\ntype Row = { key: string; value: string }\n\n/**\n * The server stores an object; while editing we keep an ordered list of rows so keys\n * can be typed freely (including temporarily duplicate or empty keys).\n */\nconst props = defineProps<{ component: KeyValueSchema }>()\nconst { value, setValue, blur, error, id, disabled, readOnly, aria } = useField<\n Record<string, unknown> | Row[] | null\n>(() => props.component)\n\nconst rows = computed<Row[]>(() => {\n if (Array.isArray(value.value)) {\n return value.value.map((row) => ({\n key: String(row.key ?? ''),\n value: row.value === null || row.value === undefined ? '' : String(row.value),\n }))\n }\n\n return Object.entries(value.value ?? {}).map(([key, rowValue]) => ({\n key,\n value: rowValue === null || rowValue === undefined ? '' : String(rowValue),\n }))\n})\n\nconst update = (next: Row[]) => setValue(next)\nconst patch = (index: number, change: Partial<Row>) =>\n update(rows.value.map((item, i) => (i === index ? { ...item, ...change } : item)))\nconst t = useT()\n\nconst context = useFieldActionContext(() => props.component)\nconst runItemAction = useRunItemAction(context)\nconst addAction = computed(() =>\n resolveItemAction('add', props.component, undefined, {\n label: props.component.addActionLabel,\n icon: 'plus',\n variant: 'ghost',\n }),\n)\nconst deleteAction = computed(() =>\n resolveItemAction('delete', props.component, undefined, {\n label: t('form.remove_row', {}, 'Remove row'),\n icon: itemActionIcon('key-value', 'delete', 'trash-2'),\n }),\n)\nconst reorderAction = computed(() =>\n resolveItemAction('reorder', props.component, undefined, {\n label: t('form.reorder_item', {}, 'Reorder'),\n icon: itemActionIcon('key-value', 'reorder', 'grip-vertical'),\n }),\n)\nconst deletable = computed(\n () => props.component.deletable && !readOnly.value && deleteAction.value !== null,\n)\nconst reorderable = computed(\n () =>\n props.component.reorderable &&\n !readOnly.value &&\n !disabled.value &&\n reorderAction.value !== null,\n)\nconst dragIndex = ref<number | null>(null)\n// Moving runs the reorder action: in the browser, or on the server when customised.\nconst move = (from: number, to: number) =>\n runItemAction(\n reorderAction.value,\n { items: reorderedItemKeys(rows.value.length, from, to) },\n () => update(moveRepeaterItem(rows.value, from, to) as Row[]),\n )\n// Move buttons: announced, one at a time, focus kept on the moved row.\nconst moves = useItemMoves(\n value,\n move,\n (index) => rows.value[index]?.key || null,\n () => rows.value.length,\n)\nconst moveAnnouncement = moves.announcement\nconst moveContainer = moves.container\nconst onRowDrop = (index: number) => {\n if (dragIndex.value !== null && dragIndex.value !== index) move(dragIndex.value, index)\n dragIndex.value = null\n}\n</script>\n\n<template>\n <FieldWrapper :field=\"props.component\" :html-for=\"id\" :error=\"error\">\n <div ref=\"moveContainer\" class=\"overflow-hidden rounded-md border\">\n <span aria-live=\"polite\" aria-atomic=\"true\" class=\"sr-only\" data-slot=\"item-move-status\">{{\n moveAnnouncement\n }}</span>\n <table\n class=\"w-full text-sm\"\n :aria-labelledby=\"props.component.label ? fieldIds(id).label : undefined\"\n :aria-describedby=\"aria['aria-describedby']\"\n >\n <thead class=\"bg-muted/50 text-muted-foreground text-xs\">\n <tr>\n <th v-if=\"reorderable\" class=\"w-16\" />\n <th class=\"px-3 py-2 text-start font-medium\">{{ props.component.keyLabel }}</th>\n <th class=\"px-3 py-2 text-start font-medium\">{{ props.component.valueLabel }}</th>\n <th v-if=\"deletable\" class=\"w-10\" />\n </tr>\n </thead>\n <tbody>\n <tr\n v-for=\"(row, index) in rows\"\n :key=\"index\"\n :data-index=\"index\"\n :draggable=\"reorderable\"\n :class=\"cn('border-t', dragIndex === index && 'opacity-50')\"\n @dragstart=\"dragIndex = index\"\n @dragover=\"reorderable && $event.preventDefault()\"\n @drop=\"onRowDrop(index)\"\n @dragend=\"dragIndex = null\"\n >\n <td v-if=\"reorderable\" class=\"p-1.5\">\n <div class=\"flex items-center\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-xs\"\n :aria-label=\"t('form.move_up', {}, 'Move up')\"\n :disabled=\"index === 0\"\n data-item-move=\"up\"\n @click=\"moves.moveWithButton(index, index - 1)\"\n ><ChevronUpIcon\n /></Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-xs\"\n :aria-label=\"t('form.move_down', {}, 'Move down')\"\n :disabled=\"index === rows.length - 1\"\n data-item-move=\"down\"\n @click=\"moves.moveWithButton(index, index + 1)\"\n ><ChevronDownIcon\n /></Button>\n </div>\n </td>\n <td class=\"p-1.5\">\n <Input\n dir=\"auto\"\n :model-value=\"row.key\"\n :readonly=\"readOnly || !props.component.editableKeys\"\n :disabled=\"disabled\"\n :placeholder=\"props.component.keyPlaceholder\"\n :aria-label=\"props.component.keyLabel\"\n :aria-invalid=\"aria['aria-invalid']\"\n class=\"h-8\"\n @update:model-value=\"patch(index, { key: $event })\"\n @blur=\"blur\"\n />\n </td>\n <td class=\"p-1.5\">\n <Input\n dir=\"auto\"\n :model-value=\"row.value\"\n :readonly=\"readOnly || !props.component.editableValues\"\n :disabled=\"disabled\"\n :placeholder=\"props.component.valuePlaceholder\"\n :aria-label=\"props.component.valueLabel\"\n :aria-invalid=\"aria['aria-invalid']\"\n class=\"h-8\"\n @update:model-value=\"patch(index, { value: $event })\"\n @blur=\"blur\"\n />\n </td>\n <td v-if=\"deletable\" class=\"p-1.5\">\n <ItemActionButton\n :action=\"deleteAction\"\n :context=\"context\"\n :args=\"{ item: String(index) }\"\n size=\"sm\"\n :disabled=\"disabled\"\n class=\"text-muted-foreground\"\n @client=\"update(rows.filter((_, i) => i !== index))\"\n />\n </td>\n </tr>\n <tr v-if=\"rows.length === 0\" class=\"border-t\">\n <td\n :colspan=\"reorderable ? 4 : 3\"\n class=\"text-muted-foreground px-3 py-4 text-center text-xs\"\n >\n —\n </td>\n </tr>\n </tbody>\n </table>\n <div v-if=\"props.component.addable && !readOnly && addAction\" class=\"border-t p-1.5\">\n <ItemActionButton\n :action=\"addAction\"\n :context=\"context\"\n size=\"sm\"\n :disabled=\"disabled\"\n @client=\"update([...rows, { key: '', value: '' }])\"\n />\n </div>\n </div>\n </FieldWrapper>\n</template>\n"],"mappings":"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"}