@dskripchenko/laravel-admin 1.32.2 → 1.34.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/README.md +3 -20
- package/dist/.vite/manifest.json +11 -0
- package/dist/app.d.ts +13 -0
- package/dist/assets/app-Bt8LixFu.js +29 -0
- package/dist/assets/app-DvKbADye.css +1 -0
- package/dist/components/ScreenPage.test.d.ts +1 -0
- package/dist/components/actions/AdminActionButton.vue.d.ts +25 -0
- package/dist/components/actions/AdminActionDialogs.vue.d.ts +6 -0
- package/dist/components/actions/AdminActionForm.vue.d.ts +8 -0
- package/dist/components/actions/AdminActionMenuItems.vue.d.ts +14 -0
- package/dist/components/dashboard/BarChartWidget.vue.d.ts +3 -0
- package/dist/components/dashboard/CartesianChartWidget.vue.d.ts +21 -0
- package/dist/components/dashboard/ChartLegend.vue.d.ts +14 -0
- package/dist/components/dashboard/ChartTooltip.vue.d.ts +15 -0
- package/dist/components/dashboard/ChartWidget.test.d.ts +1 -0
- package/dist/components/dashboard/ChartWidget.vue.d.ts +9 -7
- package/dist/components/dashboard/HeatmapWidget.vue.d.ts +1 -1
- package/dist/components/dashboard/MarkdownWidget.vue.d.ts +2 -1
- package/dist/components/dashboard/RadarChartWidget.vue.d.ts +15 -0
- package/dist/components/dashboard/StatMarkdownWidgets.test.d.ts +1 -0
- package/dist/components/dashboard/StatWidget.vue.d.ts +0 -10
- package/dist/components/dashboard/chartGeometry.d.ts +62 -0
- package/dist/components/dashboard/chartTypes.d.ts +2 -1
- package/dist/components/dashboard/useChartSize.d.ts +14 -0
- package/dist/components/fields/CascaderField.vue.d.ts +32 -0
- package/dist/components/fields/CodeField.vue.d.ts +28 -0
- package/dist/components/fields/ColorField.vue.d.ts +23 -0
- package/dist/components/fields/DateRangeField.vue.d.ts +24 -0
- package/dist/components/fields/GroupField.vue.d.ts +21 -0
- package/dist/components/fields/HiddenField.vue.d.ts +8 -0
- package/dist/components/fields/LabelField.vue.d.ts +14 -0
- package/dist/components/fields/MarkdownField.vue.d.ts +29 -0
- package/dist/components/fields/MorphSwitcherField.vue.d.ts +23 -0
- package/dist/components/fields/RadioField.vue.d.ts +21 -0
- package/dist/components/fields/RatingField.vue.d.ts +23 -0
- package/dist/components/fields/SliderField.vue.d.ts +24 -0
- package/dist/components/fields/TimeField.vue.d.ts +26 -0
- package/dist/components/fields/TreeSelectField.vue.d.ts +26 -0
- package/dist/components/fields/WysiwygField.vue.d.ts +1 -1
- package/dist/components/fields/pickerFields.test.d.ts +1 -0
- package/dist/components/fields/support/color.d.ts +18 -0
- package/dist/components/fields/support/dateRange.d.ts +9 -0
- package/dist/components/fields/support/markdown.d.ts +14 -0
- package/dist/components/fields/support/support.test.d.ts +1 -0
- package/dist/components/fields/support/tree.d.ts +23 -0
- package/dist/components/infolist/CascaderEntry.vue.d.ts +21 -0
- package/dist/components/infolist/CodeEntry.vue.d.ts +17 -0
- package/dist/components/infolist/ColorEntry.vue.d.ts +15 -0
- package/dist/components/infolist/DateRangeEntry.vue.d.ts +11 -0
- package/dist/components/infolist/FieldEntry.vue.d.ts +19 -0
- package/dist/components/infolist/GroupEntry.vue.d.ts +19 -0
- package/dist/components/infolist/HiddenEntry.vue.d.ts +2 -0
- package/dist/components/infolist/ImageEntry.vue.d.ts +21 -0
- package/dist/components/infolist/MapEntry.vue.d.ts +17 -0
- package/dist/components/infolist/MarkdownEntry.vue.d.ts +11 -0
- package/dist/components/infolist/MorphEntry.vue.d.ts +19 -0
- package/dist/components/infolist/OptionEntry.vue.d.ts +13 -0
- package/dist/components/infolist/RatingEntry.vue.d.ts +19 -0
- package/dist/components/infolist/RelationEntry.vue.d.ts +17 -0
- package/dist/components/infolist/TreeSelectEntry.vue.d.ts +15 -0
- package/dist/components/infolist/entryValue.d.ts +10 -0
- package/dist/components/infolist/viewEntries.test.d.ts +1 -0
- package/dist/components/layouts/AccordionLayout.vue.d.ts +16 -0
- package/dist/components/layouts/AuditTrailLayout.vue.d.ts +13 -0
- package/dist/components/layouts/DrawerLayout.vue.d.ts +25 -0
- package/dist/components/layouts/InfolistLayout.vue.d.ts +12 -0
- package/dist/components/layouts/ListenerLayout.test.d.ts +1 -0
- package/dist/components/layouts/ListenerLayout.vue.d.ts +18 -0
- package/dist/components/layouts/ModalLayout.vue.d.ts +22 -0
- package/dist/components/layouts/StepLayout.vue.d.ts +12 -0
- package/dist/components/layouts/ViewLayout.vue.d.ts +7 -0
- package/dist/components/layouts/WizardLayout.vue.d.ts +20 -0
- package/dist/components/layouts/WrapperLayout.vue.d.ts +12 -0
- package/dist/components/layouts/layouts.test.d.ts +1 -0
- package/dist/components/layouts/overlay.d.ts +29 -0
- package/dist/components/layouts/wizard.d.ts +39 -0
- package/dist/components/layouts/wizard.test.d.ts +1 -0
- package/dist/components/render/formState.d.ts +11 -0
- package/dist/components/render/index.d.ts +13 -0
- package/dist/components/render/listenerContext.d.ts +20 -0
- package/dist/components/render/screenContext.d.ts +75 -0
- package/dist/components/render/screenContext.test.d.ts +1 -0
- package/dist/components/resource/AuditTimeline.vue.d.ts +5 -1
- package/dist/components/resource/ResourceIndexPage.vue.d.ts +5 -5
- package/dist/components/resource/ResourceViewPage.vue.d.ts +2 -2
- package/dist/components/shell/AdminConfirmDialog.vue.d.ts +2 -0
- package/dist/composables/useActionRunner.d.ts +132 -0
- package/dist/composables/useActionRunner.test.d.ts +1 -0
- package/dist/composables/useConfirm.d.ts +31 -0
- package/dist/composables/useConfirm.test.d.ts +1 -0
- package/dist/formState-DVU2igtT.js +76 -0
- package/dist/formState-DVU2igtT.js.map +1 -0
- package/dist/formState-DqHe1Jgd.cjs +2 -0
- package/dist/formState-DqHe1Jgd.cjs.map +1 -0
- package/dist/index.cjs +19 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +9 -2
- package/dist/index.mjs +19320 -15516
- package/dist/index.mjs.map +1 -1
- package/dist/quill.cjs +1 -1
- package/dist/quill.mjs +1 -1
- package/dist/source-hash.txt +1 -0
- package/dist/stores/screen.d.ts +3 -5
- package/dist/stores/toast.d.ts +24 -0
- package/dist/stores/toast.test.d.ts +1 -0
- package/dist/style.css +1 -1
- package/dist/tinymce.cjs +1 -1
- package/dist/tinymce.mjs +1 -1
- package/package.json +5 -3
- package/dist/.gitkeep +0 -0
- package/dist/formState-DeRZBwWH.js +0 -41
- package/dist/formState-DeRZBwWH.js.map +0 -1
- package/dist/formState-yUTD6wAR.cjs +0 -2
- package/dist/formState-yUTD6wAR.cjs.map +0 -1
|
@@ -39,3 +39,14 @@ export declare function provideFormState(initial?: Record<string, unknown>, init
|
|
|
39
39
|
export declare function useFormState(): FormStateContext;
|
|
40
40
|
/** The optional form: null when there is none. */
|
|
41
41
|
export declare function tryUseFormState(): FormStateContext | null;
|
|
42
|
+
/**
|
|
43
|
+
* Provides a form context scoped to one object-valued field of `parent` — the
|
|
44
|
+
* backend's Field\Group, whose state is `{city: ..., street: ...}` under its
|
|
45
|
+
* own name.
|
|
46
|
+
*
|
|
47
|
+
* Unlike NestedFieldsGroup this keeps no copy: every read and write goes to
|
|
48
|
+
* `parent.state[name]`, and the errors are the parent's `name.child` keys —
|
|
49
|
+
* the shape Laravel's validator reports them in — seen without the prefix.
|
|
50
|
+
* Scopes nest: a group inside a group prefixes twice.
|
|
51
|
+
*/
|
|
52
|
+
export declare function provideScopedFormState(parent: FormStateContext, name: string): FormStateContext;
|
|
@@ -10,6 +10,10 @@ export type { ComponentBundle } from './registry';
|
|
|
10
10
|
export { registerBuiltinComponents } from './builtin';
|
|
11
11
|
export { provideFormState, useFormState, tryUseFormState, } from './formState';
|
|
12
12
|
export type { FormStateContext } from './formState';
|
|
13
|
+
export { createScreenContext, provideScreenContext, useScreenContext, } from './screenContext';
|
|
14
|
+
export type { ScreenContext, ScreenContextOptions, ScreenActionLike } from './screenContext';
|
|
15
|
+
export { provideListenerEndpoint, useListenerEndpoint } from './listenerContext';
|
|
16
|
+
export type { ListenerEndpoint } from './listenerContext';
|
|
13
17
|
export { default as TextField } from '../fields/TextField.vue';
|
|
14
18
|
export { default as TextAreaField } from '../fields/TextAreaField.vue';
|
|
15
19
|
export { default as NumberField } from '../fields/NumberField.vue';
|
|
@@ -22,3 +26,12 @@ export { default as RowsLayout } from '../layouts/RowsLayout.vue';
|
|
|
22
26
|
export { default as ColumnsLayout } from '../layouts/ColumnsLayout.vue';
|
|
23
27
|
export { default as SectionLayout } from '../layouts/SectionLayout.vue';
|
|
24
28
|
export { default as TabsLayout } from '../layouts/TabsLayout.vue';
|
|
29
|
+
export { default as AccordionLayout } from '../layouts/AccordionLayout.vue';
|
|
30
|
+
export { default as WizardLayout } from '../layouts/WizardLayout.vue';
|
|
31
|
+
export { default as ModalLayout } from '../layouts/ModalLayout.vue';
|
|
32
|
+
export { default as DrawerLayout } from '../layouts/DrawerLayout.vue';
|
|
33
|
+
export { default as ViewLayout } from '../layouts/ViewLayout.vue';
|
|
34
|
+
export { default as WrapperLayout } from '../layouts/WrapperLayout.vue';
|
|
35
|
+
export { default as InfolistLayout } from '../layouts/InfolistLayout.vue';
|
|
36
|
+
export { default as AuditTrailLayout } from '../layouts/AuditTrailLayout.vue';
|
|
37
|
+
export { default as ListenerLayout } from '../layouts/ListenerLayout.vue';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a Listener layout sends its requests.
|
|
3
|
+
*
|
|
4
|
+
* The page that owns the form provides it: ScreenPage points at the screen's
|
|
5
|
+
* `listener` action, ResourceFormPage at the resource's, adding the form's
|
|
6
|
+
* context and the record id. Without one — a settings page, a unit test — a
|
|
7
|
+
* listener simply draws its children as the server first sent them.
|
|
8
|
+
*/
|
|
9
|
+
import { type InjectionKey } from 'vue';
|
|
10
|
+
export interface ListenerEndpoint {
|
|
11
|
+
/** The action's URL relative to the API root, e.g. `/contact/listener`. */
|
|
12
|
+
url: () => string;
|
|
13
|
+
/** Extra body fields sent along with `{listener, state}`. */
|
|
14
|
+
extra?: () => Record<string, unknown>;
|
|
15
|
+
}
|
|
16
|
+
declare const ListenerEndpointKey: InjectionKey<ListenerEndpoint>;
|
|
17
|
+
export declare function provideListenerEndpoint(endpoint: ListenerEndpoint): void;
|
|
18
|
+
/** The endpoint, or null when no page provides one. */
|
|
19
|
+
export declare function useListenerEndpoint(): ListenerEndpoint | null;
|
|
20
|
+
export { ListenerEndpointKey };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The screen context: what a layout deep in the tree may ask of the screen it
|
|
3
|
+
* sits on.
|
|
4
|
+
*
|
|
5
|
+
* Two things live here:
|
|
6
|
+
*
|
|
7
|
+
* - the overlays — the open/closed state of the Modal and Drawer layouts,
|
|
8
|
+
* keyed by the layout's id. An action carrying `attributes.opens` (see the
|
|
9
|
+
* backend's `Action::opens()`) opens the overlay with that id;
|
|
10
|
+
* - the dispatcher — a click on an action, wherever it is drawn (the command
|
|
11
|
+
* bar, a modal's footer, a wizard's submit), goes through `dispatch`, which
|
|
12
|
+
* asks for the confirmation and opens an overlay, or hands the action to
|
|
13
|
+
* the page's action runner (`run`) — or, without one, calls the screen's
|
|
14
|
+
* method.
|
|
15
|
+
*
|
|
16
|
+
* ScreenPage provides it. Outside a screen — a resource form, a unit test —
|
|
17
|
+
* `useScreenContext()` returns null and the layouts degrade gracefully: an
|
|
18
|
+
* overlay keeps its own local state and a submit has nowhere to go.
|
|
19
|
+
*/
|
|
20
|
+
import { type InjectionKey, type Ref } from 'vue';
|
|
21
|
+
/** The shape of an action as the backend serializes it (Action::toArray). */
|
|
22
|
+
export interface ScreenActionLike {
|
|
23
|
+
name?: string;
|
|
24
|
+
label?: string;
|
|
25
|
+
type?: string;
|
|
26
|
+
icon?: string | null;
|
|
27
|
+
primary?: boolean;
|
|
28
|
+
destructive?: boolean;
|
|
29
|
+
confirm?: {
|
|
30
|
+
message: string;
|
|
31
|
+
title?: string;
|
|
32
|
+
} | null;
|
|
33
|
+
attributes?: Record<string, unknown>;
|
|
34
|
+
}
|
|
35
|
+
export interface ScreenContext {
|
|
36
|
+
isOpen: (id: string) => boolean;
|
|
37
|
+
open: (id: string) => void;
|
|
38
|
+
close: (id: string) => void;
|
|
39
|
+
/** Whether a screen method is running right now. */
|
|
40
|
+
running: Readonly<Ref<boolean>>;
|
|
41
|
+
/**
|
|
42
|
+
* Calls a screen method with the current state. Resolves to true on
|
|
43
|
+
* success, false on a failure — the errors land in the screen store.
|
|
44
|
+
*/
|
|
45
|
+
runMethod: (method: string) => Promise<boolean>;
|
|
46
|
+
/**
|
|
47
|
+
* Runs an action: the confirmation first, then either `attributes.opens`
|
|
48
|
+
* (an overlay) or `attributes.method` (a screen method). Resolves to true
|
|
49
|
+
* when the action went through.
|
|
50
|
+
*/
|
|
51
|
+
dispatch: (action: ScreenActionLike) => Promise<boolean>;
|
|
52
|
+
}
|
|
53
|
+
declare const ScreenContextKey: InjectionKey<ScreenContext>;
|
|
54
|
+
export interface ScreenContextOptions {
|
|
55
|
+
running: Readonly<Ref<boolean>>;
|
|
56
|
+
runMethod: (method: string) => Promise<boolean>;
|
|
57
|
+
/** The confirmation prompt; the panel's confirmation dialog by default. */
|
|
58
|
+
confirm?: (confirm: {
|
|
59
|
+
message: string;
|
|
60
|
+
title?: string;
|
|
61
|
+
}) => boolean | Promise<boolean>;
|
|
62
|
+
/**
|
|
63
|
+
* Runs any action that does not open an overlay — confirmation included.
|
|
64
|
+
* ScreenPage passes its action runner here, so the layouts' actions get
|
|
65
|
+
* every action type (modal, async, link…) too. Without it only
|
|
66
|
+
* `attributes.method` is understood.
|
|
67
|
+
*/
|
|
68
|
+
run?: (action: ScreenActionLike) => Promise<boolean>;
|
|
69
|
+
}
|
|
70
|
+
export declare function createScreenContext(options: ScreenContextOptions): ScreenContext;
|
|
71
|
+
export declare function provideScreenContext(options: ScreenContextOptions): ScreenContext;
|
|
72
|
+
/** The screen context, or null outside a screen. */
|
|
73
|
+
export declare function useScreenContext(): ScreenContext | null;
|
|
74
|
+
/** For tests and hosts that render layouts outside ScreenPage. */
|
|
75
|
+
export { ScreenContextKey };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -7,6 +7,10 @@ interface Props {
|
|
|
7
7
|
*/
|
|
8
8
|
subjectType: string | null;
|
|
9
9
|
subjectId: string | number;
|
|
10
|
+
/** Show at most this many of the latest events; all of them when null. */
|
|
11
|
+
limit?: number | null;
|
|
10
12
|
}
|
|
11
|
-
declare const _default: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {
|
|
13
|
+
declare const _default: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {
|
|
14
|
+
limit: number | null;
|
|
15
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
12
16
|
export default _default;
|
|
@@ -10,20 +10,20 @@ interface Props {
|
|
|
10
10
|
/** Router route name behind the “Create” action. */
|
|
11
11
|
createRouteName?: string | null;
|
|
12
12
|
}
|
|
13
|
-
declare var __VLS_5: {},
|
|
13
|
+
declare var __VLS_5: {}, __VLS_78: {}, __VLS_147: {
|
|
14
14
|
filters: Record<string, unknown>;
|
|
15
15
|
setFilter: (key: string, value: unknown) => Promise<void>;
|
|
16
|
-
},
|
|
16
|
+
}, __VLS_228: `cell-${string}`, __VLS_229: {
|
|
17
17
|
row: Record<string, unknown> | undefined;
|
|
18
18
|
};
|
|
19
19
|
type __VLS_Slots = {} & {
|
|
20
|
-
[K in NonNullable<typeof
|
|
20
|
+
[K in NonNullable<typeof __VLS_228>]?: (props: typeof __VLS_229) => any;
|
|
21
21
|
} & {
|
|
22
22
|
actions?: (props: typeof __VLS_5) => any;
|
|
23
23
|
} & {
|
|
24
|
-
'header-menu'?: (props: typeof
|
|
24
|
+
'header-menu'?: (props: typeof __VLS_78) => any;
|
|
25
25
|
} & {
|
|
26
|
-
filters?: (props: typeof
|
|
26
|
+
filters?: (props: typeof __VLS_147) => any;
|
|
27
27
|
};
|
|
28
28
|
declare const __VLS_component: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
29
29
|
import: () => any;
|
|
@@ -19,12 +19,12 @@ interface Props {
|
|
|
19
19
|
/** The prefix of the UID label next to the status: 'A-' gives 'A-1284'. */
|
|
20
20
|
uidPrefix?: string;
|
|
21
21
|
}
|
|
22
|
-
declare var
|
|
22
|
+
declare var __VLS_74: {
|
|
23
23
|
record: Record<string, unknown>;
|
|
24
24
|
resource: import("../..").ManifestResourceMeta | null;
|
|
25
25
|
};
|
|
26
26
|
type __VLS_Slots = {} & {
|
|
27
|
-
sidebar?: (props: typeof
|
|
27
|
+
sidebar?: (props: typeof __VLS_74) => any;
|
|
28
28
|
};
|
|
29
29
|
declare const __VLS_component: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {
|
|
30
30
|
indexRouteName: string | null;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
2
|
+
export default _default;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { type Router } from 'vue-router';
|
|
2
|
+
export interface ActionConfirm {
|
|
3
|
+
message: string;
|
|
4
|
+
title?: string;
|
|
5
|
+
confirmLabel?: string;
|
|
6
|
+
cancelLabel?: string;
|
|
7
|
+
}
|
|
8
|
+
/** An action as Action::toArray() serializes it, normalized. */
|
|
9
|
+
export interface AdminAction {
|
|
10
|
+
name: string;
|
|
11
|
+
label: string;
|
|
12
|
+
type: string;
|
|
13
|
+
icon: string | null;
|
|
14
|
+
confirm: ActionConfirm | null;
|
|
15
|
+
primary: boolean;
|
|
16
|
+
destructive: boolean;
|
|
17
|
+
position: string[];
|
|
18
|
+
attributes: Record<string, unknown>;
|
|
19
|
+
/** The nested actions of a dropdown. */
|
|
20
|
+
items: AdminAction[];
|
|
21
|
+
}
|
|
22
|
+
/** One run of an action. */
|
|
23
|
+
export interface ActionRunOptions {
|
|
24
|
+
/**
|
|
25
|
+
* The record keys this run applies to — a row's own menu passes its row —
|
|
26
|
+
* instead of the context's `ids()` (the selection).
|
|
27
|
+
*/
|
|
28
|
+
ids?: Array<string | number>;
|
|
29
|
+
}
|
|
30
|
+
/** How a page runs a server-side action in its own context. */
|
|
31
|
+
export interface ActionExecutor {
|
|
32
|
+
/**
|
|
33
|
+
* Runs a button, bulk or modal action; `payload` is the modal form's
|
|
34
|
+
* values, `options` what `run()` was given.
|
|
35
|
+
*/
|
|
36
|
+
execute: (action: AdminAction, payload?: Record<string, unknown>, options?: ActionRunOptions) => Promise<unknown>;
|
|
37
|
+
/** The record keys the actions apply to, when the context has any. */
|
|
38
|
+
ids?: () => Array<string | number>;
|
|
39
|
+
/** After a successful execute: a toast, a reload. */
|
|
40
|
+
onSuccess?: (action: AdminAction, result: unknown, options?: ActionRunOptions) => void | Promise<void>;
|
|
41
|
+
/** When execute fails; a toast with the error's message by default. */
|
|
42
|
+
onError?: (action: AdminAction, err: unknown) => void;
|
|
43
|
+
/** Reloads the context's data after an async action has finished. */
|
|
44
|
+
refresh?: () => void | Promise<void>;
|
|
45
|
+
}
|
|
46
|
+
export interface DelayedStatus {
|
|
47
|
+
uuid?: string;
|
|
48
|
+
status: string;
|
|
49
|
+
progress?: number | null;
|
|
50
|
+
data?: unknown;
|
|
51
|
+
error?: string | null;
|
|
52
|
+
}
|
|
53
|
+
/** Normalizes one serialized action; null when it has no name or label. */
|
|
54
|
+
export declare function normalizeAction(raw: unknown): AdminAction | null;
|
|
55
|
+
export declare function normalizeActions(raw: unknown): AdminAction[];
|
|
56
|
+
/**
|
|
57
|
+
* Whether the action applies to records: a BulkAction always does, an action
|
|
58
|
+
* marked `standalone()` never does, any other one does when it is placed in
|
|
59
|
+
* rows or in the bulk bar. The backend's Action::requiresSelection() answers
|
|
60
|
+
* the same way.
|
|
61
|
+
*/
|
|
62
|
+
export declare function needsSelection(action: AdminAction): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Whether a selection of `count` records satisfies the action's
|
|
65
|
+
* requiresAtLeast / requiresAtMost (BulkAction).
|
|
66
|
+
*/
|
|
67
|
+
export declare function selectionAllows(action: AdminAction, count: number): boolean;
|
|
68
|
+
export type ModalSize = 'sm' | 'md' | 'lg' | 'xl' | 'full';
|
|
69
|
+
/** The UidModal sizes; the backend's modalSize() is a free-form string. */
|
|
70
|
+
export declare function modalSizeOf(raw: unknown): ModalSize;
|
|
71
|
+
/**
|
|
72
|
+
* Turns an absolute href into a router path when it points inside the panel;
|
|
73
|
+
* null when it has to be a full navigation.
|
|
74
|
+
*/
|
|
75
|
+
export declare function toRouterPath(router: Router | undefined, href: string): string | null;
|
|
76
|
+
export declare function useActionRunner(executor: ActionExecutor): {
|
|
77
|
+
run: (action: AdminAction, options?: ActionRunOptions) => Promise<boolean>;
|
|
78
|
+
running: import("vue").Ref<boolean, boolean>;
|
|
79
|
+
confirm: (opts: ActionConfirm | string, destructive?: boolean) => Promise<boolean>;
|
|
80
|
+
confirmState: {
|
|
81
|
+
open: boolean;
|
|
82
|
+
title: string;
|
|
83
|
+
message: string;
|
|
84
|
+
confirmLabel: string;
|
|
85
|
+
cancelLabel: string;
|
|
86
|
+
destructive: boolean;
|
|
87
|
+
};
|
|
88
|
+
resolveConfirm: (ok: boolean) => void;
|
|
89
|
+
modalState: {
|
|
90
|
+
open: boolean;
|
|
91
|
+
seq: number;
|
|
92
|
+
action: {
|
|
93
|
+
name: string;
|
|
94
|
+
label: string;
|
|
95
|
+
type: string;
|
|
96
|
+
icon: string | null;
|
|
97
|
+
confirm: {
|
|
98
|
+
message: string;
|
|
99
|
+
title?: string | undefined;
|
|
100
|
+
confirmLabel?: string | undefined;
|
|
101
|
+
cancelLabel?: string | undefined;
|
|
102
|
+
} | null;
|
|
103
|
+
primary: boolean;
|
|
104
|
+
destructive: boolean;
|
|
105
|
+
position: string[];
|
|
106
|
+
attributes: Record<string, unknown>;
|
|
107
|
+
items: /*elided*/ any[];
|
|
108
|
+
} | null;
|
|
109
|
+
title: string;
|
|
110
|
+
submitLabel: string;
|
|
111
|
+
size: ModalSize;
|
|
112
|
+
fields: Array<Record<string, unknown>>;
|
|
113
|
+
values: Record<string, unknown>;
|
|
114
|
+
errors: Record<string, string[]>;
|
|
115
|
+
submitting: boolean;
|
|
116
|
+
options: {
|
|
117
|
+
ids?: Array<string | number> | undefined;
|
|
118
|
+
} | undefined;
|
|
119
|
+
};
|
|
120
|
+
submitModal: () => Promise<void>;
|
|
121
|
+
closeModal: () => void;
|
|
122
|
+
asyncState: {
|
|
123
|
+
open: boolean;
|
|
124
|
+
label: string;
|
|
125
|
+
status: string;
|
|
126
|
+
progress: number;
|
|
127
|
+
error: string | null;
|
|
128
|
+
finished: boolean;
|
|
129
|
+
};
|
|
130
|
+
closeAsync: () => void;
|
|
131
|
+
};
|
|
132
|
+
export type ActionRunner = ReturnType<typeof useActionRunner>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export interface ConfirmOptions {
|
|
2
|
+
message: string;
|
|
3
|
+
title?: string;
|
|
4
|
+
confirmLabel?: string;
|
|
5
|
+
cancelLabel?: string;
|
|
6
|
+
/** Paints the confirm button as dangerous. */
|
|
7
|
+
destructive?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface ConfirmState {
|
|
10
|
+
open: boolean;
|
|
11
|
+
title: string;
|
|
12
|
+
message: string;
|
|
13
|
+
confirmLabel: string;
|
|
14
|
+
cancelLabel: string;
|
|
15
|
+
destructive: boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare const confirmState: {
|
|
18
|
+
open: boolean;
|
|
19
|
+
title: string;
|
|
20
|
+
message: string;
|
|
21
|
+
confirmLabel: string;
|
|
22
|
+
cancelLabel: string;
|
|
23
|
+
destructive: boolean;
|
|
24
|
+
};
|
|
25
|
+
/** Asks a question; resolves to true when the user agreed. */
|
|
26
|
+
export declare function confirmDialog(opts: ConfirmOptions | string): Promise<boolean>;
|
|
27
|
+
/** Answers the open question (the dialog's buttons, its cross, Escape). */
|
|
28
|
+
export declare function resolveConfirmDialog(ok: boolean): void;
|
|
29
|
+
export declare function useConfirm(): {
|
|
30
|
+
confirm: typeof confirmDialog;
|
|
31
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { reactive as u, provide as d, inject as y } from "vue";
|
|
2
|
+
const f = /* @__PURE__ */ Symbol("admin.form-state");
|
|
3
|
+
function E(e = {}, i = {}, c) {
|
|
4
|
+
const n = u(e), s = u({ ...i }), l = {
|
|
5
|
+
state: n,
|
|
6
|
+
errors: s,
|
|
7
|
+
mode: c,
|
|
8
|
+
setField(o, r) {
|
|
9
|
+
n[o] = r, s[o] && delete s[o];
|
|
10
|
+
},
|
|
11
|
+
getField(o) {
|
|
12
|
+
return n[o];
|
|
13
|
+
},
|
|
14
|
+
setError(o, r) {
|
|
15
|
+
r === null || r.length === 0 ? delete s[o] : s[o] = r;
|
|
16
|
+
},
|
|
17
|
+
setErrors(o) {
|
|
18
|
+
for (const r of Object.keys(s)) delete s[r];
|
|
19
|
+
Object.assign(s, o);
|
|
20
|
+
},
|
|
21
|
+
clearErrors() {
|
|
22
|
+
for (const o of Object.keys(s)) delete s[o];
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
return d(f, l), l;
|
|
26
|
+
}
|
|
27
|
+
function a() {
|
|
28
|
+
const e = y(f);
|
|
29
|
+
if (!e)
|
|
30
|
+
throw new Error("useFormState() called outside of provideFormState() scope");
|
|
31
|
+
return e;
|
|
32
|
+
}
|
|
33
|
+
function b() {
|
|
34
|
+
return y(f, null);
|
|
35
|
+
}
|
|
36
|
+
function m(e, i) {
|
|
37
|
+
const c = `${i}.`, n = () => {
|
|
38
|
+
const r = e.getField(i);
|
|
39
|
+
return r !== null && typeof r == "object" && !Array.isArray(r) ? r : {};
|
|
40
|
+
}, s = () => Object.keys(e.errors).filter((r) => r.startsWith(c)).map((r) => r.slice(c.length)), l = new Proxy({}, {
|
|
41
|
+
get: (r, t) => typeof t == "string" ? e.errors[c + t] : void 0,
|
|
42
|
+
has: (r, t) => typeof t == "string" && c + t in e.errors,
|
|
43
|
+
ownKeys: () => s(),
|
|
44
|
+
getOwnPropertyDescriptor: (r, t) => typeof t == "string" && c + t in e.errors ? { enumerable: !0, configurable: !0, value: e.errors[c + t] } : void 0
|
|
45
|
+
}), o = {
|
|
46
|
+
get state() {
|
|
47
|
+
return n();
|
|
48
|
+
},
|
|
49
|
+
errors: l,
|
|
50
|
+
mode: e.mode,
|
|
51
|
+
setField(r, t) {
|
|
52
|
+
e.setField(i, { ...n(), [r]: t }), e.setError(c + r, null);
|
|
53
|
+
},
|
|
54
|
+
getField(r) {
|
|
55
|
+
return n()[r];
|
|
56
|
+
},
|
|
57
|
+
setError(r, t) {
|
|
58
|
+
e.setError(c + r, t);
|
|
59
|
+
},
|
|
60
|
+
setErrors(r) {
|
|
61
|
+
for (const t of s()) e.setError(c + t, null);
|
|
62
|
+
for (const [t, F] of Object.entries(r)) e.setError(c + t, F);
|
|
63
|
+
},
|
|
64
|
+
clearErrors() {
|
|
65
|
+
for (const r of s()) e.setError(c + r, null);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
return d(f, o), o;
|
|
69
|
+
}
|
|
70
|
+
export {
|
|
71
|
+
m as a,
|
|
72
|
+
E as p,
|
|
73
|
+
b as t,
|
|
74
|
+
a as u
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=formState-DVU2igtT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formState-DVU2igtT.js","sources":["../resources/ts/components/render/formState.ts"],"sourcesContent":["/**\n * The form-state composable: it exposes the state and the errors through\n * provide/inject.\n *\n * The container — a resource form, a settings page — calls\n * `provideFormState()`, and the field components in the tree call\n * `useFormState()` to read a value and change a field.\n *\n * The state is a reactive proxy that setField mutates by key; the errors are a\n * separate reactive map of field name → string[] messages.\n */\n\nimport { inject, provide, reactive, type InjectionKey } from 'vue'\n\nexport interface FormStateContext {\n state: Record<string, unknown>\n errors: Record<string, string[]>\n /** The form's context: FieldRenderer hides the fields with visibility[mode]=false. */\n mode?: 'create' | 'update' | 'view'\n setField: (name: string, value: unknown) => void\n getField: (name: string) => unknown\n setError: (name: string, messages: string[] | null) => void\n setErrors: (next: Record<string, string[]>) => void\n clearErrors: () => void\n}\n\nconst FormStateKey: InjectionKey<FormStateContext> = Symbol('admin.form-state')\n\n/**\n * Creates the form context and provides it to the descendants.\n *\n * The `initial` object given is wrapped into `reactive()`, so the mutations are\n * visible from outside too: the caller owns the state and may read it after a\n * submit.\n *\n * @param initial The state's initial values.\n * @param initialErrors The initial errors, for a re-render after a\n * ValidationError.\n */\nexport function provideFormState(\n initial: Record<string, unknown> = {},\n initialErrors: Record<string, string[]> = {},\n mode?: 'create' | 'update' | 'view',\n): FormStateContext {\n const state = reactive(initial)\n const errors = reactive<Record<string, string[]>>({ ...initialErrors })\n\n const ctx: FormStateContext = {\n state,\n errors,\n mode,\n setField(name, value) {\n ;(state as Record<string, unknown>)[name] = value\n // Clear that field's errors as it changes, as one expects.\n if (errors[name]) {\n delete errors[name]\n }\n },\n getField(name) {\n return (state as Record<string, unknown>)[name]\n },\n setError(name, messages) {\n if (messages === null || messages.length === 0) {\n delete errors[name]\n } else {\n errors[name] = messages\n }\n },\n setErrors(next) {\n for (const key of Object.keys(errors)) delete errors[key]\n Object.assign(errors, next)\n },\n clearErrors() {\n for (const key of Object.keys(errors)) delete errors[key]\n },\n }\n\n provide(FormStateKey, ctx)\n return ctx\n}\n\n/**\n * Returns the form context. It throws when called outside a\n * `provideFormState()`.\n */\nexport function useFormState(): FormStateContext {\n const ctx = inject(FormStateKey)\n if (!ctx) {\n throw new Error('useFormState() called outside of provideFormState() scope')\n }\n return ctx\n}\n\n/** The optional form: null when there is none. */\nexport function tryUseFormState(): FormStateContext | null {\n return inject(FormStateKey, null)\n}\n\n/**\n * Provides a form context scoped to one object-valued field of `parent` — the\n * backend's Field\\Group, whose state is `{city: ..., street: ...}` under its\n * own name.\n *\n * Unlike NestedFieldsGroup this keeps no copy: every read and write goes to\n * `parent.state[name]`, and the errors are the parent's `name.child` keys —\n * the shape Laravel's validator reports them in — seen without the prefix.\n * Scopes nest: a group inside a group prefixes twice.\n */\nexport function provideScopedFormState(parent: FormStateContext, name: string): FormStateContext {\n const prefix = `${name}.`\n const obj = (): Record<string, unknown> => {\n const v = parent.getField(name)\n return v !== null && typeof v === 'object' && !Array.isArray(v) ? (v as Record<string, unknown>) : {}\n }\n const ownKeys = (): string[] =>\n Object.keys(parent.errors)\n .filter((k) => k.startsWith(prefix))\n .map((k) => k.slice(prefix.length))\n\n // A live view over the parent's errors: reads go through the parent's\n // reactive map, so a component reading `errors.city` re-renders when\n // `errors['address.city']` changes.\n const errors = new Proxy({} as Record<string, string[]>, {\n get: (_t, key) => (typeof key === 'string' ? parent.errors[prefix + key] : undefined),\n has: (_t, key) => typeof key === 'string' && prefix + key in parent.errors,\n ownKeys: () => ownKeys(),\n getOwnPropertyDescriptor: (_t, key) =>\n typeof key === 'string' && prefix + key in parent.errors\n ? { enumerable: true, configurable: true, value: parent.errors[prefix + key] }\n : undefined,\n })\n\n const ctx: FormStateContext = {\n get state() {\n return obj()\n },\n errors,\n mode: parent.mode,\n setField(key, value) {\n parent.setField(name, { ...obj(), [key]: value })\n parent.setError(prefix + key, null)\n },\n getField(key) {\n return obj()[key]\n },\n setError(key, messages) {\n parent.setError(prefix + key, messages)\n },\n setErrors(next) {\n for (const key of ownKeys()) parent.setError(prefix + key, null)\n for (const [key, messages] of Object.entries(next)) parent.setError(prefix + key, messages)\n },\n clearErrors() {\n for (const key of ownKeys()) parent.setError(prefix + key, null)\n },\n }\n\n provide(FormStateKey, ctx)\n return ctx\n}\n"],"names":["FormStateKey","provideFormState","initial","initialErrors","mode","state","reactive","errors","ctx","name","value","messages","next","key","provide","useFormState","inject","tryUseFormState","provideScopedFormState","parent","prefix","obj","v","ownKeys","k","_t"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";const n=require("vue"),d=Symbol("admin.form-state");function y(e={},l={},c){const i=n.reactive(e),s=n.reactive({...l}),u={state:i,errors:s,mode:c,setField(o,r){i[o]=r,s[o]&&delete s[o]},getField(o){return i[o]},setError(o,r){r===null||r.length===0?delete s[o]:s[o]=r},setErrors(o){for(const r of Object.keys(s))delete s[r];Object.assign(s,o)},clearErrors(){for(const o of Object.keys(s))delete s[o]}};return n.provide(d,u),u}function F(){const e=n.inject(d);if(!e)throw new Error("useFormState() called outside of provideFormState() scope");return e}function v(){return n.inject(d,null)}function S(e,l){const c=`${l}.`,i=()=>{const r=e.getField(l);return r!==null&&typeof r=="object"&&!Array.isArray(r)?r:{}},s=()=>Object.keys(e.errors).filter(r=>r.startsWith(c)).map(r=>r.slice(c.length)),u=new Proxy({},{get:(r,t)=>typeof t=="string"?e.errors[c+t]:void 0,has:(r,t)=>typeof t=="string"&&c+t in e.errors,ownKeys:()=>s(),getOwnPropertyDescriptor:(r,t)=>typeof t=="string"&&c+t in e.errors?{enumerable:!0,configurable:!0,value:e.errors[c+t]}:void 0}),o={get state(){return i()},errors:u,mode:e.mode,setField(r,t){e.setField(l,{...i(),[r]:t}),e.setError(c+r,null)},getField(r){return i()[r]},setError(r,t){e.setError(c+r,t)},setErrors(r){for(const t of s())e.setError(c+t,null);for(const[t,f]of Object.entries(r))e.setError(c+t,f)},clearErrors(){for(const r of s())e.setError(c+r,null)}};return n.provide(d,o),o}exports.provideFormState=y;exports.provideScopedFormState=S;exports.tryUseFormState=v;exports.useFormState=F;
|
|
2
|
+
//# sourceMappingURL=formState-DqHe1Jgd.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formState-DqHe1Jgd.cjs","sources":["../resources/ts/components/render/formState.ts"],"sourcesContent":["/**\n * The form-state composable: it exposes the state and the errors through\n * provide/inject.\n *\n * The container — a resource form, a settings page — calls\n * `provideFormState()`, and the field components in the tree call\n * `useFormState()` to read a value and change a field.\n *\n * The state is a reactive proxy that setField mutates by key; the errors are a\n * separate reactive map of field name → string[] messages.\n */\n\nimport { inject, provide, reactive, type InjectionKey } from 'vue'\n\nexport interface FormStateContext {\n state: Record<string, unknown>\n errors: Record<string, string[]>\n /** The form's context: FieldRenderer hides the fields with visibility[mode]=false. */\n mode?: 'create' | 'update' | 'view'\n setField: (name: string, value: unknown) => void\n getField: (name: string) => unknown\n setError: (name: string, messages: string[] | null) => void\n setErrors: (next: Record<string, string[]>) => void\n clearErrors: () => void\n}\n\nconst FormStateKey: InjectionKey<FormStateContext> = Symbol('admin.form-state')\n\n/**\n * Creates the form context and provides it to the descendants.\n *\n * The `initial` object given is wrapped into `reactive()`, so the mutations are\n * visible from outside too: the caller owns the state and may read it after a\n * submit.\n *\n * @param initial The state's initial values.\n * @param initialErrors The initial errors, for a re-render after a\n * ValidationError.\n */\nexport function provideFormState(\n initial: Record<string, unknown> = {},\n initialErrors: Record<string, string[]> = {},\n mode?: 'create' | 'update' | 'view',\n): FormStateContext {\n const state = reactive(initial)\n const errors = reactive<Record<string, string[]>>({ ...initialErrors })\n\n const ctx: FormStateContext = {\n state,\n errors,\n mode,\n setField(name, value) {\n ;(state as Record<string, unknown>)[name] = value\n // Clear that field's errors as it changes, as one expects.\n if (errors[name]) {\n delete errors[name]\n }\n },\n getField(name) {\n return (state as Record<string, unknown>)[name]\n },\n setError(name, messages) {\n if (messages === null || messages.length === 0) {\n delete errors[name]\n } else {\n errors[name] = messages\n }\n },\n setErrors(next) {\n for (const key of Object.keys(errors)) delete errors[key]\n Object.assign(errors, next)\n },\n clearErrors() {\n for (const key of Object.keys(errors)) delete errors[key]\n },\n }\n\n provide(FormStateKey, ctx)\n return ctx\n}\n\n/**\n * Returns the form context. It throws when called outside a\n * `provideFormState()`.\n */\nexport function useFormState(): FormStateContext {\n const ctx = inject(FormStateKey)\n if (!ctx) {\n throw new Error('useFormState() called outside of provideFormState() scope')\n }\n return ctx\n}\n\n/** The optional form: null when there is none. */\nexport function tryUseFormState(): FormStateContext | null {\n return inject(FormStateKey, null)\n}\n\n/**\n * Provides a form context scoped to one object-valued field of `parent` — the\n * backend's Field\\Group, whose state is `{city: ..., street: ...}` under its\n * own name.\n *\n * Unlike NestedFieldsGroup this keeps no copy: every read and write goes to\n * `parent.state[name]`, and the errors are the parent's `name.child` keys —\n * the shape Laravel's validator reports them in — seen without the prefix.\n * Scopes nest: a group inside a group prefixes twice.\n */\nexport function provideScopedFormState(parent: FormStateContext, name: string): FormStateContext {\n const prefix = `${name}.`\n const obj = (): Record<string, unknown> => {\n const v = parent.getField(name)\n return v !== null && typeof v === 'object' && !Array.isArray(v) ? (v as Record<string, unknown>) : {}\n }\n const ownKeys = (): string[] =>\n Object.keys(parent.errors)\n .filter((k) => k.startsWith(prefix))\n .map((k) => k.slice(prefix.length))\n\n // A live view over the parent's errors: reads go through the parent's\n // reactive map, so a component reading `errors.city` re-renders when\n // `errors['address.city']` changes.\n const errors = new Proxy({} as Record<string, string[]>, {\n get: (_t, key) => (typeof key === 'string' ? parent.errors[prefix + key] : undefined),\n has: (_t, key) => typeof key === 'string' && prefix + key in parent.errors,\n ownKeys: () => ownKeys(),\n getOwnPropertyDescriptor: (_t, key) =>\n typeof key === 'string' && prefix + key in parent.errors\n ? { enumerable: true, configurable: true, value: parent.errors[prefix + key] }\n : undefined,\n })\n\n const ctx: FormStateContext = {\n get state() {\n return obj()\n },\n errors,\n mode: parent.mode,\n setField(key, value) {\n parent.setField(name, { ...obj(), [key]: value })\n parent.setError(prefix + key, null)\n },\n getField(key) {\n return obj()[key]\n },\n setError(key, messages) {\n parent.setError(prefix + key, messages)\n },\n setErrors(next) {\n for (const key of ownKeys()) parent.setError(prefix + key, null)\n for (const [key, messages] of Object.entries(next)) parent.setError(prefix + key, messages)\n },\n clearErrors() {\n for (const key of ownKeys()) parent.setError(prefix + key, null)\n },\n }\n\n provide(FormStateKey, ctx)\n return ctx\n}\n"],"names":["FormStateKey","provideFormState","initial","initialErrors","mode","state","reactive","errors","ctx","name","value","messages","next","key","provide","useFormState","inject","tryUseFormState","provideScopedFormState","parent","prefix","obj","v","ownKeys","k","_t"],"mappings":"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"}
|