@omnitend/dashboard-for-laravel 0.4.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +397 -0
- package/dist/components/base/DAccordion.vue.d.ts +12 -0
- package/dist/components/base/DAccordionItem.vue.d.ts +12 -0
- package/dist/components/base/DAlert.vue.d.ts +12 -0
- package/dist/components/base/DAvatar.vue.d.ts +12 -0
- package/dist/components/base/DBadge.vue.d.ts +12 -0
- package/dist/components/base/DBreadcrumb.vue.d.ts +12 -0
- package/dist/components/base/DButton.vue.d.ts +29 -0
- package/dist/components/base/DButtonGroup.vue.d.ts +12 -0
- package/dist/components/base/DButtonToolbar.vue.d.ts +12 -0
- package/dist/components/base/DCard.vue.d.ts +12 -0
- package/dist/components/base/DCarousel.vue.d.ts +12 -0
- package/dist/components/base/DCarouselSlide.vue.d.ts +12 -0
- package/dist/components/base/DCol.vue.d.ts +12 -0
- package/dist/components/base/DCollapse.vue.d.ts +12 -0
- package/dist/components/base/DContainer.vue.d.ts +12 -0
- package/dist/components/base/DDropdown.vue.d.ts +12 -0
- package/dist/components/base/DDropdownDivider.vue.d.ts +2 -0
- package/dist/components/base/DDropdownItem.vue.d.ts +12 -0
- package/dist/components/base/DForm.vue.d.ts +12 -0
- package/dist/components/base/DFormCheckbox.vue.d.ts +12 -0
- package/dist/components/base/DFormGroup.vue.d.ts +12 -0
- package/dist/components/base/DFormInput.vue.d.ts +2 -0
- package/dist/components/base/DFormInvalidFeedback.vue.d.ts +12 -0
- package/dist/components/base/DFormRadio.vue.d.ts +12 -0
- package/dist/components/base/DFormSelect.vue.d.ts +12 -0
- package/dist/components/base/DFormSpinbutton.vue.d.ts +12 -0
- package/dist/components/base/DFormTags.vue.d.ts +12 -0
- package/dist/components/base/DFormText.vue.d.ts +12 -0
- package/dist/components/base/DFormTextarea.vue.d.ts +2 -0
- package/dist/components/base/DImage.vue.d.ts +12 -0
- package/dist/components/base/DInputGroup.vue.d.ts +12 -0
- package/dist/components/base/DLink.vue.d.ts +12 -0
- package/dist/components/base/DListGroup.vue.d.ts +12 -0
- package/dist/components/base/DListGroupItem.vue.d.ts +12 -0
- package/dist/components/base/DModal.vue.d.ts +12 -0
- package/dist/components/base/DNav.vue.d.ts +12 -0
- package/dist/components/base/DNavItem.vue.d.ts +12 -0
- package/dist/components/base/DNavbar.vue.d.ts +12 -0
- package/dist/components/base/DNavbarBrand.vue.d.ts +12 -0
- package/dist/components/base/DNavbarNav.vue.d.ts +12 -0
- package/dist/components/base/DNavbarToggle.vue.d.ts +12 -0
- package/dist/components/base/DOffcanvas.vue.d.ts +12 -0
- package/dist/components/base/DOverlay.vue.d.ts +12 -0
- package/dist/components/base/DPagination.vue.d.ts +2 -0
- package/dist/components/base/DPlaceholder.vue.d.ts +12 -0
- package/dist/components/base/DPopover.vue.d.ts +12 -0
- package/dist/components/base/DProgress.vue.d.ts +12 -0
- package/dist/components/base/DRow.vue.d.ts +12 -0
- package/dist/components/base/DSpinner.vue.d.ts +2 -0
- package/dist/components/base/DTab.vue.d.ts +12 -0
- package/dist/components/base/DTable.vue.d.ts +26 -0
- package/dist/components/base/DTabs.vue.d.ts +12 -0
- package/dist/components/base/DToast.vue.d.ts +12 -0
- package/dist/components/base/DToaster.vue.d.ts +12 -0
- package/dist/components/base/DTooltip.vue.d.ts +12 -0
- package/dist/components/extended/DXBasicForm.vue.d.ts +39 -0
- package/dist/components/extended/DXDashboard.vue.d.ts +52 -0
- package/dist/components/extended/DXDashboardNavbar.vue.d.ts +53 -0
- package/dist/components/extended/DXDashboardSidebar.vue.d.ts +37 -0
- package/dist/components/extended/DXForm.vue.d.ts +31 -0
- package/dist/components/extended/DXTable.vue.d.ts +190 -0
- package/dist/composables/defineForm.d.ts +35 -0
- package/dist/composables/useForm.d.ts +46 -0
- package/dist/composables/useToast.d.ts +1 -0
- package/dist/dashboard-for-laravel.js +17748 -0
- package/dist/dashboard-for-laravel.js.map +1 -0
- package/dist/dashboard-for-laravel.umd.cjs +11 -0
- package/dist/dashboard-for-laravel.umd.cjs.map +1 -0
- package/dist/index.d.ts +73 -0
- package/dist/style.css +5 -0
- package/dist/types/index.d.ts +37 -0
- package/dist/types/navigation.d.ts +17 -0
- package/dist/utils/api.d.ts +30 -0
- package/docs/public/api-reference.json +1932 -0
- package/docs/public/docs-map.md +85 -0
- package/docs/public/llms.txt +110 -0
- package/package.json +116 -0
- package/resources/css/theme.scss +219 -0
- package/resources/js/components/base/DAccordion.vue +21 -0
- package/resources/js/components/base/DAccordionItem.vue +14 -0
- package/resources/js/components/base/DAlert.vue +14 -0
- package/resources/js/components/base/DAvatar.vue +21 -0
- package/resources/js/components/base/DBadge.vue +14 -0
- package/resources/js/components/base/DBreadcrumb.vue +21 -0
- package/resources/js/components/base/DButton.vue +58 -0
- package/resources/js/components/base/DButtonGroup.vue +21 -0
- package/resources/js/components/base/DButtonToolbar.vue +21 -0
- package/resources/js/components/base/DCard.vue +35 -0
- package/resources/js/components/base/DCarousel.vue +21 -0
- package/resources/js/components/base/DCarouselSlide.vue +14 -0
- package/resources/js/components/base/DCol.vue +14 -0
- package/resources/js/components/base/DCollapse.vue +34 -0
- package/resources/js/components/base/DContainer.vue +14 -0
- package/resources/js/components/base/DDropdown.vue +16 -0
- package/resources/js/components/base/DDropdownDivider.vue +7 -0
- package/resources/js/components/base/DDropdownItem.vue +14 -0
- package/resources/js/components/base/DForm.vue +21 -0
- package/resources/js/components/base/DFormCheckbox.vue +14 -0
- package/resources/js/components/base/DFormGroup.vue +11 -0
- package/resources/js/components/base/DFormInput.vue +7 -0
- package/resources/js/components/base/DFormInvalidFeedback.vue +16 -0
- package/resources/js/components/base/DFormRadio.vue +21 -0
- package/resources/js/components/base/DFormSelect.vue +14 -0
- package/resources/js/components/base/DFormSpinbutton.vue +21 -0
- package/resources/js/components/base/DFormTags.vue +21 -0
- package/resources/js/components/base/DFormText.vue +16 -0
- package/resources/js/components/base/DFormTextarea.vue +7 -0
- package/resources/js/components/base/DImage.vue +21 -0
- package/resources/js/components/base/DInputGroup.vue +21 -0
- package/resources/js/components/base/DLink.vue +21 -0
- package/resources/js/components/base/DListGroup.vue +21 -0
- package/resources/js/components/base/DListGroupItem.vue +14 -0
- package/resources/js/components/base/DModal.vue +11 -0
- package/resources/js/components/base/DNav.vue +14 -0
- package/resources/js/components/base/DNavItem.vue +14 -0
- package/resources/js/components/base/DNavbar.vue +21 -0
- package/resources/js/components/base/DNavbarBrand.vue +14 -0
- package/resources/js/components/base/DNavbarNav.vue +14 -0
- package/resources/js/components/base/DNavbarToggle.vue +14 -0
- package/resources/js/components/base/DOffcanvas.vue +11 -0
- package/resources/js/components/base/DOverlay.vue +21 -0
- package/resources/js/components/base/DPagination.vue +7 -0
- package/resources/js/components/base/DPlaceholder.vue +21 -0
- package/resources/js/components/base/DPopover.vue +21 -0
- package/resources/js/components/base/DProgress.vue +21 -0
- package/resources/js/components/base/DRow.vue +14 -0
- package/resources/js/components/base/DSpinner.vue +7 -0
- package/resources/js/components/base/DTab.vue +14 -0
- package/resources/js/components/base/DTable.vue +62 -0
- package/resources/js/components/base/DTabs.vue +21 -0
- package/resources/js/components/base/DToast.vue +16 -0
- package/resources/js/components/base/DToaster.vue +16 -0
- package/resources/js/components/base/DTooltip.vue +21 -0
- package/resources/js/components/extended/DXBasicForm.vue +177 -0
- package/resources/js/components/extended/DXDashboard.vue +208 -0
- package/resources/js/components/extended/DXDashboardNavbar.vue +112 -0
- package/resources/js/components/extended/DXDashboardSidebar.vue +233 -0
- package/resources/js/components/extended/DXForm.vue +44 -0
- package/resources/js/components/extended/DXTable.vue +1345 -0
- package/resources/js/composables/defineForm.ts +78 -0
- package/resources/js/composables/useForm.ts +272 -0
- package/resources/js/composables/useToast.ts +1 -0
- package/resources/js/index.ts +118 -0
- package/resources/js/types/index.ts +61 -0
- package/resources/js/types/navigation.ts +19 -0
- package/resources/js/utils/api.ts +182 -0
- package/scripts/mcp-server.mjs +359 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { useForm, type UseFormReturn } from "./useForm";
|
|
2
|
+
import type { FieldDefinition, FieldType } from "../types";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Extended field definition that includes default value
|
|
6
|
+
*/
|
|
7
|
+
export interface FormFieldDefinition<TValue = any> extends FieldDefinition {
|
|
8
|
+
/** Default/initial value for the field */
|
|
9
|
+
default: TValue;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Infer data type from field definitions
|
|
14
|
+
*/
|
|
15
|
+
type InferFormData<TFields extends readonly FormFieldDefinition[]> = {
|
|
16
|
+
[K in TFields[number] as K["key"]]: K["default"];
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Return type for defineForm
|
|
21
|
+
*/
|
|
22
|
+
export interface DefineFormReturn<TData extends Record<string, any>> {
|
|
23
|
+
form: UseFormReturn<TData>;
|
|
24
|
+
fields: FieldDefinition[];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Helper to get default value for a field type
|
|
29
|
+
*/
|
|
30
|
+
function getDefaultValueForType(type: FieldType): any {
|
|
31
|
+
switch (type) {
|
|
32
|
+
case "checkbox":
|
|
33
|
+
return false;
|
|
34
|
+
case "number":
|
|
35
|
+
return 0;
|
|
36
|
+
case "select":
|
|
37
|
+
case "radio":
|
|
38
|
+
return "";
|
|
39
|
+
default:
|
|
40
|
+
return "";
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Define a form with type-safe field definitions.
|
|
46
|
+
* Reduces duplication by inferring initial values from field definitions.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* const { form, fields } = defineForm([
|
|
50
|
+
* { key: "email", type: "email", label: "Email", default: "", required: true },
|
|
51
|
+
* { key: "password", type: "password", label: "Password", default: "", required: true },
|
|
52
|
+
* { key: "remember", type: "checkbox", label: "Remember me", default: false },
|
|
53
|
+
* ] as const);
|
|
54
|
+
*/
|
|
55
|
+
export function defineForm<const TFields extends readonly FormFieldDefinition[]>(
|
|
56
|
+
fieldDefinitions: TFields,
|
|
57
|
+
): DefineFormReturn<InferFormData<TFields>> {
|
|
58
|
+
type FormData = InferFormData<TFields>;
|
|
59
|
+
|
|
60
|
+
// Extract initial data from field definitions
|
|
61
|
+
const initialData = fieldDefinitions.reduce(
|
|
62
|
+
(acc, field) => {
|
|
63
|
+
acc[field.key] = field.default ?? getDefaultValueForType(field.type);
|
|
64
|
+
return acc;
|
|
65
|
+
},
|
|
66
|
+
{} as Record<string, any>,
|
|
67
|
+
) as FormData;
|
|
68
|
+
|
|
69
|
+
// Create form instance
|
|
70
|
+
const form = useForm<FormData>(initialData);
|
|
71
|
+
|
|
72
|
+
// Strip 'default' property from fields for OForm compatibility
|
|
73
|
+
const fields: FieldDefinition[] = fieldDefinitions.map(
|
|
74
|
+
({ default: _default, ...field }) => field,
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
return { form, fields };
|
|
78
|
+
}
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import {
|
|
2
|
+
reactive,
|
|
3
|
+
computed,
|
|
4
|
+
type ComputedRef,
|
|
5
|
+
type WritableComputedRef,
|
|
6
|
+
} from "vue";
|
|
7
|
+
import { api, type ApiError } from "../utils/api";
|
|
8
|
+
|
|
9
|
+
export interface ValidationErrors {
|
|
10
|
+
[key: string]: string[];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type FormError = ApiError;
|
|
14
|
+
|
|
15
|
+
export interface FormSubmitOptions<TPayload = unknown, TResponse = unknown> {
|
|
16
|
+
onSuccess?: (data: TResponse) => void;
|
|
17
|
+
onError?: (error: FormError) => void;
|
|
18
|
+
onBefore?: (payload: TPayload) => void;
|
|
19
|
+
onFinish?: () => void;
|
|
20
|
+
transform?: (payload: TPayload) => unknown;
|
|
21
|
+
preserveErrors?: boolean;
|
|
22
|
+
resetOnSuccess?: boolean;
|
|
23
|
+
signal?: AbortSignal;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface FormState<TData extends Record<string, any>> {
|
|
27
|
+
data: TData; // viewed as TData at the API boundary
|
|
28
|
+
errors: ValidationErrors;
|
|
29
|
+
processing: boolean;
|
|
30
|
+
message: string;
|
|
31
|
+
touched: Record<string, boolean>;
|
|
32
|
+
recentlySuccessful: boolean;
|
|
33
|
+
shouldShowMessage: boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface UseFormReturn<TData extends Record<string, any>>
|
|
37
|
+
extends FormState<TData> {
|
|
38
|
+
hasErrors: ComputedRef<boolean>;
|
|
39
|
+
hasError: (field: keyof TData | string) => boolean;
|
|
40
|
+
getError: (field: keyof TData | string) => string;
|
|
41
|
+
getState: (field: keyof TData | string) => true | false | null;
|
|
42
|
+
setErrors: (errors?: ValidationErrors) => void;
|
|
43
|
+
setMessage: (message: string) => void;
|
|
44
|
+
clearErrors: () => void;
|
|
45
|
+
clearError: (field: keyof TData | string) => void;
|
|
46
|
+
reset: (only?: Array<keyof TData>) => void;
|
|
47
|
+
field: <K extends keyof TData>(key: K) => WritableComputedRef<TData[K]>;
|
|
48
|
+
fields: { [K in keyof TData]: WritableComputedRef<TData[K]> };
|
|
49
|
+
submit: <TResponse = unknown>(
|
|
50
|
+
method: "get" | "post" | "put" | "patch" | "delete",
|
|
51
|
+
url: string,
|
|
52
|
+
options?: FormSubmitOptions<TData, TResponse>,
|
|
53
|
+
) => Promise<TResponse>;
|
|
54
|
+
post: <TResponse = unknown>(
|
|
55
|
+
url: string,
|
|
56
|
+
options?: FormSubmitOptions<TData, TResponse>,
|
|
57
|
+
) => Promise<TResponse>;
|
|
58
|
+
put: <TResponse = unknown>(
|
|
59
|
+
url: string,
|
|
60
|
+
options?: FormSubmitOptions<TData, TResponse>,
|
|
61
|
+
) => Promise<TResponse>;
|
|
62
|
+
patch: <TResponse = unknown>(
|
|
63
|
+
url: string,
|
|
64
|
+
options?: FormSubmitOptions<TData, TResponse>,
|
|
65
|
+
) => Promise<TResponse>;
|
|
66
|
+
delete: <TResponse = unknown>(
|
|
67
|
+
url: string,
|
|
68
|
+
options?: FormSubmitOptions<TData, TResponse>,
|
|
69
|
+
) => Promise<TResponse>;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// ————————————————— helpers
|
|
73
|
+
|
|
74
|
+
const deepClone = <T>(v: T): T =>
|
|
75
|
+
typeof structuredClone === "function"
|
|
76
|
+
? structuredClone(v)
|
|
77
|
+
: JSON.parse(JSON.stringify(v));
|
|
78
|
+
|
|
79
|
+
function errorsFromLaravel(error: any): {
|
|
80
|
+
errors: ValidationErrors;
|
|
81
|
+
message: string;
|
|
82
|
+
} {
|
|
83
|
+
const data = error?.response?.data ?? error?.data ?? error;
|
|
84
|
+
return {
|
|
85
|
+
errors: (data?.errors as ValidationErrors) ?? {},
|
|
86
|
+
message: (data?.message as string) ?? "An error occurred",
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// ————————————————— composable
|
|
91
|
+
|
|
92
|
+
export function useForm<TData extends Record<string, any>>(
|
|
93
|
+
initialData = {} as TData,
|
|
94
|
+
): UseFormReturn<TData> {
|
|
95
|
+
const snapshot = deepClone(initialData);
|
|
96
|
+
|
|
97
|
+
const state = reactive<FormState<TData>>({
|
|
98
|
+
data: deepClone(snapshot) as TData,
|
|
99
|
+
errors: {},
|
|
100
|
+
processing: false,
|
|
101
|
+
message: "",
|
|
102
|
+
touched: {},
|
|
103
|
+
recentlySuccessful: false,
|
|
104
|
+
shouldShowMessage: false,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
const hasErrors = computed(() =>
|
|
108
|
+
Object.keys(state.errors).some(
|
|
109
|
+
(k) => (state.errors[k]?.length ?? 0) > 0,
|
|
110
|
+
),
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
const hasError = (field: keyof TData | string): boolean => {
|
|
114
|
+
return (state.errors[field as string]?.length ?? 0) > 0;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
const getError = (field: keyof TData | string): string => {
|
|
118
|
+
return state.errors[field as string]?.[0] ?? "";
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const getState = (field: keyof TData | string): false | null =>
|
|
122
|
+
hasError(field) ? false : null;
|
|
123
|
+
|
|
124
|
+
const setErrors = (errors: ValidationErrors = {}): void => {
|
|
125
|
+
for (const k of Object.keys(state.errors)) delete state.errors[k];
|
|
126
|
+
Object.assign(state.errors, errors);
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
const setMessage = (message: string): void => {
|
|
130
|
+
state.message = message;
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const clearErrors = (): void => {
|
|
134
|
+
for (const key of Object.keys(state.errors)) delete state.errors[key];
|
|
135
|
+
state.message = "";
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const clearError = (field: keyof TData | string): void => {
|
|
139
|
+
const key = field as string;
|
|
140
|
+
if (state.errors[key]) delete state.errors[key];
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const reset = (only?: Array<keyof TData>): void => {
|
|
144
|
+
if (only?.length) {
|
|
145
|
+
for (const k of only) {
|
|
146
|
+
(state.data as any)[k as string] = deepClone(
|
|
147
|
+
(snapshot as any)[k as string],
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
} else {
|
|
151
|
+
// operate on a Record view to satisfy TS
|
|
152
|
+
const dataRecord = state.data as Record<string, unknown>;
|
|
153
|
+
for (const k of Object.keys(dataRecord))
|
|
154
|
+
delete (dataRecord as any)[k];
|
|
155
|
+
Object.assign(
|
|
156
|
+
state.data as Record<string, unknown>,
|
|
157
|
+
deepClone(snapshot),
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
clearErrors();
|
|
161
|
+
state.touched = {};
|
|
162
|
+
state.processing = false;
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
// v-model for a single field
|
|
166
|
+
const field = <K extends keyof TData>(
|
|
167
|
+
key: K,
|
|
168
|
+
): WritableComputedRef<TData[K]> =>
|
|
169
|
+
computed<TData[K]>({
|
|
170
|
+
get: () => (state.data as TData)[key],
|
|
171
|
+
set: (value) => {
|
|
172
|
+
(state.data as TData)[key] = value;
|
|
173
|
+
state.touched[key as string] = true;
|
|
174
|
+
if (state.errors[key as string])
|
|
175
|
+
delete state.errors[key as string];
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
// property-style fields map (non-Proxy, uses snapshot keys)
|
|
180
|
+
const fields = {} as UseFormReturn<TData>["fields"];
|
|
181
|
+
(Object.keys(snapshot) as Array<keyof TData>).forEach((k) => {
|
|
182
|
+
Object.defineProperty(fields, k, {
|
|
183
|
+
get: () => field(k),
|
|
184
|
+
enumerable: true,
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
const submit = async <TResponse = unknown>(
|
|
189
|
+
method: "get" | "post" | "put" | "patch" | "delete",
|
|
190
|
+
url: string,
|
|
191
|
+
options: FormSubmitOptions<TData, TResponse> = {},
|
|
192
|
+
): Promise<TResponse> => {
|
|
193
|
+
state.processing = true;
|
|
194
|
+
if (!options.preserveErrors) clearErrors();
|
|
195
|
+
|
|
196
|
+
const payloadRaw = (
|
|
197
|
+
options.transform
|
|
198
|
+
? options.transform(state.data as TData)
|
|
199
|
+
: (state.data as TData)
|
|
200
|
+
) as any;
|
|
201
|
+
|
|
202
|
+
options.onBefore?.(state.data as TData);
|
|
203
|
+
|
|
204
|
+
try {
|
|
205
|
+
const { data } =
|
|
206
|
+
method === "get"
|
|
207
|
+
? await api.get<TResponse>(
|
|
208
|
+
url,
|
|
209
|
+
payloadRaw as Record<string, unknown>,
|
|
210
|
+
{ signal: options?.signal },
|
|
211
|
+
)
|
|
212
|
+
: await api[method]<TResponse>(url, payloadRaw, {
|
|
213
|
+
signal: options?.signal,
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
state.recentlySuccessful = true;
|
|
217
|
+
setTimeout(() => (state.recentlySuccessful = false), 1500);
|
|
218
|
+
|
|
219
|
+
options.onSuccess?.(data);
|
|
220
|
+
if (options.resetOnSuccess) {
|
|
221
|
+
reset();
|
|
222
|
+
}
|
|
223
|
+
return data;
|
|
224
|
+
} catch (err) {
|
|
225
|
+
const { errors, message } = errorsFromLaravel(err);
|
|
226
|
+
setErrors(errors);
|
|
227
|
+
setMessage(message);
|
|
228
|
+
options.onError?.(err as FormError);
|
|
229
|
+
throw err;
|
|
230
|
+
} finally {
|
|
231
|
+
state.processing = false;
|
|
232
|
+
options.onFinish?.();
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
const post = <R = unknown>(url: string, o?: FormSubmitOptions<TData, R>) =>
|
|
237
|
+
submit<R>("post", url, o);
|
|
238
|
+
const put = <R = unknown>(url: string, o?: FormSubmitOptions<TData, R>) =>
|
|
239
|
+
submit<R>("put", url, o);
|
|
240
|
+
const patch = <R = unknown>(url: string, o?: FormSubmitOptions<TData, R>) =>
|
|
241
|
+
submit<R>("patch", url, o);
|
|
242
|
+
const del = <R = unknown>(url: string, o?: FormSubmitOptions<TData, R>) =>
|
|
243
|
+
submit<R>("delete", url, o);
|
|
244
|
+
|
|
245
|
+
const shouldShowMessage = computed(() => {
|
|
246
|
+
return (
|
|
247
|
+
state.message !== "" &&
|
|
248
|
+
state.processing === false &&
|
|
249
|
+
hasErrors.value === false
|
|
250
|
+
);
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
return Object.assign(state, {
|
|
254
|
+
hasErrors,
|
|
255
|
+
hasError,
|
|
256
|
+
getError,
|
|
257
|
+
getState,
|
|
258
|
+
setErrors,
|
|
259
|
+
setMessage,
|
|
260
|
+
clearErrors,
|
|
261
|
+
clearError,
|
|
262
|
+
reset,
|
|
263
|
+
field,
|
|
264
|
+
fields,
|
|
265
|
+
submit,
|
|
266
|
+
post,
|
|
267
|
+
put,
|
|
268
|
+
patch,
|
|
269
|
+
delete: del,
|
|
270
|
+
shouldShowMessage,
|
|
271
|
+
}) as UseFormReturn<TData>;
|
|
272
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useToast } from 'bootstrap-vue-next';
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// Import theme styles so they're included in the build
|
|
2
|
+
import '../css/theme.scss';
|
|
3
|
+
|
|
4
|
+
// Re-export everything from Bootstrap Vue Next for complete control
|
|
5
|
+
export * from 'bootstrap-vue-next';
|
|
6
|
+
|
|
7
|
+
// Extended components (custom functionality beyond Bootstrap Vue Next)
|
|
8
|
+
export { default as DXDashboard } from "./components/extended/DXDashboard.vue";
|
|
9
|
+
export { default as DXBasicForm } from "./components/extended/DXBasicForm.vue";
|
|
10
|
+
export { default as DXForm } from "./components/extended/DXForm.vue";
|
|
11
|
+
export { default as DXTable } from "./components/extended/DXTable.vue";
|
|
12
|
+
export { default as DXDashboardSidebar } from "./components/extended/DXDashboardSidebar.vue";
|
|
13
|
+
export { default as DXDashboardNavbar } from "./components/extended/DXDashboardNavbar.vue";
|
|
14
|
+
|
|
15
|
+
// Base components (wrapped Bootstrap with theming)
|
|
16
|
+
export { default as DAccordion } from "./components/base/DAccordion.vue";
|
|
17
|
+
export { default as DAccordionItem } from "./components/base/DAccordionItem.vue";
|
|
18
|
+
export { default as DAlert } from "./components/base/DAlert.vue";
|
|
19
|
+
export { default as DAvatar } from "./components/base/DAvatar.vue";
|
|
20
|
+
export { default as DBadge } from "./components/base/DBadge.vue";
|
|
21
|
+
export { default as DBreadcrumb } from "./components/base/DBreadcrumb.vue";
|
|
22
|
+
export { default as DButton } from "./components/base/DButton.vue";
|
|
23
|
+
export { default as DButtonGroup } from "./components/base/DButtonGroup.vue";
|
|
24
|
+
export { default as DButtonToolbar } from "./components/base/DButtonToolbar.vue";
|
|
25
|
+
export { default as DCard } from "./components/base/DCard.vue";
|
|
26
|
+
export { default as DCarousel } from "./components/base/DCarousel.vue";
|
|
27
|
+
export { default as DCarouselSlide } from "./components/base/DCarouselSlide.vue";
|
|
28
|
+
export { default as DCol } from "./components/base/DCol.vue";
|
|
29
|
+
export { default as DCollapse } from "./components/base/DCollapse.vue";
|
|
30
|
+
export { default as DContainer } from "./components/base/DContainer.vue";
|
|
31
|
+
export { default as DDropdown } from "./components/base/DDropdown.vue";
|
|
32
|
+
export { default as DDropdownDivider } from "./components/base/DDropdownDivider.vue";
|
|
33
|
+
export { default as DDropdownItem } from "./components/base/DDropdownItem.vue";
|
|
34
|
+
export { default as DForm } from "./components/base/DForm.vue";
|
|
35
|
+
export { default as DFormCheckbox } from "./components/base/DFormCheckbox.vue";
|
|
36
|
+
export { default as DFormGroup } from "./components/base/DFormGroup.vue";
|
|
37
|
+
export { default as DFormInput } from "./components/base/DFormInput.vue";
|
|
38
|
+
export { default as DFormInvalidFeedback } from "./components/base/DFormInvalidFeedback.vue";
|
|
39
|
+
export { default as DFormRadio } from "./components/base/DFormRadio.vue";
|
|
40
|
+
export { default as DFormSelect } from "./components/base/DFormSelect.vue";
|
|
41
|
+
export { default as DFormSpinbutton } from "./components/base/DFormSpinbutton.vue";
|
|
42
|
+
export { default as DFormTags } from "./components/base/DFormTags.vue";
|
|
43
|
+
export { default as DFormText } from "./components/base/DFormText.vue";
|
|
44
|
+
export { default as DFormTextarea } from "./components/base/DFormTextarea.vue";
|
|
45
|
+
export { default as DImage } from "./components/base/DImage.vue";
|
|
46
|
+
export { default as DInputGroup } from "./components/base/DInputGroup.vue";
|
|
47
|
+
export { default as DLink } from "./components/base/DLink.vue";
|
|
48
|
+
export { default as DListGroup } from "./components/base/DListGroup.vue";
|
|
49
|
+
export { default as DListGroupItem } from "./components/base/DListGroupItem.vue";
|
|
50
|
+
export { default as DModal } from "./components/base/DModal.vue";
|
|
51
|
+
export { default as DNav } from "./components/base/DNav.vue";
|
|
52
|
+
export { default as DNavbar } from "./components/base/DNavbar.vue";
|
|
53
|
+
export { default as DNavbarBrand } from "./components/base/DNavbarBrand.vue";
|
|
54
|
+
export { default as DNavbarNav } from "./components/base/DNavbarNav.vue";
|
|
55
|
+
export { default as DNavbarToggle } from "./components/base/DNavbarToggle.vue";
|
|
56
|
+
export { default as DNavItem } from "./components/base/DNavItem.vue";
|
|
57
|
+
export { default as DOffcanvas } from "./components/base/DOffcanvas.vue";
|
|
58
|
+
export { default as DOverlay } from "./components/base/DOverlay.vue";
|
|
59
|
+
export { default as DPagination } from "./components/base/DPagination.vue";
|
|
60
|
+
export { default as DPlaceholder } from "./components/base/DPlaceholder.vue";
|
|
61
|
+
export { default as DPopover } from "./components/base/DPopover.vue";
|
|
62
|
+
export { default as DProgress } from "./components/base/DProgress.vue";
|
|
63
|
+
export { default as DRow } from "./components/base/DRow.vue";
|
|
64
|
+
export { default as DSpinner } from "./components/base/DSpinner.vue";
|
|
65
|
+
export { default as DTable } from "./components/base/DTable.vue";
|
|
66
|
+
export { default as DTab } from "./components/base/DTab.vue";
|
|
67
|
+
export { default as DTabs } from "./components/base/DTabs.vue";
|
|
68
|
+
export { default as DToast } from "./components/base/DToast.vue";
|
|
69
|
+
export { default as DToaster } from "./components/base/DToaster.vue";
|
|
70
|
+
export { default as DTooltip } from "./components/base/DTooltip.vue";
|
|
71
|
+
|
|
72
|
+
// Composables
|
|
73
|
+
export { useForm } from "./composables/useForm";
|
|
74
|
+
export { defineForm } from "./composables/defineForm";
|
|
75
|
+
export { useToast } from "./composables/useToast";
|
|
76
|
+
|
|
77
|
+
// Utils
|
|
78
|
+
export { api } from "./utils/api";
|
|
79
|
+
|
|
80
|
+
// Types
|
|
81
|
+
export type {
|
|
82
|
+
FieldType,
|
|
83
|
+
FieldOption,
|
|
84
|
+
FieldDefinition,
|
|
85
|
+
} from "./types";
|
|
86
|
+
|
|
87
|
+
export type {
|
|
88
|
+
ValidationErrors,
|
|
89
|
+
FormError,
|
|
90
|
+
FormSubmitOptions,
|
|
91
|
+
FormState,
|
|
92
|
+
UseFormReturn,
|
|
93
|
+
} from "./composables/useForm";
|
|
94
|
+
|
|
95
|
+
export type {
|
|
96
|
+
FormFieldDefinition,
|
|
97
|
+
DefineFormReturn,
|
|
98
|
+
} from "./composables/defineForm";
|
|
99
|
+
|
|
100
|
+
export type {
|
|
101
|
+
ApiError,
|
|
102
|
+
ApiResponse,
|
|
103
|
+
} from "./utils/api";
|
|
104
|
+
|
|
105
|
+
export type {
|
|
106
|
+
TableField,
|
|
107
|
+
PaginationData,
|
|
108
|
+
BTableSortBy,
|
|
109
|
+
BTableProvider,
|
|
110
|
+
EditTab,
|
|
111
|
+
BTableProviderContext,
|
|
112
|
+
} from "./components/extended/DXTable.vue";
|
|
113
|
+
|
|
114
|
+
export type {
|
|
115
|
+
NavigationItem,
|
|
116
|
+
NavigationGroup,
|
|
117
|
+
Navigation,
|
|
118
|
+
} from "./types/navigation";
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Field types supported by OForm
|
|
3
|
+
*/
|
|
4
|
+
export type FieldType =
|
|
5
|
+
| "text"
|
|
6
|
+
| "email"
|
|
7
|
+
| "password"
|
|
8
|
+
| "number"
|
|
9
|
+
| "url"
|
|
10
|
+
| "tel"
|
|
11
|
+
| "date"
|
|
12
|
+
| "datetime-local"
|
|
13
|
+
| "time"
|
|
14
|
+
| "textarea"
|
|
15
|
+
| "select"
|
|
16
|
+
| "checkbox"
|
|
17
|
+
| "radio";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Option for select or radio fields
|
|
21
|
+
*/
|
|
22
|
+
export interface FieldOption extends Record<string, unknown> {
|
|
23
|
+
value: any;
|
|
24
|
+
text: string;
|
|
25
|
+
disabled?: boolean;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Field definition for OForm
|
|
30
|
+
*/
|
|
31
|
+
export interface FieldDefinition {
|
|
32
|
+
/** Field key (must match form data key) */
|
|
33
|
+
key: string;
|
|
34
|
+
|
|
35
|
+
/** Field type */
|
|
36
|
+
type: FieldType;
|
|
37
|
+
|
|
38
|
+
/** Field label (optional) */
|
|
39
|
+
label?: string;
|
|
40
|
+
|
|
41
|
+
/** Placeholder text (optional) */
|
|
42
|
+
placeholder?: string;
|
|
43
|
+
|
|
44
|
+
/** Whether field is required (optional) */
|
|
45
|
+
required?: boolean;
|
|
46
|
+
|
|
47
|
+
/** Options for select or radio fields */
|
|
48
|
+
options?: FieldOption[];
|
|
49
|
+
|
|
50
|
+
/** Number of rows for textarea (default: 3) */
|
|
51
|
+
rows?: number;
|
|
52
|
+
|
|
53
|
+
/** Help text displayed below field */
|
|
54
|
+
help?: string;
|
|
55
|
+
|
|
56
|
+
/** CSS class for the form group */
|
|
57
|
+
class?: string;
|
|
58
|
+
|
|
59
|
+
/** Additional props to pass to the input component */
|
|
60
|
+
inputProps?: Record<string, any>;
|
|
61
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface NavigationItem {
|
|
2
|
+
label: string;
|
|
3
|
+
url: string;
|
|
4
|
+
icon?: string;
|
|
5
|
+
badge?: string | number;
|
|
6
|
+
badgeColor?: string;
|
|
7
|
+
active?: boolean;
|
|
8
|
+
visible?: boolean;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface NavigationGroup {
|
|
12
|
+
label?: string;
|
|
13
|
+
items: NavigationItem[];
|
|
14
|
+
collapsible?: boolean;
|
|
15
|
+
collapsed?: boolean;
|
|
16
|
+
visible?: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type Navigation = NavigationGroup[];
|