@mano8/astro-media-m8 1.1.0 → 2.0.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 +54 -11
- package/dist/src/integration.d.ts.map +1 -1
- package/dist/src/integration.js +1 -0
- package/dist/src/integration.js.map +1 -1
- package/dist/src/runtime/api/categories.d.ts +14 -8
- package/dist/src/runtime/api/categories.d.ts.map +1 -1
- package/dist/src/runtime/api/categories.js +21 -8
- package/dist/src/runtime/api/categories.js.map +1 -1
- package/dist/src/runtime/api/index.d.ts +8 -0
- package/dist/src/runtime/api/index.d.ts.map +1 -1
- package/dist/src/runtime/api/index.js +8 -0
- package/dist/src/runtime/api/index.js.map +1 -1
- package/dist/src/runtime/api/transfer.d.ts +19 -0
- package/dist/src/runtime/api/transfer.d.ts.map +1 -0
- package/dist/src/runtime/api/transfer.js +48 -0
- package/dist/src/runtime/api/transfer.js.map +1 -0
- package/dist/src/runtime/client.d.ts.map +1 -1
- package/dist/src/runtime/client.js +7 -1
- package/dist/src/runtime/client.js.map +1 -1
- package/dist/src/runtime/compatibility.d.ts +6 -6
- package/dist/src/runtime/compatibility.d.ts.map +1 -1
- package/dist/src/runtime/compatibility.js +59 -7
- package/dist/src/runtime/compatibility.js.map +1 -1
- package/dist/src/runtime/errors.d.ts +20 -2
- package/dist/src/runtime/errors.d.ts.map +1 -1
- package/dist/src/runtime/errors.js +53 -2
- package/dist/src/runtime/errors.js.map +1 -1
- package/dist/src/runtime/hooks/index.d.ts +2 -0
- package/dist/src/runtime/hooks/index.d.ts.map +1 -1
- package/dist/src/runtime/hooks/index.js +2 -0
- package/dist/src/runtime/hooks/index.js.map +1 -1
- package/dist/src/runtime/hooks/useMediaCategories.d.ts +30 -0
- package/dist/src/runtime/hooks/useMediaCategories.d.ts.map +1 -0
- package/dist/src/runtime/hooks/useMediaCategories.js +56 -0
- package/dist/src/runtime/hooks/useMediaCategories.js.map +1 -0
- package/dist/src/runtime/hooks/useMediaObjects.d.ts.map +1 -1
- package/dist/src/runtime/hooks/useMediaObjects.js +14 -2
- package/dist/src/runtime/hooks/useMediaObjects.js.map +1 -1
- package/dist/src/runtime/hooks/useMediaTransfer.d.ts +42 -0
- package/dist/src/runtime/hooks/useMediaTransfer.d.ts.map +1 -0
- package/dist/src/runtime/hooks/useMediaTransfer.js +106 -0
- package/dist/src/runtime/hooks/useMediaTransfer.js.map +1 -0
- package/dist/src/runtime/queryKeys.d.ts +2 -0
- package/dist/src/runtime/queryKeys.d.ts.map +1 -1
- package/dist/src/runtime/queryKeys.js +2 -0
- package/dist/src/runtime/queryKeys.js.map +1 -1
- package/dist/src/runtime/react/CategoryManager.d.ts +10 -0
- package/dist/src/runtime/react/CategoryManager.d.ts.map +1 -0
- package/dist/src/runtime/react/CategoryManager.js +194 -0
- package/dist/src/runtime/react/CategoryManager.js.map +1 -0
- package/dist/src/runtime/react/CategoryMultiSelect.d.ts +73 -0
- package/dist/src/runtime/react/CategoryMultiSelect.d.ts.map +1 -0
- package/dist/src/runtime/react/CategoryMultiSelect.js +179 -0
- package/dist/src/runtime/react/CategoryMultiSelect.js.map +1 -0
- package/dist/src/runtime/react/MediaCategoryTreePane.d.ts +22 -0
- package/dist/src/runtime/react/MediaCategoryTreePane.d.ts.map +1 -0
- package/dist/src/runtime/react/MediaCategoryTreePane.js +244 -0
- package/dist/src/runtime/react/MediaCategoryTreePane.js.map +1 -0
- package/dist/src/runtime/react/MediaErrorBoundary.d.ts +53 -0
- package/dist/src/runtime/react/MediaErrorBoundary.d.ts.map +1 -0
- package/dist/src/runtime/react/MediaErrorBoundary.js +58 -0
- package/dist/src/runtime/react/MediaErrorBoundary.js.map +1 -0
- package/dist/src/runtime/react/MediaLibrary.d.ts +16 -1
- package/dist/src/runtime/react/MediaLibrary.d.ts.map +1 -1
- package/dist/src/runtime/react/MediaLibrary.js +75 -110
- package/dist/src/runtime/react/MediaLibrary.js.map +1 -1
- package/dist/src/runtime/react/MediaObjectViews.d.ts +47 -0
- package/dist/src/runtime/react/MediaObjectViews.d.ts.map +1 -0
- package/dist/src/runtime/react/MediaObjectViews.js +131 -0
- package/dist/src/runtime/react/MediaObjectViews.js.map +1 -0
- package/dist/src/runtime/react/MediaTransferPanel.d.ts +17 -0
- package/dist/src/runtime/react/MediaTransferPanel.d.ts.map +1 -0
- package/dist/src/runtime/react/MediaTransferPanel.js +93 -0
- package/dist/src/runtime/react/MediaTransferPanel.js.map +1 -0
- package/dist/src/runtime/react/MediaUploadDropzone.d.ts +36 -1
- package/dist/src/runtime/react/MediaUploadDropzone.d.ts.map +1 -1
- package/dist/src/runtime/react/MediaUploadDropzone.js +63 -3
- package/dist/src/runtime/react/MediaUploadDropzone.js.map +1 -1
- package/dist/src/runtime/react/ObjectDetail.d.ts.map +1 -1
- package/dist/src/runtime/react/ObjectDetail.js +51 -1
- package/dist/src/runtime/react/ObjectDetail.js.map +1 -1
- package/dist/src/runtime/react/categoryBranch.d.ts +38 -0
- package/dist/src/runtime/react/categoryBranch.d.ts.map +1 -0
- package/dist/src/runtime/react/categoryBranch.js +37 -0
- package/dist/src/runtime/react/categoryBranch.js.map +1 -0
- package/dist/src/runtime/react/default-ui/index.d.ts +6 -2
- package/dist/src/runtime/react/default-ui/index.d.ts.map +1 -1
- package/dist/src/runtime/react/default-ui/index.js +14 -9
- package/dist/src/runtime/react/default-ui/index.js.map +1 -1
- package/dist/src/runtime/react/index.d.ts +5 -2
- package/dist/src/runtime/react/index.d.ts.map +1 -1
- package/dist/src/runtime/react/index.js +3 -0
- package/dist/src/runtime/react/index.js.map +1 -1
- package/dist/src/runtime/react/mediaLibraryLabels.d.ts +93 -0
- package/dist/src/runtime/react/mediaLibraryLabels.d.ts.map +1 -0
- package/dist/src/runtime/react/mediaLibraryLabels.js +100 -0
- package/dist/src/runtime/react/mediaLibraryLabels.js.map +1 -0
- package/dist/src/runtime/react/mediaLibraryStyles.d.ts +44 -0
- package/dist/src/runtime/react/mediaLibraryStyles.d.ts.map +1 -0
- package/dist/src/runtime/react/mediaLibraryStyles.js +82 -0
- package/dist/src/runtime/react/mediaLibraryStyles.js.map +1 -0
- package/dist/src/runtime/routes.d.ts +2 -0
- package/dist/src/runtime/routes.d.ts.map +1 -1
- package/dist/src/runtime/routes.js +2 -0
- package/dist/src/runtime/routes.js.map +1 -1
- package/dist/src/runtime/schemas.d.ts +265 -0
- package/dist/src/runtime/schemas.d.ts.map +1 -1
- package/dist/src/runtime/schemas.js +173 -6
- package/dist/src/runtime/schemas.js.map +1 -1
- package/dist/src/runtime/upload/uploadController.d.ts +7 -0
- package/dist/src/runtime/upload/uploadController.d.ts.map +1 -1
- package/dist/src/runtime/upload/uploadController.js +10 -5
- package/dist/src/runtime/upload/uploadController.js.map +1 -1
- package/package.json +37 -30
- package/registry/r/media-category-tree.json +21 -0
- package/registry/r/media-dashboard-overview.json +1 -1
- package/registry/r/media-library-tree.json +25 -0
- package/registry/r/media-maintenance-panel.json +3 -2
- package/registry/r/media-transfer-dialog.json +26 -0
- package/registry/r/registry.json +18 -0
- package/registry.json +61 -1
- package/src/routes/categories.astro +12 -0
- package/src/scaffold/styles/media.css +395 -5
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo, useState } from "react";
|
|
3
|
+
import { useCategoryTree } from "../hooks/useMediaCategories.js";
|
|
4
|
+
import { ApiError, messageFromDetail } from "../errors.js";
|
|
5
|
+
import { collectCategoryPaths } from "./CategoryMultiSelect.js";
|
|
6
|
+
const inputClassName = "fa-media-control h-8 w-full min-w-0 rounded-lg border border-input bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40";
|
|
7
|
+
const labelClassName = "fa-media-label flex items-center gap-2 pb-2 text-sm leading-none font-medium select-none";
|
|
8
|
+
/**
|
|
9
|
+
* Copy for the refusals the category CRUD surface can answer (`U4`): an
|
|
10
|
+
* unknown/foreign parent, or a structural conflict — a cycle, a cross-tenant
|
|
11
|
+
* parent, a taken sibling name, or a delete blocked by existing children. The
|
|
12
|
+
* 409 case always surfaces the server's own message: those four conflicts
|
|
13
|
+
* each read as a distinct, already-human sentence
|
|
14
|
+
* ("Category has child categories; reparent or delete them first.", "That
|
|
15
|
+
* name is taken among its siblings.", …), and re-wording them here would
|
|
16
|
+
* drift from whichever one the server actually raised.
|
|
17
|
+
*/
|
|
18
|
+
function describeCategoryError(error) {
|
|
19
|
+
if (error instanceof ApiError) {
|
|
20
|
+
if (error.status === 404)
|
|
21
|
+
return "That parent category no longer exists. Refresh and try again.";
|
|
22
|
+
if (error.status === 403)
|
|
23
|
+
return "That parent category is not yours to use.";
|
|
24
|
+
if (error.status === 409) {
|
|
25
|
+
return messageFromDetail(error.detail) ?? "That change conflicts with the existing category tree.";
|
|
26
|
+
}
|
|
27
|
+
return messageFromDetail(error.detail) ?? error.message;
|
|
28
|
+
}
|
|
29
|
+
return error instanceof Error ? error.message : "Failed to save the category";
|
|
30
|
+
}
|
|
31
|
+
/** Every category as a flattened `{id, path}` option, plus a root option. */
|
|
32
|
+
function parentOptions(tree) {
|
|
33
|
+
const paths = collectCategoryPaths(tree);
|
|
34
|
+
const options = [{ id: null, label: "— Root —" }];
|
|
35
|
+
for (const option of paths.values()) {
|
|
36
|
+
options.push({ id: option.id, label: option.path });
|
|
37
|
+
}
|
|
38
|
+
return options;
|
|
39
|
+
}
|
|
40
|
+
function findNode(nodes, id) {
|
|
41
|
+
for (const node of nodes) {
|
|
42
|
+
if (node.id === id)
|
|
43
|
+
return node;
|
|
44
|
+
const found = findNode(node.children, id);
|
|
45
|
+
if (found)
|
|
46
|
+
return found;
|
|
47
|
+
}
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* One category row plus its subtree. Rename, reparent and delete are each a
|
|
52
|
+
* plain form action — no drag-and-drop (decided 2026-08-18) — so a cycle,
|
|
53
|
+
* cross-tenant parent, taken-sibling-name or has-children refusal is just the
|
|
54
|
+
* mutation's promise rejecting; the server stays the single source of truth
|
|
55
|
+
* for every structural guard, this row only surfaces what it says.
|
|
56
|
+
*/
|
|
57
|
+
/**
|
|
58
|
+
* The busy/error state every row mutation shares, plus the three mutations
|
|
59
|
+
* themselves. Each one reports the server's refusal through `rowError` rather
|
|
60
|
+
* than throwing on: a rejected rename, reparent or delete is a message on the
|
|
61
|
+
* row it belongs to, never a torn-down subtree.
|
|
62
|
+
*/
|
|
63
|
+
function useRowMutations(node, props) {
|
|
64
|
+
const [busy, setBusy] = useState(false);
|
|
65
|
+
const [rowError, setRowError] = useState(null);
|
|
66
|
+
async function guard(action) {
|
|
67
|
+
setBusy(true);
|
|
68
|
+
setRowError(null);
|
|
69
|
+
try {
|
|
70
|
+
await action();
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
setRowError(describeCategoryError(error));
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
finally {
|
|
78
|
+
setBusy(false);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
busy,
|
|
83
|
+
rowError,
|
|
84
|
+
rename: (name) => guard(() => props.onRename(node.id, name)),
|
|
85
|
+
reparent: (parentId) => guard(() => props.onReparent(node.id, parentId)),
|
|
86
|
+
remove: () => guard(() => props.onDelete(node.id))
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/** The row in its rename state: a single text input and its two actions. */
|
|
90
|
+
function RowRenameForm({ node, busy, onSave, onCancel }) {
|
|
91
|
+
const [draftName, setDraftName] = useState(node.name);
|
|
92
|
+
const nameInputId = `fa-media-category-manager-name-${node.id}`;
|
|
93
|
+
return (_jsxs(_Fragment, { children: [_jsx("label", { className: "fa-media-category-manager-sr-label", htmlFor: nameInputId, children: `Rename ${node.name}` }), _jsx("input", { id: nameInputId, className: inputClassName, value: draftName, disabled: busy, onChange: (event) => setDraftName(event.currentTarget.value) }), _jsx("button", { type: "button", disabled: busy, onClick: () => onSave(draftName), children: "Save" }), _jsx("button", { type: "button", disabled: busy, onClick: onCancel, children: "Cancel" })] }));
|
|
94
|
+
}
|
|
95
|
+
/** The row at rest: name, count, and the rename/add-child/reparent/delete actions. */
|
|
96
|
+
function RowActions({ node, options, busy, onStartRename, onAddChild, onReparent, onDelete }) {
|
|
97
|
+
// A node cannot be its own parent — the one cycle worth foreclosing
|
|
98
|
+
// client-side. Every deeper cycle (reparenting under a descendant) is left
|
|
99
|
+
// to the server's 409, surfaced on the row.
|
|
100
|
+
const reparentOptions = options.filter((option) => option.id !== node.id);
|
|
101
|
+
const parentSelectId = `fa-media-category-manager-parent-${node.id}`;
|
|
102
|
+
return (_jsxs(_Fragment, { children: [_jsx("span", { className: "fa-media-category-manager-name", children: node.name }), _jsx("span", { className: "fa-media-badge fa-media-category-count", children: node.total_object_count }), _jsx("button", { type: "button", disabled: busy, onClick: onStartRename, children: "Rename" }), _jsx("button", { type: "button", disabled: busy, onClick: () => onAddChild(node.id), children: "Add child" }), _jsxs("label", { className: "fa-media-category-manager-reparent-label", htmlFor: parentSelectId, children: ["Parent", _jsx("select", { id: parentSelectId, className: inputClassName, disabled: busy, value: node.parent_id ?? "", onChange: (event) => {
|
|
103
|
+
const value = event.currentTarget.value;
|
|
104
|
+
onReparent(value === "" ? null : Number(value));
|
|
105
|
+
}, children: reparentOptions.map((option) => (_jsx("option", { value: option.id ?? "", children: option.label }, option.id ?? "root"))) })] }), _jsx("button", { type: "button", disabled: busy, onClick: onDelete, children: "Delete" })] }));
|
|
106
|
+
}
|
|
107
|
+
function CategoryManagerRow(props) {
|
|
108
|
+
const { node, depth, options, onAddChild } = props;
|
|
109
|
+
const [renaming, setRenaming] = useState(false);
|
|
110
|
+
const { busy, rowError, rename, reparent, remove } = useRowMutations(node, props);
|
|
111
|
+
// An empty or unchanged name is not a rename — leave the row as it was
|
|
112
|
+
// rather than sending the server a no-op it would have to answer.
|
|
113
|
+
async function saveRename(draft) {
|
|
114
|
+
const trimmed = draft.trim();
|
|
115
|
+
if (!trimmed || trimmed === node.name) {
|
|
116
|
+
setRenaming(false);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (await rename(trimmed))
|
|
120
|
+
setRenaming(false);
|
|
121
|
+
}
|
|
122
|
+
return (_jsxs("li", { className: "fa-media-category-manager-node", "aria-level": depth, children: [_jsx("div", { className: "fa-media-category-manager-row", children: renaming ? (_jsx(RowRenameForm, { node: node, busy: busy, onSave: (draft) => void saveRename(draft), onCancel: () => setRenaming(false) }, node.name)) : (_jsx(RowActions, { node: node, options: options, busy: busy, onStartRename: () => setRenaming(true), onAddChild: onAddChild, onReparent: (parentId) => {
|
|
123
|
+
if (parentId !== node.parent_id)
|
|
124
|
+
void reparent(parentId);
|
|
125
|
+
}, onDelete: () => void remove() })) }), rowError ? (_jsx("p", { role: "alert", className: "fa-media-category-manager-error", children: rowError })) : null, node.children.length > 0 ? (_jsx("ul", { className: "fa-media-category-manager-children", children: node.children.map((child) => (_jsx(CategoryManagerRow, { ...props, node: child, depth: depth + 1 }, child.id))) })) : null] }));
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Create/rename/reparent/delete over the caller's user category tree
|
|
129
|
+
* (`useCategoryTree`). Reparenting and deleting are plain form actions, not
|
|
130
|
+
* drag-and-drop, per the 2026-08-18 decision — this keeps the manager
|
|
131
|
+
* Sonnet-scale and sidesteps the a11y/touch surface a draggable tree would
|
|
132
|
+
* need. This component owns CRUD only; browsing/filtering the tree is `U7`'s
|
|
133
|
+
* job on `MediaLibrary`.
|
|
134
|
+
*/
|
|
135
|
+
export function CategoryManager() {
|
|
136
|
+
const { tree, count, loading, error, create, update, remove } = useCategoryTree();
|
|
137
|
+
const options = useMemo(() => parentOptions(tree), [tree]);
|
|
138
|
+
const createForm = useCreateForm(create);
|
|
139
|
+
const loadErrorMessage = describeLoadError(error);
|
|
140
|
+
// Rename and reparent are the same `PUT` with one half held constant, so each
|
|
141
|
+
// reads the node's current other half back out of the tree first.
|
|
142
|
+
async function rename(id, name) {
|
|
143
|
+
await update(id, { name, parent_id: findNode(tree, id)?.parent_id ?? null });
|
|
144
|
+
}
|
|
145
|
+
async function reparent(id, parentId) {
|
|
146
|
+
await update(id, { name: findNode(tree, id)?.name ?? "", parent_id: parentId });
|
|
147
|
+
}
|
|
148
|
+
return (_jsxs("section", { className: "not-content fa-media-panel", children: [_jsx("h2", { children: "Categories" }), loadErrorMessage ? _jsx("p", { role: "alert", children: loadErrorMessage }) : null, !loading && !loadErrorMessage && tree.length === 0 ? (_jsx("p", { className: "fa-media-category-hint", children: "No user categories yet. Create one below." })) : null, tree.length > 0 ? (_jsx("ul", { className: "fa-media-category-manager-tree", children: tree.map((node) => (_jsx(CategoryManagerRow, { node: node, depth: 1, options: options, onRename: rename, onReparent: reparent, onDelete: remove, onAddChild: createForm.addChildTo }, node.id))) })) : null, _jsx(CategoryCreateForm, { form: createForm, options: options, count: count })] }));
|
|
149
|
+
}
|
|
150
|
+
function describeLoadError(error) {
|
|
151
|
+
if (!error)
|
|
152
|
+
return null;
|
|
153
|
+
const detail = error instanceof ApiError ? messageFromDetail(error.detail) : null;
|
|
154
|
+
if (detail)
|
|
155
|
+
return detail;
|
|
156
|
+
return error instanceof Error ? error.message : "Failed to load categories";
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* The one create form the manager owns. "Add child" on a row pre-selects that
|
|
160
|
+
* row as this form's parent — one form, not a second inline one per node.
|
|
161
|
+
*/
|
|
162
|
+
function useCreateForm(create) {
|
|
163
|
+
const [name, setName] = useState("");
|
|
164
|
+
const [parentId, setParentId] = useState("");
|
|
165
|
+
const [busy, setBusy] = useState(false);
|
|
166
|
+
const [error, setError] = useState(null);
|
|
167
|
+
async function submit() {
|
|
168
|
+
const trimmed = name.trim();
|
|
169
|
+
if (!trimmed)
|
|
170
|
+
return;
|
|
171
|
+
setBusy(true);
|
|
172
|
+
setError(null);
|
|
173
|
+
try {
|
|
174
|
+
await create({ name: trimmed, parent_id: parentId === "" ? null : Number(parentId) });
|
|
175
|
+
setName("");
|
|
176
|
+
setParentId("");
|
|
177
|
+
}
|
|
178
|
+
catch (failure) {
|
|
179
|
+
setError(describeCategoryError(failure));
|
|
180
|
+
}
|
|
181
|
+
finally {
|
|
182
|
+
setBusy(false);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
function addChildTo(nextParentId) {
|
|
186
|
+
setParentId(String(nextParentId));
|
|
187
|
+
setError(null);
|
|
188
|
+
}
|
|
189
|
+
return { name, setName, parentId, setParentId, busy, error, submit, addChildTo };
|
|
190
|
+
}
|
|
191
|
+
function CategoryCreateForm({ form, options, count }) {
|
|
192
|
+
return (_jsxs("fieldset", { className: "fa-media-category-manager-create", children: [_jsx("legend", { children: `New category (${count} total)` }), _jsxs("div", { className: "fa-media-field-control", children: [_jsx("label", { className: labelClassName, htmlFor: "fa-media-category-manager-new-name", children: "Name" }), _jsx("input", { id: "fa-media-category-manager-new-name", className: inputClassName, value: form.name, disabled: form.busy, onChange: (event) => form.setName(event.currentTarget.value) })] }), _jsxs("div", { className: "fa-media-field-control", children: [_jsx("label", { className: labelClassName, htmlFor: "fa-media-category-manager-new-parent", children: "Parent" }), _jsx("select", { id: "fa-media-category-manager-new-parent", className: inputClassName, value: form.parentId, disabled: form.busy, onChange: (event) => form.setParentId(event.currentTarget.value), children: options.map((option) => (_jsx("option", { value: option.id ?? "", children: option.label }, option.id ?? "root"))) })] }), _jsx("button", { type: "button", disabled: form.busy || !form.name.trim(), onClick: () => void form.submit(), children: form.busy ? "Creating…" : "Add category" }), form.error ? _jsx("p", { role: "alert", children: form.error }) : null] }));
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=CategoryManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CategoryManager.js","sourceRoot":"","sources":["../../../../src/runtime/react/CategoryManager.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { CategoryNode } from "../schemas.js";
|
|
2
|
+
/**
|
|
3
|
+
* A resolved selection entry: the category id plus the slash-joined name path
|
|
4
|
+
* used as chip copy (`"Invoices / 2026"`), mirroring the server's
|
|
5
|
+
* `MediaObjectCategoryRef.path`.
|
|
6
|
+
*/
|
|
7
|
+
export type CategoryPathOption = {
|
|
8
|
+
id: number;
|
|
9
|
+
name: string;
|
|
10
|
+
path: string;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Flatten a nested tree into an id -> `{name, path}` map. Kept as a `Map` (not
|
|
14
|
+
* a plain object) so a lookup never becomes computed member access on a
|
|
15
|
+
* server-supplied key — `eslint-plugin-security`'s object-injection rule is on
|
|
16
|
+
* here, and a `Map` is the right structure for a numeric key anyway.
|
|
17
|
+
*/
|
|
18
|
+
export declare function collectCategoryPaths(nodes: readonly CategoryNode[], prefix?: string, into?: Map<number, CategoryPathOption>): Map<number, CategoryPathOption>;
|
|
19
|
+
/**
|
|
20
|
+
* Compare two `category_ids` selections as sets, so a caller can tell "the user
|
|
21
|
+
* changed the filing" from "the user toggled one off and back on". Exported
|
|
22
|
+
* because `ObjectDetail` needs exactly this to drive its dirty state, and
|
|
23
|
+
* because `PATCH` set semantics (`U4`) make order meaningless on the wire.
|
|
24
|
+
*/
|
|
25
|
+
export declare function isSameCategorySelection(left: readonly number[], right: readonly number[]): boolean;
|
|
26
|
+
export interface CategoryMultiSelectLabels {
|
|
27
|
+
legend: string;
|
|
28
|
+
emptyHint: string;
|
|
29
|
+
expand: (name: string) => string;
|
|
30
|
+
collapse: (name: string) => string;
|
|
31
|
+
descendantSelected: string;
|
|
32
|
+
loadError: string;
|
|
33
|
+
loading: string;
|
|
34
|
+
selected: string;
|
|
35
|
+
remove: (path: string) => string;
|
|
36
|
+
clearAll: string;
|
|
37
|
+
noneSelected: string;
|
|
38
|
+
}
|
|
39
|
+
export type CategoryMultiSelectViewProps = {
|
|
40
|
+
/** The currently selected user-category ids — the `category_ids` payload. */
|
|
41
|
+
value: readonly number[];
|
|
42
|
+
onChange: (next: number[]) => void;
|
|
43
|
+
tree: readonly CategoryNode[];
|
|
44
|
+
loading?: boolean;
|
|
45
|
+
error?: unknown;
|
|
46
|
+
disabled?: boolean;
|
|
47
|
+
/** Fieldset legend; the picker is optional everywhere it is used today. */
|
|
48
|
+
legend?: string;
|
|
49
|
+
/** Copy shown when the caller has no user categories yet. */
|
|
50
|
+
emptyHint?: string;
|
|
51
|
+
/**
|
|
52
|
+
* Labels for ids that are selected but absent from the tree — e.g. an object
|
|
53
|
+
* filed into a category the tree request has not resolved yet. Keeps a chip
|
|
54
|
+
* from degrading to a bare id.
|
|
55
|
+
*/
|
|
56
|
+
fallbackLabels?: ReadonlyMap<number, string>;
|
|
57
|
+
/** Prefix for the generated element ids; must be unique per mounted picker. */
|
|
58
|
+
idPrefix?: string;
|
|
59
|
+
labels?: Partial<CategoryMultiSelectLabels>;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Presentational multi-select nested category picker: a checkbox tree plus a
|
|
63
|
+
* chip list of the current selection. Fully controlled — it holds no selection
|
|
64
|
+
* state of its own, only expand/collapse.
|
|
65
|
+
*/
|
|
66
|
+
export declare function CategoryMultiSelectView(props: CategoryMultiSelectViewProps): import("react").JSX.Element;
|
|
67
|
+
export type CategoryMultiSelectProps = Omit<CategoryMultiSelectViewProps, "tree" | "loading" | "error">;
|
|
68
|
+
/**
|
|
69
|
+
* The picker wired to `useCategoryTree()`. Use this on a page; use
|
|
70
|
+
* `CategoryMultiSelectView` when the tree is already in hand (or under test).
|
|
71
|
+
*/
|
|
72
|
+
export declare function CategoryMultiSelect(props: CategoryMultiSelectProps): import("react").JSX.Element;
|
|
73
|
+
//# sourceMappingURL=CategoryMultiSelect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CategoryMultiSelect.d.ts","sourceRoot":"","sources":["../../../../src/runtime/react/CategoryMultiSelect.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAKlD;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,SAAS,YAAY,EAAE,EAC9B,MAAM,SAAK,EACX,IAAI,GAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAa,GAChD,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAOjC;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAIlG;AA2BD,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACjC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACnC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB;AAsGD,MAAM,MAAM,4BAA4B,GAAG;IACzC,6EAA6E;IAC7E,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACnC,IAAI,EAAE,SAAS,YAAY,EAAE,CAAC;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,cAAc,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7C,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC,yBAAyB,CAAC,CAAC;CAC7C,CAAC;AA6BF;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,4BAA4B,+BAoD1E;AAyHD,MAAM,MAAM,wBAAwB,GAAG,IAAI,CACzC,4BAA4B,EAC5B,MAAM,GAAG,SAAS,GAAG,OAAO,CAC7B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,+BAGlE"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useMemo, useState } from "react";
|
|
3
|
+
import { useCategoryTree } from "../hooks/useMediaCategories.js";
|
|
4
|
+
import { ApiError, messageFromDetail } from "../errors.js";
|
|
5
|
+
const labelClassName = "fa-media-label flex items-center gap-2 text-sm leading-none font-medium select-none";
|
|
6
|
+
/**
|
|
7
|
+
* Flatten a nested tree into an id -> `{name, path}` map. Kept as a `Map` (not
|
|
8
|
+
* a plain object) so a lookup never becomes computed member access on a
|
|
9
|
+
* server-supplied key — `eslint-plugin-security`'s object-injection rule is on
|
|
10
|
+
* here, and a `Map` is the right structure for a numeric key anyway.
|
|
11
|
+
*/
|
|
12
|
+
export function collectCategoryPaths(nodes, prefix = "", into = new Map()) {
|
|
13
|
+
for (const node of nodes) {
|
|
14
|
+
const path = prefix ? `${prefix} / ${node.name}` : node.name;
|
|
15
|
+
into.set(node.id, { id: node.id, name: node.name, path });
|
|
16
|
+
collectCategoryPaths(node.children, path, into);
|
|
17
|
+
}
|
|
18
|
+
return into;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Compare two `category_ids` selections as sets, so a caller can tell "the user
|
|
22
|
+
* changed the filing" from "the user toggled one off and back on". Exported
|
|
23
|
+
* because `ObjectDetail` needs exactly this to drive its dirty state, and
|
|
24
|
+
* because `PATCH` set semantics (`U4`) make order meaningless on the wire.
|
|
25
|
+
*/
|
|
26
|
+
export function isSameCategorySelection(left, right) {
|
|
27
|
+
if (left.length !== right.length)
|
|
28
|
+
return false;
|
|
29
|
+
const seen = new Set(right);
|
|
30
|
+
return left.every((id) => seen.has(id));
|
|
31
|
+
}
|
|
32
|
+
function hasSelectedDescendant(nodes, selected) {
|
|
33
|
+
return nodes.some((node) => selected.has(node.id) || hasSelectedDescendant(node.children, selected));
|
|
34
|
+
}
|
|
35
|
+
const DEFAULT_LABELS = {
|
|
36
|
+
legend: "User categories (optional)",
|
|
37
|
+
emptyHint: "No user categories yet. Create one from the category manager to file media here.",
|
|
38
|
+
expand: (name) => `Expand ${name}`,
|
|
39
|
+
collapse: (name) => `Collapse ${name}`,
|
|
40
|
+
descendantSelected: "A category below this one is selected",
|
|
41
|
+
loadError: "Failed to load categories",
|
|
42
|
+
loading: "Loading categories…",
|
|
43
|
+
selected: "Selected categories",
|
|
44
|
+
remove: (path) => `Remove ${path}`,
|
|
45
|
+
clearAll: "Clear all",
|
|
46
|
+
noneSelected: "No user categories selected."
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* One tree row plus its subtree.
|
|
50
|
+
*
|
|
51
|
+
* The picker is a **form control**, not the navigation tree `U6`/`U7` own, so
|
|
52
|
+
* it is built from native checkboxes inside nested lists rather than
|
|
53
|
+
* `role="tree"` + roving tabindex: a native checkbox already carries focus,
|
|
54
|
+
* keyboard toggling and checked-state announcements, and layering a
|
|
55
|
+
* single-selection tree pattern over it would take those away. Nesting and
|
|
56
|
+
* depth stay conveyable through plain nested `<ul>`s plus `aria-level` — the
|
|
57
|
+
* list role is left implicit on purpose, since an explicit `role="group"` on
|
|
58
|
+
* the `<ul>` would cost its `<li>` children the `listitem` role that
|
|
59
|
+
* `aria-level` is defined against.
|
|
60
|
+
*
|
|
61
|
+
* Selection does **not** cascade to children. The server stores an explicit set
|
|
62
|
+
* of assignments (`U4` set semantics), so checking "Invoices" must not silently
|
|
63
|
+
* file the object into "Invoices / 2026"; a collapsed-or-not branch holding a
|
|
64
|
+
* selected descendant is marked with a dot instead.
|
|
65
|
+
*/
|
|
66
|
+
function BranchToggle({ node, ctx, groupId }) {
|
|
67
|
+
if (node.children.length === 0) {
|
|
68
|
+
return _jsx("span", { className: "fa-media-category-toggle-spacer", "aria-hidden": "true" });
|
|
69
|
+
}
|
|
70
|
+
const isCollapsed = ctx.collapsed.has(node.id);
|
|
71
|
+
return (_jsx("button", { type: "button", className: "fa-media-category-toggle", "aria-expanded": !isCollapsed, "aria-controls": groupId, "aria-label": isCollapsed ? ctx.labels.expand(node.name) : ctx.labels.collapse(node.name), onClick: () => ctx.onToggleCollapsed(node.id), children: isCollapsed ? "▸" : "▾" }));
|
|
72
|
+
}
|
|
73
|
+
function BranchCheckbox({ node, ctx }) {
|
|
74
|
+
const inputId = `${ctx.idPrefix}-node-${node.id}`;
|
|
75
|
+
const descendantSelected = node.children.length > 0 &&
|
|
76
|
+
!ctx.selected.has(node.id) &&
|
|
77
|
+
hasSelectedDescendant(node.children, ctx.selected);
|
|
78
|
+
return (_jsxs("label", { className: labelClassName, htmlFor: inputId, children: [_jsx("input", { id: inputId, type: "checkbox", checked: ctx.selected.has(node.id), disabled: ctx.disabled, onChange: () => ctx.onToggleSelected(node.id) }), _jsx("span", { className: "fa-media-category-name", children: node.name }), descendantSelected ? (_jsx("span", { className: "fa-media-category-marker", title: ctx.labels.descendantSelected, children: "•" })) : null, _jsx("span", { className: "fa-media-badge fa-media-category-count", children: node.total_object_count })] }));
|
|
79
|
+
}
|
|
80
|
+
function CategoryBranch({ node, depth, ctx }) {
|
|
81
|
+
const hasChildren = node.children.length > 0;
|
|
82
|
+
const groupId = `${ctx.idPrefix}-group-${node.id}`;
|
|
83
|
+
return (_jsxs("li", { className: "fa-media-category-node", "aria-level": depth, children: [_jsxs("div", { className: "fa-media-category-row", children: [_jsx(BranchToggle, { node: node, ctx: ctx, groupId: groupId }), _jsx(BranchCheckbox, { node: node, ctx: ctx })] }), hasChildren && !ctx.collapsed.has(node.id) ? (_jsx("ul", { id: groupId, className: "fa-media-category-children", children: node.children.map((child) => (_jsx(CategoryBranch, { node: child, depth: depth + 1, ctx: ctx }, child.id))) })) : null] }));
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* The picker's only local state: which branches are collapsed. Selection stays
|
|
87
|
+
* the caller's — `toggleSelected` reports the next set rather than storing it —
|
|
88
|
+
* so the control remains fully controlled (`U4` set semantics).
|
|
89
|
+
*/
|
|
90
|
+
function usePickerState(value, onChange) {
|
|
91
|
+
const [collapsed, setCollapsed] = useState(() => new Set());
|
|
92
|
+
const selected = useMemo(() => new Set(value), [value]);
|
|
93
|
+
const toggleSelected = useCallback((id) => {
|
|
94
|
+
onChange(value.includes(id) ? value.filter((current) => current !== id) : [...value, id]);
|
|
95
|
+
}, [onChange, value]);
|
|
96
|
+
const toggleCollapsed = useCallback((id) => {
|
|
97
|
+
setCollapsed((previous) => {
|
|
98
|
+
const next = new Set(previous);
|
|
99
|
+
if (!next.delete(id))
|
|
100
|
+
next.add(id);
|
|
101
|
+
return next;
|
|
102
|
+
});
|
|
103
|
+
}, []);
|
|
104
|
+
return { collapsed, selected, toggleSelected, toggleCollapsed };
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Presentational multi-select nested category picker: a checkbox tree plus a
|
|
108
|
+
* chip list of the current selection. Fully controlled — it holds no selection
|
|
109
|
+
* state of its own, only expand/collapse.
|
|
110
|
+
*/
|
|
111
|
+
export function CategoryMultiSelectView(props) {
|
|
112
|
+
const { value, onChange, tree, loading = false, error = null, disabled = false, legend, emptyHint, fallbackLabels, idPrefix = "fa-media-categories", labels: labelOverrides } = props;
|
|
113
|
+
const labels = { ...DEFAULT_LABELS, ...labelOverrides };
|
|
114
|
+
const { collapsed, selected, toggleSelected, toggleCollapsed } = usePickerState(value, onChange);
|
|
115
|
+
const paths = useMemo(() => collectCategoryPaths(tree), [tree]);
|
|
116
|
+
const chips = resolveChips(value, paths, fallbackLabels);
|
|
117
|
+
const errorMessage = resolveErrorMessage(error, labels.loadError);
|
|
118
|
+
const ctx = {
|
|
119
|
+
idPrefix,
|
|
120
|
+
selected,
|
|
121
|
+
collapsed,
|
|
122
|
+
disabled,
|
|
123
|
+
onToggleSelected: toggleSelected,
|
|
124
|
+
onToggleCollapsed: toggleCollapsed,
|
|
125
|
+
labels
|
|
126
|
+
};
|
|
127
|
+
return (_jsxs("fieldset", { className: "fa-media-category-picker", children: [_jsx("legend", { children: legend ?? labels.legend }), _jsx(CategoryPickerStatus, { errorMessage: errorMessage, loading: loading, isEmpty: tree.length === 0, emptyHint: emptyHint ?? labels.emptyHint, loadingLabel: labels.loading }), _jsx(CategoryTreeList, { tree: tree, ctx: ctx }), _jsx(CategorySelection, { chips: chips, labels: labels, disabled: disabled, onRemove: toggleSelected, onClear: () => onChange([]) })] }));
|
|
128
|
+
}
|
|
129
|
+
/** The root list. Renders nothing at all when the account has no categories. */
|
|
130
|
+
function CategoryTreeList({ tree, ctx }) {
|
|
131
|
+
if (tree.length === 0)
|
|
132
|
+
return null;
|
|
133
|
+
return (_jsx("ul", { className: "fa-media-category-tree", children: tree.map((node) => (_jsx(CategoryBranch, { node: node, depth: 1, ctx: ctx }, node.id))) }));
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* The picker's three mutually informative status lines: a load error, the
|
|
137
|
+
* first-load hint while the tree is still resolving, and the "nothing to pick
|
|
138
|
+
* from" hint. The empty hint stays suppressed while an error is showing, so a
|
|
139
|
+
* failed request never reads as an empty account.
|
|
140
|
+
*/
|
|
141
|
+
function CategoryPickerStatus({ errorMessage, loading, isEmpty, emptyHint, loadingLabel }) {
|
|
142
|
+
return (_jsxs(_Fragment, { children: [errorMessage ? (_jsx("p", { role: "alert", className: "fa-media-category-error", children: errorMessage })) : null, loading && isEmpty ? _jsx("p", { className: "fa-media-category-hint", children: loadingLabel }) : null, !loading && !errorMessage && isEmpty ? (_jsx("p", { className: "fa-media-category-hint", children: emptyHint })) : null] }));
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Resolve each selected id to its chip copy: the tree's slash-joined path when
|
|
146
|
+
* the tree holds it, the caller's fallback label when it does not, and `#id` as
|
|
147
|
+
* the last resort so a chip never renders empty.
|
|
148
|
+
*/
|
|
149
|
+
function resolveChips(value, paths, fallbackLabels) {
|
|
150
|
+
return value.map((id) => {
|
|
151
|
+
const known = paths.get(id);
|
|
152
|
+
if (known)
|
|
153
|
+
return known;
|
|
154
|
+
const fallback = fallbackLabels?.get(id) ?? `#${id}`;
|
|
155
|
+
return { id, name: fallback, path: fallback };
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
function resolveErrorMessage(error, loadError) {
|
|
159
|
+
if (!error)
|
|
160
|
+
return null;
|
|
161
|
+
const detail = error instanceof ApiError ? messageFromDetail(error.detail) : null;
|
|
162
|
+
return detail ?? (error instanceof Error ? error.message : loadError);
|
|
163
|
+
}
|
|
164
|
+
/** The chip list of the current selection, plus its clear-all action. */
|
|
165
|
+
function CategorySelection({ chips, labels, disabled, onRemove, onClear }) {
|
|
166
|
+
if (chips.length === 0) {
|
|
167
|
+
return (_jsx("div", { className: "fa-media-category-selection", children: _jsx("p", { className: "fa-media-category-hint", children: labels.noneSelected }) }));
|
|
168
|
+
}
|
|
169
|
+
return (_jsxs("div", { className: "fa-media-category-selection", children: [_jsx("ul", { className: "fa-media-category-chips", "aria-label": labels.selected, children: chips.map((chip) => (_jsxs("li", { className: "fa-media-badge fa-media-category-chip", children: [_jsx("span", { children: chip.path }), _jsx("button", { type: "button", className: "fa-media-category-chip-remove", "aria-label": labels.remove(chip.path), disabled: disabled, onClick: () => onRemove(chip.id), children: "×" })] }, chip.id))) }), _jsx("button", { type: "button", className: "fa-media-category-clear", disabled: disabled, onClick: onClear, children: labels.clearAll })] }));
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* The picker wired to `useCategoryTree()`. Use this on a page; use
|
|
173
|
+
* `CategoryMultiSelectView` when the tree is already in hand (or under test).
|
|
174
|
+
*/
|
|
175
|
+
export function CategoryMultiSelect(props) {
|
|
176
|
+
const { tree, loading, error } = useCategoryTree();
|
|
177
|
+
return _jsx(CategoryMultiSelectView, { ...props, tree: tree, loading: loading, error: error });
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=CategoryMultiSelect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CategoryMultiSelect.js","sourceRoot":"","sources":["../../../../src/runtime/react/CategoryMultiSelect.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { CategoryBranchSelection } from "./categoryBranch.js";
|
|
2
|
+
import type { MediaLibraryLabels } from "./mediaLibraryLabels.js";
|
|
3
|
+
/**
|
|
4
|
+
* The left pane of the tree view: the caller's nested user categories with
|
|
5
|
+
* their counts.
|
|
6
|
+
*
|
|
7
|
+
* `useCategoryTree()` lives **here** rather than in `MediaLibrary` so the
|
|
8
|
+
* category request is only issued once the user actually opens the tree view —
|
|
9
|
+
* the list/grid/masonry views must not pay for a fetch they never render.
|
|
10
|
+
*
|
|
11
|
+
* The a11y contract matches `astro-ui-m8`'s `tree-view` registry block so the
|
|
12
|
+
* runtime pane and the registry skin do not diverge: `role="tree"` /
|
|
13
|
+
* `role="group"` / `role="treeitem"`, `aria-level`, `aria-selected`,
|
|
14
|
+
* `aria-expanded` on parents, a roving tabindex holding exactly one tab stop,
|
|
15
|
+
* and ArrowUp/ArrowDown/Home/End/ArrowRight/ArrowLeft/Enter/Space.
|
|
16
|
+
*/
|
|
17
|
+
export declare function MediaCategoryTreePane({ selection, onSelect, labels }: {
|
|
18
|
+
selection: CategoryBranchSelection;
|
|
19
|
+
onSelect: (selection: CategoryBranchSelection) => void;
|
|
20
|
+
labels: MediaLibraryLabels["tree"];
|
|
21
|
+
}): import("react").JSX.Element;
|
|
22
|
+
//# sourceMappingURL=MediaCategoryTreePane.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MediaCategoryTreePane.d.ts","sourceRoot":"","sources":["../../../../src/runtime/react/MediaCategoryTreePane.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAsOlE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,SAAS,EACT,QAAQ,EACR,MAAM,EACP,EAAE;IACD,SAAS,EAAE,uBAAuB,CAAC;IACnC,QAAQ,EAAE,CAAC,SAAS,EAAE,uBAAuB,KAAK,IAAI,CAAC;IACvD,MAAM,EAAE,kBAAkB,CAAC,MAAM,CAAC,CAAC;CACpC,+BA6JA"}
|