@svadmin/core 0.0.6 → 0.3.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.
- package/package.json +4 -1
- package/src/audit.ts +37 -0
- package/src/auth-hooks.test.ts +205 -0
- package/src/context.ts +65 -15
- package/src/data-transfer.ts +148 -70
- package/src/form-hooks.svelte.ts +266 -0
- package/src/helpers.ts +157 -0
- package/src/hook-utils.svelte.ts +121 -0
- package/src/hooks.svelte.ts +277 -530
- package/src/http-error.test.ts +85 -0
- package/src/i18n.svelte.ts +18 -0
- package/src/index.ts +39 -8
- package/src/inferencer-openapi.test.ts +192 -0
- package/src/inferencer-openapi.ts +290 -0
- package/src/live-sse.ts +146 -0
- package/src/live-websocket.ts +141 -0
- package/src/live.test.ts +134 -0
- package/src/live.ts +60 -8
- package/src/mutation-hooks.svelte.ts +301 -0
- package/src/options.ts +95 -0
- package/src/query-hooks.svelte.ts +213 -0
- package/src/query-keys.ts +22 -0
- package/src/resource-types.test.ts +79 -0
- package/src/router.ts +28 -4
- package/src/routing-hooks.svelte.ts +99 -0
- package/src/table-hooks.svelte.ts +178 -0
- package/src/toast.svelte.ts +8 -4
- package/src/types.ts +124 -47
- package/src/unsaved-changes.svelte.ts +62 -0
- package/src/url-sync.ts +15 -0
- package/src/useParsed.ts +39 -3
- package/src/useStepsForm.svelte.ts +71 -0
- package/src/utility-hooks.svelte.ts +161 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { useForm, type UseFormOptions } from './form-hooks.svelte';
|
|
2
|
+
import { useQueryClient } from '@tanstack/svelte-query';
|
|
3
|
+
import { useParsed } from './useParsed';
|
|
4
|
+
import { getResource, getResources } from './context';
|
|
5
|
+
import { getAdminOptions } from './options';
|
|
6
|
+
import { navigate } from './router';
|
|
7
|
+
import { t } from './i18n.svelte';
|
|
8
|
+
import type { BaseRecord, HttpError, Filter, KnownResources, ResourceDefinition } from './types';
|
|
9
|
+
import { useList, type UseListOptions } from './query-hooks.svelte';
|
|
10
|
+
import { toast } from './toast.svelte';
|
|
11
|
+
|
|
12
|
+
// ─── useModal ─────────────────────────────────────────────────
|
|
13
|
+
export function useModal(options?: { defaultVisible?: boolean }) {
|
|
14
|
+
let visible = $state(options?.defaultVisible ?? false);
|
|
15
|
+
return {
|
|
16
|
+
get visible() { return visible; },
|
|
17
|
+
show() { visible = true; },
|
|
18
|
+
close() { visible = false; },
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// ─── useModalForm ─────────────────────────────────────────────
|
|
23
|
+
|
|
24
|
+
export interface UseModalFormOptions<TQueryFnData extends BaseRecord = BaseRecord, TError = HttpError, TVariables = Record<string, unknown>, TData extends BaseRecord = TQueryFnData> extends UseFormOptions<TQueryFnData, TError, TVariables, TData> {
|
|
25
|
+
defaultVisible?: boolean;
|
|
26
|
+
autoSave?: UseFormOptions<TQueryFnData, TError, TVariables, TData>['autoSave'] & {
|
|
27
|
+
invalidateOnClose?: boolean;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function useModalForm<
|
|
32
|
+
TQueryFnData extends BaseRecord = BaseRecord,
|
|
33
|
+
TError = HttpError,
|
|
34
|
+
TVariables = Record<string, unknown>,
|
|
35
|
+
TData extends BaseRecord = TQueryFnData
|
|
36
|
+
>(options: UseModalFormOptions<TQueryFnData, TError, TVariables, TData> = {}) {
|
|
37
|
+
const queryClient = useQueryClient();
|
|
38
|
+
const formState = useForm(options);
|
|
39
|
+
let visible = $state(options.defaultVisible ?? false);
|
|
40
|
+
|
|
41
|
+
function show(id?: string | number) {
|
|
42
|
+
if (id !== undefined) formState.setId(id);
|
|
43
|
+
visible = true;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function close() {
|
|
47
|
+
visible = false;
|
|
48
|
+
formState.clearErrors();
|
|
49
|
+
if (options.autoSave?.invalidateOnClose) {
|
|
50
|
+
queryClient.invalidateQueries({ queryKey: [formState.resource] });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
get visible() { return visible; },
|
|
56
|
+
show,
|
|
57
|
+
close,
|
|
58
|
+
get modalProps() { return { visible, close }; },
|
|
59
|
+
formState,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export const useDrawerForm = useModalForm; // Alias for UI variations
|
|
64
|
+
|
|
65
|
+
// ─── useMenu ──────────────────────────────────────────────────
|
|
66
|
+
|
|
67
|
+
export interface MenuConfig {
|
|
68
|
+
name: string;
|
|
69
|
+
route: string;
|
|
70
|
+
label: string;
|
|
71
|
+
icon?: string;
|
|
72
|
+
parentName?: string;
|
|
73
|
+
order?: number;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function useMenu() {
|
|
77
|
+
const adminOptions = getAdminOptions();
|
|
78
|
+
const resources = getResources();
|
|
79
|
+
const parsed = useParsed();
|
|
80
|
+
|
|
81
|
+
const menuItems = $derived.by<MenuConfig[]>(() => {
|
|
82
|
+
let items: MenuConfig[] = resources
|
|
83
|
+
.filter((r: ResourceDefinition) => r.showInMenu !== false)
|
|
84
|
+
.map((r: ResourceDefinition): MenuConfig => ({
|
|
85
|
+
name: r.name,
|
|
86
|
+
route: `/${r.name}`,
|
|
87
|
+
label: r.label || r.name, // Usually handled by i18n label mapping
|
|
88
|
+
icon: r.icon,
|
|
89
|
+
parentName: r.parentName,
|
|
90
|
+
order: r.menuOrder ?? 999,
|
|
91
|
+
}));
|
|
92
|
+
|
|
93
|
+
if (adminOptions.menuItems) items = adminOptions.menuItems(items);
|
|
94
|
+
items.sort((a, b) => (a.order ?? 999) - (b.order ?? 999));
|
|
95
|
+
return items;
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
get menuItems() { return menuItems; },
|
|
100
|
+
get selectedKey() { return parsed.resource ?? '/'; },
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// ─── useBreadcrumb ────────────────────────────────────────────
|
|
105
|
+
|
|
106
|
+
export interface BreadcrumbItem {
|
|
107
|
+
label: string;
|
|
108
|
+
link?: string;
|
|
109
|
+
icon?: string;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function useBreadcrumb() {
|
|
113
|
+
const parsed = useParsed();
|
|
114
|
+
|
|
115
|
+
const items = $derived.by<BreadcrumbItem[]>(() => {
|
|
116
|
+
const list: BreadcrumbItem[] = [];
|
|
117
|
+
if (!parsed.resource) return list;
|
|
118
|
+
|
|
119
|
+
try {
|
|
120
|
+
const res = getResource(parsed.resource);
|
|
121
|
+
list.push({ label: res.label || res.name, link: `/${res.name}`, icon: res.icon });
|
|
122
|
+
|
|
123
|
+
if (parsed.action === 'create') {
|
|
124
|
+
list.push({ label: t('common.create') });
|
|
125
|
+
} else if (parsed.action === 'edit' && parsed.id) {
|
|
126
|
+
list.push({ label: t('common.edit') });
|
|
127
|
+
list.push({ label: String(parsed.id) });
|
|
128
|
+
} else if (parsed.action === 'show' && parsed.id) {
|
|
129
|
+
list.push({ label: t('common.show') });
|
|
130
|
+
list.push({ label: String(parsed.id) });
|
|
131
|
+
}
|
|
132
|
+
} catch {
|
|
133
|
+
// Ignored
|
|
134
|
+
}
|
|
135
|
+
return list;
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
return { get items() { return items; } };
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// ─── useRelation ───────────────────────────────────────────
|
|
142
|
+
|
|
143
|
+
export interface UseRelationOptions<TData extends BaseRecord = BaseRecord, TError = HttpError> {
|
|
144
|
+
resource: KnownResources;
|
|
145
|
+
id?: string | number;
|
|
146
|
+
pagination?: { current?: number; pageSize?: number };
|
|
147
|
+
sorters?: { field: string; order: 'asc' | 'desc' }[];
|
|
148
|
+
filters?: Filter[];
|
|
149
|
+
queryOptions?: { enabled?: boolean; staleTime?: number };
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export function useRelation<TData extends BaseRecord = BaseRecord, TError = HttpError>(options: UseRelationOptions<TData, TError>) {
|
|
153
|
+
return useList<TData, TError>({
|
|
154
|
+
...options
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// ─── useNotification ────────────────────────────────────────
|
|
159
|
+
export function useNotification() {
|
|
160
|
+
return { open: toast.info, success: toast.success, error: toast.error, warning: toast.warning };
|
|
161
|
+
}
|