@modufolio/panel 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +165 -0
  3. package/dist/Builder/ImageNodeView.d.ts +33 -0
  4. package/dist/Builder/document.d.ts +17 -0
  5. package/dist/Builder/dragHandle.d.ts +13 -0
  6. package/dist/Builder/editing.d.ts +53 -0
  7. package/dist/Builder/plugins.d.ts +27 -0
  8. package/dist/Builder/schema.d.ts +20 -0
  9. package/dist/Components/Actions/Action.vue.d.ts +116 -0
  10. package/dist/Components/Actions/ActionGroup.vue.d.ts +25 -0
  11. package/dist/Components/Actions/ActionGroupItem.vue.d.ts +48 -0
  12. package/dist/Components/Auth/ForgotPassword.vue.d.ts +17 -0
  13. package/dist/Components/Auth/Login.vue.d.ts +33 -0
  14. package/dist/Components/Auth/ResetPassword.vue.d.ts +27 -0
  15. package/dist/Components/Auth/TwoFactor.vue.d.ts +32 -0
  16. package/dist/Components/Auth/TwoFactorVerify.vue.d.ts +31 -0
  17. package/dist/Components/Columns/BadgeColumn.vue.d.ts +34 -0
  18. package/dist/Components/Columns/BooleanColumn.vue.d.ts +78 -0
  19. package/dist/Components/Columns/CellActions.vue.d.ts +34 -0
  20. package/dist/Components/Columns/ColorColumn.vue.d.ts +84 -0
  21. package/dist/Components/Columns/CopyButton.vue.d.ts +15 -0
  22. package/dist/Components/Columns/DateColumn.vue.d.ts +60 -0
  23. package/dist/Components/Columns/IconColumn.vue.d.ts +56 -0
  24. package/dist/Components/Columns/ImageColumn.vue.d.ts +46 -0
  25. package/dist/Components/Columns/SelectColumn.vue.d.ts +71 -0
  26. package/dist/Components/Columns/TextColumn.vue.d.ts +69 -0
  27. package/dist/Components/Columns/TextInputColumn.vue.d.ts +75 -0
  28. package/dist/Components/Columns/ToggleColumn.vue.d.ts +91 -0
  29. package/dist/Components/Columns/TreeColumn.vue.d.ts +60 -0
  30. package/dist/Components/Columns/columnRegistry.d.ts +6 -0
  31. package/dist/Components/Composables/useInlineEdit.d.ts +27 -0
  32. package/dist/Components/Composables/useRelationship.d.ts +38 -0
  33. package/dist/Components/Core/Badge.vue.d.ts +47 -0
  34. package/dist/Components/Core/Button.vue.d.ts +131 -0
  35. package/dist/Components/Core/Dropdown.vue.d.ts +24 -0
  36. package/dist/Components/Core/Empty.vue.d.ts +54 -0
  37. package/dist/Components/Core/ErrorBoundary.vue.d.ts +24 -0
  38. package/dist/Components/Core/FlashMessages.vue.d.ts +7 -0
  39. package/dist/Components/Core/Icon.vue.d.ts +23 -0
  40. package/dist/Components/Core/Icons/DocumentLinesIcon.vue.d.ts +3 -0
  41. package/dist/Components/Core/Icons/SitemapIcon.vue.d.ts +3 -0
  42. package/dist/Components/Core/Label.vue.d.ts +52 -0
  43. package/dist/Components/Core/LoadingButton.vue.d.ts +18 -0
  44. package/dist/Components/Core/Modal.vue.d.ts +26 -0
  45. package/dist/Components/Core/Pagination.vue.d.ts +10 -0
  46. package/dist/Components/Core/SelectInput.vue.d.ts +26 -0
  47. package/dist/Components/Core/Tag.vue.d.ts +65 -0
  48. package/dist/Components/Core/TextInput.vue.d.ts +25 -0
  49. package/dist/Components/Core/iconRegistry.d.ts +3 -0
  50. package/dist/Components/Dialogs/ConfirmDialog.vue.d.ts +16 -0
  51. package/dist/Components/Dialogs/DeleteConfirmDialog.vue.d.ts +30 -0
  52. package/dist/Components/Dialogs/Dialog.vue.d.ts +81 -0
  53. package/dist/Components/Drawer/Drawer.vue.d.ts +130 -0
  54. package/dist/Components/Drawer/DrawerFieldGrid.vue.d.ts +39 -0
  55. package/dist/Components/Drawer/DrawerLink.vue.d.ts +96 -0
  56. package/dist/Components/Drawer/DrawerRelationList.vue.d.ts +81 -0
  57. package/dist/Components/Drawer/DrawerStack.vue.d.ts +93 -0
  58. package/dist/Components/Drawer/DrawerTabs.vue.d.ts +42 -0
  59. package/dist/Components/Drawer/NestedDrawerForm.vue.d.ts +55 -0
  60. package/dist/Components/Drawer/drawerFieldGrid.d.ts +25 -0
  61. package/dist/Components/Drawer/drawerTabs.d.ts +16 -0
  62. package/dist/Components/Drawer/useDrawerPage.d.ts +34 -0
  63. package/dist/Components/Drawer/useDrawerStack.d.ts +93 -0
  64. package/dist/Components/Drawer/useFocusedStackRow.d.ts +22 -0
  65. package/dist/Components/Drawer/useIsDrawer.d.ts +66 -0
  66. package/dist/Components/Drawer/visitDrawer.d.ts +48 -0
  67. package/dist/Components/Fields/BelongsToSelect.vue.d.ts +247 -0
  68. package/dist/Components/Fields/BlueprintForm.vue.d.ts +96 -0
  69. package/dist/Components/Fields/Calendar/CalendarPanel.vue.d.ts +63 -0
  70. package/dist/Components/Fields/Calendar/MonthGrid.vue.d.ts +82 -0
  71. package/dist/Components/Fields/CheckboxField.vue.d.ts +92 -0
  72. package/dist/Components/Fields/ColorPickerField.vue.d.ts +105 -0
  73. package/dist/Components/Fields/DatePickerField.vue.d.ts +102 -0
  74. package/dist/Components/Fields/DateRangePickerField.vue.d.ts +138 -0
  75. package/dist/Components/Fields/DateTimePickerField.vue.d.ts +134 -0
  76. package/dist/Components/Fields/FieldGrid.vue.d.ts +13 -0
  77. package/dist/Components/Fields/FileUploadField.vue.d.ts +117 -0
  78. package/dist/Components/Fields/MultiSelectField.vue.d.ts +129 -0
  79. package/dist/Components/Fields/ProseMirrorBuilderField.vue.d.ts +71 -0
  80. package/dist/Components/Fields/RangeField.vue.d.ts +122 -0
  81. package/dist/Components/Fields/RepeaterField.vue.d.ts +174 -0
  82. package/dist/Components/Fields/RichTextEditorField.vue.d.ts +118 -0
  83. package/dist/Components/Fields/SelectField.vue.d.ts +102 -0
  84. package/dist/Components/Fields/TagsField.vue.d.ts +102 -0
  85. package/dist/Components/Fields/TextField.vue.d.ts +138 -0
  86. package/dist/Components/Fields/TextareaField.vue.d.ts +111 -0
  87. package/dist/Components/Fields/TimePickerField.vue.d.ts +115 -0
  88. package/dist/Components/Fields/ToggleButtonsField.vue.d.ts +93 -0
  89. package/dist/Components/Fields/ToggleField.vue.d.ts +95 -0
  90. package/dist/Components/Fields/fieldRegistry.d.ts +25 -0
  91. package/dist/Components/Fields/fieldsFromSpec.d.ts +10 -0
  92. package/dist/Components/Fields/useBlueprint.d.ts +94 -0
  93. package/dist/Components/Fields/useFieldWidth.d.ts +10 -0
  94. package/dist/Components/Fields/validation.d.ts +43 -0
  95. package/dist/Components/Filters/DateRangeFilter.vue.d.ts +92 -0
  96. package/dist/Components/Filters/FacetedFilter.vue.d.ts +41 -0
  97. package/dist/Components/Filters/FilterIndicators.vue.d.ts +40 -0
  98. package/dist/Components/Filters/FilterPopover.vue.d.ts +38 -0
  99. package/dist/Components/Filters/MultiSelectFilter.vue.d.ts +51 -0
  100. package/dist/Components/Filters/NumberFilter.vue.d.ts +61 -0
  101. package/dist/Components/Filters/QueryBuilder.vue.d.ts +32 -0
  102. package/dist/Components/Filters/SelectFilter.vue.d.ts +61 -0
  103. package/dist/Components/Filters/TernaryFilter.vue.d.ts +73 -0
  104. package/dist/Components/Layout/AppLayout.vue.d.ts +137 -0
  105. package/dist/Components/Layout/Breadcrumbs.vue.d.ts +44 -0
  106. package/dist/Components/Layout/Cluster.vue.d.ts +88 -0
  107. package/dist/Components/Layout/Container.vue.d.ts +69 -0
  108. package/dist/Components/Layout/Grid.vue.d.ts +110 -0
  109. package/dist/Components/Layout/PageHeader.vue.d.ts +62 -0
  110. package/dist/Components/Layout/Sidebar.vue.d.ts +59 -0
  111. package/dist/Components/Layout/Stack.vue.d.ts +69 -0
  112. package/dist/Components/Layout/TopNavigation.vue.d.ts +124 -0
  113. package/dist/Components/Media/MediaPickerDialog.vue.d.ts +20 -0
  114. package/dist/Components/Media/mediaEndpoints.d.ts +18 -0
  115. package/dist/Components/Notifications/Toast.vue.d.ts +17 -0
  116. package/dist/Components/Notifications/useToast.d.ts +43 -0
  117. package/dist/Components/Relations/RelationManager.vue.d.ts +232 -0
  118. package/dist/Components/Sections/FieldsSection.vue.d.ts +56 -0
  119. package/dist/Components/Sections/FilesSection.vue.d.ts +120 -0
  120. package/dist/Components/Sections/FormSection.vue.d.ts +111 -0
  121. package/dist/Components/Sections/InfoSection.vue.d.ts +77 -0
  122. package/dist/Components/Sections/Section.vue.d.ts +67 -0
  123. package/dist/Components/Table/ColumnToggle.vue.d.ts +42 -0
  124. package/dist/Components/Table/ExportButton.vue.d.ts +93 -0
  125. package/dist/Components/Table/SchemaCell.d.ts +50 -0
  126. package/dist/Components/Table/SchemaFilterPanel.vue.d.ts +64 -0
  127. package/dist/Components/Table/SchemaTable.vue.d.ts +255 -0
  128. package/dist/Components/Table/Table.vue.d.ts +232 -0
  129. package/dist/Components/Table/TableEmptyState.vue.d.ts +24 -0
  130. package/dist/Components/Table/TablePagination.vue.d.ts +71 -0
  131. package/dist/Components/Table/TableSkeletonRows.vue.d.ts +52 -0
  132. package/dist/Components/Table/TableSortButton.vue.d.ts +38 -0
  133. package/dist/Components/Table/TableToolbar.vue.d.ts +62 -0
  134. package/dist/Components/Table/schemaLinks.d.ts +16 -0
  135. package/dist/Components/Table/tableSchema.d.ts +243 -0
  136. package/dist/Components/Table/tableTypes.d.ts +13 -0
  137. package/dist/Components/Table/useSchemaActions.d.ts +82 -0
  138. package/dist/Components/Table/useSchemaFilters.d.ts +28 -0
  139. package/dist/Components/Table/useTableExport.d.ts +16 -0
  140. package/dist/Components/Table/useTableGrouping.d.ts +9 -0
  141. package/dist/Components/Table/useTableRowFocus.d.ts +27 -0
  142. package/dist/Components/Table/useTableSelection.d.ts +15 -0
  143. package/dist/Components/Table/useTableTree.d.ts +23 -0
  144. package/dist/Components/Widgets/StatCard.vue.d.ts +81 -0
  145. package/dist/Components/Widgets/StatsWidget.vue.d.ts +27 -0
  146. package/dist/Components/Wizard/Wizard.vue.d.ts +99 -0
  147. package/dist/Composables/useAsyncData.d.ts +48 -0
  148. package/dist/Composables/useDeleteConfirmation.d.ts +86 -0
  149. package/dist/Composables/useDragReorder.d.ts +12 -0
  150. package/dist/Composables/useFieldSaver.d.ts +15 -0
  151. package/dist/Composables/useFocusTrap.d.ts +5 -0
  152. package/dist/Composables/useLocalStoragePersistence.d.ts +18 -0
  153. package/dist/Composables/useNestedDrawerForm.d.ts +58 -0
  154. package/dist/Composables/usePagination.d.ts +23 -0
  155. package/dist/Composables/usePendingKeys.d.ts +30 -0
  156. package/dist/Composables/useQuery.d.ts +61 -0
  157. package/dist/Composables/useReconciled.d.ts +22 -0
  158. package/dist/Composables/useUnsavedChangesWarning.d.ts +16 -0
  159. package/dist/Primitives/hideOthers.d.ts +12 -0
  160. package/dist/Primitives/teleportTarget.d.ts +2 -0
  161. package/dist/Primitives/useAnchoredPosition.d.ts +32 -0
  162. package/dist/Primitives/useArrowNavigation.d.ts +30 -0
  163. package/dist/Primitives/useBodyScrollLock.d.ts +9 -0
  164. package/dist/Primitives/useDismissableLayer.d.ts +46 -0
  165. package/dist/Primitives/useId.d.ts +13 -0
  166. package/dist/Primitives/useTypeahead.d.ts +11 -0
  167. package/dist/Utils/apiFetch.d.ts +28 -0
  168. package/dist/Utils/csrf.d.ts +2 -0
  169. package/dist/Utils/dates.d.ts +50 -0
  170. package/dist/Utils/moduleSingleton.d.ts +21 -0
  171. package/dist/Utils/optimistic.d.ts +33 -0
  172. package/dist/Utils/reconcile.d.ts +17 -0
  173. package/dist/Utils/tagsChanged.d.ts +16 -0
  174. package/dist/Utils/url.d.ts +40 -0
  175. package/dist/Utils/writeGate.d.ts +82 -0
  176. package/dist/index.css +1 -0
  177. package/dist/index.d.ts +157 -0
  178. package/dist/index.js +27193 -0
  179. package/dist/index.js.map +1 -0
  180. package/dist/injectionKeys.d.ts +10 -0
  181. package/dist/plugin.d.ts +36 -0
  182. package/dist/types/menu.d.ts +11 -0
  183. package/docs/async-writes.md +159 -0
  184. package/docs/custom-fields.md +71 -0
  185. package/docs/drawer-protocol.md +130 -0
  186. package/docs/overlays.md +106 -0
  187. package/docs/relation-fields.md +112 -0
  188. package/docs/roadmap.md +38 -0
  189. package/docs/table-schema.md +371 -0
  190. package/package.json +150 -0
  191. package/styles/buttons.css +31 -0
  192. package/styles/form.css +74 -0
  193. package/styles/index.css +15 -0
  194. package/styles/tokens.css +79 -0
@@ -0,0 +1,27 @@
1
+ import { TableRecord } from './tableTypes';
2
+ interface RowFocusOptions {
3
+ /** -1 means "nothing external is driving the highlight". */
4
+ externalIndex: () => number;
5
+ loading: () => boolean;
6
+ bulkActionsEnabled: () => boolean;
7
+ /** The rendered rows, which is what an index refers to. */
8
+ visibleRecords: () => TableRecord[];
9
+ toggleSelect: (record: TableRecord) => void;
10
+ onActivate: (record: TableRecord) => void;
11
+ /** Root element, so focus stays inside this table when several are mounted. */
12
+ root: () => HTMLElement | null;
13
+ }
14
+ /**
15
+ * Keyboard navigation and the highlighted row.
16
+ *
17
+ * The highlight lags the index deliberately: a drawer opening or a record
18
+ * paginating pushes several indexes through in quick succession, and moving
19
+ * the highlight for each one reads as a flicker.
20
+ */
21
+ export declare function useTableRowFocus(options: RowFocusOptions): {
22
+ focusedRowIndex: import('vue').ComputedRef<number>;
23
+ stableFocusedRowIndex: import('vue').Ref<number, number>;
24
+ handleTableKeyDown: (event: KeyboardEvent) => void;
25
+ handleRowFocus: (index: number) => void;
26
+ };
27
+ export {};
@@ -0,0 +1,15 @@
1
+ import { Ref } from 'vue';
2
+ import { TableRecord } from './tableTypes';
3
+ /**
4
+ * Row selection for the bulk-actions bar.
5
+ *
6
+ * Records are held by identity rather than by id: a table's rows are the very
7
+ * objects handed to it, so nothing has to know which field is the key.
8
+ */
9
+ export declare function useTableSelection(records: () => TableRecord[]): {
10
+ selectedRecords: Ref<TableRecord[], TableRecord[]>;
11
+ allSelected: import('vue').ComputedRef<boolean>;
12
+ isSelected: (record: TableRecord) => boolean;
13
+ toggleSelect: (record: TableRecord) => void;
14
+ toggleSelectAll: () => void;
15
+ };
@@ -0,0 +1,23 @@
1
+ import { TableRecord } from './tableTypes';
2
+ interface TreeOptions {
3
+ /** Off for tables whose records are a flat list. */
4
+ enabled: () => boolean;
5
+ records: () => TableRecord[];
6
+ /** Field on each record holding its nesting level (0 = top-level). */
7
+ depthKey: () => string;
8
+ }
9
+ /**
10
+ * Collapsible hierarchy for tables whose records arrive in depth-first order
11
+ * (a page tree, say). Parentage is read off the depth of the *next* row, so
12
+ * nothing needs a parent id.
13
+ */
14
+ export declare function useTableTree({ enabled, records, depthKey }: TreeOptions): {
15
+ collapsedRecords: import('vue').Reactive<Set<TableRecord>>;
16
+ treeParents: import('vue').ComputedRef<Set<TableRecord>>;
17
+ showTreeToggle: import('vue').ComputedRef<boolean>;
18
+ allTreeCollapsed: import('vue').ComputedRef<boolean>;
19
+ visibleRecords: import('vue').ComputedRef<TableRecord[]>;
20
+ toggleCollapse: (record: TableRecord) => void;
21
+ toggleAllTree: () => void;
22
+ };
23
+ export {};
@@ -0,0 +1,81 @@
1
+ declare var __VLS_11: {};
2
+ type __VLS_Slots = {} & {
3
+ default?: (props: typeof __VLS_11) => any;
4
+ };
5
+ declare const __VLS_base: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
6
+ label: {
7
+ type: StringConstructor;
8
+ required: true;
9
+ };
10
+ value: {
11
+ type: (StringConstructor | NumberConstructor)[];
12
+ required: true;
13
+ };
14
+ description: {
15
+ type: StringConstructor;
16
+ default: string;
17
+ };
18
+ change: {
19
+ type: NumberConstructor;
20
+ default: null;
21
+ };
22
+ icon: {
23
+ type: (StringConstructor | ObjectConstructor)[];
24
+ default: null;
25
+ };
26
+ format: {
27
+ type: StringConstructor;
28
+ default: string;
29
+ validator: (value: unknown) => boolean;
30
+ };
31
+ color: {
32
+ type: StringConstructor;
33
+ default: string;
34
+ validator: (value: unknown) => boolean;
35
+ };
36
+ }>, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
37
+ label: {
38
+ type: StringConstructor;
39
+ required: true;
40
+ };
41
+ value: {
42
+ type: (StringConstructor | NumberConstructor)[];
43
+ required: true;
44
+ };
45
+ description: {
46
+ type: StringConstructor;
47
+ default: string;
48
+ };
49
+ change: {
50
+ type: NumberConstructor;
51
+ default: null;
52
+ };
53
+ icon: {
54
+ type: (StringConstructor | ObjectConstructor)[];
55
+ default: null;
56
+ };
57
+ format: {
58
+ type: StringConstructor;
59
+ default: string;
60
+ validator: (value: unknown) => boolean;
61
+ };
62
+ color: {
63
+ type: StringConstructor;
64
+ default: string;
65
+ validator: (value: unknown) => boolean;
66
+ };
67
+ }>> & Readonly<{}>, {
68
+ color: string;
69
+ change: number;
70
+ description: string;
71
+ format: string;
72
+ icon: string | Record<string, any>;
73
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
74
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
75
+ declare const _default: typeof __VLS_export;
76
+ export default _default;
77
+ type __VLS_WithSlots<T, S> = T & {
78
+ new (): {
79
+ $slots: S;
80
+ };
81
+ };
@@ -0,0 +1,27 @@
1
+ declare var __VLS_1: {};
2
+ type __VLS_Slots = {} & {
3
+ default?: (props: typeof __VLS_1) => any;
4
+ };
5
+ declare const __VLS_base: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
6
+ columns: {
7
+ type: NumberConstructor;
8
+ default: number;
9
+ validator: (value: unknown) => boolean;
10
+ };
11
+ }>, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
12
+ columns: {
13
+ type: NumberConstructor;
14
+ default: number;
15
+ validator: (value: unknown) => boolean;
16
+ };
17
+ }>> & Readonly<{}>, {
18
+ columns: number;
19
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
20
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
21
+ declare const _default: typeof __VLS_export;
22
+ export default _default;
23
+ type __VLS_WithSlots<T, S> = T & {
24
+ new (): {
25
+ $slots: S;
26
+ };
27
+ };
@@ -0,0 +1,99 @@
1
+ import { PropType } from 'vue';
2
+ interface WizardStep {
3
+ label: string;
4
+ description?: string;
5
+ disabled?: boolean;
6
+ }
7
+ declare var __VLS_2: `step-${number}`, __VLS_3: {
8
+ currentStep: number;
9
+ stepIndex: number;
10
+ };
11
+ type __VLS_Slots = {} & {
12
+ [K in NonNullable<typeof __VLS_2>]?: (props: typeof __VLS_3) => any;
13
+ };
14
+ declare const __VLS_base: import('vue').DefineComponent<import('vue').ExtractPropTypes<{
15
+ steps: {
16
+ type: PropType<WizardStep[]>;
17
+ required: true;
18
+ validator: (steps: unknown) => boolean;
19
+ };
20
+ modelValue: {
21
+ type: NumberConstructor;
22
+ default: number;
23
+ };
24
+ skippable: {
25
+ type: BooleanConstructor;
26
+ default: boolean;
27
+ };
28
+ submitting: {
29
+ type: BooleanConstructor;
30
+ default: boolean;
31
+ };
32
+ submitLabel: {
33
+ type: StringConstructor;
34
+ default: string;
35
+ };
36
+ showCancel: {
37
+ type: BooleanConstructor;
38
+ default: boolean;
39
+ };
40
+ cancelLabel: {
41
+ type: StringConstructor;
42
+ default: string;
43
+ };
44
+ }>, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
45
+ "update:modelValue": (...args: any[]) => void;
46
+ submit: (...args: any[]) => void;
47
+ cancel: (...args: any[]) => void;
48
+ "step-change": (...args: any[]) => void;
49
+ }, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
50
+ steps: {
51
+ type: PropType<WizardStep[]>;
52
+ required: true;
53
+ validator: (steps: unknown) => boolean;
54
+ };
55
+ modelValue: {
56
+ type: NumberConstructor;
57
+ default: number;
58
+ };
59
+ skippable: {
60
+ type: BooleanConstructor;
61
+ default: boolean;
62
+ };
63
+ submitting: {
64
+ type: BooleanConstructor;
65
+ default: boolean;
66
+ };
67
+ submitLabel: {
68
+ type: StringConstructor;
69
+ default: string;
70
+ };
71
+ showCancel: {
72
+ type: BooleanConstructor;
73
+ default: boolean;
74
+ };
75
+ cancelLabel: {
76
+ type: StringConstructor;
77
+ default: string;
78
+ };
79
+ }>> & Readonly<{
80
+ "onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
81
+ onSubmit?: ((...args: any[]) => any) | undefined;
82
+ onCancel?: ((...args: any[]) => any) | undefined;
83
+ "onStep-change"?: ((...args: any[]) => any) | undefined;
84
+ }>, {
85
+ modelValue: number;
86
+ submitting: boolean;
87
+ showCancel: boolean;
88
+ submitLabel: string;
89
+ cancelLabel: string;
90
+ skippable: boolean;
91
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
92
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
93
+ declare const _default: typeof __VLS_export;
94
+ export default _default;
95
+ type __VLS_WithSlots<T, S> = T & {
96
+ new (): {
97
+ $slots: S;
98
+ };
99
+ };
@@ -0,0 +1,48 @@
1
+ import { Ref, WatchSource } from 'vue';
2
+ /**
3
+ * Reactive async-data primitive — the panel's standard way to run a fetch and
4
+ * expose its lifecycle. Inspired by Solid's `createResource`: one place owns
5
+ * `{ data, loading, error }`, requests are guarded against stale/post-teardown
6
+ * resolution, and cleanup is automatic via the current effect scope.
7
+ *
8
+ * The fetcher receives a `{ signal }` context first (pass it to `apiFetch` so
9
+ * a superseded or torn-down request is actually cancelled, not just ignored),
10
+ * then whatever arguments `execute` was called with:
11
+ *
12
+ * const { data, loading, error, execute } = useAsyncData(
13
+ * ({ signal }, id: number) => apiFetch(`/panel/api/tags/media/${id}`, { signal }),
14
+ * )
15
+ * await execute(mediaId)
16
+ *
17
+ * Errors are captured on `error` (and passed to `onError`) rather than thrown,
18
+ * so callers can branch on `error.value` without a try/catch at every site.
19
+ * An abort is not an error: it never touches `error` or `onError`.
20
+ */
21
+ /** Per-request context handed to the fetcher. */
22
+ export interface FetchContext {
23
+ /** Aborted when the request is superseded or the owning scope is disposed. */
24
+ signal: AbortSignal;
25
+ }
26
+ export declare function isAbortError(err: unknown): boolean;
27
+ export interface UseAsyncDataOptions<T> {
28
+ /** Run the fetcher once on creation (with no arguments). Default false. */
29
+ immediate?: boolean;
30
+ /** Seed value for `data` before the first successful fetch. */
31
+ initialData?: T | null;
32
+ /** Refetch (re-running the last call) whenever any source changes. */
33
+ watch?: WatchSource | WatchSource[];
34
+ /** Called with the error when a fetch rejects. */
35
+ onError?: (error: unknown) => void;
36
+ }
37
+ export interface UseAsyncData<T, A extends unknown[]> {
38
+ data: Ref<T | null>;
39
+ error: Ref<unknown>;
40
+ loading: Ref<boolean>;
41
+ /** Run the fetcher with the given args; resolves with the data (or null on error). */
42
+ execute: (...args: A) => Promise<T | null>;
43
+ /** Re-run the fetcher with the arguments from the last `execute` call. */
44
+ refresh: () => Promise<T | null>;
45
+ /** Optimistically set `data` locally (value or updater), e.g. before a write. */
46
+ mutate: (updater: (T | null) | ((current: T | null) => T | null)) => void;
47
+ }
48
+ export declare function useAsyncData<T, A extends unknown[] = []>(fetcher: (ctx: FetchContext, ...args: A) => Promise<T>, options?: UseAsyncDataOptions<T>): UseAsyncData<T, A>;
@@ -0,0 +1,86 @@
1
+ /**
2
+ * One record's deletion, from "are you sure?" to done.
3
+ *
4
+ * A bare confirm() asks the user to guarantee something only the server knows.
5
+ * Given a `previewUrl`, this asks the server first and hands the answer to the
6
+ * dialog: what would go with the record, or what is protecting it. Without one
7
+ * it degrades to a plain confirmation — which is what a page with no preview
8
+ * endpoint had anyway, now at least consistent with the rest of the panel.
9
+ *
10
+ * Deliberately not tied to generated resources: most pages that delete things
11
+ * are hand-written, and they are the ones still calling confirm().
12
+ */
13
+ export interface DeletionPlan {
14
+ blocked: boolean;
15
+ /** Human labels of the records standing in the way. */
16
+ protected?: string[];
17
+ /** Nested tree of what would be deleted. */
18
+ nested?: Array<{
19
+ label: string;
20
+ type?: string;
21
+ children?: any[];
22
+ }>;
23
+ counts?: Record<string, number>;
24
+ linkCounts?: Record<string, number>;
25
+ /** True when the record is only trashed, so nothing is at stake. */
26
+ soft?: boolean;
27
+ }
28
+ export interface DeleteConfirmationState<T = any> {
29
+ open: boolean;
30
+ record: T | null;
31
+ plan: DeletionPlan | null;
32
+ /** The preview is in flight. */
33
+ loading: boolean;
34
+ /** The delete itself is in flight. */
35
+ deleting: boolean;
36
+ error: string | null;
37
+ }
38
+ export interface UseDeleteConfirmationOptions<T = any> {
39
+ /**
40
+ * Where to ask what deleting `record` would do. Omit for a plain
41
+ * confirmation.
42
+ */
43
+ previewUrl?: (record: T) => string;
44
+ /**
45
+ * A plan stated up front, for a page whose server has no preview endpoint
46
+ * but whose behaviour is known anyway — most usefully `{ soft: true }` when
47
+ * the delete is reversible. Without it the dialog says "cannot be undone",
48
+ * which for a soft delete is a lie in the frightening direction.
49
+ *
50
+ * Ignored when `previewUrl` is given: the server's answer wins over a guess.
51
+ */
52
+ plan?: DeletionPlan | ((record: T) => DeletionPlan);
53
+ /** Performs the delete once confirmed. */
54
+ onConfirm: (record: T) => void | Promise<void>;
55
+ /** Shown when there is no preview to describe consequences with. */
56
+ message?: (record: T) => string;
57
+ }
58
+ export declare function useDeleteConfirmation<T = any>(options: UseDeleteConfirmationOptions<T>): {
59
+ state: {
60
+ open: boolean;
61
+ record: import('vue').UnwrapRef<T> | null;
62
+ plan: {
63
+ blocked: boolean;
64
+ protected?: string[]
65
+ /** Nested tree of what would be deleted. */
66
+ | undefined;
67
+ nested?: {
68
+ label: string;
69
+ type?: string | undefined;
70
+ children?: any[] | undefined;
71
+ }[] | undefined;
72
+ counts?: Record<string, number> | undefined;
73
+ linkCounts?: Record<string, number>
74
+ /** True when the record is only trashed, so nothing is at stake. */
75
+ | undefined;
76
+ soft?: boolean | undefined;
77
+ } | null;
78
+ loading: boolean;
79
+ deleting: boolean;
80
+ error: string | null;
81
+ };
82
+ request: (record: T) => Promise<void>;
83
+ confirm: () => Promise<void>;
84
+ close: () => void;
85
+ message: ((record: T) => string) | undefined;
86
+ };
@@ -0,0 +1,12 @@
1
+ import { Ref } from 'vue';
2
+ /**
3
+ * Composable for drag-and-drop reordering of items.
4
+ *
5
+ * @param itemsRef - The reactive array of items to reorder
6
+ * @param onReorder - Callback when reorder happens, receives the new order
7
+ */
8
+ export declare function useDragReorder<T>(itemsRef: Ref<T[]>, onReorder?: (items: T[]) => void): {
9
+ dragSourceIndex: Ref<number | null>;
10
+ dragOverIndex: Ref<number | null>;
11
+ handleDrop: (targetIndex: number) => void;
12
+ };
@@ -0,0 +1,15 @@
1
+ import { Ref } from 'vue';
2
+ export type SaveStatus = null | 'saving' | 'saved' | 'error';
3
+ export interface UseFieldSaver<A extends unknown[]> {
4
+ saveStatus: Ref<SaveStatus>;
5
+ save: (...args: A) => Promise<void>;
6
+ debouncedSave: (...args: A) => void;
7
+ }
8
+ /**
9
+ * Save a form field with debouncing and transient status tracking.
10
+ *
11
+ * The debounce timer and the "reset status to idle" timer are kept separate so
12
+ * they can't cancel each other, and both are cleared when the owning scope is
13
+ * disposed so a trailing save/reset can't run against an unmounted component.
14
+ */
15
+ export declare function useFieldSaver<A extends unknown[] = unknown[]>(saveFunction: (...args: A) => Promise<unknown>, debounceMs?: number): UseFieldSaver<A>;
@@ -0,0 +1,5 @@
1
+ import { Ref } from 'vue';
2
+ export declare function useFocusTrap(containerRef: Ref<HTMLElement | null>): {
3
+ activate: () => void;
4
+ deactivate: () => void;
5
+ };
@@ -0,0 +1,18 @@
1
+ import { Ref } from 'vue';
2
+ interface UseLocalStoragePersistenceOptions<T> {
3
+ key: string;
4
+ defaultValue: T;
5
+ serialize?: (value: T) => string;
6
+ deserialize?: (value: string) => T;
7
+ onError?: (error: Error) => void;
8
+ }
9
+ interface UseLocalStoragePersistenceReturn<T> {
10
+ value: Ref<T>;
11
+ setValue: (newValue: T) => void;
12
+ removeValue: () => void;
13
+ }
14
+ /**
15
+ * Generic composable for persisting reactive values to localStorage with error handling
16
+ */
17
+ export declare function useLocalStoragePersistence<T>({ key, defaultValue, serialize, deserialize, onError, }: UseLocalStoragePersistenceOptions<T>): UseLocalStoragePersistenceReturn<T>;
18
+ export {};
@@ -0,0 +1,58 @@
1
+ import { ComputedRef, Ref } from 'vue';
2
+ export interface FieldConfig {
3
+ name: string;
4
+ label: string;
5
+ type: 'text' | 'email' | 'select' | 'textarea' | 'number' | 'hidden' | 'date' | 'time' | 'datetime' | 'checkbox';
6
+ placeholder?: string;
7
+ required?: boolean;
8
+ maxlength?: number;
9
+ /** Bounds for date/time/datetime inputs, in the input's own value format. */
10
+ min?: string;
11
+ max?: string;
12
+ options?: Array<{
13
+ value: string | number;
14
+ label: string;
15
+ }>;
16
+ grid?: 'full' | 'half';
17
+ }
18
+ export interface FormState {
19
+ visible: boolean;
20
+ saving: boolean;
21
+ mode: 'create' | 'edit';
22
+ /**
23
+ * Identifier of the record the form hangs off, and of the row being edited.
24
+ *
25
+ * Both accept strings: a parent is addressed by uuid in this panel, and only
26
+ * some children keep a numeric id. These were typed `number`, which every
27
+ * caller had always violated — the contact uuid is a string — and nothing
28
+ * caught it until the drawer's tab declaration made the call sites explicit.
29
+ */
30
+ parentId: string | number | null;
31
+ recordId: string | number | null;
32
+ [key: string]: unknown;
33
+ }
34
+ export interface UseNestedDrawerFormReturn {
35
+ state: FormState;
36
+ errors: Ref<Record<string, string>>;
37
+ serverError: Ref<string | null>;
38
+ isValid: () => boolean;
39
+ openForm: (parentId: string | number, recordId?: string | number, initialData?: Record<string, unknown>) => void;
40
+ closeForm: () => void;
41
+ resetForm: () => void;
42
+ getFormData: () => Record<string, unknown>;
43
+ /**
44
+ * True while the open form holds edits that have not been submitted —
45
+ * what an "unsaved changes" guard asks before letting a navigation
46
+ * (including Logout) discard them. False whenever the form is closed:
47
+ * a closed form's leftover state is not something the user can see or
48
+ * lose. Also false while a submit is in flight, for the same reason.
49
+ */
50
+ isDirty: ComputedRef<boolean>;
51
+ setFieldValue: (field: string, value: unknown) => void;
52
+ submit: (onSubmit: (data: Record<string, unknown>, mode: 'create' | 'edit') => Promise<void>) => Promise<void>;
53
+ }
54
+ /**
55
+ * Composable for managing nested drawer form state and submission
56
+ * Handles form visibility, validation, and data submission
57
+ */
58
+ export declare function useNestedDrawerForm(fields: FieldConfig[], defaultValues?: Record<string, unknown>): UseNestedDrawerFormReturn;
@@ -0,0 +1,23 @@
1
+ import { Ref, ComputedRef } from 'vue';
2
+ type PaginationItem = {
3
+ type: 'page';
4
+ key: string;
5
+ value: number;
6
+ } | {
7
+ type: 'ellipsis';
8
+ key: string;
9
+ };
10
+ interface UsePaginationOptions {
11
+ pagination: Ref<{
12
+ total?: number;
13
+ totalPages?: number;
14
+ }>;
15
+ currentPage: Ref<number>;
16
+ onNavigate: (page: number) => void;
17
+ }
18
+ interface UsePaginationReturn {
19
+ paginationItems: ComputedRef<PaginationItem[]>;
20
+ goToPage: (page: number) => void;
21
+ }
22
+ export declare function usePagination(options: UsePaginationOptions): UsePaginationReturn;
23
+ export {};
@@ -0,0 +1,30 @@
1
+ import { ComputedRef } from 'vue';
2
+ /**
3
+ * Keyed in-flight tracking: which records have a request running right now.
4
+ *
5
+ * One boolean per component answers "is anything saving"; a list needs "is
6
+ * *this row* saving", or every row shows the same spinner and a double-click
7
+ * on row A blocks row B. Keying the pending state is the difference —
8
+ * the same reason frappe-ui's write actions expose `isLoading(name)` rather
9
+ * than a bare flag.
10
+ *
11
+ * const { isPending, run } = usePendingKeys()
12
+ * const toggle = (file) => run(file.id, async () => { ... })
13
+ * // template: <Spinner v-if="isPending(file.id)" />
14
+ *
15
+ * `run` also guards re-entry: a key with a request in flight refuses a
16
+ * second one, which is what a double-click should mean.
17
+ */
18
+ export interface UsePendingKeys<K = string | number> {
19
+ /** True while `run` is executing for this key. */
20
+ isPending: (key: K) => boolean;
21
+ /** True while anything at all is in flight. */
22
+ anyPending: ComputedRef<boolean>;
23
+ /**
24
+ * Execute `fn` tracked under `key`. Resolves with its result, or with
25
+ * `undefined` when the key was already pending and the call was refused.
26
+ * Rejections propagate after the key is released.
27
+ */
28
+ run: <T>(key: K, fn: () => Promise<T>) => Promise<T | undefined>;
29
+ }
30
+ export declare function usePendingKeys<K = string | number>(): UsePendingKeys<K>;
@@ -0,0 +1,61 @@
1
+ import { Ref } from 'vue';
2
+ import { FetchContext } from './useAsyncData';
3
+ /**
4
+ * Keyed server-state cache — `useAsyncData` plus sharing. Components that ask
5
+ * for the same key share one `data` ref, one in-flight request and one cached
6
+ * result, with stale-while-revalidate semantics: a new subscriber gets the
7
+ * cached value instantly while a background refetch runs. Fresh payloads are
8
+ * `reconcile`d into the cached object in place, so identity survives
9
+ * revalidation and only effects reading changed fields re-run.
10
+ *
11
+ * const counts = useQuery('library:counts',
12
+ * ({ signal }) => apiFetch('/panel/api/library/counts', { signal }))
13
+ *
14
+ * Keys are hierarchical by convention (`'tags:search:cats'`);
15
+ * `invalidateQueries('tags')` marks `tags` and every `tags:*` entry stale and
16
+ * refetches the ones with live subscribers. Call it after a mutation that
17
+ * changes what a query would return.
18
+ */
19
+ type Fetcher<T> = (ctx: FetchContext) => Promise<T>;
20
+ export interface UseQueryOptions<T> {
21
+ /**
22
+ * How long (ms) a cached result is served without a background revalidation
23
+ * when a new subscriber appears. Default 0: always revalidate (SWR).
24
+ */
25
+ staleTime?: number;
26
+ /** Seed value for `data` before the first successful fetch. */
27
+ initialData?: T;
28
+ }
29
+ export interface UseQueryReturn<T> {
30
+ data: Ref<T | null>;
31
+ error: Ref<unknown>;
32
+ /** True only during the first fetch, before any data exists. */
33
+ loading: Ref<boolean>;
34
+ /** True whenever a fetch (including a background revalidation) is running. */
35
+ fetching: Ref<boolean>;
36
+ /** Fetch now (deduped against an already in-flight request). */
37
+ refresh: () => Promise<void>;
38
+ /** Optimistically set the shared cached data (value or updater). */
39
+ mutate: (updater: (T | null) | ((current: T | null) => T | null)) => void;
40
+ }
41
+ export declare function useQuery<T>(key: string, fetcher: Fetcher<T>, options?: UseQueryOptions<T>): UseQueryReturn<T>;
42
+ /**
43
+ * Mark matching queries stale and refetch the ones that currently have
44
+ * subscribers. `key` matches itself and everything below it (`key` and
45
+ * `key:*`); omit it to invalidate everything.
46
+ *
47
+ * If a matching entry is already fetching, its in-flight request is left
48
+ * alone (not aborted) and exactly one follow-up fetch is queued for once it
49
+ * settles — so any number of invalidate calls arriving in a burst (e.g. one
50
+ * per file in a batch upload, each firing on its own network completion)
51
+ * coalesce into at most one extra request per entry, instead of each call
52
+ * aborting and restarting the previous one. The returned promise resolves
53
+ * once every matching entry's current fetch (in-flight or freshly started)
54
+ * settles — for an entry that gets coalesced, that's the in-flight fetch,
55
+ * not the queued follow-up; nothing in the app depends on finer-grained
56
+ * timing than that.
57
+ */
58
+ export declare function invalidateQueries(key?: string): Promise<void>;
59
+ /** Drop every cache entry. Intended for tests. */
60
+ export declare function clearQueryCache(): void;
61
+ export {};
@@ -0,0 +1,22 @@
1
+ import { Ref } from 'vue';
2
+ /**
3
+ * A locally-mutable reactive copy of server-provided data that stays in sync
4
+ * without losing identity.
5
+ *
6
+ * Replaces the `reactive({ ...props.media })` + `watch(() => props.media, …)`
7
+ * rebuild pattern: when `source` changes (Inertia re-sends the prop) the new
8
+ * data is reconciled into the existing copy in place, so unchanged rows keep
9
+ * their object identity and transient UI state survives navigation.
10
+ *
11
+ * const media = useReconciled(() => props.media)
12
+ * media.value.rating = 5 // local edits are fine
13
+ * // …server re-sends props.media → reconciled in, local identity preserved
14
+ */
15
+ export declare function useReconciled<T extends object>(source: () => T, key?: string): Ref<T>;
16
+ /**
17
+ * Like {@link useReconciled} but returns a `reactive` object instead of a ref —
18
+ * a drop-in replacement for `reactive({ ...props.x })` that additionally stays
19
+ * in sync with the source. Access members directly (`state.title`) with no
20
+ * `.value`.
21
+ */
22
+ export declare function useReconciledReactive<T extends object>(source: () => T, key?: string): T;