@alfakit/vue 0.1.1 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/dist/AlfakitRoot.js.map +1 -1
- package/dist/AlfakitRoot.vue.d.ts.map +1 -1
- package/dist/AlfakitRoot.vue_vue_type_script_setup_true_lang.js +3 -1
- package/dist/AlfakitRoot.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/actions/ActionButton.js.map +1 -1
- package/dist/components/actions/ActionButton.vue.d.ts.map +1 -1
- package/dist/components/actions/ActionButton.vue_vue_type_script_setup_true_lang.js +160 -159
- package/dist/components/actions/ActionButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/actions/ActionGroupMenu.js.map +1 -1
- package/dist/components/actions/ActionGroupMenu.vue.d.ts.map +1 -1
- package/dist/components/actions/ActionGroupMenu.vue_vue_type_script_setup_true_lang.js +69 -65
- package/dist/components/actions/ActionGroupMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/actions/ActionModal.js.map +1 -1
- package/dist/components/actions/ActionModal.vue.d.ts.map +1 -1
- package/dist/components/actions/ActionModal.vue_vue_type_script_setup_true_lang.js +221 -219
- package/dist/components/actions/ActionModal.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/ai/AiCopilot.js.map +1 -1
- package/dist/components/ai/AiCopilot.vue.d.ts +2 -0
- package/dist/components/ai/AiCopilot.vue.d.ts.map +1 -1
- package/dist/components/ai/AiCopilot.vue_vue_type_script_setup_true_lang.js +7 -2
- package/dist/components/ai/AiCopilot.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/cms/CmsPage.vue_vue_type_script_setup_true_lang.js +19 -19
- package/dist/components/cms/CmsPage.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/cms/LivePreview.js.map +1 -1
- package/dist/components/cms/LivePreview.vue.d.ts.map +1 -1
- package/dist/components/cms/LivePreview.vue_vue_type_script_setup_true_lang.js +83 -83
- package/dist/components/cms/LivePreview.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/fields/BuilderField.js.map +1 -1
- package/dist/components/fields/BuilderField.vue.d.ts.map +1 -1
- package/dist/components/fields/BuilderField.vue_vue_type_script_setup_true_lang.js +162 -157
- package/dist/components/fields/BuilderField.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/fields/ColorPickerField.js.map +1 -1
- package/dist/components/fields/ColorPickerField.vue.d.ts.map +1 -1
- package/dist/components/fields/ColorPickerField.vue_vue_type_script_setup_true_lang.js +1 -0
- package/dist/components/fields/ColorPickerField.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/fields/ComboboxSelect.js.map +1 -1
- package/dist/components/fields/ComboboxSelect.vue.d.ts.map +1 -1
- package/dist/components/fields/ComboboxSelect.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/fields/ComboboxSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/fields/FileUploadField.js.map +1 -1
- package/dist/components/fields/FileUploadField.vue.d.ts.map +1 -1
- package/dist/components/fields/FileUploadField.vue_vue_type_script_setup_true_lang.js +183 -183
- package/dist/components/fields/FileUploadField.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/fields/ImageEditorDialog.js.map +1 -1
- package/dist/components/fields/ImageEditorDialog.vue.d.ts.map +1 -1
- package/dist/components/fields/ImageEditorDialog.vue_vue_type_script_setup_true_lang.js +46 -46
- package/dist/components/fields/ImageEditorDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/fields/KeyValueField.js.map +1 -1
- package/dist/components/fields/KeyValueField.vue.d.ts.map +1 -1
- package/dist/components/fields/KeyValueField.vue_vue_type_script_setup_true_lang.js +66 -66
- package/dist/components/fields/KeyValueField.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/fields/ModalTablePicker.js.map +1 -1
- package/dist/components/fields/ModalTablePicker.vue.d.ts.map +1 -1
- package/dist/components/fields/ModalTablePicker.vue_vue_type_script_setup_true_lang.js +113 -113
- package/dist/components/fields/ModalTablePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/fields/OneTimeCodeInputField.js.map +1 -1
- package/dist/components/fields/OneTimeCodeInputField.vue_vue_type_script_setup_true_lang.js +1 -2
- package/dist/components/fields/OneTimeCodeInputField.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/fields/RepeaterField.js.map +1 -1
- package/dist/components/fields/RepeaterField.vue.d.ts.map +1 -1
- package/dist/components/fields/RepeaterField.vue_vue_type_script_setup_true_lang.js +12 -12
- package/dist/components/fields/RepeaterField.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/fields/RichEditorInput.js.map +1 -1
- package/dist/components/fields/RichEditorInput.vue.d.ts.map +1 -1
- package/dist/components/fields/RichEditorInput.vue_vue_type_script_setup_true_lang.js +166 -165
- package/dist/components/fields/RichEditorInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/fields/SelectField.js.map +1 -1
- package/dist/components/fields/SelectField.vue.d.ts.map +1 -1
- package/dist/components/fields/SelectField.vue_vue_type_script_setup_true_lang.js +2 -2
- package/dist/components/fields/SelectField.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/fields/SliderField.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/fields/TableColumnHeaders.js.map +1 -1
- package/dist/components/fields/TableColumnHeaders.vue.d.ts.map +1 -1
- package/dist/components/fields/TableColumnHeaders.vue_vue_type_script_setup_true_lang.js +6 -3
- package/dist/components/fields/TableColumnHeaders.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/fields/item-actions.d.ts +2 -2
- package/dist/components/fields/item-actions.d.ts.map +1 -1
- package/dist/components/fields/item-actions.js +31 -31
- package/dist/components/fields/item-actions.js.map +1 -1
- package/dist/components/file-manager/FileManagerView.js.map +1 -1
- package/dist/components/file-manager/FileManagerView.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/file-manager/FileManagerView.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/form/FormBlock.js.map +1 -1
- package/dist/components/form/FormBlock.vue.d.ts.map +1 -1
- package/dist/components/form/FormBlock.vue_vue_type_script_setup_true_lang.js +81 -77
- package/dist/components/form/FormBlock.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/form/form-context.js +25 -25
- package/dist/components/form/form-context.js.map +1 -1
- package/dist/components/kanban/KanbanBoard.js.map +1 -1
- package/dist/components/kanban/KanbanBoard.vue.d.ts.map +1 -1
- package/dist/components/kanban/KanbanBoard.vue_vue_type_script_setup_true_lang.js +5 -2
- package/dist/components/kanban/KanbanBoard.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/kanban/KanbanColumnHeader.js.map +1 -1
- package/dist/components/kanban/KanbanColumnHeader.vue.d.ts.map +1 -1
- package/dist/components/kanban/KanbanColumnHeader.vue_vue_type_script_setup_true_lang.js +64 -64
- package/dist/components/kanban/KanbanColumnHeader.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/layout/FusedGroupComponent.js.map +1 -1
- package/dist/components/layout/FusedGroupComponent.vue.d.ts.map +1 -1
- package/dist/components/layout/FusedGroupComponent.vue_vue_type_script_setup_true_lang.js +1 -0
- package/dist/components/layout/FusedGroupComponent.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/layout/SectionComponent.js.map +1 -1
- package/dist/components/layout/SectionComponent.vue.d.ts.map +1 -1
- package/dist/components/layout/SectionComponent.vue_vue_type_script_setup_true_lang.js +23 -23
- package/dist/components/layout/SectionComponent.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/layout/TabsComponent.js.map +1 -1
- package/dist/components/layout/TabsComponent.vue.d.ts.map +1 -1
- package/dist/components/layout/TabsComponent.vue_vue_type_script_setup_true_lang.js +76 -55
- package/dist/components/layout/TabsComponent.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/notifications/NotificationsMenu.js.map +1 -1
- package/dist/components/notifications/NotificationsMenu.vue.d.ts.map +1 -1
- package/dist/components/notifications/NotificationsMenu.vue_vue_type_script_setup_true_lang.js +44 -42
- package/dist/components/notifications/NotificationsMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/panel/DebugPanel.vue_vue_type_script_setup_true_lang.js +8 -8
- package/dist/components/panel/DebugPanel.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/panel/GlobalSearch.js.map +1 -1
- package/dist/components/panel/GlobalSearch.vue.d.ts.map +1 -1
- package/dist/components/panel/GlobalSearch.vue_vue_type_script_setup_true_lang.js +1 -0
- package/dist/components/panel/GlobalSearch.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/panel/GlobalSearchPalette.js.map +1 -1
- package/dist/components/panel/GlobalSearchPalette.vue.d.ts.map +1 -1
- package/dist/components/panel/GlobalSearchPalette.vue_vue_type_script_setup_true_lang.js +102 -96
- package/dist/components/panel/GlobalSearchPalette.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/panel/NavGroup.vue_vue_type_script_setup_true_lang.js +10 -10
- package/dist/components/panel/NavGroup.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/panel/NavGroupFlyout.vue_vue_type_script_setup_true_lang.js +9 -9
- package/dist/components/panel/NavGroupFlyout.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/panel/NavItem.vue_vue_type_script_setup_true_lang.js +16 -16
- package/dist/components/panel/NavItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/panel/NavSubItem.vue_vue_type_script_setup_true_lang.js +10 -10
- package/dist/components/panel/NavSubItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/panel/ShortcutKeys.js.map +1 -1
- package/dist/components/panel/ShortcutKeys.vue.d.ts.map +1 -1
- package/dist/components/panel/ShortcutKeys.vue_vue_type_script_setup_true_lang.js +4 -1
- package/dist/components/panel/ShortcutKeys.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/panel/TenantMenu.js.map +1 -1
- package/dist/components/panel/TenantMenu.vue_vue_type_script_setup_true_lang.js +37 -37
- package/dist/components/panel/TenantMenu.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/panel/Topbar.vue_vue_type_script_setup_true_lang.js +11 -11
- package/dist/components/panel/Topbar.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/realtime/use-live-updates.d.ts.map +1 -1
- package/dist/components/realtime/use-live-updates.js +24 -23
- package/dist/components/realtime/use-live-updates.js.map +1 -1
- package/dist/components/table/BooleanCell.vue_vue_type_script_setup_true_lang.js +2 -1
- package/dist/components/table/BooleanCell.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/table/ColumnHeader.js.map +1 -1
- package/dist/components/table/ColumnHeader.vue.d.ts.map +1 -1
- package/dist/components/table/ColumnHeader.vue_vue_type_script_setup_true_lang.js +55 -49
- package/dist/components/table/ColumnHeader.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/table/ColumnManager.js.map +1 -1
- package/dist/components/table/ColumnManager.vue.d.ts.map +1 -1
- package/dist/components/table/ColumnManager.vue_vue_type_script_setup_true_lang.js +5 -4
- package/dist/components/table/ColumnManager.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/table/ContentLayoutSort.js.map +1 -1
- package/dist/components/table/ContentLayoutSort.vue.d.ts.map +1 -1
- package/dist/components/table/ContentLayoutSort.vue_vue_type_script_setup_true_lang.js +5 -5
- package/dist/components/table/ContentLayoutSort.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/table/GroupHeaderRow.js.map +1 -1
- package/dist/components/table/GroupHeaderRow.vue.d.ts.map +1 -1
- package/dist/components/table/GroupHeaderRow.vue_vue_type_script_setup_true_lang.js +55 -34
- package/dist/components/table/GroupHeaderRow.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/table/SelectCell.js.map +1 -1
- package/dist/components/table/SelectCell.vue.d.ts.map +1 -1
- package/dist/components/table/SelectCell.vue_vue_type_script_setup_true_lang.js +26 -20
- package/dist/components/table/SelectCell.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/table/SelectComboboxCell.vue_vue_type_script_setup_true_lang.js +2 -1
- package/dist/components/table/SelectComboboxCell.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/table/TableCellContent.js.map +1 -1
- package/dist/components/table/TableCellContent.vue.d.ts.map +1 -1
- package/dist/components/table/TableCellContent.vue_vue_type_script_setup_true_lang.js +4 -3
- package/dist/components/table/TableCellContent.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/table/TablePagination.js.map +1 -1
- package/dist/components/table/TablePagination.vue.d.ts.map +1 -1
- package/dist/components/table/TablePagination.vue_vue_type_script_setup_true_lang.js +87 -87
- package/dist/components/table/TablePagination.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/table/TextInputCell.js.map +1 -1
- package/dist/components/table/TextInputCell.vue.d.ts.map +1 -1
- package/dist/components/table/TextInputCell.vue_vue_type_script_setup_true_lang.js +40 -34
- package/dist/components/table/TextInputCell.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/table/cell-update.d.ts +6 -0
- package/dist/components/table/cell-update.d.ts.map +1 -1
- package/dist/components/table/cell-update.js.map +1 -1
- package/dist/components/translation-manager/TranslationManagerView.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/components/translation-manager/TranslationManagerView.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/ui/CommandAutoHighlight.js +7 -0
- package/dist/components/ui/CommandAutoHighlight.js.map +1 -0
- package/dist/components/ui/CommandAutoHighlight.vue.d.ts +21 -0
- package/dist/components/ui/CommandAutoHighlight.vue.d.ts.map +1 -0
- package/dist/components/ui/CommandAutoHighlight.vue_vue_type_script_setup_true_lang.js +18 -0
- package/dist/components/ui/CommandAutoHighlight.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/components/ui/DialogContent.js.map +1 -1
- package/dist/components/ui/DialogContent.vue.d.ts.map +1 -1
- package/dist/components/ui/DialogContent.vue_vue_type_script_setup_true_lang.js +13 -12
- package/dist/components/ui/DialogContent.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/ui/PopoverContent.js.map +1 -1
- package/dist/components/ui/PopoverContent.vue.d.ts.map +1 -1
- package/dist/components/ui/PopoverContent.vue_vue_type_script_setup_true_lang.js +9 -8
- package/dist/components/ui/PopoverContent.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/ui/SheetContent.js.map +1 -1
- package/dist/components/ui/SheetContent.vue.d.ts.map +1 -1
- package/dist/components/ui/SheetContent.vue_vue_type_script_setup_true_lang.js +13 -12
- package/dist/components/ui/SheetContent.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components/ui/TooltipContent.js.map +1 -1
- package/dist/components/ui/TooltipContent.vue.d.ts.map +1 -1
- package/dist/components/ui/TooltipContent.vue_vue_type_script_setup_true_lang.js +9 -8
- package/dist/components/ui/TooltipContent.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/components.css +347 -0
- package/dist/context.d.ts +7 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +29 -26
- package/dist/context.js.map +1 -1
- package/dist/create-alfakit.d.ts.map +1 -1
- package/dist/create-alfakit.js +33 -31
- package/dist/create-alfakit.js.map +1 -1
- package/dist/eject-manifest.json +11 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +219 -217
- package/dist/layouts/AppLayout.vue_vue_type_script_setup_true_lang.js +8 -8
- package/dist/layouts/AppLayout.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/layouts/AuthLayout.vue_vue_type_script_setup_true_lang.js +9 -9
- package/dist/layouts/FullscreenLayout.vue_vue_type_script_setup_true_lang.js +8 -8
- package/dist/layouts/FullscreenLayout.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/layouts/TopNavLayout.vue_vue_type_script_setup_true_lang.js +15 -15
- package/dist/layouts/TopNavLayout.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/layouts/lazy-layouts.d.ts +10 -0
- package/dist/layouts/lazy-layouts.d.ts.map +1 -0
- package/dist/layouts/lazy-layouts.js +8 -0
- package/dist/layouts/lazy-layouts.js.map +1 -0
- package/dist/layouts/panel-layouts.d.ts +8 -0
- package/dist/layouts/panel-layouts.d.ts.map +1 -0
- package/dist/layouts/panel-layouts.js +15 -0
- package/dist/layouts/panel-layouts.js.map +1 -0
- package/dist/lib/lazy.d.ts.map +1 -1
- package/dist/lib/lazy.js +2 -2
- package/dist/lib/lazy.js.map +1 -1
- package/dist/pages/PageShell.js.map +1 -1
- package/dist/pages/PageShell.vue.d.ts.map +1 -1
- package/dist/pages/PageShell.vue_vue_type_script_setup_true_lang.js +39 -42
- package/dist/pages/PageShell.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/standalone/AlfakitComponent.js.map +1 -1
- package/dist/standalone/AlfakitComponent.vue.d.ts.map +1 -1
- package/dist/standalone/AlfakitComponent.vue_vue_type_script_setup_true_lang.js +56 -52
- package/dist/standalone/AlfakitComponent.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/standalone/AlfakitToaster.js.map +1 -1
- package/dist/standalone/AlfakitToaster.vue.d.ts.map +1 -1
- package/dist/standalone/AlfakitToaster.vue_vue_type_script_setup_true_lang.js +23 -15
- package/dist/standalone/AlfakitToaster.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/standalone.css +54 -0
- package/dist/starter-kit/AlfakitStarterKitRoot.js.map +1 -1
- package/dist/starter-kit/AlfakitStarterKitRoot.vue.d.ts +2 -2
- package/dist/starter-kit/AlfakitStarterKitRoot.vue.d.ts.map +1 -1
- package/dist/starter-kit/AlfakitStarterKitRoot.vue_vue_type_script_setup_true_lang.js +17 -12
- package/dist/starter-kit/AlfakitStarterKitRoot.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/starter-kit/dashboard-widgets.d.ts +54 -0
- package/dist/starter-kit/dashboard-widgets.d.ts.map +1 -0
- package/dist/starter-kit/dashboard-widgets.js +54 -0
- package/dist/starter-kit/dashboard-widgets.js.map +1 -0
- package/dist/starter-kit/index.d.ts +2 -1
- package/dist/starter-kit/index.d.ts.map +1 -1
- package/dist/starter-kit/index.js +5 -4
- package/dist/starter-kit/runtime.d.ts +6 -0
- package/dist/starter-kit/runtime.d.ts.map +1 -1
- package/dist/starter-kit/runtime.js +19 -15
- package/dist/starter-kit/runtime.js.map +1 -1
- package/dist/starter-kit/starter-kit.d.ts.map +1 -1
- package/dist/starter-kit/starter-kit.js +8 -8
- package/dist/starter-kit/starter-kit.js.map +1 -1
- package/dist/starter-kit/widgets/CopilotTrigger.js +7 -0
- package/dist/starter-kit/widgets/CopilotTrigger.js.map +1 -0
- package/dist/starter-kit/widgets/CopilotTrigger.vue.d.ts +12 -0
- package/dist/starter-kit/widgets/CopilotTrigger.vue.d.ts.map +1 -0
- package/dist/starter-kit/widgets/CopilotTrigger.vue_vue_type_script_setup_true_lang.js +23 -0
- package/dist/starter-kit/widgets/CopilotTrigger.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/starter-kit/widgets/LoadedCopilot.js +7 -0
- package/dist/starter-kit/widgets/LoadedCopilot.js.map +1 -0
- package/dist/starter-kit/widgets/LoadedCopilot.vue.d.ts +8 -0
- package/dist/starter-kit/widgets/LoadedCopilot.vue.d.ts.map +1 -0
- package/dist/starter-kit/widgets/LoadedCopilot.vue_vue_type_script_setup_true_lang.js +31 -0
- package/dist/starter-kit/widgets/LoadedCopilot.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/starter-kit/widgets/SearchTrigger.js.map +1 -1
- package/dist/starter-kit/widgets/SearchTrigger.vue.d.ts.map +1 -1
- package/dist/starter-kit/widgets/SearchTrigger.vue_vue_type_script_setup_true_lang.js +1 -0
- package/dist/starter-kit/widgets/SearchTrigger.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/starter-kit/widgets/StarterKitImpersonationBanner.js +7 -0
- package/dist/starter-kit/widgets/StarterKitImpersonationBanner.js.map +1 -0
- package/dist/starter-kit/widgets/StarterKitImpersonationBanner.vue.d.ts +8 -0
- package/dist/starter-kit/widgets/StarterKitImpersonationBanner.vue.d.ts.map +1 -0
- package/dist/starter-kit/widgets/StarterKitImpersonationBanner.vue_vue_type_script_setup_true_lang.js +34 -0
- package/dist/starter-kit/widgets/StarterKitImpersonationBanner.vue_vue_type_script_setup_true_lang.js.map +1 -0
- package/dist/starter-kit/widgets/TenantChooser.js.map +1 -1
- package/dist/starter-kit/widgets/TenantChooser.vue_vue_type_script_setup_true_lang.js +1 -1
- package/dist/starter-kit/widgets/TenantChooser.vue_vue_type_script_setup_true_lang.js.map +1 -1
- package/dist/starter-kit/widgets/index.d.ts +40 -9
- package/dist/starter-kit/widgets/index.d.ts.map +1 -1
- package/dist/starter-kit/widgets/index.js +21 -18
- package/dist/starter-kit/widgets/index.js.map +1 -1
- package/dist/starter-kit/widgets/loaded.d.ts +10 -0
- package/dist/starter-kit/widgets/loaded.d.ts.map +1 -0
- package/dist/starter-kit/widgets/loaded.js +5 -0
- package/dist/styles.css +9 -2
- package/dist/themes.css +8 -335
- package/package.json +3 -3
- package/src/AlfakitRoot.vue +9 -1
- package/src/components/actions/ActionButton.vue +14 -6
- package/src/components/actions/ActionGroupMenu.vue +13 -1
- package/src/components/actions/ActionModal.vue +12 -1
- package/src/components/ai/AiCopilot.vue +7 -1
- package/src/components/cms/LivePreview.vue +8 -2
- package/src/components/fields/BuilderField.vue +15 -2
- package/src/components/fields/ColorPickerField.vue +1 -0
- package/src/components/fields/ComboboxSelect.vue +1 -1
- package/src/components/fields/FileUploadField.vue +14 -11
- package/src/components/fields/ImageEditorDialog.vue +7 -3
- package/src/components/fields/KeyValueField.vue +3 -2
- package/src/components/fields/ModalTablePicker.vue +7 -2
- package/src/components/fields/OneTimeCodeInputField.vue +1 -1
- package/src/components/fields/RepeaterField.vue +2 -3
- package/src/components/fields/RichEditorInput.vue +3 -0
- package/src/components/fields/SelectField.vue +4 -2
- package/src/components/fields/TableColumnHeaders.vue +6 -1
- package/src/components/fields/item-actions.ts +31 -10
- package/src/components/file-manager/FileManagerView.vue +1 -1
- package/src/components/form/FormBlock.vue +26 -1
- package/src/components/form/form-context.ts +3 -3
- package/src/components/kanban/KanbanBoard.vue +15 -3
- package/src/components/kanban/KanbanColumnHeader.vue +6 -4
- package/src/components/layout/FusedGroupComponent.vue +1 -0
- package/src/components/layout/SectionComponent.vue +10 -4
- package/src/components/layout/TabsComponent.vue +61 -5
- package/src/components/notifications/NotificationsMenu.vue +11 -0
- package/src/components/panel/GlobalSearch.vue +1 -0
- package/src/components/panel/GlobalSearchPalette.vue +2 -0
- package/src/components/panel/ShortcutKeys.vue +1 -0
- package/src/components/panel/TenantMenu.vue +2 -2
- package/src/components/realtime/use-live-updates.ts +3 -1
- package/src/components/table/ColumnHeader.vue +23 -12
- package/src/components/table/ColumnManager.vue +12 -8
- package/src/components/table/ContentLayoutSort.vue +7 -1
- package/src/components/table/GroupHeaderRow.vue +27 -0
- package/src/components/table/SelectCell.vue +5 -2
- package/src/components/table/TableCellContent.vue +4 -2
- package/src/components/table/TablePagination.vue +12 -7
- package/src/components/table/TextInputCell.vue +11 -5
- package/src/components/table/cell-update.ts +6 -0
- package/src/components/ui/CommandAutoHighlight.vue +27 -0
- package/src/components/ui/DialogContent.vue +5 -1
- package/src/components/ui/PopoverContent.vue +5 -1
- package/src/components/ui/SheetContent.vue +5 -1
- package/src/components/ui/TooltipContent.vue +5 -1
- package/src/context.ts +10 -0
- package/src/create-alfakit.ts +5 -0
- package/src/index.ts +2 -0
- package/src/layouts/lazy-layouts.ts +14 -0
- package/src/layouts/panel-layouts.ts +17 -0
- package/src/lib/lazy.ts +11 -1
- package/src/pages/PageShell.vue +5 -6
- package/src/standalone/AlfakitComponent.vue +17 -6
- package/src/standalone/AlfakitToaster.vue +12 -2
- package/src/starter-kit/AlfakitStarterKitRoot.vue +12 -3
- package/src/starter-kit/dashboard-widgets.ts +93 -0
- package/src/starter-kit/index.ts +7 -1
- package/src/starter-kit/runtime.ts +17 -1
- package/src/starter-kit/starter-kit.ts +2 -1
- package/src/starter-kit/widgets/CopilotTrigger.vue +58 -0
- package/src/starter-kit/widgets/LoadedCopilot.vue +29 -0
- package/src/starter-kit/widgets/SearchTrigger.vue +1 -0
- package/src/starter-kit/widgets/StarterKitImpersonationBanner.vue +57 -0
- package/src/starter-kit/widgets/TenantChooser.vue +1 -1
- package/src/starter-kit/widgets/index.ts +56 -11
- package/src/starter-kit/widgets/loaded.ts +9 -0
- package/src/styles.css +9 -2
|
@@ -1,102 +1,106 @@
|
|
|
1
|
-
import { useActionRunner as e, useAlfakitProps as t, usePageSchema as
|
|
2
|
-
import { useStore as
|
|
3
|
-
import
|
|
4
|
-
import { provideForm as
|
|
5
|
-
import
|
|
6
|
-
import { showToast as
|
|
7
|
-
import { FormStore as
|
|
8
|
-
import { router as
|
|
9
|
-
import { computed as
|
|
1
|
+
import { useActionRunner as e, useAlfakitProps as t, usePageSchema as ee, usePanel as n, useT as r } from "../../context.js";
|
|
2
|
+
import { useStore as i } from "../../composables/use-store.js";
|
|
3
|
+
import te from "../actions/ActionList.js";
|
|
4
|
+
import { provideForm as ne } from "./form-context.js";
|
|
5
|
+
import re from "../schema/SchemaRenderer.js";
|
|
6
|
+
import { showToast as ie } from "../notifications/flash-toasts.js";
|
|
7
|
+
import { FormStore as ae, applyFormRefresh as oe, formActionsVisible as a, formIdentity as o, formRefreshFor as s, isImplicitSubmit as c, isLeavingVisit as l, pageFlash as u, pageFormName as d, registerConflictForm as f, registerFormSubmitter as p, registerPageForm as m, resolvePartialProps as h, shouldResyncForm as se, wizardProgressStore as g } from "@alfakit/core";
|
|
8
|
+
import { router as _ } from "@inertiajs/vue3";
|
|
9
|
+
import { computed as v, createCommentVNode as ce, createElementBlock as y, createElementVNode as le, createVNode as b, defineComponent as x, onBeforeUnmount as S, onMounted as C, onScopeDispose as ue, openBlock as w, unref as T, watch as E, withModifiers as D } from "vue";
|
|
10
10
|
//#region src/components/form/FormBlock.vue?vue&type=script&setup=true&lang.ts
|
|
11
|
-
var
|
|
11
|
+
var O = ["disabled"], k = {
|
|
12
12
|
key: 0,
|
|
13
13
|
"data-slot": "form-actions",
|
|
14
14
|
class: "border-t pt-6"
|
|
15
|
-
},
|
|
15
|
+
}, A = /*@__PURE__*/ x({
|
|
16
16
|
__name: "FormBlock",
|
|
17
17
|
props: { block: {} },
|
|
18
|
-
setup(
|
|
19
|
-
let
|
|
20
|
-
token:
|
|
21
|
-
component:
|
|
22
|
-
refreshUrl:
|
|
23
|
-
optionsUrl:
|
|
24
|
-
validateUrl:
|
|
25
|
-
onNotifications: (e) => e.forEach((e) =>
|
|
18
|
+
setup(x) {
|
|
19
|
+
let A = x, j = n(), M = ee(), N = t(), P = e(), F = r(), I = v(() => M.value?.token ?? ""), L = new ae(A.block, {
|
|
20
|
+
token: I.value,
|
|
21
|
+
component: A.block.component,
|
|
22
|
+
refreshUrl: j.value.endpoints.schemaRefresh,
|
|
23
|
+
optionsUrl: j.value.endpoints.schemaOptions,
|
|
24
|
+
validateUrl: j.value.endpoints.schemaValidate,
|
|
25
|
+
onNotifications: (e) => e.forEach((e) => ie(e)),
|
|
26
26
|
onRefreshed: () => {
|
|
27
|
-
|
|
27
|
+
A.block.liveFilters && _.reload({ only: h(["page"]) });
|
|
28
28
|
}
|
|
29
29
|
});
|
|
30
|
-
|
|
31
|
-
let
|
|
32
|
-
|
|
33
|
-
let e =
|
|
34
|
-
e && (
|
|
30
|
+
ne(L);
|
|
31
|
+
let R;
|
|
32
|
+
C(() => {
|
|
33
|
+
let e = d(A.block.component);
|
|
34
|
+
e && (R = m(e, L));
|
|
35
35
|
});
|
|
36
|
-
let
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}),
|
|
40
|
-
let
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}),
|
|
44
|
-
|
|
45
|
-
}),
|
|
46
|
-
let
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}),
|
|
50
|
-
let
|
|
51
|
-
token:
|
|
36
|
+
let z;
|
|
37
|
+
C(() => {
|
|
38
|
+
A.block.component === "form" && (z = f(L));
|
|
39
|
+
}), S(() => z?.());
|
|
40
|
+
let B;
|
|
41
|
+
C(() => {
|
|
42
|
+
B = p(A.block.component, (e, t) => Z(e, t));
|
|
43
|
+
}), S(() => {
|
|
44
|
+
R?.(), B?.();
|
|
45
|
+
}), E(() => o(M.value, A.block), () => L.fill(A.block)), E(I, (e) => L.setToken(e));
|
|
46
|
+
let V = null, H = !1, U = !1, W = null;
|
|
47
|
+
E(() => A.block, (e) => {
|
|
48
|
+
H && (H = !1, L.fill(e)), U && (U = !1, L.isDirty || L.fill(e));
|
|
49
|
+
}), E(() => N.value.errors, (e) => L.setErrors(e ?? {}), { immediate: !0 });
|
|
50
|
+
let G = i(L.store), K = v(() => ({
|
|
51
|
+
token: I.value,
|
|
52
52
|
component: "page"
|
|
53
|
-
})),
|
|
53
|
+
})), q = !1, J = v(() => A.block.actions.map((e) => ({
|
|
54
54
|
...e,
|
|
55
55
|
hasModal: !1
|
|
56
|
-
}))),
|
|
57
|
-
if (e.url && !e.hasAction) return
|
|
58
|
-
|
|
59
|
-
},
|
|
56
|
+
}))), Y = v(() => J.value[0]), de = i(g(L)), X = v(() => a(A.block, de.value)), Z = async (e, t) => {
|
|
57
|
+
if (e.url && !e.hasAction) return P.trigger(e, t);
|
|
58
|
+
q = !0, V = A.block, L.setProcessing(!0), L.whenSettled(() => P.execute(e, t, L.state.values));
|
|
59
|
+
}, Q = null, fe = _.on("start", (e) => {
|
|
60
60
|
let t = e.detail.visit;
|
|
61
|
-
|
|
62
|
-
}),
|
|
63
|
-
let t =
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
61
|
+
q && !Q && t.method !== "get" && (Q = t.id), t.method !== "get" && (W = A.block);
|
|
62
|
+
}), pe = _.on("success", (e) => {
|
|
63
|
+
let t = Q;
|
|
64
|
+
if (!t && se(u(e.detail.page), L)) {
|
|
65
|
+
A.block === W ? U = !0 : L.fill(A.block);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
t && (e.detail.visitId ?? t) === t && u(e.detail.page).alfakitAction?.status !== "halted" && (A.block === V ? H = !0 : L.fill(A.block));
|
|
69
|
+
}), me = _.on("success", (e) => {
|
|
70
|
+
let t = s(u(e.detail.page), A.block.component);
|
|
71
|
+
t && oe(L, t);
|
|
72
|
+
}), he = _.on("finish", (e) => {
|
|
73
|
+
Q && e.detail.visit.id !== Q || (L.setProcessing(!1), q = !1, Q = null);
|
|
74
|
+
}), ge = _.on("before", (e) => {
|
|
75
|
+
j.value.unsavedChangesAlerts && L.isDirty && !q && l(e.detail.visit) && !window.confirm(F("unsaved_changes", {}, "You have unsaved changes. Leave anyway?")) && e.preventDefault();
|
|
72
76
|
});
|
|
73
|
-
|
|
74
|
-
|
|
77
|
+
ue(() => {
|
|
78
|
+
fe(), pe(), me(), he(), ge(), L.destroy();
|
|
75
79
|
});
|
|
76
|
-
let
|
|
77
|
-
|
|
78
|
-
},
|
|
79
|
-
|
|
80
|
+
let $ = () => {
|
|
81
|
+
Y.value && X.value && Z(Y.value, K.value);
|
|
82
|
+
}, _e = (e) => {
|
|
83
|
+
Y.value && X.value && c(e, e.currentTarget) && (e.preventDefault(), Z(Y.value, K.value));
|
|
80
84
|
};
|
|
81
|
-
return (e, t) => (
|
|
85
|
+
return (e, t) => (w(), y("form", {
|
|
82
86
|
"data-slot": "form-block",
|
|
83
87
|
class: "flex flex-col gap-6",
|
|
84
|
-
onSubmit:
|
|
85
|
-
onKeydown:
|
|
86
|
-
}, [
|
|
87
|
-
disabled:
|
|
88
|
+
onSubmit: D($, ["prevent"]),
|
|
89
|
+
onKeydown: _e
|
|
90
|
+
}, [le("fieldset", {
|
|
91
|
+
disabled: T(G).processing || A.block.operation === "view",
|
|
88
92
|
class: "contents"
|
|
89
|
-
}, [
|
|
90
|
-
components:
|
|
91
|
-
columns:
|
|
92
|
-
}, null, 8, ["components", "columns"])], 8,
|
|
93
|
-
actions:
|
|
94
|
-
context:
|
|
95
|
-
"on-trigger":
|
|
96
|
-
}, null, 8, ["actions", "context"])])) :
|
|
93
|
+
}, [b(re, {
|
|
94
|
+
components: T(G).components,
|
|
95
|
+
columns: T(G).columns
|
|
96
|
+
}, null, 8, ["components", "columns"])], 8, O), J.value.length > 0 && X.value ? (w(), y("div", k, [b(te, {
|
|
97
|
+
actions: J.value,
|
|
98
|
+
context: K.value,
|
|
99
|
+
"on-trigger": Z
|
|
100
|
+
}, null, 8, ["actions", "context"])])) : ce("", !0)], 32));
|
|
97
101
|
}
|
|
98
102
|
});
|
|
99
103
|
//#endregion
|
|
100
|
-
export {
|
|
104
|
+
export { A as default };
|
|
101
105
|
|
|
102
106
|
//# sourceMappingURL=FormBlock.vue_vue_type_script_setup_true_lang.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormBlock.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_withModifiers","_createElementVNode","_unref","_createVNode","SchemaRenderer","ActionList","_createCommentVNode","ActionList_default","SchemaRenderer_default","_hoisted_1","_hoisted_2","FormBlock_vue_vue_type_script_setup_true_lang_default","props","__props","panel","usePanel","page","usePageSchema","pageProps","useAlfakitProps","runner","useActionRunner","t","useT","token","computed","store","FormStore","notifications","showToast","n","router","resolvePartialProps","unregisterPageForm","name","pageFormName","registerPageForm","unregisterConflictForm","onMounted","registerConflictForm","onBeforeUnmount","unregisterSubmitter","registerFormSubmitter","trigger","action","ctx","watch","formIdentity","value","submittedBlock","refillPending","block","errors","state","useStore","context","submitting","actions","primary","progress","wizardProgressStore","showActions","formActionsVisible","submitVisit","offStart","visit","event","offSuccess","id","pageFlash","offRefresh","refresh","formRefreshFor","applyFormRefresh","offFinish","offBefore","isLeavingVisit","onSubmit","onKeydown","isImplicitSubmit","openBlock","createElementBlock","withModifiers","createElementVNode","unref","createVNode","createCommentVNode"],"sources":["../../../src/components/form/FormBlock.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ActionContext, ActionSchema, FormBlock as FormBlockSchema } from '@alfakit/core'\nimport {\n FormStore,\n applyFormRefresh,\n formActionsVisible,\n formIdentity,\n formRefreshFor,\n isImplicitSubmit,\n isLeavingVisit,\n pageFlash,\n pageFormName,\n registerConflictForm,\n registerFormSubmitter,\n registerPageForm,\n resolvePartialProps,\n wizardProgressStore,\n} from '@alfakit/core'\nimport { router } from '@inertiajs/vue3'\nimport { computed, onBeforeUnmount, onMounted, onScopeDispose, watch } from 'vue'\nimport { useStore } from '../../composables/use-store'\nimport { useActionRunner, useAlfakitProps, usePageSchema, usePanel, useT } from '../../context'\nimport ActionList from '../actions/ActionList.vue'\nimport SchemaRenderer from '../schema/SchemaRenderer.vue'\nimport { showToast } from '../notifications/flash-toasts'\nimport { provideForm } from './form-context'\n\n/**\n * A page form: its state lives in a FormStore, and its buttons are actions that post the\n * current values through the action endpoint.\n */\nconst props = defineProps<{ block: FormBlockSchema }>()\n\nconst panel = usePanel()\nconst page = usePageSchema()\nconst pageProps = useAlfakitProps()\nconst runner = useActionRunner()\nconst t = useT()\nconst token = computed(() => page.value?.token ?? '')\n\nconst store = new FormStore(props.block, {\n token: token.value,\n component: props.block.component,\n refreshUrl: panel.value.endpoints.schemaRefresh,\n optionsUrl: panel.value.endpoints.schemaOptions,\n validateUrl: panel.value.endpoints.schemaValidate,\n // A halted wizard step shows what its hook sent.\n onNotifications: (notifications) => notifications.forEach((n) => showToast(n)),\n // Live dashboard filters are applied by the refresh; the widgets reload to follow.\n onRefreshed: () => {\n if (props.block.liveFilters) router.reload({ only: resolvePartialProps(['page']) })\n },\n})\n\nprovideForm(store)\n\n// Named forms of custom pages (`<PageForm name>`) publish their store for page method calls\n// (browser only: mounted hooks never run during a server render).\nlet unregisterPageForm: (() => void) | undefined\n\nonMounted(() => {\n const name = pageFormName(props.block.component)\n\n if (name) unregisterPageForm = registerPageForm(name, store)\n})\n\n// Edit pages: the conflict banner diffs and merges the main form (`detectConflicts()`).\nlet unregisterConflictForm: (() => void) | undefined\n\nonMounted(() => {\n if (props.block.component === 'form') unregisterConflictForm = registerConflictForm(store)\n})\n\nonBeforeUnmount(() => unregisterConflictForm?.())\n\n// Buttons elsewhere with `formId('form')` (a header \"Save\") submit through this form.\nlet unregisterSubmitter: (() => void) | undefined\n\nonMounted(() => {\n unregisterSubmitter = registerFormSubmitter(props.block.component, (action, ctx) =>\n trigger(action, ctx),\n )\n})\n\nonBeforeUnmount(() => {\n unregisterPageForm?.()\n unregisterSubmitter?.()\n})\n\n// The store survives reloads of the same form (table sorting/paging, polling,\n// relation-manager actions all deliver a new `block` object); only a different form\n// identity starts from server state again. The token is re-issued per response, so it\n// is swapped in place instead of being part of the identity.\nwatch(\n () => formIdentity(page.value, props.block),\n () => store.fill(props.block),\n)\n\nwatch(token, (value) => store.setToken(value))\n\n// After this form's own successful submit, refill from the server's new state. The new\n// block may arrive before or after Inertia's `success` event, so handle both orders.\nlet submittedBlock: FormBlockSchema | null = null\nlet refillPending = false\n\nwatch(\n () => props.block,\n (block) => {\n if (refillPending) {\n refillPending = false\n store.fill(block)\n }\n },\n)\n\nwatch(\n () => pageProps.value.errors,\n (errors) => store.setErrors((errors as Record<string, string>) ?? {}),\n { immediate: true },\n)\n\nconst state = useStore(store.store)\nconst context = computed<ActionContext>(() => ({ token: token.value, component: 'page' }))\nlet submitting = false\n\nconst actions = computed<ActionSchema[]>(() =>\n props.block.actions.map((action) => ({ ...action, hasModal: false })),\n)\nconst primary = computed(() => actions.value[0])\n\n// Wizard forms (`HasWizard` pages) show their buttons on the last step only.\nconst progress = useStore(wizardProgressStore(store))\nconst showActions = computed(() => formActionsVisible(props.block, progress.value))\n\nconst trigger = async (action: ActionSchema, ctx: ActionContext) => {\n if (action.url && !action.hasAction) {\n return runner.trigger(action, ctx)\n }\n\n submitting = true\n submittedBlock = props.block\n store.setProcessing(true)\n runner.execute(action, ctx, store.state.values)\n}\n\n// Track this form's own submit visit so unrelated reloads finishing meanwhile (polling,\n// relation-manager paging) neither end its processing state nor count as its success.\nlet submitVisit: string | null = null\n\nconst offStart = router.on('start', (event) => {\n const visit = event.detail.visit\n\n if (submitting && !submitVisit && visit.method !== 'get') {\n submitVisit = visit.id\n }\n})\n\nconst offSuccess = router.on('success', (event) => {\n const id = submitVisit\n\n if (!id || (event.detail.visitId ?? id) !== id) return\n\n // A halted action (rate limit, `halt()`) saved nothing: keep what the user typed.\n if (pageFlash(event.detail.page).alfakitAction?.status === 'halted') return\n\n if (props.block !== submittedBlock) {\n store.fill(props.block)\n } else {\n refillPending = true\n }\n})\n\n// `refreshFormData([...])`: an action changed the record; copy those fields in.\nconst offRefresh = router.on('success', (event) => {\n const refresh = formRefreshFor(pageFlash(event.detail.page), props.block.component)\n\n if (refresh) applyFormRefresh(store, refresh)\n})\n\nconst offFinish = router.on('finish', (event) => {\n if (submitVisit && event.detail.visit.id !== submitVisit) return\n\n store.setProcessing(false)\n submitting = false\n submitVisit = null\n})\n\nconst offBefore = router.on('before', (event) => {\n if (!panel.value.unsavedChangesAlerts) {\n return\n }\n\n if (\n store.isDirty &&\n !submitting &&\n isLeavingVisit(event.detail.visit) &&\n !window.confirm(t('unsaved_changes', {}, 'You have unsaved changes. Leave anyway?'))\n ) {\n event.preventDefault()\n }\n})\n\nonScopeDispose(() => {\n offStart()\n offSuccess()\n offRefresh()\n offFinish()\n offBefore()\n store.destroy()\n})\n\nconst onSubmit = () => {\n if (primary.value && showActions.value) {\n void trigger(primary.value, context.value)\n }\n}\n\n// Enter in a text field runs the primary action (actions are type=\"button\").\nconst onKeydown = (event: KeyboardEvent) => {\n if (\n primary.value &&\n showActions.value &&\n isImplicitSubmit(event, event.currentTarget as HTMLFormElement)\n ) {\n event.preventDefault()\n void trigger(primary.value, context.value)\n }\n}\n</script>\n\n<template>\n <form\n data-slot=\"form-block\"\n class=\"flex flex-col gap-6\"\n @submit.prevent=\"onSubmit\"\n @keydown=\"onKeydown\"\n >\n <fieldset :disabled=\"state.processing || props.block.operation === 'view'\" class=\"contents\">\n <SchemaRenderer :components=\"state.components\" :columns=\"state.columns\" />\n </fieldset>\n <div v-if=\"actions.length > 0 && showActions\" data-slot=\"form-actions\" class=\"border-t pt-6\">\n <ActionList :actions=\"actions\" :context=\"context\" :on-trigger=\"trigger\" />\n </div>\n </form>\n</template>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FormBlock.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createElementBlock","_withModifiers","_createElementVNode","_unref","_createVNode","SchemaRenderer","ActionList","_createCommentVNode","ActionList_default","SchemaRenderer_default","_hoisted_1","_hoisted_2","FormBlock_vue_vue_type_script_setup_true_lang_default","props","__props","panel","usePanel","page","usePageSchema","pageProps","useAlfakitProps","runner","useActionRunner","t","useT","token","computed","store","FormStore","notifications","showToast","n","router","resolvePartialProps","unregisterPageForm","name","pageFormName","registerPageForm","unregisterConflictForm","onMounted","registerConflictForm","onBeforeUnmount","unregisterSubmitter","registerFormSubmitter","trigger","action","ctx","watch","formIdentity","value","submittedBlock","refillPending","resyncPending","visitBlock","block","errors","state","useStore","context","submitting","actions","primary","progress","wizardProgressStore","showActions","formActionsVisible","submitVisit","offStart","visit","event","offSuccess","id","shouldResyncForm","pageFlash","offRefresh","refresh","formRefreshFor","applyFormRefresh","offFinish","offBefore","isLeavingVisit","onSubmit","onKeydown","isImplicitSubmit","openBlock","createElementBlock","withModifiers","createElementVNode","unref","createVNode","createCommentVNode"],"sources":["../../../src/components/form/FormBlock.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ActionContext, ActionSchema, FormBlock as FormBlockSchema } from '@alfakit/core'\nimport {\n FormStore,\n applyFormRefresh,\n formActionsVisible,\n formIdentity,\n formRefreshFor,\n isImplicitSubmit,\n isLeavingVisit,\n pageFlash,\n pageFormName,\n registerConflictForm,\n registerFormSubmitter,\n registerPageForm,\n resolvePartialProps,\n shouldResyncForm,\n wizardProgressStore,\n} from '@alfakit/core'\nimport { router } from '@inertiajs/vue3'\nimport { computed, onBeforeUnmount, onMounted, onScopeDispose, watch } from 'vue'\nimport { useStore } from '../../composables/use-store'\nimport { useActionRunner, useAlfakitProps, usePageSchema, usePanel, useT } from '../../context'\nimport ActionList from '../actions/ActionList.vue'\nimport SchemaRenderer from '../schema/SchemaRenderer.vue'\nimport { showToast } from '../notifications/flash-toasts'\nimport { provideForm } from './form-context'\n\n/**\n * A page form: its state lives in a FormStore, and its buttons are actions that post the\n * current values through the action endpoint.\n */\nconst props = defineProps<{ block: FormBlockSchema }>()\n\nconst panel = usePanel()\nconst page = usePageSchema()\nconst pageProps = useAlfakitProps()\nconst runner = useActionRunner()\nconst t = useT()\nconst token = computed(() => page.value?.token ?? '')\n\nconst store = new FormStore(props.block, {\n token: token.value,\n component: props.block.component,\n refreshUrl: panel.value.endpoints.schemaRefresh,\n optionsUrl: panel.value.endpoints.schemaOptions,\n validateUrl: panel.value.endpoints.schemaValidate,\n // A halted wizard step shows what its hook sent.\n onNotifications: (notifications) => notifications.forEach((n) => showToast(n)),\n // Live dashboard filters are applied by the refresh; the widgets reload to follow.\n onRefreshed: () => {\n if (props.block.liveFilters) router.reload({ only: resolvePartialProps(['page']) })\n },\n})\n\nprovideForm(store)\n\n// Named forms of custom pages (`<PageForm name>`) publish their store for page method calls\n// (browser only: mounted hooks never run during a server render).\nlet unregisterPageForm: (() => void) | undefined\n\nonMounted(() => {\n const name = pageFormName(props.block.component)\n\n if (name) unregisterPageForm = registerPageForm(name, store)\n})\n\n// Edit pages: the conflict banner diffs and merges the main form (`detectConflicts()`).\nlet unregisterConflictForm: (() => void) | undefined\n\nonMounted(() => {\n if (props.block.component === 'form') unregisterConflictForm = registerConflictForm(store)\n})\n\nonBeforeUnmount(() => unregisterConflictForm?.())\n\n// Buttons elsewhere with `formId('form')` (a header \"Save\") submit through this form.\nlet unregisterSubmitter: (() => void) | undefined\n\nonMounted(() => {\n unregisterSubmitter = registerFormSubmitter(props.block.component, (action, ctx) =>\n trigger(action, ctx),\n )\n})\n\nonBeforeUnmount(() => {\n unregisterPageForm?.()\n unregisterSubmitter?.()\n})\n\n// The store survives reloads of the same form (table sorting/paging, polling,\n// relation-manager actions all deliver a new `block` object); only a different form\n// identity starts from server state again. The token is re-issued per response, so it\n// is swapped in place instead of being part of the identity.\nwatch(\n () => formIdentity(page.value, props.block),\n () => store.fill(props.block),\n)\n\nwatch(token, (value) => store.setToken(value))\n\n// After this form's own successful submit, refill from the server's new state. The new\n// block may arrive before or after Inertia's `success` event, so handle both orders.\nlet submittedBlock: FormBlockSchema | null = null\nlet refillPending = false\n// Another action succeeded and its new block has not arrived yet.\nlet resyncPending = false\n// The block when the latest non-GET visit started, to tell whether its response arrived.\nlet visitBlock: FormBlockSchema | null = null\n\nwatch(\n () => props.block,\n (block) => {\n if (refillPending) {\n refillPending = false\n store.fill(block)\n }\n\n if (resyncPending) {\n resyncPending = false\n\n if (!store.isDirty) store.fill(block)\n }\n },\n)\n\nwatch(\n () => pageProps.value.errors,\n (errors) => store.setErrors((errors as Record<string, string>) ?? {}),\n { immediate: true },\n)\n\nconst state = useStore(store.store)\nconst context = computed<ActionContext>(() => ({ token: token.value, component: 'page' }))\nlet submitting = false\n\nconst actions = computed<ActionSchema[]>(() =>\n props.block.actions.map((action) => ({ ...action, hasModal: false })),\n)\nconst primary = computed(() => actions.value[0])\n\n// Wizard forms (`HasWizard` pages) show their buttons on the last step only.\nconst progress = useStore(wizardProgressStore(store))\nconst showActions = computed(() => formActionsVisible(props.block, progress.value))\n\nconst trigger = async (action: ActionSchema, ctx: ActionContext) => {\n if (action.url && !action.hasAction) {\n return runner.trigger(action, ctx)\n }\n\n submitting = true\n submittedBlock = props.block\n store.setProcessing(true)\n // A click that blurred a live field started a refresh: send the state it returns.\n store.whenSettled(() => runner.execute(action, ctx, store.state.values))\n}\n\n// Track this form's own submit visit so unrelated reloads finishing meanwhile (polling,\n// relation-manager paging) neither end its processing state nor count as its success.\nlet submitVisit: string | null = null\n\nconst offStart = router.on('start', (event) => {\n const visit = event.detail.visit\n\n if (submitting && !submitVisit && visit.method !== 'get') {\n submitVisit = visit.id\n }\n\n if (visit.method !== 'get') visitBlock = props.block\n})\n\nconst offSuccess = router.on('success', (event) => {\n const id = submitVisit\n\n // Another action changed the record: show the server's new form unless it holds edits.\n if (!id && shouldResyncForm(pageFlash(event.detail.page), store)) {\n if (props.block !== visitBlock) {\n store.fill(props.block)\n } else {\n resyncPending = true\n }\n\n return\n }\n\n if (!id || (event.detail.visitId ?? id) !== id) return\n\n // A halted action (rate limit, `halt()`) saved nothing: keep what the user typed.\n if (pageFlash(event.detail.page).alfakitAction?.status === 'halted') return\n\n if (props.block !== submittedBlock) {\n store.fill(props.block)\n } else {\n refillPending = true\n }\n})\n\n// `refreshFormData([...])`: an action changed the record; copy those fields in.\nconst offRefresh = router.on('success', (event) => {\n const refresh = formRefreshFor(pageFlash(event.detail.page), props.block.component)\n\n if (refresh) applyFormRefresh(store, refresh)\n})\n\nconst offFinish = router.on('finish', (event) => {\n if (submitVisit && event.detail.visit.id !== submitVisit) return\n\n store.setProcessing(false)\n submitting = false\n submitVisit = null\n})\n\nconst offBefore = router.on('before', (event) => {\n if (!panel.value.unsavedChangesAlerts) {\n return\n }\n\n if (\n store.isDirty &&\n !submitting &&\n isLeavingVisit(event.detail.visit) &&\n !window.confirm(t('unsaved_changes', {}, 'You have unsaved changes. Leave anyway?'))\n ) {\n event.preventDefault()\n }\n})\n\nonScopeDispose(() => {\n offStart()\n offSuccess()\n offRefresh()\n offFinish()\n offBefore()\n store.destroy()\n})\n\nconst onSubmit = () => {\n if (primary.value && showActions.value) {\n void trigger(primary.value, context.value)\n }\n}\n\n// Enter in a text field runs the primary action (actions are type=\"button\").\nconst onKeydown = (event: KeyboardEvent) => {\n if (\n primary.value &&\n showActions.value &&\n isImplicitSubmit(event, event.currentTarget as HTMLFormElement)\n ) {\n event.preventDefault()\n void trigger(primary.value, context.value)\n }\n}\n</script>\n\n<template>\n <form\n data-slot=\"form-block\"\n class=\"flex flex-col gap-6\"\n @submit.prevent=\"onSubmit\"\n @keydown=\"onKeydown\"\n >\n <fieldset :disabled=\"state.processing || props.block.operation === 'view'\" class=\"contents\">\n <SchemaRenderer :components=\"state.components\" :columns=\"state.columns\" />\n </fieldset>\n <div v-if=\"actions.length > 0 && showActions\" data-slot=\"form-actions\" class=\"border-t pt-6\">\n <ActionList :actions=\"actions\" :context=\"context\" :on-trigger=\"trigger\" />\n </div>\n </form>\n</template>\n"],"mappings":"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"}
|
|
@@ -1,43 +1,43 @@
|
|
|
1
1
|
import { useStore as e } from "../../composables/use-store.js";
|
|
2
|
-
import { fieldAria as t } from "@alfakit/core";
|
|
3
|
-
import { computed as
|
|
2
|
+
import { fieldAria as t, fieldDomId as n, fieldError as r } from "@alfakit/core";
|
|
3
|
+
import { computed as i, inject as a, provide as o, toValue as s } from "vue";
|
|
4
4
|
//#region src/components/form/form-context.ts
|
|
5
|
-
var
|
|
6
|
-
function
|
|
7
|
-
|
|
5
|
+
var c = Symbol("alfakit.form");
|
|
6
|
+
function l(e) {
|
|
7
|
+
o(c, e);
|
|
8
8
|
}
|
|
9
|
-
function
|
|
10
|
-
let e =
|
|
9
|
+
function u() {
|
|
10
|
+
let e = a(c, null);
|
|
11
11
|
if (!e) throw Error("Form fields must be rendered inside provideForm().");
|
|
12
12
|
return e;
|
|
13
13
|
}
|
|
14
|
-
function
|
|
15
|
-
return
|
|
14
|
+
function d() {
|
|
15
|
+
return a(c, null);
|
|
16
16
|
}
|
|
17
|
-
function
|
|
18
|
-
return e(
|
|
17
|
+
function f() {
|
|
18
|
+
return e(u().store);
|
|
19
19
|
}
|
|
20
|
-
function
|
|
21
|
-
let
|
|
22
|
-
let e =
|
|
23
|
-
for (let t of
|
|
20
|
+
function p(a) {
|
|
21
|
+
let o = u(), c = e(o.store), l = s(a).statePath, d = i(() => {
|
|
22
|
+
let e = c.value.values;
|
|
23
|
+
for (let t of l.split(".")) {
|
|
24
24
|
if (typeof e != "object" || !e) return;
|
|
25
25
|
e = e[t];
|
|
26
26
|
}
|
|
27
27
|
return e;
|
|
28
|
-
}),
|
|
28
|
+
}), f = i(() => r(c.value.errors, l)), p = i(() => !!s(a).disabled), m = i(() => !!s(a).readOnly), h = s(a).id ?? n(o.idPrefix, l);
|
|
29
29
|
return {
|
|
30
|
-
value:
|
|
31
|
-
setValue: (e) =>
|
|
32
|
-
blur: () =>
|
|
33
|
-
error:
|
|
34
|
-
id:
|
|
35
|
-
disabled:
|
|
36
|
-
readOnly:
|
|
37
|
-
aria:
|
|
30
|
+
value: d,
|
|
31
|
+
setValue: (e) => o.setValue(l, e),
|
|
32
|
+
blur: () => o.blur(l),
|
|
33
|
+
error: f,
|
|
34
|
+
id: h,
|
|
35
|
+
disabled: p,
|
|
36
|
+
readOnly: m,
|
|
37
|
+
aria: i(() => t(h, s(a), f.value))
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
40
|
//#endregion
|
|
41
|
-
export {
|
|
41
|
+
export { c as FORM_STORE_KEY, l as provideForm, p as useField, f as useFormState, u as useFormStore, d as useOptionalFormStore };
|
|
42
42
|
|
|
43
43
|
//# sourceMappingURL=form-context.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form-context.js","names":["FORM_STORE_KEY","provideForm","store","useFormStore","inject","useOptionalFormStore","useFormState","useStore","useField","state","path","toValue","field","value","computed","current","segment","error","disabled","readOnly","id","next","fieldAria"],"sources":["../../../src/components/form/form-context.ts"],"sourcesContent":["import type { BaseField, FieldAriaAttributes, FormState, FormStore } from '@alfakit/core'\nimport { fieldAria } from '@alfakit/core'\nimport {\n computed,\n inject,\n provide,\n toValue,\n type ComputedRef,\n type InjectionKey,\n type MaybeRefOrGetter,\n type ShallowRef,\n} from 'vue'\nimport { useStore } from '../../composables/use-store'\n\nexport const FORM_STORE_KEY: InjectionKey<FormStore> = Symbol('alfakit.form')\n\nexport function provideForm(store: FormStore): void {\n provide(FORM_STORE_KEY, store)\n}\n\nexport function useFormStore(): FormStore {\n const store = inject(FORM_STORE_KEY, null)\n\n if (!store) {\n throw new Error('Form fields must be rendered inside provideForm().')\n }\n\n return store\n}\n\nexport function useOptionalFormStore(): FormStore | null {\n return inject(FORM_STORE_KEY, null)\n}\n\nexport function useFormState(): ShallowRef<FormState> {\n return useStore(useFormStore().store)\n}\n\nexport interface FieldBinding<T = unknown> {\n value: ComputedRef<T>\n setValue: (value: T) => void\n blur: () => void\n error: ComputedRef<string | undefined>\n id: string\n /** The field cannot be interacted with at all (`disabled()`). */\n disabled: ComputedRef<boolean>\n /** The field shows its value but the user cannot change it (`readOnly()`). */\n readOnly: ComputedRef<boolean>\n /** `aria-describedby` (hint, helper text, error), `aria-invalid` and `aria-required` for the control. */\n aria: ComputedRef<FieldAriaAttributes>\n}\n\n/** Bind a field schema to the form store. */\nexport function useField<T = unknown>(field: MaybeRefOrGetter<BaseField>): FieldBinding<T> {\n const store = useFormStore()\n const state = useStore(store.store)\n const path = toValue(field).statePath\n\n const value = computed(() => {\n let current: unknown = state.value.values\n\n for (const segment of path.split('.')) {\n if (current === null || current === undefined || typeof current !== 'object') {\n return undefined as T\n }\n\n current = (current as Record<string, unknown>)[segment]\n }\n\n return current as T\n })\n\n const error = computed(() => state.value.errors
|
|
1
|
+
{"version":3,"file":"form-context.js","names":["FORM_STORE_KEY","provideForm","store","useFormStore","inject","useOptionalFormStore","useFormState","useStore","useField","state","path","toValue","field","value","computed","current","segment","error","fieldError","disabled","readOnly","id","fieldDomId","next","fieldAria"],"sources":["../../../src/components/form/form-context.ts"],"sourcesContent":["import type { BaseField, FieldAriaAttributes, FormState, FormStore } from '@alfakit/core'\nimport { fieldAria, fieldDomId, fieldError } from '@alfakit/core'\nimport {\n computed,\n inject,\n provide,\n toValue,\n type ComputedRef,\n type InjectionKey,\n type MaybeRefOrGetter,\n type ShallowRef,\n} from 'vue'\nimport { useStore } from '../../composables/use-store'\n\nexport const FORM_STORE_KEY: InjectionKey<FormStore> = Symbol('alfakit.form')\n\nexport function provideForm(store: FormStore): void {\n provide(FORM_STORE_KEY, store)\n}\n\nexport function useFormStore(): FormStore {\n const store = inject(FORM_STORE_KEY, null)\n\n if (!store) {\n throw new Error('Form fields must be rendered inside provideForm().')\n }\n\n return store\n}\n\nexport function useOptionalFormStore(): FormStore | null {\n return inject(FORM_STORE_KEY, null)\n}\n\nexport function useFormState(): ShallowRef<FormState> {\n return useStore(useFormStore().store)\n}\n\nexport interface FieldBinding<T = unknown> {\n value: ComputedRef<T>\n setValue: (value: T) => void\n blur: () => void\n error: ComputedRef<string | undefined>\n id: string\n /** The field cannot be interacted with at all (`disabled()`). */\n disabled: ComputedRef<boolean>\n /** The field shows its value but the user cannot change it (`readOnly()`). */\n readOnly: ComputedRef<boolean>\n /** `aria-describedby` (hint, helper text, error), `aria-invalid` and `aria-required` for the control. */\n aria: ComputedRef<FieldAriaAttributes>\n}\n\n/** Bind a field schema to the form store. */\nexport function useField<T = unknown>(field: MaybeRefOrGetter<BaseField>): FieldBinding<T> {\n const store = useFormStore()\n const state = useStore(store.store)\n const path = toValue(field).statePath\n\n const value = computed(() => {\n let current: unknown = state.value.values\n\n for (const segment of path.split('.')) {\n if (current === null || current === undefined || typeof current !== 'object') {\n return undefined as T\n }\n\n current = (current as Record<string, unknown>)[segment]\n }\n\n return current as T\n })\n\n const error = computed(() => fieldError(state.value.errors, path))\n // Fields stay enabled during a live refresh: the store keeps edits made while the request\n // is in flight, so locking inputs would only swallow keystrokes.\n const disabled = computed(() => Boolean(toValue(field).disabled))\n const readOnly = computed(() => Boolean(toValue(field).readOnly))\n const id = toValue(field).id ?? fieldDomId(store.idPrefix, path)\n const aria = computed(() => fieldAria(id, toValue(field), error.value))\n\n return {\n value,\n setValue: (next: T) => store.setValue(path, next),\n blur: () => store.blur(path),\n error,\n id,\n disabled,\n readOnly,\n aria,\n }\n}\n"],"mappings":";;;;AAcA,IAAaA,IAA0C,OAAO,cAAc;AAE5E,SAAgBC,EAAY,GAAwB;CAClD,EAAQD,GAAgBE,CAAK;AAC/B;AAEA,SAAgBC,IAA0B;CACxC,IAAMD,IAAQE,EAAOJ,GAAgB,IAAI;CAEzC,IAAI,CAACE,GACH,MAAU,MAAM,oDAAoD;CAGtE,OAAOA;AACT;AAEA,SAAgBG,IAAyC;CACvD,OAAOD,EAAOJ,GAAgB,IAAI;AACpC;AAEA,SAAgBM,IAAsC;CACpD,OAAOC,EAASJ,EAAa,CAAC,CAAC,KAAK;AACtC;AAiBA,SAAgBK,EAAsB,GAAqD;CACzF,IAAMN,IAAQC,EAAa,GACrBM,IAAQF,EAASL,EAAM,KAAK,GAC5BQ,IAAOC,EAAQC,CAAK,CAAC,CAAC,WAEtBC,IAAQC,QAAe;EAC3B,IAAIC,IAAmBN,EAAM,MAAM;EAEnC,KAAK,IAAMO,KAAWN,EAAK,MAAM,GAAG,GAAG;GACrC,IAAiD,OAAOK,KAAY,aAAhEA,GACF;GAGF,IAAWA,EAAoCC;EACjD;EAEA,OAAOD;CACT,CAAC,GAEKE,IAAQH,QAAeI,EAAWT,EAAM,MAAM,QAAQC,CAAI,CAAC,GAG3DS,IAAWL,QAAe,EAAQH,EAAQC,CAAK,CAAC,CAAC,QAAS,GAC1DQ,IAAWN,QAAe,EAAQH,EAAQC,CAAK,CAAC,CAAC,QAAS,GAC1DS,IAAKV,EAAQC,CAAK,CAAC,CAAC,MAAMU,EAAWpB,EAAM,UAAUQ,CAAI;CAG/D,OAAO;EACL;EACA,WAAW,MAAYR,EAAM,SAASQ,GAAMa,CAAI;EAChD,YAAYrB,EAAM,KAAKQ,CAAI;EAC3B;EACA;EACA;EACA;EACA,MAVWI,QAAeU,EAAUH,GAAIV,EAAQC,CAAK,GAAGK,EAAM,KAAK,CAUnE;CACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KanbanBoard.js","names":["_sfc_main","KanbanBoard_vue_vue_type_script_setup_true_lang_default","KanbanBoard_default"],"sources":["../../../src/components/kanban/KanbanBoard.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { KanbanEnvironment, KanbanSchema } from '@alfakit/core'\nimport {\n KanbanController,\n attachKanbanPointer,\n clientErrorNotification,\n createKanbanFiltersStore,\n kanbanActiveFilters,\n kanbanCardsIn,\n kanbanInitials,\n} from '@alfakit/core'\nimport { router } from '@inertiajs/vue3'\nimport { ChevronRightIcon, SearchIcon } from '@lucide/vue'\nimport { computed, nextTick, onBeforeUnmount, onMounted, ref, toRaw, useId, watch } from 'vue'\nimport { useStore } from '../../composables/use-store'\nimport { useActionRunner, useDirection, usePanel, useT } from '../../context'\nimport { Icon } from '../../lib/icons'\nimport { cn } from '../../lib/utils'\nimport { usePageActionContext } from '../actions/action-context'\nimport { showToast } from '../notifications/flash-toasts'\nimport Avatar from '../ui/Avatar.vue'\nimport AvatarFallback from '../ui/AvatarFallback.vue'\nimport AvatarImage from '../ui/AvatarImage.vue'\nimport Badge from '../ui/Badge.vue'\nimport Button from '../ui/Button.vue'\nimport Card from '../ui/Card.vue'\nimport CardTitle from '../ui/CardTitle.vue'\nimport Input from '../ui/Input.vue'\nimport Spinner from '../ui/Spinner.vue'\nimport KanbanCard from './KanbanCard.vue'\nimport KanbanColumnHeader from './KanbanColumnHeader.vue'\nimport KanbanFilters from './KanbanFilters.vue'\n\n/**\n * Cards move by dragging (mouse, pen, touch) or with the keyboard, and every move is\n * saved in one request.\n */\nconst props = defineProps<{ board: KanbanSchema }>()\n\nconst runner = useActionRunner()\nconst page = usePageActionContext()\nconst panel = usePanel()\nconst t = useT()\nconst direction = useDirection()\nconst labelId = useId()\nconst instructionsId = useId()\n\nconst environment = (): KanbanEnvironment => ({\n runner,\n token: page.token,\n t,\n notify: (notifications) => notifications.forEach((notification) => showToast(notification)),\n error: (message) => showToast(clientErrorNotification('kanban', message)),\n visit: (url) => router.visit(url),\n})\n\nconst controller = new KanbanController(toRaw(props.board), environment())\nconst filters = createKanbanFiltersStore(\n toRaw(props.board),\n page.token,\n panel.value.endpoints.schemaOptions,\n)\nconst state = useStore(controller.store)\nconst root = ref<{ $el: HTMLElement } | null>(null)\nconst cards = new Map<string, HTMLElement>()\nconst focused = ref<string | null>(null)\nconst search = ref(state.value.search)\nlet detach: (() => void) | null = null\nlet stopPolling: (() => void) | null = null\n\nwatch(\n () => props.board,\n (board) => controller.setBoard(toRaw(board)),\n)\nwatch(\n () => state.value.search,\n (value) => {\n if (value !== search.value) search.value = value\n },\n)\n\nonMounted(() => {\n const element = root.value?.$el\n\n if (element instanceof HTMLElement) detach = attachKanbanPointer(element, controller)\n\n stopPolling = controller.startPolling()\n})\n\nonBeforeUnmount(() => {\n detach?.()\n stopPolling?.()\n controller.destroy()\n filters?.destroy()\n})\n\nconst schema = computed(() => {\n // Re-read when the state changes (the controller swaps its schema with the board).\n void state.value.columns\n\n return controller.schema\n})\nconst lanes = computed(() => {\n void state.value.columns\n\n return controller.lanes()\n})\nconst filtered = computed(\n () => state.value.search !== '' || kanbanActiveFilters(state.value.filters) > 0,\n)\nconst keys = computed(() =>\n state.value.columns.flatMap((column) => column.cards.map((card) => card.key)),\n)\nconst current = computed(() =>\n focused.value !== null && keys.value.includes(focused.value)\n ? focused.value\n : (keys.value[0] ?? null),\n)\nconst template = computed(() =>\n state.value.columns\n .map((column) => (state.value.collapsed.has(column.key) ? '3.25rem' : 'minmax(16rem, 20rem)'))\n .join(' '),\n)\n\nconst setCard = (key: string) => (element: unknown) => {\n if (element instanceof HTMLElement) cards.set(key, element)\n else cards.delete(key)\n}\n\nconst focus = (key: string | undefined) => {\n if (!key) return\n focused.value = key\n void nextTick(() => cards.get(key)?.focus())\n}\n\n// A card picked up with the keyboard moves to another list: keep the focus on it.\nwatch(\n () => state.value.picked,\n (picked) => {\n if (picked?.via !== 'keyboard') return\n\n void nextTick(() => {\n const element = cards.get(picked.key)\n\n if (element && document.activeElement !== element) element.focus()\n })\n },\n)\n\nconst onKeyDown = (key: string, event: KeyboardEvent) => {\n if (event.target !== event.currentTarget) return\n\n const result = controller.handleKey(key, event, direction.value)\n\n if (!result.handled) return\n\n event.preventDefault()\n\n if (result.open) controller.open(key)\n else focus(result.focus)\n}\n\nconst onSearch = (value: string) => {\n search.value = value\n controller.setSearch(value)\n}\n\nconst laneCount = (lane: string) =>\n state.value.columns.reduce((sum, column) => sum + kanbanCardsIn(column, lane).length, 0)\n</script>\n\n<template>\n <Card ref=\"root\" role=\"region\" :aria-labelledby=\"labelId\" class=\"gap-3 py-4\" data-slot=\"kanban\">\n <div class=\"flex flex-wrap items-center gap-2 px-4\" data-slot=\"kanban-toolbar\">\n <CardTitle v-if=\"schema.heading\" :id=\"labelId\" class=\"text-base\">{{\n schema.heading\n }}</CardTitle>\n <span v-else :id=\"labelId\" class=\"sr-only\">{{ t('kanban.label', {}, 'Kanban board') }}</span>\n <div class=\"ms-auto flex w-full flex-wrap items-center gap-2 sm:w-auto\">\n <Spinner v-if=\"state.loading\" class=\"size-4\" />\n <div v-if=\"schema.searchable\" class=\"relative w-full sm:w-64\">\n <SearchIcon\n class=\"text-muted-foreground pointer-events-none absolute start-2.5 top-1/2 size-4 -translate-y-1/2\"\n aria-hidden=\"true\"\n />\n <Input\n type=\"search\"\n :model-value=\"search\"\n class=\"h-8 ps-8\"\n :placeholder=\"t('kanban.search_placeholder', {}, 'Search…')\"\n :aria-label=\"t('kanban.search', {}, 'Search cards')\"\n @update:model-value=\"onSearch\"\n />\n </div>\n <KanbanFilters v-if=\"filters\" :controller=\"controller\" :store=\"filters\" />\n </div>\n </div>\n <p :id=\"instructionsId\" class=\"sr-only\">\n {{\n t(\n 'kanban.instructions',\n {},\n 'Press Space to pick up a card. While it is picked up, use the arrow keys to move it, Space to drop it and Escape to cancel.',\n )\n }}\n </p>\n <div\n class=\"relative overflow-x-auto overscroll-x-contain px-4 pb-2\"\n data-slot=\"kanban-scroller\"\n >\n <div class=\"grid w-max min-w-full snap-x gap-3\" :style=\"{ gridTemplateColumns: template }\">\n <KanbanColumnHeader\n v-for=\"column in state.columns\"\n :id=\"`${labelId}-column-${column.key}`\"\n :key=\"column.key\"\n :column=\"column\"\n :collapsed=\"state.collapsed.has(column.key)\"\n :creatable=\"Boolean(column.creatable && schema.createAction)\"\n :filtered=\"filtered\"\n @toggle=\"controller.toggleColumn(column.key)\"\n @create=\"controller.create(column.key)\"\n />\n <template v-for=\"lane in lanes\" :key=\"lane?.key ?? '__board'\">\n <div\n v-if=\"lane\"\n class=\"flex items-center gap-2 pt-2\"\n style=\"grid-column: 1 / -1\"\n data-slot=\"kanban-lane\"\n :data-lane=\"lane.key\"\n >\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n :aria-expanded=\"!state.collapsedLanes.has(lane.key)\"\n :aria-label=\"\n state.collapsedLanes.has(lane.key)\n ? t('kanban.expand_lane', { lane: lane.label }, 'Expand row :lane')\n : t('kanban.collapse_lane', { lane: lane.label }, 'Collapse row :lane')\n \"\n @click=\"controller.toggleLane(lane.key)\"\n >\n <ChevronRightIcon\n :class=\"\n cn(\n 'transition-transform rtl:rotate-180',\n !state.collapsedLanes.has(lane.key) && 'rotate-90 rtl:rotate-90',\n )\n \"\n aria-hidden=\"true\"\n />\n </Button>\n <Avatar v-if=\"lane.avatar\" class=\"size-6\">\n <AvatarImage :src=\"lane.avatar\" alt=\"\" />\n <AvatarFallback>{{ kanbanInitials(lane.label) }}</AvatarFallback>\n </Avatar>\n <Icon v-else-if=\"lane.icon\" :name=\"lane.icon\" class=\"text-muted-foreground size-4\" />\n <span :id=\"`${labelId}-lane-${lane.key}`\" class=\"text-sm font-semibold\">{{\n lane.label\n }}</span>\n <Badge variant=\"secondary\" class=\"h-5 px-1.5 tabular-nums\">{{\n laneCount(lane.key)\n }}</Badge>\n </div>\n <template v-if=\"!lane || !state.collapsedLanes.has(lane.key)\">\n <ul\n v-for=\"column in state.columns\"\n :key=\"column.key\"\n role=\"list\"\n :aria-labelledby=\"\n [\n `${labelId}-column-${column.key}`,\n lane ? `${labelId}-lane-${lane.key}` : undefined,\n ]\n .filter(Boolean)\n .join(' ')\n \"\n data-slot=\"kanban-dropzone\"\n :data-column=\"column.key\"\n :data-lane=\"lane?.key\"\n :data-refused=\"state.picked && state.refused?.column === column.key ? '' : undefined\"\n :class=\"\n cn(\n 'bg-muted/40 flex min-h-24 flex-col gap-2 rounded-lg p-2',\n lane === null && 'max-h-[70vh] overflow-y-auto',\n )\n \"\n >\n <template v-if=\"!state.collapsed.has(column.key)\">\n <KanbanCard\n v-for=\"card in kanbanCardsIn(column, lane?.key ?? null)\"\n :key=\"card.key\"\n :card=\"card\"\n :board=\"schema\"\n :token=\"page.token\"\n :current=\"current === card.key\"\n :picked=\"state.picked?.key === card.key ? state.picked.via : undefined\"\n :saving=\"state.saving.has(card.key)\"\n :described-by=\"instructionsId\"\n :set-ref=\"setCard(card.key)\"\n @focus=\"focused = card.key\"\n @keydown=\"onKeyDown(card.key, $event)\"\n @open=\"controller.open(card.key)\"\n />\n <li\n v-if=\"kanbanCardsIn(column, lane?.key ?? null).length === 0\"\n class=\"text-muted-foreground rounded-md border border-dashed px-2 py-6 text-center text-xs\"\n data-slot=\"kanban-empty\"\n >\n {{\n filtered\n ? t('kanban.no_results', {}, 'No cards match')\n : (column.emptyState ?? t('kanban.empty', {}, 'No cards'))\n }}\n </li>\n <li\n v-if=\"lane === null && column.total > column.cards.length\"\n class=\"text-muted-foreground px-2 text-center text-xs\"\n >\n {{\n t(\n 'kanban.more_cards',\n { count: column.total - column.cards.length },\n '+:count more',\n )\n }}\n </li>\n </template>\n </ul>\n </template>\n </template>\n </div>\n </div>\n <div class=\"sr-only\" role=\"status\" aria-live=\"polite\">{{ state.announcement }}</div>\n </Card>\n</template>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"KanbanBoard.js","names":["_sfc_main","KanbanBoard_vue_vue_type_script_setup_true_lang_default","KanbanBoard_default"],"sources":["../../../src/components/kanban/KanbanBoard.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { KanbanEnvironment, KanbanSchema } from '@alfakit/core'\nimport {\n KanbanController,\n attachKanbanPointer,\n clientErrorNotification,\n createKanbanFiltersStore,\n kanbanActiveFilters,\n kanbanCardsIn,\n kanbanInitials,\n} from '@alfakit/core'\nimport { router } from '@inertiajs/vue3'\nimport { ChevronRightIcon, SearchIcon } from '@lucide/vue'\nimport { computed, nextTick, onBeforeUnmount, onMounted, ref, toRaw, useId, watch } from 'vue'\nimport { useStore } from '../../composables/use-store'\nimport { useActionRunner, useDirection, usePanel, useT } from '../../context'\nimport { Icon } from '../../lib/icons'\nimport { cn } from '../../lib/utils'\nimport { usePageActionContext } from '../actions/action-context'\nimport { showToast } from '../notifications/flash-toasts'\nimport Avatar from '../ui/Avatar.vue'\nimport AvatarFallback from '../ui/AvatarFallback.vue'\nimport AvatarImage from '../ui/AvatarImage.vue'\nimport Badge from '../ui/Badge.vue'\nimport Button from '../ui/Button.vue'\nimport Card from '../ui/Card.vue'\nimport CardTitle from '../ui/CardTitle.vue'\nimport Input from '../ui/Input.vue'\nimport Spinner from '../ui/Spinner.vue'\nimport KanbanCard from './KanbanCard.vue'\nimport KanbanColumnHeader from './KanbanColumnHeader.vue'\nimport KanbanFilters from './KanbanFilters.vue'\n\n/**\n * Cards move by dragging (mouse, pen, touch) or with the keyboard, and every move is\n * saved in one request.\n */\nconst props = defineProps<{ board: KanbanSchema }>()\n\nconst runner = useActionRunner()\nconst page = usePageActionContext()\nconst panel = usePanel()\nconst t = useT()\nconst direction = useDirection()\nconst labelId = useId()\nconst instructionsId = useId()\n\nconst environment = (): KanbanEnvironment => ({\n runner,\n token: page.token,\n t,\n notify: (notifications) => notifications.forEach((notification) => showToast(notification)),\n error: (message) => showToast(clientErrorNotification('kanban', message)),\n visit: (url) => router.visit(url),\n})\n\nconst controller = new KanbanController(toRaw(props.board), environment())\nconst filters = createKanbanFiltersStore(\n toRaw(props.board),\n page.token,\n panel.value.endpoints.schemaOptions,\n)\nconst state = useStore(controller.store)\nconst root = ref<{ $el: HTMLElement } | null>(null)\nconst cards = new Map<string, HTMLElement>()\nconst focused = ref<string | null>(null)\nconst search = ref(state.value.search)\nlet detach: (() => void) | null = null\nlet stopPolling: (() => void) | null = null\n\nwatch(\n () => props.board,\n (board) => controller.setBoard(toRaw(board)),\n)\nwatch(\n () => state.value.search,\n (value) => {\n if (value !== search.value) search.value = value\n },\n)\n\nonMounted(() => {\n const element = root.value?.$el\n\n if (element instanceof HTMLElement) detach = attachKanbanPointer(element, controller)\n\n stopPolling = controller.startPolling()\n})\n\nonBeforeUnmount(() => {\n detach?.()\n stopPolling?.()\n controller.destroy()\n filters?.destroy()\n})\n\nconst schema = computed(() => {\n // Re-read when the state changes (the controller swaps its schema with the board).\n void state.value.columns\n\n return controller.schema\n})\nconst lanes = computed(() => {\n void state.value.columns\n\n return controller.lanes()\n})\nconst filtered = computed(\n () => state.value.search !== '' || kanbanActiveFilters(state.value.filters) > 0,\n)\nconst keys = computed(() =>\n state.value.columns.flatMap((column) => column.cards.map((card) => card.key)),\n)\nconst current = computed(() =>\n focused.value !== null && keys.value.includes(focused.value)\n ? focused.value\n : (keys.value[0] ?? null),\n)\nconst template = computed(() =>\n state.value.columns\n .map((column) => (state.value.collapsed.has(column.key) ? '3.25rem' : 'minmax(16rem, 20rem)'))\n .join(' '),\n)\n\n// A card moved to another column is mounted there before its old element is unmounted, so\n// an unmount only forgets the element it registered itself (else the moved card would lose\n// its entry and the keyboard focus).\nconst setCard = (key: string) => {\n let own: HTMLElement | null = null\n\n return (element: unknown) => {\n if (element instanceof HTMLElement) {\n own = element\n cards.set(key, element)\n } else if (own !== null) {\n if (cards.get(key) === own) cards.delete(key)\n own = null\n }\n }\n}\n\nconst focus = (key: string | undefined) => {\n if (!key) return\n focused.value = key\n void nextTick(() => cards.get(key)?.focus())\n}\n\n// A card picked up with the keyboard moves to another list: keep the focus on it.\nwatch(\n () => state.value.picked,\n (picked) => {\n if (picked?.via !== 'keyboard') return\n\n void nextTick(() => {\n const element = cards.get(picked.key)\n\n if (element && document.activeElement !== element) element.focus()\n })\n },\n)\n\nconst onKeyDown = (key: string, event: KeyboardEvent) => {\n if (event.target !== event.currentTarget) return\n\n const result = controller.handleKey(key, event, direction.value)\n\n if (!result.handled) return\n\n event.preventDefault()\n\n if (result.open) controller.open(key)\n else focus(result.focus)\n}\n\nconst onSearch = (value: string) => {\n search.value = value\n controller.setSearch(value)\n}\n\nconst laneCount = (lane: string) =>\n state.value.columns.reduce((sum, column) => sum + kanbanCardsIn(column, lane).length, 0)\n</script>\n\n<template>\n <Card ref=\"root\" role=\"region\" :aria-labelledby=\"labelId\" class=\"gap-3 py-4\" data-slot=\"kanban\">\n <div class=\"flex flex-wrap items-center gap-2 px-4\" data-slot=\"kanban-toolbar\">\n <CardTitle v-if=\"schema.heading\" :id=\"labelId\" class=\"text-base\">{{\n schema.heading\n }}</CardTitle>\n <span v-else :id=\"labelId\" class=\"sr-only\">{{ t('kanban.label', {}, 'Kanban board') }}</span>\n <div class=\"ms-auto flex w-full flex-wrap items-center gap-2 sm:w-auto\">\n <Spinner v-if=\"state.loading\" class=\"size-4\" />\n <div v-if=\"schema.searchable\" class=\"relative w-full sm:w-64\">\n <SearchIcon\n class=\"text-muted-foreground pointer-events-none absolute start-2.5 top-1/2 size-4 -translate-y-1/2\"\n aria-hidden=\"true\"\n />\n <Input\n type=\"search\"\n :model-value=\"search\"\n class=\"h-8 ps-8\"\n :placeholder=\"t('kanban.search_placeholder', {}, 'Search…')\"\n :aria-label=\"t('kanban.search', {}, 'Search cards')\"\n @update:model-value=\"onSearch\"\n />\n </div>\n <KanbanFilters v-if=\"filters\" :controller=\"controller\" :store=\"filters\" />\n </div>\n </div>\n <p :id=\"instructionsId\" class=\"sr-only\">\n {{\n t(\n 'kanban.instructions',\n {},\n 'Press Space to pick up a card. While it is picked up, use the arrow keys to move it, Space to drop it and Escape to cancel.',\n )\n }}\n </p>\n <div\n class=\"relative overflow-x-auto overscroll-x-contain px-4 pb-2\"\n data-slot=\"kanban-scroller\"\n >\n <div class=\"grid w-max min-w-full snap-x gap-3\" :style=\"{ gridTemplateColumns: template }\">\n <KanbanColumnHeader\n v-for=\"column in state.columns\"\n :id=\"`${labelId}-column-${column.key}`\"\n :key=\"column.key\"\n :column=\"column\"\n :collapsed=\"state.collapsed.has(column.key)\"\n :creatable=\"Boolean(column.creatable && schema.createAction)\"\n :filtered=\"filtered\"\n @toggle=\"controller.toggleColumn(column.key)\"\n @create=\"controller.create(column.key)\"\n />\n <template v-for=\"lane in lanes\" :key=\"lane?.key ?? '__board'\">\n <div\n v-if=\"lane\"\n class=\"flex items-center gap-2 pt-2\"\n style=\"grid-column: 1 / -1\"\n data-slot=\"kanban-lane\"\n :data-lane=\"lane.key\"\n >\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n :aria-expanded=\"!state.collapsedLanes.has(lane.key)\"\n :aria-label=\"\n state.collapsedLanes.has(lane.key)\n ? t('kanban.expand_lane', { lane: lane.label }, 'Expand row :lane')\n : t('kanban.collapse_lane', { lane: lane.label }, 'Collapse row :lane')\n \"\n @click=\"controller.toggleLane(lane.key)\"\n >\n <ChevronRightIcon\n :class=\"\n cn(\n 'transition-transform rtl:rotate-180',\n !state.collapsedLanes.has(lane.key) && 'rotate-90 rtl:rotate-90',\n )\n \"\n aria-hidden=\"true\"\n />\n </Button>\n <Avatar v-if=\"lane.avatar\" class=\"size-6\">\n <AvatarImage :src=\"lane.avatar\" alt=\"\" />\n <AvatarFallback>{{ kanbanInitials(lane.label) }}</AvatarFallback>\n </Avatar>\n <Icon v-else-if=\"lane.icon\" :name=\"lane.icon\" class=\"text-muted-foreground size-4\" />\n <span :id=\"`${labelId}-lane-${lane.key}`\" class=\"text-sm font-semibold\">{{\n lane.label\n }}</span>\n <Badge variant=\"secondary\" class=\"h-5 px-1.5 tabular-nums\">{{\n laneCount(lane.key)\n }}</Badge>\n </div>\n <template v-if=\"!lane || !state.collapsedLanes.has(lane.key)\">\n <ul\n v-for=\"column in state.columns\"\n :key=\"column.key\"\n role=\"list\"\n :aria-labelledby=\"\n [\n `${labelId}-column-${column.key}`,\n lane ? `${labelId}-lane-${lane.key}` : undefined,\n ]\n .filter(Boolean)\n .join(' ')\n \"\n data-slot=\"kanban-dropzone\"\n :data-column=\"column.key\"\n :data-lane=\"lane?.key\"\n :data-refused=\"state.picked && state.refused?.column === column.key ? '' : undefined\"\n :class=\"\n cn(\n 'bg-muted/40 flex min-h-24 flex-col gap-2 rounded-lg p-2',\n lane === null && 'max-h-[70vh] overflow-y-auto',\n )\n \"\n >\n <template v-if=\"!state.collapsed.has(column.key)\">\n <KanbanCard\n v-for=\"card in kanbanCardsIn(column, lane?.key ?? null)\"\n :key=\"card.key\"\n :card=\"card\"\n :board=\"schema\"\n :token=\"page.token\"\n :current=\"current === card.key\"\n :picked=\"state.picked?.key === card.key ? state.picked.via : undefined\"\n :saving=\"state.saving.has(card.key)\"\n :described-by=\"instructionsId\"\n :set-ref=\"setCard(card.key)\"\n @focus=\"focused = card.key\"\n @keydown=\"onKeyDown(card.key, $event)\"\n @open=\"controller.open(card.key)\"\n />\n <li\n v-if=\"kanbanCardsIn(column, lane?.key ?? null).length === 0\"\n class=\"text-muted-foreground rounded-md border border-dashed px-2 py-6 text-center text-xs\"\n data-slot=\"kanban-empty\"\n >\n {{\n filtered\n ? t('kanban.no_results', {}, 'No cards match')\n : (column.emptyState ?? t('kanban.empty', {}, 'No cards'))\n }}\n </li>\n <li\n v-if=\"lane === null && column.total > column.cards.length\"\n class=\"text-muted-foreground px-2 text-center text-xs\"\n >\n {{\n t(\n 'kanban.more_cards',\n { count: column.total - column.cards.length },\n '+:count more',\n )\n }}\n </li>\n </template>\n </ul>\n </template>\n </template>\n </div>\n </div>\n <div class=\"sr-only\" role=\"status\" aria-live=\"polite\">{{ state.announcement }}</div>\n </Card>\n</template>\n"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KanbanBoard.vue.d.ts","sourceRoot":"","sources":["../../../src/components/kanban/KanbanBoard.vue"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"KanbanBoard.vue.d.ts","sourceRoot":"","sources":["../../../src/components/kanban/KanbanBoard.vue"],"names":[],"mappings":"AA8VA,OAAO,KAAK,EAAqB,YAAY,EAAE,MAAM,eAAe,CAAA;AAgCpE;;;GAGG;AACH,KAAK,WAAW,GAAG;IAAE,KAAK,EAAE,YAAY,CAAA;CAAE,CAAC;;AAmrB3C,wBAMG"}
|
|
@@ -66,8 +66,11 @@ var F = {
|
|
|
66
66
|
}), _e(() => {
|
|
67
67
|
Y?.(), X?.(), H.destroy(), U?.destroy();
|
|
68
68
|
});
|
|
69
|
-
let Z = m(() => (W.value.columns, H.schema)), Me = m(() => (W.value.columns, H.lanes())), Q = m(() => W.value.search !== "" || pe(W.value.filters) > 0), $ = m(() => W.value.columns.flatMap((e) => e.cards.map((e) => e.key))), Ne = m(() => q.value !== null && $.value.includes(q.value) ? q.value : $.value[0] ?? null), Pe = m(() => W.value.columns.map((e) => W.value.collapsed.has(e.key) ? "3.25rem" : "minmax(16rem, 20rem)").join(" ")), Fe = (e) =>
|
|
70
|
-
|
|
69
|
+
let Z = m(() => (W.value.columns, H.schema)), Me = m(() => (W.value.columns, H.lanes())), Q = m(() => W.value.search !== "" || pe(W.value.filters) > 0), $ = m(() => W.value.columns.flatMap((e) => e.cards.map((e) => e.key))), Ne = m(() => q.value !== null && $.value.includes(q.value) ? q.value : $.value[0] ?? null), Pe = m(() => W.value.columns.map((e) => W.value.collapsed.has(e.key) ? "3.25rem" : "minmax(16rem, 20rem)").join(" ")), Fe = (e) => {
|
|
70
|
+
let t = null;
|
|
71
|
+
return (n) => {
|
|
72
|
+
n instanceof HTMLElement ? (t = n, K.set(e, n)) : t !== null && (K.get(e) === t && K.delete(e), t = null);
|
|
73
|
+
};
|
|
71
74
|
}, Ie = (e) => {
|
|
72
75
|
e && (q.value = e, S(() => K.get(e)?.focus()));
|
|
73
76
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KanbanBoard.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createBlock","Card","_unref","_withCtx","_createElementVNode","CardTitle","_createTextVNode","_toDisplayString","_createElementBlock","Spinner","_createCommentVNode","_createVNode","Input","KanbanFilters","_normalizeStyle","_Fragment","_renderList","KanbanColumnHeader","Button","_normalizeClass","Avatar","AvatarImage","AvatarFallback","Icon","Badge","KanbanCard","Icon_default","Badge_default","Button_default","Spinner_default","Input_default","Card_default","Avatar_default","AvatarFallback_default","AvatarImage_default","CardTitle_default","KanbanCard_default","KanbanColumnHeader_default","KanbanFilters_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","KanbanBoard_vue_vue_type_script_setup_true_lang_default","props","__props","runner","useActionRunner","page","usePageActionContext","panel","usePanel","t","useT","direction","useDirection","labelId","useId","instructionsId","controller","KanbanController","toRaw","notifications","showToast","notification","clientErrorNotification","message","router","url","filters","createKanbanFiltersStore","state","useStore","root","ref","cards","focused","search","detach","stopPolling","watch","board","value","onMounted","element","attachKanbanPointer","onBeforeUnmount","schema","computed","lanes","filtered","kanbanActiveFilters","keys","column","card","current","template","setCard","key","focus","nextTick","picked","onKeyDown","event","result","onSearch","laneCount","sum","kanbanCardsIn","lane","openBlock","createBlock","unref","withCtx","createElementVNode","createTextVNode","toDisplayString","createElementBlock","createCommentVNode","createVNode","SearchIcon","normalizeStyle","Fragment","renderList","ChevronRightIcon","normalizeClass","cn","kanbanInitials","$event"],"sources":["../../../src/components/kanban/KanbanBoard.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { KanbanEnvironment, KanbanSchema } from '@alfakit/core'\nimport {\n KanbanController,\n attachKanbanPointer,\n clientErrorNotification,\n createKanbanFiltersStore,\n kanbanActiveFilters,\n kanbanCardsIn,\n kanbanInitials,\n} from '@alfakit/core'\nimport { router } from '@inertiajs/vue3'\nimport { ChevronRightIcon, SearchIcon } from '@lucide/vue'\nimport { computed, nextTick, onBeforeUnmount, onMounted, ref, toRaw, useId, watch } from 'vue'\nimport { useStore } from '../../composables/use-store'\nimport { useActionRunner, useDirection, usePanel, useT } from '../../context'\nimport { Icon } from '../../lib/icons'\nimport { cn } from '../../lib/utils'\nimport { usePageActionContext } from '../actions/action-context'\nimport { showToast } from '../notifications/flash-toasts'\nimport Avatar from '../ui/Avatar.vue'\nimport AvatarFallback from '../ui/AvatarFallback.vue'\nimport AvatarImage from '../ui/AvatarImage.vue'\nimport Badge from '../ui/Badge.vue'\nimport Button from '../ui/Button.vue'\nimport Card from '../ui/Card.vue'\nimport CardTitle from '../ui/CardTitle.vue'\nimport Input from '../ui/Input.vue'\nimport Spinner from '../ui/Spinner.vue'\nimport KanbanCard from './KanbanCard.vue'\nimport KanbanColumnHeader from './KanbanColumnHeader.vue'\nimport KanbanFilters from './KanbanFilters.vue'\n\n/**\n * Cards move by dragging (mouse, pen, touch) or with the keyboard, and every move is\n * saved in one request.\n */\nconst props = defineProps<{ board: KanbanSchema }>()\n\nconst runner = useActionRunner()\nconst page = usePageActionContext()\nconst panel = usePanel()\nconst t = useT()\nconst direction = useDirection()\nconst labelId = useId()\nconst instructionsId = useId()\n\nconst environment = (): KanbanEnvironment => ({\n runner,\n token: page.token,\n t,\n notify: (notifications) => notifications.forEach((notification) => showToast(notification)),\n error: (message) => showToast(clientErrorNotification('kanban', message)),\n visit: (url) => router.visit(url),\n})\n\nconst controller = new KanbanController(toRaw(props.board), environment())\nconst filters = createKanbanFiltersStore(\n toRaw(props.board),\n page.token,\n panel.value.endpoints.schemaOptions,\n)\nconst state = useStore(controller.store)\nconst root = ref<{ $el: HTMLElement } | null>(null)\nconst cards = new Map<string, HTMLElement>()\nconst focused = ref<string | null>(null)\nconst search = ref(state.value.search)\nlet detach: (() => void) | null = null\nlet stopPolling: (() => void) | null = null\n\nwatch(\n () => props.board,\n (board) => controller.setBoard(toRaw(board)),\n)\nwatch(\n () => state.value.search,\n (value) => {\n if (value !== search.value) search.value = value\n },\n)\n\nonMounted(() => {\n const element = root.value?.$el\n\n if (element instanceof HTMLElement) detach = attachKanbanPointer(element, controller)\n\n stopPolling = controller.startPolling()\n})\n\nonBeforeUnmount(() => {\n detach?.()\n stopPolling?.()\n controller.destroy()\n filters?.destroy()\n})\n\nconst schema = computed(() => {\n // Re-read when the state changes (the controller swaps its schema with the board).\n void state.value.columns\n\n return controller.schema\n})\nconst lanes = computed(() => {\n void state.value.columns\n\n return controller.lanes()\n})\nconst filtered = computed(\n () => state.value.search !== '' || kanbanActiveFilters(state.value.filters) > 0,\n)\nconst keys = computed(() =>\n state.value.columns.flatMap((column) => column.cards.map((card) => card.key)),\n)\nconst current = computed(() =>\n focused.value !== null && keys.value.includes(focused.value)\n ? focused.value\n : (keys.value[0] ?? null),\n)\nconst template = computed(() =>\n state.value.columns\n .map((column) => (state.value.collapsed.has(column.key) ? '3.25rem' : 'minmax(16rem, 20rem)'))\n .join(' '),\n)\n\nconst setCard = (key: string) => (element: unknown) => {\n if (element instanceof HTMLElement) cards.set(key, element)\n else cards.delete(key)\n}\n\nconst focus = (key: string | undefined) => {\n if (!key) return\n focused.value = key\n void nextTick(() => cards.get(key)?.focus())\n}\n\n// A card picked up with the keyboard moves to another list: keep the focus on it.\nwatch(\n () => state.value.picked,\n (picked) => {\n if (picked?.via !== 'keyboard') return\n\n void nextTick(() => {\n const element = cards.get(picked.key)\n\n if (element && document.activeElement !== element) element.focus()\n })\n },\n)\n\nconst onKeyDown = (key: string, event: KeyboardEvent) => {\n if (event.target !== event.currentTarget) return\n\n const result = controller.handleKey(key, event, direction.value)\n\n if (!result.handled) return\n\n event.preventDefault()\n\n if (result.open) controller.open(key)\n else focus(result.focus)\n}\n\nconst onSearch = (value: string) => {\n search.value = value\n controller.setSearch(value)\n}\n\nconst laneCount = (lane: string) =>\n state.value.columns.reduce((sum, column) => sum + kanbanCardsIn(column, lane).length, 0)\n</script>\n\n<template>\n <Card ref=\"root\" role=\"region\" :aria-labelledby=\"labelId\" class=\"gap-3 py-4\" data-slot=\"kanban\">\n <div class=\"flex flex-wrap items-center gap-2 px-4\" data-slot=\"kanban-toolbar\">\n <CardTitle v-if=\"schema.heading\" :id=\"labelId\" class=\"text-base\">{{\n schema.heading\n }}</CardTitle>\n <span v-else :id=\"labelId\" class=\"sr-only\">{{ t('kanban.label', {}, 'Kanban board') }}</span>\n <div class=\"ms-auto flex w-full flex-wrap items-center gap-2 sm:w-auto\">\n <Spinner v-if=\"state.loading\" class=\"size-4\" />\n <div v-if=\"schema.searchable\" class=\"relative w-full sm:w-64\">\n <SearchIcon\n class=\"text-muted-foreground pointer-events-none absolute start-2.5 top-1/2 size-4 -translate-y-1/2\"\n aria-hidden=\"true\"\n />\n <Input\n type=\"search\"\n :model-value=\"search\"\n class=\"h-8 ps-8\"\n :placeholder=\"t('kanban.search_placeholder', {}, 'Search…')\"\n :aria-label=\"t('kanban.search', {}, 'Search cards')\"\n @update:model-value=\"onSearch\"\n />\n </div>\n <KanbanFilters v-if=\"filters\" :controller=\"controller\" :store=\"filters\" />\n </div>\n </div>\n <p :id=\"instructionsId\" class=\"sr-only\">\n {{\n t(\n 'kanban.instructions',\n {},\n 'Press Space to pick up a card. While it is picked up, use the arrow keys to move it, Space to drop it and Escape to cancel.',\n )\n }}\n </p>\n <div\n class=\"relative overflow-x-auto overscroll-x-contain px-4 pb-2\"\n data-slot=\"kanban-scroller\"\n >\n <div class=\"grid w-max min-w-full snap-x gap-3\" :style=\"{ gridTemplateColumns: template }\">\n <KanbanColumnHeader\n v-for=\"column in state.columns\"\n :id=\"`${labelId}-column-${column.key}`\"\n :key=\"column.key\"\n :column=\"column\"\n :collapsed=\"state.collapsed.has(column.key)\"\n :creatable=\"Boolean(column.creatable && schema.createAction)\"\n :filtered=\"filtered\"\n @toggle=\"controller.toggleColumn(column.key)\"\n @create=\"controller.create(column.key)\"\n />\n <template v-for=\"lane in lanes\" :key=\"lane?.key ?? '__board'\">\n <div\n v-if=\"lane\"\n class=\"flex items-center gap-2 pt-2\"\n style=\"grid-column: 1 / -1\"\n data-slot=\"kanban-lane\"\n :data-lane=\"lane.key\"\n >\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n :aria-expanded=\"!state.collapsedLanes.has(lane.key)\"\n :aria-label=\"\n state.collapsedLanes.has(lane.key)\n ? t('kanban.expand_lane', { lane: lane.label }, 'Expand row :lane')\n : t('kanban.collapse_lane', { lane: lane.label }, 'Collapse row :lane')\n \"\n @click=\"controller.toggleLane(lane.key)\"\n >\n <ChevronRightIcon\n :class=\"\n cn(\n 'transition-transform rtl:rotate-180',\n !state.collapsedLanes.has(lane.key) && 'rotate-90 rtl:rotate-90',\n )\n \"\n aria-hidden=\"true\"\n />\n </Button>\n <Avatar v-if=\"lane.avatar\" class=\"size-6\">\n <AvatarImage :src=\"lane.avatar\" alt=\"\" />\n <AvatarFallback>{{ kanbanInitials(lane.label) }}</AvatarFallback>\n </Avatar>\n <Icon v-else-if=\"lane.icon\" :name=\"lane.icon\" class=\"text-muted-foreground size-4\" />\n <span :id=\"`${labelId}-lane-${lane.key}`\" class=\"text-sm font-semibold\">{{\n lane.label\n }}</span>\n <Badge variant=\"secondary\" class=\"h-5 px-1.5 tabular-nums\">{{\n laneCount(lane.key)\n }}</Badge>\n </div>\n <template v-if=\"!lane || !state.collapsedLanes.has(lane.key)\">\n <ul\n v-for=\"column in state.columns\"\n :key=\"column.key\"\n role=\"list\"\n :aria-labelledby=\"\n [\n `${labelId}-column-${column.key}`,\n lane ? `${labelId}-lane-${lane.key}` : undefined,\n ]\n .filter(Boolean)\n .join(' ')\n \"\n data-slot=\"kanban-dropzone\"\n :data-column=\"column.key\"\n :data-lane=\"lane?.key\"\n :data-refused=\"state.picked && state.refused?.column === column.key ? '' : undefined\"\n :class=\"\n cn(\n 'bg-muted/40 flex min-h-24 flex-col gap-2 rounded-lg p-2',\n lane === null && 'max-h-[70vh] overflow-y-auto',\n )\n \"\n >\n <template v-if=\"!state.collapsed.has(column.key)\">\n <KanbanCard\n v-for=\"card in kanbanCardsIn(column, lane?.key ?? null)\"\n :key=\"card.key\"\n :card=\"card\"\n :board=\"schema\"\n :token=\"page.token\"\n :current=\"current === card.key\"\n :picked=\"state.picked?.key === card.key ? state.picked.via : undefined\"\n :saving=\"state.saving.has(card.key)\"\n :described-by=\"instructionsId\"\n :set-ref=\"setCard(card.key)\"\n @focus=\"focused = card.key\"\n @keydown=\"onKeyDown(card.key, $event)\"\n @open=\"controller.open(card.key)\"\n />\n <li\n v-if=\"kanbanCardsIn(column, lane?.key ?? null).length === 0\"\n class=\"text-muted-foreground rounded-md border border-dashed px-2 py-6 text-center text-xs\"\n data-slot=\"kanban-empty\"\n >\n {{\n filtered\n ? t('kanban.no_results', {}, 'No cards match')\n : (column.emptyState ?? t('kanban.empty', {}, 'No cards'))\n }}\n </li>\n <li\n v-if=\"lane === null && column.total > column.cards.length\"\n class=\"text-muted-foreground px-2 text-center text-xs\"\n >\n {{\n t(\n 'kanban.more_cards',\n { count: column.total - column.cards.length },\n '+:count more',\n )\n }}\n </li>\n </template>\n </ul>\n </template>\n </template>\n </div>\n </div>\n <div class=\"sr-only\" role=\"status\" aria-live=\"polite\">{{ state.announcement }}</div>\n </Card>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAqCA,IAAMqD,IAAQC,GAERC,KAASC,EAAgB,GACzBC,IAAOC,GAAqB,GAC5BC,KAAQC,EAAS,GACjBC,IAAIC,GAAK,GACTC,KAAYC,EAAa,GACzBC,IAAUC,EAAM,GAChBC,IAAiBD,EAAM,GAWvBE,IAAa,IAAIC,GAAiBC,EAAMjB,EAAM,KAAK,GATX;GAC5C;GACA,OAAOI,EAAK;GACZ;GACA,SAAS,MAAkBc,EAAc,SAAS,MAAiBC,EAAUC,CAAY,CAAC;GAC1F,QAAQ,MAAYD,EAAUE,GAAwB,UAAUC,CAAO,CAAC;GACxE,QAAQ,MAAQC,GAAO,MAAMC,CAAG;EAClC,CAEyE,GACnEC,IAAUC,GACdT,EAAMjB,EAAM,KAAK,GACjBI,EAAK,OACLE,GAAM,MAAM,UAAU,aACxB,GACMqB,IAAQC,GAASb,EAAW,KAAK,GACjCc,IAAOC,EAAiC,IAAI,GAC5CC,oBAAQ,IAAI,IAAyB,GACrCC,IAAUF,EAAmB,IAAI,GACjCG,IAASH,EAAIH,EAAM,MAAM,MAAM,GACjCO,IAA8B,MAC9BC,IAAmC;EAqBvC,AAnBAC,QACQpC,EAAM,QACX,MAAUe,EAAW,SAASE,EAAMoB,CAAK,CAAC,CAC7C,GACAD,QACQT,EAAM,MAAM,SACjB,MAAU;GACT,AAAIW,MAAUL,EAAO,UAAO,EAAO,QAAQK;EAC7C,CACF,GAEAC,SAAgB;GACd,IAAMC,IAAUX,EAAK,OAAO;GAI5B,AAFIW,aAAmB,gBAAa,IAASC,GAAoBD,GAASzB,CAAU,IAEpF,IAAcA,EAAW,aAAa;EACxC,CAAC,GAED2B,SAAsB;GAIpB,AAHAR,IAAS,GACTC,IAAc,GACdpB,EAAW,QAAQ,GACnBU,GAAS,QAAQ;EACnB,CAAC;EAED,IAAMkB,IAASC,SAEbjB,EAAW,MAAM,SAEVZ,EAAW,OACnB,GACK8B,KAAQD,SACZjB,EAAW,MAAM,SAEVZ,EAAW,MAAM,EACzB,GACK+B,IAAWF,QACTjB,EAAM,MAAM,WAAW,MAAMoB,GAAoBpB,EAAM,MAAM,OAAO,IAAI,CAChF,GACMqB,IAAOJ,QACXjB,EAAM,MAAM,QAAQ,SAAS,MAAWsB,EAAO,MAAM,KAAK,MAASC,EAAK,GAAG,CAAC,CAC9E,GACMC,KAAUP,QACdZ,EAAQ,UAAU,QAAQgB,EAAK,MAAM,SAAShB,EAAQ,KAAK,IACvDA,EAAQ,QACPgB,EAAK,MAAM,MAAM,IACxB,GACMI,KAAWR,QACfjB,EAAM,MAAM,QACT,KAAK,MAAYA,EAAM,MAAM,UAAU,IAAIsB,EAAO,GAAG,IAAI,YAAY,sBAAuB,CAAA,CAC5F,KAAK,GAAG,CACb,GAEMI,MAAW,OAAiB,MAAqB;GACrD,AAAIb,aAAmB,cAAaT,EAAM,IAAIuB,GAAKd,CAAO,IACrDT,EAAM,OAAOuB,CAAG;EACvB,GAEMC,MAAS,MAA4B;GACzC,AAAKD,MACL,EAAQ,QAAQA,GAChBE,QAAoBzB,EAAM,IAAIuB,CAAG,CAAC,EAAE,MAAM,CAAC;EAC7C;EAGA,QACQ3B,EAAM,MAAM,SACjB,MAAW;GACV,AAAI8B,GAAQ,QAAQ,cAEpBD,QAAoB;IAClB,IAAMhB,IAAUT,EAAM,IAAI0B,EAAO,GAAG;IAEpC,AAAIjB,KAAW,SAAS,kBAAkBA,KAASA,EAAQ,MAAM;GACnE,CAAC;EACH,CACF;EAEA,IAAMkB,MAAa,GAAa,MAAyB;GACvD,IAAIC,EAAM,WAAWA,EAAM,eAAe;GAE1C,IAAMC,IAAS7C,EAAW,UAAUuC,GAAKK,GAAOjD,GAAU,KAAK;GAE/D,AAAKkD,EAAO,YAEZD,EAAM,eAAe,GAEjBC,EAAO,OAAM7C,EAAW,KAAKuC,CAAG,IAC/BC,GAAMK,EAAO,KAAK;EACzB,GAEMC,MAAY,MAAkB;GAElC,AADA,EAAO,QAAQvB,GACfvB,EAAW,UAAUuB,CAAK;EAC5B,GAEMwB,MAAa,MACjBnC,EAAM,MAAM,QAAQ,QAAQ,GAAK,MAAWoC,IAAMC,EAAcf,GAAQgB,CAAI,CAAC,CAAC,QAAQ,CAAC;oBAIvFtH,EAAA,GAAAC,EAkKOC,IAAA;GAlKG,SAAA;GAAJ,KAAIgF;GAAO,MAAK;GAAU,mBAAiB/E,EAAA8D,CAAA;GAAS,OAAM;GAAa,aAAU;;GACrF,SAAA7D,QAuBM;IAvBNC,EAuBM,OAvBNmC,GAuBM,CAtBawD,EAAA,MAAO,WAAxBhG,EAAA,GAAAC,EAEcK,GAAA;;KAFoB,IAAIH,EAAA8D,CAAA;KAAS,OAAM;;KAAY,SAAA7D,QAE/D,CADAG,EAAAC,EAAAwF,EAAA,MAAO,OAAO,GAAA,CAAA,CAAA,CAAA;;IAEhBhG,GAAAA,GAAAA,CAAAA,IAAAA,CAAAA,MAAAA,EAAA,GAAAS,EAA6F,QAAA;;KAA/E,IAAIN,EAAA8D,CAAA;KAAS,OAAM;IAAa,GAAAzD,EAAAL,EAAA0D,CAAA,CAAC,CAAA,gBAAA,CAAA,GAAA,cAAA,CAAA,GAAA,GAAApB,EAAA,IAC/CpC,EAiBM,OAjBNqC,IAiBM;KAhBWvC,EAAA6E,CAAA,CAAK,CAAC,WAArBhF,EAAA,GAAAC,EAA+CS,IAAA;;MAAjB,OAAM;;KACzBsF,EAAA,MAAO,cAAlBhG,EAAA,GAAAS,EAaM,OAbNkC,IAaM,CAZJ/B,EAGET,EAAA8H,CAAA,GAAA;MAFA,OAAM;MACN,eAAY;KAEdrH,CAAAA,GAAAA,EAOEC,IAAA;MANA,MAAK;MACJ,eAAayE,EAAA;MACd,OAAM;MACL,aAAanF,EAAA0D,CAAA,CAAC,CAAA,6BAAA,CAAA,GAAA,SAAA;MACd,cAAY1D,EAAA0D,CAAA,CAAC,CAAA,iBAAA,CAAA,GAAA,cAAA;MACb,uBAAoBqD;;;;;;KAGJ/G,EAAA2E,CAAA,KAArB9E,EAAA,GAAAC,EAA0Ea,IAAA;;MAA3C,YAAYX,EAAAiE,CAAA;MAAa,OAAOjE,EAAA2E,CAAA;;;IAGnEzE,EAQI,KAAA;KARA,IAAIF,EAAAgE,CAAA;KAAgB,OAAM;IAE1B,GAAA3D,EAAAL,EAAA0D,CAAA,CAAC,CAAA,uBAAA,CAAA,GAAA,6HAAA,CAAA,GAAA,GAAAjB,EAAA;IAOLvC,EA8HM,OA9HNwC,IA8HM,CA1HJxC,EAyHM,OAAA;KAzHD,OAAM;KAAsC,OAAKU,GAAA,EAAA,qBAAyB0F,GAAA,MAAQ,CAAA;IACrFzG,GAAAA,EAAAA,EAAA,EAAA,GAAAS,EAUEO,GAAA,MAAAC,EATiBd,EAAA6E,CAAA,CAAK,CAAC,UAAhB,OADThF,EAAA,GAAAC,EAUEiB,GAAA;KARC,IAAE,GAAKf,EAAA8D,CAAA,EAAO,UAAWqC,EAAO;KAChC,KAAKA,EAAO;KACJ;KACR,WAAWnG,EAAA6E,CAAA,CAAK,CAAC,UAAU,IAAIsB,EAAO,GAAG;KACzC,WAAW,GAAQA,EAAO,aAAaN,EAAA,MAAO;KAC9C,UAAUG,EAAA;KACV,WAAM,MAAEhG,EAAAiE,CAAA,CAAU,CAAC,aAAakC,EAAO,GAAG;KAC1C,WAAM,MAAEnG,EAAAiE,CAAA,CAAU,CAAC,OAAOkC,EAAO,GAAG;;;;;;;;;OAEvCtG,GAAAA,GAAAA,KAAAA,EAAA,EAAA,GAAAS,EA4GWO,GAAA,MAAAC,EA5GciF,GAAA,QAAR,OAAqBqB,EAAA,GAAAO,EAAAK,GAAA,EAAA,KAAAb,GAAM,OAAG,UAAA,GAAA,CAErCA,KADRtH,EAAA,GAAAS,EAwCM,OAAA;;KAtCJ,OAAM;KACN,OAAA,EAAA,eAAA,SAAA;KACA,aAAU;KACT,aAAW6G,EAAK;;KAEjB1G,EAqBSO,GAAA;MApBP,MAAK;MACL,SAAQ;MACR,MAAK;MACJ,iBAAa,CAAGhB,EAAA6E,CAAA,CAAK,CAAC,eAAe,IAAIsC,EAAK,GAAG;MACjD,cAA6BnH,EAAA6E,CAAA,CAAK,CAAC,eAAe,IAAIsC,EAAK,GAAG,IAAsBnH,EAAA0D,CAAA,CAAC,CAAA,sBAAA,EAAA,MAA+ByD,EAAK,MAAK,GAAA,kBAAA,IAA4CnH,EAAA0D,CAAA,CAAC,CAAA,wBAAA,EAAA,MAAiCyD,EAAK,MAAK,GAAA,oBAAA;MAKtN,UAAK,MAAEnH,EAAAiE,CAAA,CAAU,CAAC,WAAWkD,EAAK,GAAG;;MAEtC,SAAAlH,QAQE,CARFQ,EAQET,EAAAkI,CAAA,GAAA;OAPC,OAAKjH,EAAqBjB,EAAAoI,CAAA,CAAE,CAAA,uCAAkF,CAAApI,EAAA6E,CAAA,CAAK,CAAC,eAAe,IAAIsC,EAAK,GAAG,KAAA,yBAAA,CAAA;OAMhJ,eAAY;;;;;;;;KAGFA,EAAK,UAAnBtH,EAAA,GAAAC,EAGSoB,GAAA;;MAHkB,OAAM;;MAC/B,SAAAjB,QAAyC,CAAzCQ,EAAyCU,GAAA;OAA3B,KAAKgG,EAAK;OAAQ,KAAI;MACpC1G,GAAAA,MAAAA,GAAAA,CAAAA,KAAAA,CAAAA,GAAAA,EAAiEW,GAAA,MAAA;OAAjD,SAAAnB,QAAgC,CAA7BG,EAAAC,EAAAL,EAAAqI,EAAA,CAAc,CAAClB,EAAK,KAAK,CAAA,GAAA,CAAA,CAAA,CAAA;;;;KAE7B,GAAA,IAAA,KAAAA,EAAK,QAAtBtH,EAAA,GAAAC,EAAqFE,EAAAqB,EAAA,GAAA;;MAAxD,MAAM8F,EAAK;MAAM,OAAM;;KACpDjH,EAES,QAAA;MAFF,IAAE,GAAKF,EAAA8D,CAAA,EAAO,QAASqD,EAAK;MAAO,OAAM;KAC9C,GAAA9G,EAAA8G,EAAK,KAAK,GAAA,GAAAvE,EAAA;KAEZnC,EAEUa,IAAA;MAFH,SAAQ;MAAY,OAAM;;MAA0B,SAAArB,QAEzD,CADAG,EAAAC,EAAA2G,GAAUG,EAAK,GAAG,CAAA,GAAA,CAAA,CAAA,CAAA;;;IAGL,GAAA,GAAAxE,CAAA,KAAAiF,EAAA,IAAA,EAAA,GAAA,CAAAT,KAAI,CAAKnH,EAAA6E,CAAA,CAAK,CAAC,eAAe,IAAIsC,EAAK,GAAG,KACzDtH,EAAA,EAAA,GAAAS,EA+DKO,GAAA,EAAA,KAAA,EAAA,GAAAC,EA9Dcd,EAAA6E,CAAA,CAAK,CAAC,UAAhB,OADThF,EAAA,GAAAS,EA+DK,MAAA;KA7DF,KAAK6F,EAAO;KACb,MAAK;KACJ,mBAAA,CAAyD,GAAAnG,EAAA8D,CAAA,EAAO,UAAWqC,EAAO,OAAyBgB,IAAI,GAAMnH,EAAA8D,CAAA,EAAO,QAASqD,EAAK,QAAQ,KAAA,CAAA,CAAA,CAAgD,OAAO,OAAO,CAAA,CAAqB,KAAI,GAAA;KAQ1O,aAAU;KACT,eAAahB,EAAO;KACpB,aAAWgB,GAAM;KACjB,gBAAcnH,EAAA6E,CAAA,CAAK,CAAC,UAAU7E,EAAA6E,CAAA,CAAK,CAAC,SAAS,WAAWsB,EAAO,MAAG,KAAQ,KAAA;KAC1E,OAAKlF,EAAmBjB,EAAAoI,CAAA,CAAE,CAAA,2DAAiGjB,MAAI,QAAA,8BAAA,CAAA;IAO/G,GAAA,CAAAnH,EAAA6E,CAAA,CAAK,CAAC,UAAU,IAAIsB,EAAO,GAAG,iBAA/CtG,EAAA,GAAAS,EAuCWO,GAAA,EAAA,KAAA,EAAA,GAAA;MAtCThB,EAAA,EAAA,GAAAS,EAcEO,GAAA,MAAAC,EAbed,EAAAkH,CAAA,CAAa,CAACf,GAAQgB,GAAM,OAAG,IAAA,IAAvC,OADTtH,EAAA,GAAAC,EAcEyB,GAAA;MAZC,KAAK6E,EAAK;MACJ;MACN,OAAOP,EAAA;MACP,OAAO7F,EAAAsD,CAAA,CAAI,CAAC;MACZ,SAAS+C,GAAA,UAAYD,EAAK;MAC1B,QAAQpG,EAAA6E,CAAA,CAAK,CAAC,QAAQ,QAAQuB,EAAK,MAAMpG,EAAA6E,CAAA,CAAK,CAAC,OAAO,MAAM,KAAA;MAC5D,QAAQ7E,EAAA6E,CAAA,CAAK,CAAC,OAAO,IAAIuB,EAAK,GAAG;MACjC,gBAAcpG,EAAAgE,CAAA;MACd,WAASuC,GAAQH,EAAK,GAAG;MACzB,UAAK,MAAE,EAAA,QAAUA,EAAK;MACtB,YAAO,MAAEQ,GAAUR,EAAK,KAAKkC,CAAM;MACnC,SAAI,MAAEtI,EAAAiE,CAAA,CAAU,CAAC,KAAKmC,EAAK,GAAG;;;;;;;;;;;;;;KAGzBpG,EAAAkH,CAAA,CAAa,CAACf,GAAQgB,GAAM,OAAG,IAAA,CAAA,CAAU,WAAM,KADvDtH,EAAA,GAAAS,EAUK,MAVLwC,IAUKzC,EAJD2F,EAAA,QAAiChG,EAAA0D,CAAA,CAAC,CAAA,qBAAA,CAAA,GAAA,gBAAA,IAAqEyC,EAAO,cAAcnG,EAAA0D,CAAA,CAAC,CAAA,gBAAA,CAAA,GAAA,UAAA,CAAA,GAAA,CAAA,KAAAkE,EAAA,IAAA,EAAA;KAMzHT,MAAI,QAAahB,EAAO,QAAQA,EAAO,MAAM,UADrDtG,EAAA,GAAAS,EAWK,MAXLyC,IAWK1C,EANDL,EAAA0D,CAAA,CAAC,CAAA,qBAA4E,EAAA,OAAAyC,EAAO,QAAQA,EAAO,MAAM,OAAM,GAAA,cAAA,CAAA,GAAA,CAAA,KAAAyB,EAAA,IAAA,EAAA;;IAa/H1H,EAAoF,OAApF8C,IAAoF3C,EAA3BL,EAAA6E,CAAA,CAAK,CAAC,YAAY,GAAA,CAAA"}
|
|
1
|
+
{"version":3,"file":"KanbanBoard.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createBlock","Card","_unref","_withCtx","_createElementVNode","CardTitle","_createTextVNode","_toDisplayString","_createElementBlock","Spinner","_createCommentVNode","_createVNode","Input","KanbanFilters","_normalizeStyle","_Fragment","_renderList","KanbanColumnHeader","Button","_normalizeClass","Avatar","AvatarImage","AvatarFallback","Icon","Badge","KanbanCard","Icon_default","Badge_default","Button_default","Spinner_default","Input_default","Card_default","Avatar_default","AvatarFallback_default","AvatarImage_default","CardTitle_default","KanbanCard_default","KanbanColumnHeader_default","KanbanFilters_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","KanbanBoard_vue_vue_type_script_setup_true_lang_default","props","__props","runner","useActionRunner","page","usePageActionContext","panel","usePanel","t","useT","direction","useDirection","labelId","useId","instructionsId","controller","KanbanController","toRaw","notifications","showToast","notification","clientErrorNotification","message","router","url","filters","createKanbanFiltersStore","state","useStore","root","ref","cards","focused","search","detach","stopPolling","watch","board","value","onMounted","element","attachKanbanPointer","onBeforeUnmount","schema","computed","lanes","filtered","kanbanActiveFilters","keys","column","card","current","template","setCard","own","key","focus","nextTick","picked","onKeyDown","event","result","onSearch","laneCount","sum","kanbanCardsIn","lane","openBlock","createBlock","unref","withCtx","createElementVNode","createTextVNode","toDisplayString","createElementBlock","createCommentVNode","createVNode","SearchIcon","normalizeStyle","Fragment","renderList","ChevronRightIcon","normalizeClass","cn","kanbanInitials","$event"],"sources":["../../../src/components/kanban/KanbanBoard.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { KanbanEnvironment, KanbanSchema } from '@alfakit/core'\nimport {\n KanbanController,\n attachKanbanPointer,\n clientErrorNotification,\n createKanbanFiltersStore,\n kanbanActiveFilters,\n kanbanCardsIn,\n kanbanInitials,\n} from '@alfakit/core'\nimport { router } from '@inertiajs/vue3'\nimport { ChevronRightIcon, SearchIcon } from '@lucide/vue'\nimport { computed, nextTick, onBeforeUnmount, onMounted, ref, toRaw, useId, watch } from 'vue'\nimport { useStore } from '../../composables/use-store'\nimport { useActionRunner, useDirection, usePanel, useT } from '../../context'\nimport { Icon } from '../../lib/icons'\nimport { cn } from '../../lib/utils'\nimport { usePageActionContext } from '../actions/action-context'\nimport { showToast } from '../notifications/flash-toasts'\nimport Avatar from '../ui/Avatar.vue'\nimport AvatarFallback from '../ui/AvatarFallback.vue'\nimport AvatarImage from '../ui/AvatarImage.vue'\nimport Badge from '../ui/Badge.vue'\nimport Button from '../ui/Button.vue'\nimport Card from '../ui/Card.vue'\nimport CardTitle from '../ui/CardTitle.vue'\nimport Input from '../ui/Input.vue'\nimport Spinner from '../ui/Spinner.vue'\nimport KanbanCard from './KanbanCard.vue'\nimport KanbanColumnHeader from './KanbanColumnHeader.vue'\nimport KanbanFilters from './KanbanFilters.vue'\n\n/**\n * Cards move by dragging (mouse, pen, touch) or with the keyboard, and every move is\n * saved in one request.\n */\nconst props = defineProps<{ board: KanbanSchema }>()\n\nconst runner = useActionRunner()\nconst page = usePageActionContext()\nconst panel = usePanel()\nconst t = useT()\nconst direction = useDirection()\nconst labelId = useId()\nconst instructionsId = useId()\n\nconst environment = (): KanbanEnvironment => ({\n runner,\n token: page.token,\n t,\n notify: (notifications) => notifications.forEach((notification) => showToast(notification)),\n error: (message) => showToast(clientErrorNotification('kanban', message)),\n visit: (url) => router.visit(url),\n})\n\nconst controller = new KanbanController(toRaw(props.board), environment())\nconst filters = createKanbanFiltersStore(\n toRaw(props.board),\n page.token,\n panel.value.endpoints.schemaOptions,\n)\nconst state = useStore(controller.store)\nconst root = ref<{ $el: HTMLElement } | null>(null)\nconst cards = new Map<string, HTMLElement>()\nconst focused = ref<string | null>(null)\nconst search = ref(state.value.search)\nlet detach: (() => void) | null = null\nlet stopPolling: (() => void) | null = null\n\nwatch(\n () => props.board,\n (board) => controller.setBoard(toRaw(board)),\n)\nwatch(\n () => state.value.search,\n (value) => {\n if (value !== search.value) search.value = value\n },\n)\n\nonMounted(() => {\n const element = root.value?.$el\n\n if (element instanceof HTMLElement) detach = attachKanbanPointer(element, controller)\n\n stopPolling = controller.startPolling()\n})\n\nonBeforeUnmount(() => {\n detach?.()\n stopPolling?.()\n controller.destroy()\n filters?.destroy()\n})\n\nconst schema = computed(() => {\n // Re-read when the state changes (the controller swaps its schema with the board).\n void state.value.columns\n\n return controller.schema\n})\nconst lanes = computed(() => {\n void state.value.columns\n\n return controller.lanes()\n})\nconst filtered = computed(\n () => state.value.search !== '' || kanbanActiveFilters(state.value.filters) > 0,\n)\nconst keys = computed(() =>\n state.value.columns.flatMap((column) => column.cards.map((card) => card.key)),\n)\nconst current = computed(() =>\n focused.value !== null && keys.value.includes(focused.value)\n ? focused.value\n : (keys.value[0] ?? null),\n)\nconst template = computed(() =>\n state.value.columns\n .map((column) => (state.value.collapsed.has(column.key) ? '3.25rem' : 'minmax(16rem, 20rem)'))\n .join(' '),\n)\n\n// A card moved to another column is mounted there before its old element is unmounted, so\n// an unmount only forgets the element it registered itself (else the moved card would lose\n// its entry and the keyboard focus).\nconst setCard = (key: string) => {\n let own: HTMLElement | null = null\n\n return (element: unknown) => {\n if (element instanceof HTMLElement) {\n own = element\n cards.set(key, element)\n } else if (own !== null) {\n if (cards.get(key) === own) cards.delete(key)\n own = null\n }\n }\n}\n\nconst focus = (key: string | undefined) => {\n if (!key) return\n focused.value = key\n void nextTick(() => cards.get(key)?.focus())\n}\n\n// A card picked up with the keyboard moves to another list: keep the focus on it.\nwatch(\n () => state.value.picked,\n (picked) => {\n if (picked?.via !== 'keyboard') return\n\n void nextTick(() => {\n const element = cards.get(picked.key)\n\n if (element && document.activeElement !== element) element.focus()\n })\n },\n)\n\nconst onKeyDown = (key: string, event: KeyboardEvent) => {\n if (event.target !== event.currentTarget) return\n\n const result = controller.handleKey(key, event, direction.value)\n\n if (!result.handled) return\n\n event.preventDefault()\n\n if (result.open) controller.open(key)\n else focus(result.focus)\n}\n\nconst onSearch = (value: string) => {\n search.value = value\n controller.setSearch(value)\n}\n\nconst laneCount = (lane: string) =>\n state.value.columns.reduce((sum, column) => sum + kanbanCardsIn(column, lane).length, 0)\n</script>\n\n<template>\n <Card ref=\"root\" role=\"region\" :aria-labelledby=\"labelId\" class=\"gap-3 py-4\" data-slot=\"kanban\">\n <div class=\"flex flex-wrap items-center gap-2 px-4\" data-slot=\"kanban-toolbar\">\n <CardTitle v-if=\"schema.heading\" :id=\"labelId\" class=\"text-base\">{{\n schema.heading\n }}</CardTitle>\n <span v-else :id=\"labelId\" class=\"sr-only\">{{ t('kanban.label', {}, 'Kanban board') }}</span>\n <div class=\"ms-auto flex w-full flex-wrap items-center gap-2 sm:w-auto\">\n <Spinner v-if=\"state.loading\" class=\"size-4\" />\n <div v-if=\"schema.searchable\" class=\"relative w-full sm:w-64\">\n <SearchIcon\n class=\"text-muted-foreground pointer-events-none absolute start-2.5 top-1/2 size-4 -translate-y-1/2\"\n aria-hidden=\"true\"\n />\n <Input\n type=\"search\"\n :model-value=\"search\"\n class=\"h-8 ps-8\"\n :placeholder=\"t('kanban.search_placeholder', {}, 'Search…')\"\n :aria-label=\"t('kanban.search', {}, 'Search cards')\"\n @update:model-value=\"onSearch\"\n />\n </div>\n <KanbanFilters v-if=\"filters\" :controller=\"controller\" :store=\"filters\" />\n </div>\n </div>\n <p :id=\"instructionsId\" class=\"sr-only\">\n {{\n t(\n 'kanban.instructions',\n {},\n 'Press Space to pick up a card. While it is picked up, use the arrow keys to move it, Space to drop it and Escape to cancel.',\n )\n }}\n </p>\n <div\n class=\"relative overflow-x-auto overscroll-x-contain px-4 pb-2\"\n data-slot=\"kanban-scroller\"\n >\n <div class=\"grid w-max min-w-full snap-x gap-3\" :style=\"{ gridTemplateColumns: template }\">\n <KanbanColumnHeader\n v-for=\"column in state.columns\"\n :id=\"`${labelId}-column-${column.key}`\"\n :key=\"column.key\"\n :column=\"column\"\n :collapsed=\"state.collapsed.has(column.key)\"\n :creatable=\"Boolean(column.creatable && schema.createAction)\"\n :filtered=\"filtered\"\n @toggle=\"controller.toggleColumn(column.key)\"\n @create=\"controller.create(column.key)\"\n />\n <template v-for=\"lane in lanes\" :key=\"lane?.key ?? '__board'\">\n <div\n v-if=\"lane\"\n class=\"flex items-center gap-2 pt-2\"\n style=\"grid-column: 1 / -1\"\n data-slot=\"kanban-lane\"\n :data-lane=\"lane.key\"\n >\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n :aria-expanded=\"!state.collapsedLanes.has(lane.key)\"\n :aria-label=\"\n state.collapsedLanes.has(lane.key)\n ? t('kanban.expand_lane', { lane: lane.label }, 'Expand row :lane')\n : t('kanban.collapse_lane', { lane: lane.label }, 'Collapse row :lane')\n \"\n @click=\"controller.toggleLane(lane.key)\"\n >\n <ChevronRightIcon\n :class=\"\n cn(\n 'transition-transform rtl:rotate-180',\n !state.collapsedLanes.has(lane.key) && 'rotate-90 rtl:rotate-90',\n )\n \"\n aria-hidden=\"true\"\n />\n </Button>\n <Avatar v-if=\"lane.avatar\" class=\"size-6\">\n <AvatarImage :src=\"lane.avatar\" alt=\"\" />\n <AvatarFallback>{{ kanbanInitials(lane.label) }}</AvatarFallback>\n </Avatar>\n <Icon v-else-if=\"lane.icon\" :name=\"lane.icon\" class=\"text-muted-foreground size-4\" />\n <span :id=\"`${labelId}-lane-${lane.key}`\" class=\"text-sm font-semibold\">{{\n lane.label\n }}</span>\n <Badge variant=\"secondary\" class=\"h-5 px-1.5 tabular-nums\">{{\n laneCount(lane.key)\n }}</Badge>\n </div>\n <template v-if=\"!lane || !state.collapsedLanes.has(lane.key)\">\n <ul\n v-for=\"column in state.columns\"\n :key=\"column.key\"\n role=\"list\"\n :aria-labelledby=\"\n [\n `${labelId}-column-${column.key}`,\n lane ? `${labelId}-lane-${lane.key}` : undefined,\n ]\n .filter(Boolean)\n .join(' ')\n \"\n data-slot=\"kanban-dropzone\"\n :data-column=\"column.key\"\n :data-lane=\"lane?.key\"\n :data-refused=\"state.picked && state.refused?.column === column.key ? '' : undefined\"\n :class=\"\n cn(\n 'bg-muted/40 flex min-h-24 flex-col gap-2 rounded-lg p-2',\n lane === null && 'max-h-[70vh] overflow-y-auto',\n )\n \"\n >\n <template v-if=\"!state.collapsed.has(column.key)\">\n <KanbanCard\n v-for=\"card in kanbanCardsIn(column, lane?.key ?? null)\"\n :key=\"card.key\"\n :card=\"card\"\n :board=\"schema\"\n :token=\"page.token\"\n :current=\"current === card.key\"\n :picked=\"state.picked?.key === card.key ? state.picked.via : undefined\"\n :saving=\"state.saving.has(card.key)\"\n :described-by=\"instructionsId\"\n :set-ref=\"setCard(card.key)\"\n @focus=\"focused = card.key\"\n @keydown=\"onKeyDown(card.key, $event)\"\n @open=\"controller.open(card.key)\"\n />\n <li\n v-if=\"kanbanCardsIn(column, lane?.key ?? null).length === 0\"\n class=\"text-muted-foreground rounded-md border border-dashed px-2 py-6 text-center text-xs\"\n data-slot=\"kanban-empty\"\n >\n {{\n filtered\n ? t('kanban.no_results', {}, 'No cards match')\n : (column.emptyState ?? t('kanban.empty', {}, 'No cards'))\n }}\n </li>\n <li\n v-if=\"lane === null && column.total > column.cards.length\"\n class=\"text-muted-foreground px-2 text-center text-xs\"\n >\n {{\n t(\n 'kanban.more_cards',\n { count: column.total - column.cards.length },\n '+:count more',\n )\n }}\n </li>\n </template>\n </ul>\n </template>\n </template>\n </div>\n </div>\n <div class=\"sr-only\" role=\"status\" aria-live=\"polite\">{{ state.announcement }}</div>\n </Card>\n</template>\n"],"mappings":"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"}
|