@webx-ui/module-admin 0.14.4 → 0.16.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/dist/BackButton.d.ts +1 -1
- package/dist/DateText.d.ts +1 -1
- package/dist/HelpButton.d.ts +1 -1
- package/dist/LinkField.d.ts +1 -1
- package/dist/LinkPicker.d.ts +1 -1
- package/dist/RenameButton.d.ts +4 -4
- package/dist/RowMenu.d.ts +1 -1
- package/dist/Screen.d.ts +1 -1
- package/dist/SlugField.d.ts +2 -0
- package/dist/address.d.ts +25 -0
- package/dist/categories/CategoriesField.d.ts +29 -0
- package/dist/categories/CategoriesPage.d.ts +6 -0
- package/dist/categories/CategoryCreateDialog.d.ts +8 -0
- package/dist/categories/CategoryEditorPage.d.ts +6 -0
- package/dist/categories/api.d.ts +38 -0
- package/dist/categories/editor.d.ts +22 -0
- package/dist/categories/index.d.ts +6 -0
- package/dist/categories/ordering.d.ts +41 -0
- package/dist/categories/routes.d.ts +12 -0
- package/dist/categories/types.d.ts +68 -0
- package/dist/categories/words.d.ts +9 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +1664 -959
- package/dist/index.js.map +1 -1
- package/dist/screenTypes.d.ts +5 -0
- package/dist/style.css +1 -1
- package/package.json +2 -2
package/dist/BackButton.d.ts
CHANGED
|
@@ -19,7 +19,7 @@ type __VLS_Props = {
|
|
|
19
19
|
size?: ActionSize;
|
|
20
20
|
};
|
|
21
21
|
declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
22
|
-
size: ActionSize;
|
|
23
22
|
label: string;
|
|
23
|
+
size: ActionSize;
|
|
24
24
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
25
25
|
export default _default;
|
package/dist/DateText.d.ts
CHANGED
|
@@ -22,8 +22,8 @@ type __VLS_Props = {
|
|
|
22
22
|
tone?: TextTone;
|
|
23
23
|
};
|
|
24
24
|
declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
25
|
-
size: TextSize;
|
|
26
25
|
tone: TextTone;
|
|
26
|
+
size: TextSize;
|
|
27
27
|
compact: boolean;
|
|
28
28
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
29
29
|
export default _default;
|
package/dist/HelpButton.d.ts
CHANGED
|
@@ -24,8 +24,8 @@ type __VLS_Props = {
|
|
|
24
24
|
};
|
|
25
25
|
declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
26
26
|
title: string;
|
|
27
|
-
size: ActionSize;
|
|
28
27
|
label: string;
|
|
28
|
+
size: ActionSize;
|
|
29
29
|
width: number | string;
|
|
30
30
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
31
31
|
export default _default;
|
package/dist/LinkField.d.ts
CHANGED
|
@@ -14,8 +14,8 @@ declare const _default: import('vue').DefineComponent<__VLS_PublicProps, {}, {},
|
|
|
14
14
|
}, string, import('vue').PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
15
15
|
"onUpdate:modelValue"?: ((value: LinkValue | null) => any) | undefined;
|
|
16
16
|
}>, {
|
|
17
|
+
disabled: boolean;
|
|
17
18
|
allowNone: boolean;
|
|
18
19
|
attributes: boolean;
|
|
19
|
-
disabled: boolean;
|
|
20
20
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
21
21
|
export default _default;
|
package/dist/LinkPicker.d.ts
CHANGED
|
@@ -14,8 +14,8 @@ declare const _default: import('vue').DefineComponent<__VLS_PublicProps, {}, {},
|
|
|
14
14
|
}, string, import('vue').PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
15
15
|
"onUpdate:modelValue"?: ((value: LinkValue | null) => any) | undefined;
|
|
16
16
|
}>, {
|
|
17
|
+
disabled: boolean;
|
|
17
18
|
allowNone: boolean;
|
|
18
19
|
attributes: boolean;
|
|
19
|
-
disabled: boolean;
|
|
20
20
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
|
|
21
21
|
export default _default;
|
package/dist/RenameButton.d.ts
CHANGED
|
@@ -27,9 +27,9 @@ declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {
|
|
|
27
27
|
}>, {
|
|
28
28
|
name: string;
|
|
29
29
|
disabled: boolean;
|
|
30
|
-
placeholder: string;
|
|
31
|
-
size: ActionSize;
|
|
32
30
|
label: string;
|
|
31
|
+
size: ActionSize;
|
|
32
|
+
placeholder: string;
|
|
33
33
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
|
|
34
34
|
field: ({
|
|
35
35
|
$: import('vue').ComponentInternalInstance;
|
|
@@ -68,7 +68,7 @@ declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {
|
|
|
68
68
|
$root: import('vue').ComponentPublicInstance | null;
|
|
69
69
|
$parent: import('vue').ComponentPublicInstance | null;
|
|
70
70
|
$host: Element | null;
|
|
71
|
-
$emit: ((event: "update:modelValue", value: import('@webx-ui/core').InputModelValue) => void) & ((event: "
|
|
71
|
+
$emit: ((event: "update:modelValue", value: import('@webx-ui/core').InputModelValue) => void) & ((event: "input", value: string) => void) & ((event: "change", value: string) => void) & ((event: "clear") => void) & ((event: "focus", event: FocusEvent) => void) & ((event: "blur", event: FocusEvent) => void);
|
|
72
72
|
$el: any;
|
|
73
73
|
$options: import('vue').ComponentOptionsBase<Readonly<{
|
|
74
74
|
modelValue?: import('@webx-ui/core').InputModelValue;
|
|
@@ -148,7 +148,7 @@ declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {
|
|
|
148
148
|
onClear?: (() => any) | undefined;
|
|
149
149
|
onBlur?: ((event: FocusEvent) => any) | undefined;
|
|
150
150
|
onFocus?: ((event: FocusEvent) => any) | undefined;
|
|
151
|
-
}>, "
|
|
151
|
+
}>, "disabled" | "type" | "id" | "size" | "clearable" | "placeholder" | "status" | "ariaLabel" | "input" | "select" | "readonly" | "maxlength" | "showCount" | "autocomplete" | "localized" | "focus" | "blur"> & {
|
|
152
152
|
focus: () => void | undefined;
|
|
153
153
|
blur: () => void | undefined;
|
|
154
154
|
select: () => void | undefined;
|
package/dist/RowMenu.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ type __VLS_Props = {
|
|
|
8
8
|
size?: ActionSize;
|
|
9
9
|
};
|
|
10
10
|
declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
11
|
-
size: ActionSize;
|
|
12
11
|
label: string;
|
|
12
|
+
size: ActionSize;
|
|
13
13
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
14
14
|
export default _default;
|
package/dist/Screen.d.ts
CHANGED
|
@@ -33,7 +33,7 @@ declare const _default: import('vue').DefineComponent<__VLS_PublicProps, {
|
|
|
33
33
|
disabled: boolean;
|
|
34
34
|
size: "sm" | "md" | "lg";
|
|
35
35
|
errors: Record<string, string[]>;
|
|
36
|
-
labelPosition: "top" | "left";
|
|
37
36
|
labelWidth: string;
|
|
37
|
+
labelPosition: "top" | "left";
|
|
38
38
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
|
|
39
39
|
export default _default;
|
|
@@ -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,25 @@
|
|
|
1
|
+
import { InjectionKey, Ref } from 'vue';
|
|
2
|
+
import { ScreenModel } from '@webx-ui/schema';
|
|
3
|
+
/**
|
|
4
|
+
* What a record's editor knows about its address and a described screen cannot carry.
|
|
5
|
+
*
|
|
6
|
+
* The address of a service, a category, an article is the module's prefix and the record's slug.
|
|
7
|
+
* The slug is a field of the screen; the prefix is configuration the editor was handed with the
|
|
8
|
+
* record, and the address the site answers at right now is the registry's. `wx-slug` needs all
|
|
9
|
+
* three to print the whole address and to warn before it moves — so the page that hosts the
|
|
10
|
+
* screen provides them, the same way it provides the preview to `wx-blocks`.
|
|
11
|
+
*/
|
|
12
|
+
export interface RecordAddress {
|
|
13
|
+
/** The values of the screen as they are right now, edits included. */
|
|
14
|
+
values: Ref<ScreenModel>;
|
|
15
|
+
/** Where the module's addresses start: `services`, `''` for the root, `null` for none at all. */
|
|
16
|
+
prefix: Ref<string | null>;
|
|
17
|
+
/** The address the registry holds for the record in this language, without a leading slash. */
|
|
18
|
+
path: Ref<string | null | undefined>;
|
|
19
|
+
/** "The address is changing" — in the module's words. */
|
|
20
|
+
moving: () => string;
|
|
21
|
+
}
|
|
22
|
+
export declare const recordAddressKey: InjectionKey<RecordAddress>;
|
|
23
|
+
export declare function provideRecordAddress(address: RecordAddress): void;
|
|
24
|
+
/** The editor above this field, or `null` outside one — a demo, a test, a stray screen. */
|
|
25
|
+
export declare function useRecordAddress(): RecordAddress | null;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
/** The API the categories answer at, under the panel's: `blog/rubrics`. */
|
|
3
|
+
source: string;
|
|
4
|
+
/** Whether the first one is the main one, and wears the badge that says so. */
|
|
5
|
+
main?: boolean;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
mainText?: string;
|
|
8
|
+
addText?: string;
|
|
9
|
+
removeText?: string;
|
|
10
|
+
emptyText?: string;
|
|
11
|
+
noneLeftText?: string;
|
|
12
|
+
};
|
|
13
|
+
type __VLS_PublicProps = {
|
|
14
|
+
modelValue?: number[] | null;
|
|
15
|
+
} & __VLS_Props;
|
|
16
|
+
declare const _default: import('vue').DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
17
|
+
"update:modelValue": (value: number[] | null) => any;
|
|
18
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
19
|
+
"onUpdate:modelValue"?: ((value: number[] | null) => any) | undefined;
|
|
20
|
+
}>, {
|
|
21
|
+
main: boolean;
|
|
22
|
+
disabled: boolean;
|
|
23
|
+
mainText: string;
|
|
24
|
+
addText: string;
|
|
25
|
+
removeText: string;
|
|
26
|
+
emptyText: string;
|
|
27
|
+
noneLeftText: string;
|
|
28
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
|
|
29
|
+
export default _default;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { CategoriesOptions } from './types';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
options: CategoriesOptions;
|
|
4
|
+
};
|
|
5
|
+
declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
|
|
6
|
+
export default _default;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { CategoriesOptions } from './types';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
options: CategoriesOptions;
|
|
4
|
+
};
|
|
5
|
+
declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
|
|
6
|
+
field: HTMLDivElement;
|
|
7
|
+
}, any>;
|
|
8
|
+
export default _default;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { CategoriesOptions } from './types';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
options: CategoriesOptions;
|
|
4
|
+
};
|
|
5
|
+
declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
|
|
6
|
+
export default _default;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { ScreenModel } from '@webx-ui/schema';
|
|
2
|
+
import { AdminContext } from '../admin';
|
|
3
|
+
import { CategoriesPayload, CategoryDetail, CategoryRow } from './types';
|
|
4
|
+
/**
|
|
5
|
+
* The categories of one module, behind the routes `CategoryRoutes::register()` gives it.
|
|
6
|
+
*
|
|
7
|
+
* The path is the module's (`blog/rubrics`), the answers are everybody's: one controller serves
|
|
8
|
+
* every module, so one client does too.
|
|
9
|
+
*/
|
|
10
|
+
export interface CategoriesApi {
|
|
11
|
+
/** Every category, in the order of the site's menu. `q` narrows by name or address. */
|
|
12
|
+
list(query?: {
|
|
13
|
+
q?: string;
|
|
14
|
+
visible?: boolean;
|
|
15
|
+
}): Promise<CategoriesPayload>;
|
|
16
|
+
/** A name, and an address made of it unless one is given. */
|
|
17
|
+
create(input: {
|
|
18
|
+
title: string;
|
|
19
|
+
slug?: string;
|
|
20
|
+
}): Promise<CategoryRow>;
|
|
21
|
+
get(id: number): Promise<CategoryDetail>;
|
|
22
|
+
/** The values of the screen. A refused field comes back as a 422 under its name. */
|
|
23
|
+
save(id: number, values: ScreenModel): Promise<CategoryDetail>;
|
|
24
|
+
/** Into the bin — a 422 naming the number of items while it still holds any. */
|
|
25
|
+
remove(id: number): Promise<void>;
|
|
26
|
+
restore(id: number): Promise<CategoryRow>;
|
|
27
|
+
/** The whole order, as it is on screen. */
|
|
28
|
+
reorder(ids: number[]): Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
export declare function createCategoriesApi(admin: AdminContext, path: string): CategoriesApi;
|
|
31
|
+
/**
|
|
32
|
+
* The order of a module's records, written the way it is dragged (§2.5 of the services spec):
|
|
33
|
+
* without `category` the whole list, with it the order inside that one category.
|
|
34
|
+
*
|
|
35
|
+
* `path` is the module's list of records (`services/items`); the server half is
|
|
36
|
+
* `CategoryRoutes::items()`. A module that orders by date — the blog — never calls it.
|
|
37
|
+
*/
|
|
38
|
+
export declare function reorderItems(admin: AdminContext, path: string, ids: number[], category?: number | null): Promise<void>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { InjectionKey, Ref } from 'vue';
|
|
2
|
+
import { ScreenModel } from '@webx-ui/schema';
|
|
3
|
+
import { CategoryRow } from './types';
|
|
4
|
+
/**
|
|
5
|
+
* What the category editor knows and the nodes of its screen do not — the same seam the article
|
|
6
|
+
* editor has. `wx-category-slug` (`wx-slug`) prints the whole address, and the prefix of the module is
|
|
7
|
+
* configuration the editor was handed with the record, not something a description can carry.
|
|
8
|
+
*/
|
|
9
|
+
export interface CategoryEditorContext {
|
|
10
|
+
/** The category as the server last answered it, or `null` while the first request is out. */
|
|
11
|
+
category: Ref<CategoryRow | null>;
|
|
12
|
+
/** The values of the screen as they are right now, edits included. */
|
|
13
|
+
values: Ref<ScreenModel>;
|
|
14
|
+
/** Where the module's addresses start; `null` for categories without an address. */
|
|
15
|
+
prefix: Ref<string | null>;
|
|
16
|
+
/** "The address is changing" — in the module's words. */
|
|
17
|
+
moving: () => string;
|
|
18
|
+
}
|
|
19
|
+
export declare const categoryEditorKey: InjectionKey<CategoryEditorContext>;
|
|
20
|
+
export declare function provideCategoryEditor(editor: CategoryEditorContext): void;
|
|
21
|
+
/** The editor above this node, or `null` outside one — a demo, a test, a stray screen. */
|
|
22
|
+
export declare function useCategoryEditor(): CategoryEditorContext | null;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { createCategoriesApi, reorderItems, type CategoriesApi } from './api';
|
|
2
|
+
export { useCategoryEditor, type CategoryEditorContext } from './editor';
|
|
3
|
+
export { itemOrderMode, useItemOrder, type ItemOrder, type ItemOrderMode, type ItemOrderState, } from './ordering';
|
|
4
|
+
export { categoryRoutes } from './routes';
|
|
5
|
+
export { useCategoryWords } from './words';
|
|
6
|
+
export type { CategoriesOptions, CategoriesPayload, CategoryDetail, CategoryRow, CategoryWord, } from './types';
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { ComputedRef } from 'vue';
|
|
2
|
+
/**
|
|
3
|
+
* What the list of a module's records looks like right now, as far as its order is concerned.
|
|
4
|
+
*/
|
|
5
|
+
export interface ItemOrderState {
|
|
6
|
+
/** What is typed in the search box. */
|
|
7
|
+
q?: string | null;
|
|
8
|
+
/** The one category the list is narrowed to, if it is. */
|
|
9
|
+
category?: number | null;
|
|
10
|
+
/** Whether any filter other than the category is on — status, author, the bin. */
|
|
11
|
+
filtered?: boolean;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Which order a drag would write (decision 5 of the services spec).
|
|
15
|
+
*
|
|
16
|
+
* - `all` — the whole list is on screen, and dragging moves the common order;
|
|
17
|
+
* - `category` — one category and nothing else, and dragging moves that category's own order;
|
|
18
|
+
* - `locked` — a search or another filter is on, and the rows on screen are a selection: the
|
|
19
|
+
* gaps between them are records nobody can see, so a drag here would move them blind.
|
|
20
|
+
*/
|
|
21
|
+
export type ItemOrderMode = 'all' | 'category' | 'locked';
|
|
22
|
+
export declare function itemOrderMode(state: ItemOrderState): ItemOrderMode;
|
|
23
|
+
export interface ItemOrder {
|
|
24
|
+
mode: ComputedRef<ItemOrderMode>;
|
|
25
|
+
/** Whether the handles are drawn at all. */
|
|
26
|
+
sortable: ComputedRef<boolean>;
|
|
27
|
+
/** One line under the list: what a drag does here, or why there is nothing to drag. */
|
|
28
|
+
hint: ComputedRef<string>;
|
|
29
|
+
/** Write the order the rows are in on screen — the whole list, or the category's. */
|
|
30
|
+
move(ids: number[]): Promise<void>;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The order of a module's records, dragged in the list the editor is looking at.
|
|
34
|
+
*
|
|
35
|
+
* A composable rather than a component, because the list it belongs to is the module's own —
|
|
36
|
+
* a table, a sortable list, cards — and what is shared is the rule about which order a drag
|
|
37
|
+
* writes and the sentence that says so. `path` is the list's API (`services/items`), served by
|
|
38
|
+
* `CategoryRoutes::items()`. A module whose records are ordered by something else (the blog, by
|
|
39
|
+
* date) does not call it, and its list has no handles.
|
|
40
|
+
*/
|
|
41
|
+
export declare function useItemOrder(path: string, state: () => ItemOrderState): ItemOrder;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { RouteRecordRaw } from 'vue-router';
|
|
2
|
+
import { CategoriesOptions } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* The two screens of a module's categories — the list and the page of one — as routes to put
|
|
5
|
+
* into the module's section:
|
|
6
|
+
*
|
|
7
|
+
* { id: 'rubrics', path: '/blog/rubrics', routes: categoryRoutes({ api: 'blog/rubrics', … }) }
|
|
8
|
+
*
|
|
9
|
+
* One description for both, so the list links to the editor and the editor back to the list
|
|
10
|
+
* without either being told the other's address.
|
|
11
|
+
*/
|
|
12
|
+
export declare function categoryRoutes(options: CategoriesOptions): RouteRecordRaw[];
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { LocalizedValue } from '@webx-ui/core';
|
|
2
|
+
import { ScreenModel } from '@webx-ui/schema';
|
|
3
|
+
import { RouteLocationRaw } from 'vue-router';
|
|
4
|
+
/**
|
|
5
|
+
* One category as its list draws it — the same row for every module, because the server half is
|
|
6
|
+
* one controller (`WebxUi\Admin\Categories\Http\CategoryResource`).
|
|
7
|
+
*
|
|
8
|
+
* How many items are in it travels under the module's own word (`articles_count`), so it is not
|
|
9
|
+
* a field here: read it with {@link CategoriesOptions.count}.
|
|
10
|
+
*/
|
|
11
|
+
export interface CategoryRow {
|
|
12
|
+
id: number;
|
|
13
|
+
/** What to show: the title of this language, its address, or its number — in that order. */
|
|
14
|
+
name: string;
|
|
15
|
+
title: LocalizedValue | null;
|
|
16
|
+
slug: LocalizedValue | null;
|
|
17
|
+
/** `null` — no address in the language the panel is open in, or categories without addresses. */
|
|
18
|
+
path: string | null;
|
|
19
|
+
url: string | null;
|
|
20
|
+
is_visible: boolean;
|
|
21
|
+
position: number;
|
|
22
|
+
deleted_at: string | null;
|
|
23
|
+
}
|
|
24
|
+
export interface CategoriesPayload {
|
|
25
|
+
data: CategoryRow[];
|
|
26
|
+
/** Where the module's addresses start; `null` for categories without an address. */
|
|
27
|
+
prefix: string | null;
|
|
28
|
+
}
|
|
29
|
+
/** One category as its editor opens it: the row, the values of its screen and the prefix. */
|
|
30
|
+
export interface CategoryDetail {
|
|
31
|
+
category: CategoryRow;
|
|
32
|
+
values: ScreenModel;
|
|
33
|
+
prefix: string | null;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The words the shared screens say, by what they are for.
|
|
37
|
+
*
|
|
38
|
+
* Each is a full key — `webx-blog::rubric.new` — and every one has a default under
|
|
39
|
+
* `webx-admin::categories.*` that calls the thing a category. A module overrides the ones that
|
|
40
|
+
* name it: the blog says "rubric" and "articles", and keeps the panel's "Edit" and "Cancel".
|
|
41
|
+
*/
|
|
42
|
+
export type CategoryWord = 'new' | 'empty' | 'empty-help' | 'order' | 'hidden' | 'no-address' | 'count' | 'show-items' | 'edit' | 'open-on-site' | 'delete' | 'delete-blocked' | 'delete-title' | 'delete-text' | 'deleted' | 'cancel' | 'create' | 'save' | 'saved' | 'save-failed' | 'reorder-failed' | 'field-title' | 'field-slug' | 'address-moving' | 'untitled' | 'trail' | 'leave-title' | 'leave-text' | 'leave';
|
|
43
|
+
/**
|
|
44
|
+
* What a module says about its categories, once, for the list, the dialog and the editor.
|
|
45
|
+
*
|
|
46
|
+
* The server half reads the same things off `CategoryKind`; this is its front-end twin, and
|
|
47
|
+
* {@link categoryRoutes} is how a module mounts both screens from one description.
|
|
48
|
+
*/
|
|
49
|
+
export interface CategoriesOptions {
|
|
50
|
+
/** Under the panel's API path: `blog/rubrics`. */
|
|
51
|
+
api: string;
|
|
52
|
+
/** The list in the panel: `/blog/rubrics`. One category is edited at `{path}/{id}`. */
|
|
53
|
+
path: string;
|
|
54
|
+
/** The route names: `{name}` for the list, `{name}.edit` for the editor. */
|
|
55
|
+
name: string;
|
|
56
|
+
/** The module the list is — its title in the manifest is the heading of both screens. */
|
|
57
|
+
module: string;
|
|
58
|
+
/** The described screen of one category: `blog.category-form`. */
|
|
59
|
+
screen: string;
|
|
60
|
+
/** The permission everything that writes asks for. */
|
|
61
|
+
manage: string;
|
|
62
|
+
/** The key the number of items travels under: `articles_count`. */
|
|
63
|
+
count: string;
|
|
64
|
+
/** Where the items of one category are listed, for the row's menu. Left out, no such item. */
|
|
65
|
+
items?: (id: number) => RouteLocationRaw;
|
|
66
|
+
/** The module's own words over the panel's — see {@link CategoryWord}. */
|
|
67
|
+
words?: Partial<Record<CategoryWord, string>>;
|
|
68
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { CategoryWord } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* The shared screens' words, the module's where it has them and the panel's where it does not.
|
|
4
|
+
*
|
|
5
|
+
* The panel's say "category"; a module that calls them something else hands its own keys in,
|
|
6
|
+
* because a blog that says "rubric" on its list and "category" in the dialog over it has two
|
|
7
|
+
* words for one thing (CLAUDE.md §4 — the words of a shared component are the caller's).
|
|
8
|
+
*/
|
|
9
|
+
export declare function useCategoryWords(words?: Partial<Record<CategoryWord, string>>): (word: CategoryWord, params?: Record<string, string | number>) => string;
|
package/dist/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export { createNotesApi, type EntityNote, type NoteAuthor, type NotesApi } from
|
|
|
10
10
|
export { createLinksApi, emptyLink, type LinkCandidate, type LinkRel, type LinkSourceInfo, type LinkTarget, type LinkValue, type LinksApi, type ResolvedLink, } from './links';
|
|
11
11
|
export { createHttp, readCookie, HttpError, type Http, type HttpOptions, type RequestOptions, } from './http';
|
|
12
12
|
export { adminTypes } from './screenTypes';
|
|
13
|
+
export { categoryRoutes, createCategoriesApi, itemOrderMode, reorderItems, useCategoryEditor, useCategoryWords, useItemOrder, type CategoriesApi, type CategoriesOptions, type CategoriesPayload, type CategoryDetail, type CategoryEditorContext, type CategoryRow, type CategoryWord, type ItemOrder, type ItemOrderMode, type ItemOrderState, } from './categories';
|
|
13
14
|
export type { AdminModule, AdminStatus, AdminUser, Manifest, ManifestModule, NavEntry, PickedImage, RowAction, ScreenAction, AppliedFilter, } from './types';
|
|
14
15
|
export { default as AdminShell } from './AdminShell';
|
|
15
16
|
export { default as AdminNav } from './AdminNav';
|
|
@@ -30,3 +31,11 @@ export { default as WxBackupNote } from './BackupNote';
|
|
|
30
31
|
export { default as WxRichTextField } from './RichTextField';
|
|
31
32
|
export { default as WxLinkPicker } from './LinkPicker';
|
|
32
33
|
export { default as WxLinkField } from './LinkField';
|
|
34
|
+
export { default as WxCategoriesPage } from './categories/CategoriesPage';
|
|
35
|
+
export { default as WxCategoryCreateDialog } from './categories/CategoryCreateDialog';
|
|
36
|
+
export { default as WxCategoryEditorPage } from './categories/CategoryEditorPage';
|
|
37
|
+
export { default as WxCategoriesField } from './categories/CategoriesField';
|
|
38
|
+
export { default as WxSlugField } from './SlugField';
|
|
39
|
+
/** The shared address field under the name it was released with. */
|
|
40
|
+
export { default as WxCategorySlug } from './SlugField';
|
|
41
|
+
export { provideRecordAddress, recordAddressKey, useRecordAddress, type RecordAddress, } from './address';
|