@emdash-cms/admin 0.9.0 → 0.10.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/{LocaleDirectionProvider-BGcmv_N7.js → LocaleDirectionProvider-xcSZTLFA.js} +22 -22
- package/dist/LocaleDirectionProvider-xcSZTLFA.js.map +1 -0
- package/dist/{config-YdN-uv6S.d.ts → config-DJUFU9nY.d.ts} +3 -3
- package/dist/{config-YdN-uv6S.d.ts.map → config-DJUFU9nY.d.ts.map} +1 -1
- package/dist/index.d.ts +123 -35
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1560 -969
- package/dist/index.js.map +1 -1
- package/dist/locales/ar/messages.mjs +1 -1
- package/dist/locales/de/messages.mjs +1 -1
- package/dist/locales/en/messages.mjs +1 -1
- package/dist/locales/es-419/messages.mjs +1 -1
- package/dist/locales/eu/messages.mjs +1 -1
- package/dist/locales/fa/messages.mjs +1 -1
- package/dist/locales/fr/messages.mjs +1 -1
- package/dist/locales/id/messages.mjs +1 -1
- package/dist/locales/index.d.ts +1 -1
- package/dist/locales/index.js +1 -1
- package/dist/locales/ja/messages.mjs +1 -1
- package/dist/locales/ko/messages.mjs +1 -1
- package/dist/locales/pl/messages.mjs +1 -1
- package/dist/locales/pseudo/messages.mjs +1 -1
- package/dist/locales/pt-BR/messages.mjs +1 -1
- package/dist/locales/zh-CN/messages.mjs +1 -1
- package/dist/locales/zh-TW/messages.mjs +1 -1
- package/dist/messages-BLHOmJoS.js +6 -0
- package/dist/messages-BLHOmJoS.js.map +1 -0
- package/dist/messages-BLPEG0Mx.js +6 -0
- package/dist/messages-BLPEG0Mx.js.map +1 -0
- package/dist/messages-BYyq7qnh.js +6 -0
- package/dist/messages-BYyq7qnh.js.map +1 -0
- package/dist/messages-BcI5YTGJ.js +6 -0
- package/dist/messages-BcI5YTGJ.js.map +1 -0
- package/dist/messages-BpVvs7xa.js +6 -0
- package/dist/messages-BpVvs7xa.js.map +1 -0
- package/dist/messages-CSs_iEr-.js +6 -0
- package/dist/messages-CSs_iEr-.js.map +1 -0
- package/dist/messages-CvhBZHPh.js +6 -0
- package/dist/messages-CvhBZHPh.js.map +1 -0
- package/dist/messages-CyUGKznD.js +6 -0
- package/dist/messages-CyUGKznD.js.map +1 -0
- package/dist/messages-D7GebqCf.js +6 -0
- package/dist/messages-D7GebqCf.js.map +1 -0
- package/dist/messages-DDVTav-Y.js +6 -0
- package/dist/messages-DDVTav-Y.js.map +1 -0
- package/dist/messages-DMBcuYFC.js +6 -0
- package/dist/messages-DMBcuYFC.js.map +1 -0
- package/dist/messages-DRrZDx80.js +6 -0
- package/dist/messages-DRrZDx80.js.map +1 -0
- package/dist/messages-aWiCO6Ou.js +6 -0
- package/dist/messages-aWiCO6Ou.js.map +1 -0
- package/dist/messages-hcBnbmbA.js +6 -0
- package/dist/messages-hcBnbmbA.js.map +1 -0
- package/dist/messages-wnKLF74l.js +6 -0
- package/dist/messages-wnKLF74l.js.map +1 -0
- package/package.json +2 -2
- package/dist/LocaleDirectionProvider-BGcmv_N7.js.map +0 -1
- package/dist/messages-B2njiT3N.js +0 -6
- package/dist/messages-B2njiT3N.js.map +0 -1
- package/dist/messages-BH4d_eo3.js +0 -6
- package/dist/messages-BH4d_eo3.js.map +0 -1
- package/dist/messages-BI3LQfHj.js +0 -6
- package/dist/messages-BI3LQfHj.js.map +0 -1
- package/dist/messages-BLk7kRSt.js +0 -6
- package/dist/messages-BLk7kRSt.js.map +0 -1
- package/dist/messages-C0fFDufP.js +0 -6
- package/dist/messages-C0fFDufP.js.map +0 -1
- package/dist/messages-C2W1GOne.js +0 -6
- package/dist/messages-C2W1GOne.js.map +0 -1
- package/dist/messages-C7bn0sIO.js +0 -6
- package/dist/messages-C7bn0sIO.js.map +0 -1
- package/dist/messages-CKVC1F84.js +0 -6
- package/dist/messages-CKVC1F84.js.map +0 -1
- package/dist/messages-D6pXx3hr.js +0 -6
- package/dist/messages-D6pXx3hr.js.map +0 -1
- package/dist/messages-DQUgrzIz.js +0 -6
- package/dist/messages-DQUgrzIz.js.map +0 -1
- package/dist/messages-DfGxk-9q.js +0 -6
- package/dist/messages-DfGxk-9q.js.map +0 -1
- package/dist/messages-Dkb9TndV.js +0 -6
- package/dist/messages-Dkb9TndV.js.map +0 -1
- package/dist/messages-DzS9GmJY.js +0 -6
- package/dist/messages-DzS9GmJY.js.map +0 -1
- package/dist/messages-FaHuWwRM.js +0 -6
- package/dist/messages-FaHuWwRM.js.map +0 -1
- package/dist/messages-lrnW_v3N.js +0 -6
- package/dist/messages-lrnW_v3N.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { c as fetchAuthMode, d as throwResponseError, i as fetchPlugins, l as fetchManifest, n as enablePlugin, o as API_BASE, r as fetchPlugin, s as apiFetch, t as disablePlugin, u as parseApiResponse } from "./plugins-DUJY_8HN.js";
|
|
2
|
-
import { a as SUPPORTED_LOCALES, i as DEFAULT_LOCALE, l as resolveLocale, n as useLocale, o as SUPPORTED_LOCALE_CODES, t as LocaleDirectionProvider } from "./LocaleDirectionProvider-
|
|
2
|
+
import { a as SUPPORTED_LOCALES, i as DEFAULT_LOCALE, l as resolveLocale, n as useLocale, o as SUPPORTED_LOCALE_CODES, t as LocaleDirectionProvider } from "./LocaleDirectionProvider-xcSZTLFA.js";
|
|
3
3
|
import "./locales/index.js";
|
|
4
4
|
import { Badge, Button, Checkbox, CommandPalette, Dialog, Input, InputArea, Label, LinkButton, Loader, Popover, Select, Sidebar as KumoSidebar, Switch, Tabs, Toast, Toasty, Tooltip, buttonVariants, useSidebar } from "@cloudflare/kumo";
|
|
5
5
|
import { i18n } from "@lingui/core";
|
|
6
6
|
import { I18nProvider, Trans, useLingui } from "@lingui/react";
|
|
7
7
|
import { QueryClient, QueryClientProvider, useInfiniteQuery, useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
8
8
|
import { Link, Link as Link$1, Outlet, RouterProvider, createRootRouteWithContext, createRoute, createRouter, useLocation, useNavigate, useNavigate as useNavigate$1, useParams, useParams as useParams$1, useSearch } from "@tanstack/react-router";
|
|
9
|
-
import * as React from "react";
|
|
10
|
-
import { createContext, useCallback, useContext, useEffect, useState } from "react";
|
|
9
|
+
import * as React$1 from "react";
|
|
10
|
+
import React, { createContext, useCallback, useContext, useEffect, useState } from "react";
|
|
11
11
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
12
12
|
import { Dialog as Dialog$1 } from "@cloudflare/kumo/primitives";
|
|
13
|
-
import { ArrowCounterClockwise, ArrowRight, ArrowRightIcon, ArrowSquareOut, ArrowUUpLeft, ArrowUUpRight, ArrowsClockwise, ArrowsInSimple, ArrowsLeftRight, ArrowsOutSimple, BracketsCurly, Calendar, CalendarBlank, CaretDown, CaretRightIcon, CaretUp, CaretUpDown, ChatCircle, Check, CheckCircle, CircleDashed, CircleNotch, ClockCounterClockwise, Cloud, Code, CodeBlock, Copy, Cube, Database, DeviceMobile, DotsSixVertical, DownloadSimple, Envelope, EnvelopeSimple, Eye, EyeSlash, File, FileArrowDown, FileText, FloppyDisk, FolderOpen, Gear, GithubLogo, Globe, GlobeSimple, GridFour, HardDrive, Hash, Image as Image$1, ImageSquare, Info, Key, Link as Link$2, LinkBreak, LinkSimple, List, ListBullets, ListChecks, ListNumbers, MagnifyingGlass, Minus, Monitor, Moon, Palette, PaperPlaneTilt, Paragraph, Pencil, PencilSimple, PlugsConnected, Plus, Prohibit, PuzzlePiece, Quotes, Rows, Ruler, ShareNetwork, Shield, ShieldCheck, ShieldWarning, SignOut, SlidersHorizontal, Sparkle, SquaresFour, Stack, Storefront, Sun, TextAlignCenter, TextAlignLeft, TextAlignRight, TextB, TextHOne, TextHThree, TextHTwo, TextItalic, TextStrikethrough, TextT, TextUnderline, ToggleLeft, Trash, Upload, User, UserCircle, UserPlus, Users, Warning, WarningCircle, WebhooksLogo, X, YoutubeLogo } from "@phosphor-icons/react";
|
|
13
|
+
import { ArrowCounterClockwise, ArrowRight, ArrowRightIcon, ArrowSquareOut, ArrowUUpLeft, ArrowUUpRight, ArrowsClockwise, ArrowsInSimple, ArrowsLeftRight, ArrowsOutSimple, BracketsCurly, Calendar, CalendarBlank, CaretDown, CaretRightIcon, CaretUp, CaretUpDown, ChatCircle, Check, CheckCircle, CircleDashed, CircleNotch, ClockCounterClockwise, Cloud, Code, CodeBlock, Copy, Cube, Database, DeviceMobile, DotsSixVertical, DownloadSimple, Envelope, EnvelopeSimple, Eye, EyeSlash, File, FileArrowDown, FileText, FloppyDisk, FolderOpen, Gear, GithubLogo, Globe, GlobeSimple, GridFour, HardDrive, Hash, Image as Image$1, ImageSquare, Info, Key, Link as Link$2, LinkBreak, LinkSimple, List, ListBullets, ListChecks, ListNumbers, MagnifyingGlass, Minus, Monitor, Moon, Palette, PaperPlaneTilt, Paperclip, Paragraph, Pencil, PencilSimple, PlugsConnected, Plus, Prohibit, PuzzlePiece, Quotes, Rows, Ruler, ShareNetwork, Shield, ShieldCheck, ShieldWarning, SignOut, SlidersHorizontal, Sparkle, SquaresFour, Stack, Storefront, Sun, TextAlignCenter, TextAlignLeft, TextAlignRight, TextB, TextHOne, TextHThree, TextHTwo, TextItalic, TextStrikethrough, TextT, TextUnderline, ToggleLeft, Trash, Upload, User, UserCircle, UserPlus, Users, Warning, WarningCircle, WebhooksLogo, X, YoutubeLogo } from "@phosphor-icons/react";
|
|
14
14
|
import { clsx } from "clsx";
|
|
15
15
|
import { twMerge } from "tailwind-merge";
|
|
16
16
|
import { DndContext, DragOverlay, KeyboardSensor, PointerSensor, closestCenter, rectIntersection, useDraggable, useDroppable, useSensor, useSensors } from "@dnd-kit/core";
|
|
@@ -37,7 +37,7 @@ import { Marked, Renderer } from "marked";
|
|
|
37
37
|
import { useHotkeys } from "react-hotkeys-hook";
|
|
38
38
|
|
|
39
39
|
//#region src/components/ThemeProvider.tsx
|
|
40
|
-
const ThemeContext = React.createContext(void 0);
|
|
40
|
+
const ThemeContext = React$1.createContext(void 0);
|
|
41
41
|
const STORAGE_KEY = "emdash-theme";
|
|
42
42
|
function getSystemTheme() {
|
|
43
43
|
if (typeof window === "undefined") return "light";
|
|
@@ -50,19 +50,19 @@ function getStoredTheme() {
|
|
|
50
50
|
return "system";
|
|
51
51
|
}
|
|
52
52
|
function ThemeProvider({ children, defaultTheme = "system" }) {
|
|
53
|
-
const [theme, setThemeState] = React.useState(() => {
|
|
53
|
+
const [theme, setThemeState] = React$1.useState(() => {
|
|
54
54
|
const stored = getStoredTheme();
|
|
55
55
|
return stored === "system" ? defaultTheme : stored;
|
|
56
56
|
});
|
|
57
|
-
const [resolvedTheme, setResolvedTheme] = React.useState(() => {
|
|
57
|
+
const [resolvedTheme, setResolvedTheme] = React$1.useState(() => {
|
|
58
58
|
if (theme === "system") return getSystemTheme();
|
|
59
59
|
return theme;
|
|
60
60
|
});
|
|
61
|
-
React.useEffect(() => {
|
|
61
|
+
React$1.useEffect(() => {
|
|
62
62
|
if (theme === "system") setResolvedTheme(getSystemTheme());
|
|
63
63
|
else setResolvedTheme(theme);
|
|
64
64
|
}, [theme]);
|
|
65
|
-
React.useEffect(() => {
|
|
65
|
+
React$1.useEffect(() => {
|
|
66
66
|
if (theme !== "system") return;
|
|
67
67
|
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
68
68
|
const handler = (e) => {
|
|
@@ -71,16 +71,16 @@ function ThemeProvider({ children, defaultTheme = "system" }) {
|
|
|
71
71
|
mediaQuery.addEventListener("change", handler);
|
|
72
72
|
return () => mediaQuery.removeEventListener("change", handler);
|
|
73
73
|
}, [theme]);
|
|
74
|
-
React.useEffect(() => {
|
|
74
|
+
React$1.useEffect(() => {
|
|
75
75
|
const root = document.documentElement;
|
|
76
76
|
root.setAttribute("data-theme", "classic");
|
|
77
77
|
root.setAttribute("data-mode", resolvedTheme);
|
|
78
78
|
}, [resolvedTheme]);
|
|
79
|
-
const setTheme = React.useCallback((newTheme) => {
|
|
79
|
+
const setTheme = React$1.useCallback((newTheme) => {
|
|
80
80
|
setThemeState(newTheme);
|
|
81
81
|
localStorage.setItem(STORAGE_KEY, newTheme);
|
|
82
82
|
}, []);
|
|
83
|
-
const value = React.useMemo(() => ({
|
|
83
|
+
const value = React$1.useMemo(() => ({
|
|
84
84
|
theme,
|
|
85
85
|
setTheme,
|
|
86
86
|
resolvedTheme
|
|
@@ -95,7 +95,7 @@ function ThemeProvider({ children, defaultTheme = "system" }) {
|
|
|
95
95
|
});
|
|
96
96
|
}
|
|
97
97
|
function useTheme() {
|
|
98
|
-
const context = React.useContext(ThemeContext);
|
|
98
|
+
const context = React$1.useContext(ThemeContext);
|
|
99
99
|
if (context === void 0) throw new Error("useTheme must be used within a ThemeProvider");
|
|
100
100
|
return context;
|
|
101
101
|
}
|
|
@@ -334,7 +334,7 @@ function ConfirmDialog({ open, onClose, title, description, confirmLabel, pendin
|
|
|
334
334
|
*/
|
|
335
335
|
function CommentDetail({ comment, onClose, onStatusChange, onDelete, isAdmin, isStatusPending }) {
|
|
336
336
|
const { _: _t } = useLingui();
|
|
337
|
-
React.useEffect(() => {
|
|
337
|
+
React$1.useEffect(() => {
|
|
338
338
|
const handler = (e) => {
|
|
339
339
|
if (e.key === "Escape" && !e.defaultPrevented) {
|
|
340
340
|
e.preventDefault();
|
|
@@ -601,11 +601,11 @@ function CommentStatusBadge({ status }) {
|
|
|
601
601
|
const PAGE_SIZE$1 = 20;
|
|
602
602
|
function CommentInbox({ comments, counts, isLoading, nextCursor, collections, activeStatus, onStatusChange, collectionFilter, onCollectionFilterChange, searchQuery, onSearchChange, onCommentStatusChange, onCommentDelete, onBulkAction, onLoadMore, isAdmin, isStatusPending, deleteError, onDeleteErrorReset }) {
|
|
603
603
|
const { _: _t } = useLingui();
|
|
604
|
-
const [selected, setSelected] = React.useState(/* @__PURE__ */ new Set());
|
|
605
|
-
const [detailComment, setDetailComment] = React.useState(null);
|
|
606
|
-
const [deleteId, setDeleteId] = React.useState(null);
|
|
607
|
-
const [page, setPage] = React.useState(0);
|
|
608
|
-
React.useEffect(() => {
|
|
604
|
+
const [selected, setSelected] = React$1.useState(/* @__PURE__ */ new Set());
|
|
605
|
+
const [detailComment, setDetailComment] = React$1.useState(null);
|
|
606
|
+
const [deleteId, setDeleteId] = React$1.useState(null);
|
|
607
|
+
const [page, setPage] = React$1.useState(0);
|
|
608
|
+
React$1.useEffect(() => {
|
|
609
609
|
setSelected(/* @__PURE__ */ new Set());
|
|
610
610
|
setPage(0);
|
|
611
611
|
}, [
|
|
@@ -613,7 +613,7 @@ function CommentInbox({ comments, counts, isLoading, nextCursor, collections, ac
|
|
|
613
613
|
collectionFilter,
|
|
614
614
|
searchQuery
|
|
615
615
|
]);
|
|
616
|
-
const clearSelection = React.useCallback(() => setSelected(/* @__PURE__ */ new Set()), []);
|
|
616
|
+
const clearSelection = React$1.useCallback(() => setSelected(/* @__PURE__ */ new Set()), []);
|
|
617
617
|
const totalPages = Math.max(1, Math.ceil(comments.length / PAGE_SIZE$1));
|
|
618
618
|
const paginatedComments = comments.slice(page * PAGE_SIZE$1, (page + 1) * PAGE_SIZE$1);
|
|
619
619
|
const allOnPageSelected = paginatedComments.length > 0 && paginatedComments.every((c) => selected.has(c.id));
|
|
@@ -1901,19 +1901,26 @@ async function deleteByline(id) {
|
|
|
1901
1901
|
//#endregion
|
|
1902
1902
|
//#region src/lib/api/menus.ts
|
|
1903
1903
|
/**
|
|
1904
|
-
* Menu management APIs
|
|
1904
|
+
* Menu management APIs.
|
|
1905
|
+
*
|
|
1906
|
+
* i18n: all endpoints accept an optional `locale`. When omitted, the server
|
|
1907
|
+
* returns or acts on all locales (legacy behaviour for clients that haven't
|
|
1908
|
+
* been updated yet).
|
|
1905
1909
|
*/
|
|
1910
|
+
function withLocale$1(path, locale) {
|
|
1911
|
+
return locale ? `${path}${path.includes("?") ? "&" : "?"}locale=${encodeURIComponent(locale)}` : path;
|
|
1912
|
+
}
|
|
1906
1913
|
/**
|
|
1907
1914
|
* Fetch all menus
|
|
1908
1915
|
*/
|
|
1909
|
-
async function fetchMenus() {
|
|
1910
|
-
return parseApiResponse(await apiFetch(`${API_BASE}/menus
|
|
1916
|
+
async function fetchMenus(options = {}) {
|
|
1917
|
+
return parseApiResponse(await apiFetch(withLocale$1(`${API_BASE}/menus`, options.locale)), "Failed to fetch menus");
|
|
1911
1918
|
}
|
|
1912
1919
|
/**
|
|
1913
1920
|
* Fetch a single menu with items
|
|
1914
1921
|
*/
|
|
1915
|
-
async function fetchMenu(name) {
|
|
1916
|
-
return parseApiResponse(await apiFetch(`${API_BASE}/menus/${name}
|
|
1922
|
+
async function fetchMenu(name, options = {}) {
|
|
1923
|
+
return parseApiResponse(await apiFetch(withLocale$1(`${API_BASE}/menus/${name}`, options.locale)), "Failed to fetch menu");
|
|
1917
1924
|
}
|
|
1918
1925
|
/**
|
|
1919
1926
|
* Create a menu
|
|
@@ -1928,8 +1935,8 @@ async function createMenu(input) {
|
|
|
1928
1935
|
/**
|
|
1929
1936
|
* Update a menu
|
|
1930
1937
|
*/
|
|
1931
|
-
async function updateMenu(name, input) {
|
|
1932
|
-
return parseApiResponse(await apiFetch(`${API_BASE}/menus/${name}`, {
|
|
1938
|
+
async function updateMenu(name, input, options = {}) {
|
|
1939
|
+
return parseApiResponse(await apiFetch(withLocale$1(`${API_BASE}/menus/${name}`, options.locale), {
|
|
1933
1940
|
method: "PUT",
|
|
1934
1941
|
headers: { "Content-Type": "application/json" },
|
|
1935
1942
|
body: JSON.stringify(input)
|
|
@@ -1938,15 +1945,15 @@ async function updateMenu(name, input) {
|
|
|
1938
1945
|
/**
|
|
1939
1946
|
* Delete a menu
|
|
1940
1947
|
*/
|
|
1941
|
-
async function deleteMenu(name) {
|
|
1942
|
-
const response = await apiFetch(`${API_BASE}/menus/${name}`, { method: "DELETE" });
|
|
1948
|
+
async function deleteMenu(name, options = {}) {
|
|
1949
|
+
const response = await apiFetch(withLocale$1(`${API_BASE}/menus/${name}`, options.locale), { method: "DELETE" });
|
|
1943
1950
|
if (!response.ok) await throwResponseError(response, "Failed to delete menu");
|
|
1944
1951
|
}
|
|
1945
1952
|
/**
|
|
1946
1953
|
* Create a menu item
|
|
1947
1954
|
*/
|
|
1948
|
-
async function createMenuItem(menuName, input) {
|
|
1949
|
-
return parseApiResponse(await apiFetch(`${API_BASE}/menus/${menuName}/items`, {
|
|
1955
|
+
async function createMenuItem(menuName, input, options = {}) {
|
|
1956
|
+
return parseApiResponse(await apiFetch(withLocale$1(`${API_BASE}/menus/${menuName}/items`, options.locale), {
|
|
1950
1957
|
method: "POST",
|
|
1951
1958
|
headers: { "Content-Type": "application/json" },
|
|
1952
1959
|
body: JSON.stringify(input)
|
|
@@ -1955,8 +1962,8 @@ async function createMenuItem(menuName, input) {
|
|
|
1955
1962
|
/**
|
|
1956
1963
|
* Update a menu item
|
|
1957
1964
|
*/
|
|
1958
|
-
async function updateMenuItem(menuName, itemId, input) {
|
|
1959
|
-
return parseApiResponse(await apiFetch(`${API_BASE}/menus/${menuName}/items?id=${itemId}`, {
|
|
1965
|
+
async function updateMenuItem(menuName, itemId, input, options = {}) {
|
|
1966
|
+
return parseApiResponse(await apiFetch(withLocale$1(`${API_BASE}/menus/${menuName}/items?id=${itemId}`, options.locale), {
|
|
1960
1967
|
method: "PUT",
|
|
1961
1968
|
headers: { "Content-Type": "application/json" },
|
|
1962
1969
|
body: JSON.stringify(input)
|
|
@@ -1965,20 +1972,35 @@ async function updateMenuItem(menuName, itemId, input) {
|
|
|
1965
1972
|
/**
|
|
1966
1973
|
* Delete a menu item
|
|
1967
1974
|
*/
|
|
1968
|
-
async function deleteMenuItem(menuName, itemId) {
|
|
1969
|
-
const response = await apiFetch(`${API_BASE}/menus/${menuName}/items?id=${itemId}`, { method: "DELETE" });
|
|
1975
|
+
async function deleteMenuItem(menuName, itemId, options = {}) {
|
|
1976
|
+
const response = await apiFetch(withLocale$1(`${API_BASE}/menus/${menuName}/items?id=${itemId}`, options.locale), { method: "DELETE" });
|
|
1970
1977
|
if (!response.ok) await throwResponseError(response, "Failed to delete menu item");
|
|
1971
1978
|
}
|
|
1972
1979
|
/**
|
|
1973
1980
|
* Reorder menu items
|
|
1974
1981
|
*/
|
|
1975
|
-
async function reorderMenuItems(menuName, input) {
|
|
1976
|
-
return parseApiResponse(await apiFetch(`${API_BASE}/menus/${menuName}/reorder`, {
|
|
1982
|
+
async function reorderMenuItems(menuName, input, options = {}) {
|
|
1983
|
+
return parseApiResponse(await apiFetch(withLocale$1(`${API_BASE}/menus/${menuName}/reorder`, options.locale), {
|
|
1977
1984
|
method: "POST",
|
|
1978
1985
|
headers: { "Content-Type": "application/json" },
|
|
1979
1986
|
body: JSON.stringify(input)
|
|
1980
1987
|
}), "Failed to reorder menu items");
|
|
1981
1988
|
}
|
|
1989
|
+
/** List every translation (locale variant) of a menu. */
|
|
1990
|
+
async function fetchMenuTranslations(name, options = {}) {
|
|
1991
|
+
return parseApiResponse(await apiFetch(withLocale$1(`${API_BASE}/menus/${name}/translations`, options.locale)), "Failed to fetch menu translations");
|
|
1992
|
+
}
|
|
1993
|
+
/**
|
|
1994
|
+
* Create a new locale translation of a menu. The new menu inherits the
|
|
1995
|
+
* source's items and label unless overridden.
|
|
1996
|
+
*/
|
|
1997
|
+
async function createMenuTranslation(name, input, options = {}) {
|
|
1998
|
+
return parseApiResponse(await apiFetch(withLocale$1(`${API_BASE}/menus/${name}/translations`, options.locale), {
|
|
1999
|
+
method: "POST",
|
|
2000
|
+
headers: { "Content-Type": "application/json" },
|
|
2001
|
+
body: JSON.stringify(input)
|
|
2002
|
+
}), "Failed to create menu translation");
|
|
2003
|
+
}
|
|
1982
2004
|
|
|
1983
2005
|
//#endregion
|
|
1984
2006
|
//#region src/lib/api/widgets.ts
|
|
@@ -2112,19 +2134,27 @@ async function deleteSection(slug) {
|
|
|
2112
2134
|
//#endregion
|
|
2113
2135
|
//#region src/lib/api/taxonomies.ts
|
|
2114
2136
|
/**
|
|
2115
|
-
* Taxonomies API (categories, tags, custom taxonomies)
|
|
2137
|
+
* Taxonomies API (categories, tags, custom taxonomies).
|
|
2138
|
+
*
|
|
2139
|
+
* All endpoints are locale-aware. When no `locale` option is passed we omit
|
|
2140
|
+
* the query param and the server falls back to its usual resolution (no
|
|
2141
|
+
* filter, returning every locale — same as pre-i18n behaviour for clients
|
|
2142
|
+
* that haven't yet been updated).
|
|
2116
2143
|
*/
|
|
2144
|
+
function withLocale(path, locale) {
|
|
2145
|
+
return locale ? `${path}${path.includes("?") ? "&" : "?"}locale=${encodeURIComponent(locale)}` : path;
|
|
2146
|
+
}
|
|
2117
2147
|
/**
|
|
2118
2148
|
* Fetch all taxonomy definitions
|
|
2119
2149
|
*/
|
|
2120
|
-
async function fetchTaxonomyDefs() {
|
|
2121
|
-
return (await parseApiResponse(await apiFetch(`${API_BASE}/taxonomies
|
|
2150
|
+
async function fetchTaxonomyDefs(options = {}) {
|
|
2151
|
+
return (await parseApiResponse(await apiFetch(withLocale(`${API_BASE}/taxonomies`, options.locale)), "Failed to fetch taxonomies")).taxonomies;
|
|
2122
2152
|
}
|
|
2123
2153
|
/**
|
|
2124
2154
|
* Fetch taxonomy definition by name
|
|
2125
2155
|
*/
|
|
2126
|
-
async function fetchTaxonomyDef(name) {
|
|
2127
|
-
return (await fetchTaxonomyDefs()).find((t) => t.name === name) || null;
|
|
2156
|
+
async function fetchTaxonomyDef(name, options = {}) {
|
|
2157
|
+
return (await fetchTaxonomyDefs(options)).find((t) => t.name === name) || null;
|
|
2128
2158
|
}
|
|
2129
2159
|
/**
|
|
2130
2160
|
* Create a custom taxonomy definition
|
|
@@ -2139,8 +2169,8 @@ async function createTaxonomy(input) {
|
|
|
2139
2169
|
/**
|
|
2140
2170
|
* Fetch terms for a taxonomy
|
|
2141
2171
|
*/
|
|
2142
|
-
async function fetchTerms(taxonomyName) {
|
|
2143
|
-
return (await parseApiResponse(await apiFetch(`${API_BASE}/taxonomies/${taxonomyName}/terms
|
|
2172
|
+
async function fetchTerms(taxonomyName, options = {}) {
|
|
2173
|
+
return (await parseApiResponse(await apiFetch(withLocale(`${API_BASE}/taxonomies/${taxonomyName}/terms`, options.locale)), "Failed to fetch terms")).terms;
|
|
2144
2174
|
}
|
|
2145
2175
|
/**
|
|
2146
2176
|
* Create a term
|
|
@@ -2155,8 +2185,8 @@ async function createTerm(taxonomyName, input) {
|
|
|
2155
2185
|
/**
|
|
2156
2186
|
* Update a term
|
|
2157
2187
|
*/
|
|
2158
|
-
async function updateTerm(taxonomyName, slug, input) {
|
|
2159
|
-
return (await parseApiResponse(await apiFetch(`${API_BASE}/taxonomies/${taxonomyName}/terms/${slug}`, {
|
|
2188
|
+
async function updateTerm(taxonomyName, slug, input, options = {}) {
|
|
2189
|
+
return (await parseApiResponse(await apiFetch(withLocale(`${API_BASE}/taxonomies/${taxonomyName}/terms/${slug}`, options.locale), {
|
|
2160
2190
|
method: "PUT",
|
|
2161
2191
|
headers: { "Content-Type": "application/json" },
|
|
2162
2192
|
body: JSON.stringify(input)
|
|
@@ -2165,10 +2195,25 @@ async function updateTerm(taxonomyName, slug, input) {
|
|
|
2165
2195
|
/**
|
|
2166
2196
|
* Delete a term
|
|
2167
2197
|
*/
|
|
2168
|
-
async function deleteTerm(taxonomyName, slug) {
|
|
2169
|
-
const response = await apiFetch(`${API_BASE}/taxonomies/${taxonomyName}/terms/${slug}`, { method: "DELETE" });
|
|
2198
|
+
async function deleteTerm(taxonomyName, slug, options = {}) {
|
|
2199
|
+
const response = await apiFetch(withLocale(`${API_BASE}/taxonomies/${taxonomyName}/terms/${slug}`, options.locale), { method: "DELETE" });
|
|
2170
2200
|
if (!response.ok) await throwResponseError(response, "Failed to delete term");
|
|
2171
2201
|
}
|
|
2202
|
+
/** List every translation (locale variant) of a term. */
|
|
2203
|
+
async function fetchTermTranslations(taxonomyName, slug, options = {}) {
|
|
2204
|
+
return parseApiResponse(await apiFetch(withLocale(`${API_BASE}/taxonomies/${taxonomyName}/terms/${slug}/translations`, options.locale)), "Failed to fetch term translations");
|
|
2205
|
+
}
|
|
2206
|
+
/**
|
|
2207
|
+
* Create a new locale translation of a term. The new term inherits slug,
|
|
2208
|
+
* label, parent, and description from the source unless overridden in `input`.
|
|
2209
|
+
*/
|
|
2210
|
+
async function createTermTranslation(taxonomyName, slug, input, options = {}) {
|
|
2211
|
+
return (await parseApiResponse(await apiFetch(withLocale(`${API_BASE}/taxonomies/${taxonomyName}/terms/${slug}/translations`, options.locale), {
|
|
2212
|
+
method: "POST",
|
|
2213
|
+
headers: { "Content-Type": "application/json" },
|
|
2214
|
+
body: JSON.stringify(input)
|
|
2215
|
+
}), "Failed to create term translation")).term;
|
|
2216
|
+
}
|
|
2172
2217
|
|
|
2173
2218
|
//#endregion
|
|
2174
2219
|
//#region src/lib/api/import.ts
|
|
@@ -2715,6 +2760,44 @@ function fromDatetimeLocalInputValue(value) {
|
|
|
2715
2760
|
return value === "" ? "" : `${value}:00.000Z`;
|
|
2716
2761
|
}
|
|
2717
2762
|
|
|
2763
|
+
//#endregion
|
|
2764
|
+
//#region src/lib/media-utils.ts
|
|
2765
|
+
function providerItemToMediaItem(providerId, item) {
|
|
2766
|
+
return {
|
|
2767
|
+
id: item.id,
|
|
2768
|
+
filename: item.filename,
|
|
2769
|
+
mimeType: item.mimeType,
|
|
2770
|
+
url: item.previewUrl || "",
|
|
2771
|
+
size: item.size || 0,
|
|
2772
|
+
width: item.width,
|
|
2773
|
+
height: item.height,
|
|
2774
|
+
alt: item.alt,
|
|
2775
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2776
|
+
provider: providerId,
|
|
2777
|
+
meta: item.meta
|
|
2778
|
+
};
|
|
2779
|
+
}
|
|
2780
|
+
function getFileIcon(mimeType) {
|
|
2781
|
+
if (mimeType.startsWith("video/")) return "🎬";
|
|
2782
|
+
if (mimeType.startsWith("audio/")) return "🎵";
|
|
2783
|
+
if (mimeType.includes("pdf")) return "📄";
|
|
2784
|
+
if (mimeType.includes("document") || mimeType.includes("word")) return "📝";
|
|
2785
|
+
if (mimeType.includes("spreadsheet") || mimeType.includes("excel")) return "📊";
|
|
2786
|
+
return "📁";
|
|
2787
|
+
}
|
|
2788
|
+
function formatFileSize(bytes) {
|
|
2789
|
+
if (bytes === 0) return "0 B";
|
|
2790
|
+
const k = 1024;
|
|
2791
|
+
const sizes = [
|
|
2792
|
+
"B",
|
|
2793
|
+
"KB",
|
|
2794
|
+
"MB",
|
|
2795
|
+
"GB"
|
|
2796
|
+
];
|
|
2797
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
2798
|
+
return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + " " + sizes[i];
|
|
2799
|
+
}
|
|
2800
|
+
|
|
2718
2801
|
//#endregion
|
|
2719
2802
|
//#region src/lib/url.ts
|
|
2720
2803
|
/**
|
|
@@ -2767,44 +2850,6 @@ function safeIconUrl(url, width) {
|
|
|
2767
2850
|
}
|
|
2768
2851
|
}
|
|
2769
2852
|
|
|
2770
|
-
//#endregion
|
|
2771
|
-
//#region src/lib/media-utils.ts
|
|
2772
|
-
function providerItemToMediaItem(providerId, item) {
|
|
2773
|
-
return {
|
|
2774
|
-
id: item.id,
|
|
2775
|
-
filename: item.filename,
|
|
2776
|
-
mimeType: item.mimeType,
|
|
2777
|
-
url: item.previewUrl || "",
|
|
2778
|
-
size: item.size || 0,
|
|
2779
|
-
width: item.width,
|
|
2780
|
-
height: item.height,
|
|
2781
|
-
alt: item.alt,
|
|
2782
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2783
|
-
provider: providerId,
|
|
2784
|
-
meta: item.meta
|
|
2785
|
-
};
|
|
2786
|
-
}
|
|
2787
|
-
function getFileIcon(mimeType) {
|
|
2788
|
-
if (mimeType.startsWith("video/")) return "🎬";
|
|
2789
|
-
if (mimeType.startsWith("audio/")) return "🎵";
|
|
2790
|
-
if (mimeType.includes("pdf")) return "📄";
|
|
2791
|
-
if (mimeType.includes("document") || mimeType.includes("word")) return "📝";
|
|
2792
|
-
if (mimeType.includes("spreadsheet") || mimeType.includes("excel")) return "📊";
|
|
2793
|
-
return "📁";
|
|
2794
|
-
}
|
|
2795
|
-
function formatFileSize(bytes) {
|
|
2796
|
-
if (bytes === 0) return "0 B";
|
|
2797
|
-
const k = 1024;
|
|
2798
|
-
const sizes = [
|
|
2799
|
-
"B",
|
|
2800
|
-
"KB",
|
|
2801
|
-
"MB",
|
|
2802
|
-
"GB"
|
|
2803
|
-
];
|
|
2804
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
2805
|
-
return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + " " + sizes[i];
|
|
2806
|
-
}
|
|
2807
|
-
|
|
2808
2853
|
//#endregion
|
|
2809
2854
|
//#region src/components/MediaPickerModal.tsx
|
|
2810
2855
|
/**
|
|
@@ -2832,22 +2877,41 @@ function probeImageDimensions(url) {
|
|
|
2832
2877
|
img.src = url;
|
|
2833
2878
|
});
|
|
2834
2879
|
}
|
|
2835
|
-
function MediaPickerModal({ open, onOpenChange, onSelect, mimeTypeFilter = "image/", title: providedTitle }) {
|
|
2880
|
+
function MediaPickerModal({ open, onOpenChange, onSelect, mimeTypeFilter = "image/", title: providedTitle, hideUrlInput = false, mediaKind = "image" }) {
|
|
2836
2881
|
const { _: _t } = useLingui();
|
|
2837
|
-
const
|
|
2882
|
+
const isFileKind = mediaKind === "file";
|
|
2883
|
+
const title = providedTitle ?? (isFileKind ? _t({
|
|
2884
|
+
id: "+Xjyeo",
|
|
2885
|
+
message: "Select File"
|
|
2886
|
+
}) : _t({
|
|
2838
2887
|
id: "bAiEJP",
|
|
2839
2888
|
message: "Select Image"
|
|
2889
|
+
}));
|
|
2890
|
+
const emptyStateUploadHint = isFileKind ? _t({
|
|
2891
|
+
id: "R5f0DH",
|
|
2892
|
+
message: "Upload a file to get started"
|
|
2893
|
+
}) : _t({
|
|
2894
|
+
id: "pzjc9K",
|
|
2895
|
+
message: "Upload an image to get started"
|
|
2896
|
+
});
|
|
2897
|
+
const emptyStateUploadCta = isFileKind ? _t({
|
|
2898
|
+
id: "IQ3gAw",
|
|
2899
|
+
message: "Upload File"
|
|
2900
|
+
}) : _t({
|
|
2901
|
+
id: "lnCMdg",
|
|
2902
|
+
message: "Upload Image"
|
|
2840
2903
|
});
|
|
2904
|
+
const EmptyStateIcon = isFileKind ? Paperclip : Image$1;
|
|
2841
2905
|
const queryClient = useQueryClient();
|
|
2842
|
-
const [selectedItem, setSelectedItem] = React.useState(null);
|
|
2843
|
-
const [activeProvider, setActiveProvider] = React.useState("local");
|
|
2844
|
-
const [searchQuery, setSearchQuery] = React.useState("");
|
|
2845
|
-
const fileInputRef = React.useRef(null);
|
|
2846
|
-
const [imageUrl, setImageUrl] = React.useState("");
|
|
2847
|
-
const [isProbing, setIsProbing] = React.useState(false);
|
|
2848
|
-
const [urlError, setUrlError] = React.useState(null);
|
|
2849
|
-
const [providerDimensions, setProviderDimensions] = React.useState({});
|
|
2850
|
-
React.useEffect(() => {
|
|
2906
|
+
const [selectedItem, setSelectedItem] = React$1.useState(null);
|
|
2907
|
+
const [activeProvider, setActiveProvider] = React$1.useState("local");
|
|
2908
|
+
const [searchQuery, setSearchQuery] = React$1.useState("");
|
|
2909
|
+
const fileInputRef = React$1.useRef(null);
|
|
2910
|
+
const [imageUrl, setImageUrl] = React$1.useState("");
|
|
2911
|
+
const [isProbing, setIsProbing] = React$1.useState(false);
|
|
2912
|
+
const [urlError, setUrlError] = React$1.useState(null);
|
|
2913
|
+
const [providerDimensions, setProviderDimensions] = React$1.useState({});
|
|
2914
|
+
React$1.useEffect(() => {
|
|
2851
2915
|
if (open) {
|
|
2852
2916
|
setSelectedItem(null);
|
|
2853
2917
|
setActiveProvider("local");
|
|
@@ -2864,7 +2928,7 @@ function MediaPickerModal({ open, onOpenChange, onSelect, mimeTypeFilter = "imag
|
|
|
2864
2928
|
enabled: open,
|
|
2865
2929
|
placeholderData: []
|
|
2866
2930
|
});
|
|
2867
|
-
const activeProviderInfo = React.useMemo(() => {
|
|
2931
|
+
const activeProviderInfo = React$1.useMemo(() => {
|
|
2868
2932
|
if (activeProvider === "local") return {
|
|
2869
2933
|
id: "local",
|
|
2870
2934
|
name: "Library",
|
|
@@ -2901,7 +2965,7 @@ function MediaPickerModal({ open, onOpenChange, onSelect, mimeTypeFilter = "imag
|
|
|
2901
2965
|
enabled: open && activeProvider !== "local"
|
|
2902
2966
|
});
|
|
2903
2967
|
const isLoading = activeProvider === "local" ? localLoading : providerLoading;
|
|
2904
|
-
const [uploadError, setUploadError] = React.useState(null);
|
|
2968
|
+
const [uploadError, setUploadError] = React$1.useState(null);
|
|
2905
2969
|
const uploadLocalMutation = useMutation({
|
|
2906
2970
|
mutationFn: (file) => uploadMedia(file),
|
|
2907
2971
|
onSuccess: (item) => {
|
|
@@ -2931,7 +2995,7 @@ function MediaPickerModal({ open, onOpenChange, onSelect, mimeTypeFilter = "imag
|
|
|
2931
2995
|
}
|
|
2932
2996
|
});
|
|
2933
2997
|
const isUploading = uploadLocalMutation.isPending || uploadProviderMutation.isPending;
|
|
2934
|
-
const updatedDimensionsRef = React.useRef(/* @__PURE__ */ new Set());
|
|
2998
|
+
const updatedDimensionsRef = React$1.useRef(/* @__PURE__ */ new Set());
|
|
2935
2999
|
const dimensionsMutation = useMutation({
|
|
2936
3000
|
mutationFn: ({ id, width, height }) => updateMedia(id, {
|
|
2937
3001
|
width,
|
|
@@ -2962,7 +3026,7 @@ function MediaPickerModal({ open, onOpenChange, onSelect, mimeTypeFilter = "imag
|
|
|
2962
3026
|
console.warn("Failed to update media dimensions:", error);
|
|
2963
3027
|
}
|
|
2964
3028
|
});
|
|
2965
|
-
const handleDimensionsDetected = React.useCallback((id, width, height) => {
|
|
3029
|
+
const handleDimensionsDetected = React$1.useCallback((id, width, height) => {
|
|
2966
3030
|
if (updatedDimensionsRef.current.has(id)) return;
|
|
2967
3031
|
updatedDimensionsRef.current.add(id);
|
|
2968
3032
|
dimensionsMutation.mutate({
|
|
@@ -2971,7 +3035,7 @@ function MediaPickerModal({ open, onOpenChange, onSelect, mimeTypeFilter = "imag
|
|
|
2971
3035
|
height
|
|
2972
3036
|
});
|
|
2973
3037
|
}, [dimensionsMutation]);
|
|
2974
|
-
const items = React.useMemo(() => {
|
|
3038
|
+
const items = React$1.useMemo(() => {
|
|
2975
3039
|
if (activeProvider === "local") {
|
|
2976
3040
|
const localItems = localData?.items || [];
|
|
2977
3041
|
if (!mimeTypeFilter) return localItems;
|
|
@@ -3064,7 +3128,7 @@ function MediaPickerModal({ open, onOpenChange, onSelect, mimeTypeFilter = "imag
|
|
|
3064
3128
|
};
|
|
3065
3129
|
const canUpload = activeProvider === "local" || (activeProviderInfo?.capabilities.upload ?? false);
|
|
3066
3130
|
const canSearch = activeProviderInfo?.capabilities.search ?? false;
|
|
3067
|
-
const providerTabs = React.useMemo(() => {
|
|
3131
|
+
const providerTabs = React$1.useMemo(() => {
|
|
3068
3132
|
const tabs = [{
|
|
3069
3133
|
id: "local",
|
|
3070
3134
|
name: "Library",
|
|
@@ -3115,7 +3179,7 @@ function MediaPickerModal({ open, onOpenChange, onSelect, mimeTypeFilter = "imag
|
|
|
3115
3179
|
})
|
|
3116
3180
|
})]
|
|
3117
3181
|
}),
|
|
3118
|
-
/* @__PURE__ */ jsxs("div", {
|
|
3182
|
+
!hideUrlInput && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
|
|
3119
3183
|
className: "border-b pb-4",
|
|
3120
3184
|
children: [
|
|
3121
3185
|
/* @__PURE__ */ jsx(Label, { children: _t({
|
|
@@ -3155,8 +3219,7 @@ function MediaPickerModal({ open, onOpenChange, onSelect, mimeTypeFilter = "imag
|
|
|
3155
3219
|
children: urlError
|
|
3156
3220
|
})
|
|
3157
3221
|
]
|
|
3158
|
-
}),
|
|
3159
|
-
/* @__PURE__ */ jsxs("div", {
|
|
3222
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
3160
3223
|
className: "relative py-2",
|
|
3161
3224
|
children: [/* @__PURE__ */ jsx("div", {
|
|
3162
3225
|
className: "absolute inset-0 flex items-center",
|
|
@@ -3171,7 +3234,7 @@ function MediaPickerModal({ open, onOpenChange, onSelect, mimeTypeFilter = "imag
|
|
|
3171
3234
|
})
|
|
3172
3235
|
})
|
|
3173
3236
|
})]
|
|
3174
|
-
}),
|
|
3237
|
+
})] }),
|
|
3175
3238
|
providerTabs.length > 1 && /* @__PURE__ */ jsx("div", {
|
|
3176
3239
|
className: "flex gap-2 border-b pb-3 flex-wrap",
|
|
3177
3240
|
children: providerTabs.map((tab) => /* @__PURE__ */ jsxs("button", {
|
|
@@ -3255,7 +3318,7 @@ function MediaPickerModal({ open, onOpenChange, onSelect, mimeTypeFilter = "imag
|
|
|
3255
3318
|
}) : items.length === 0 ? /* @__PURE__ */ jsxs("div", {
|
|
3256
3319
|
className: "flex flex-col items-center justify-center h-full text-center p-8",
|
|
3257
3320
|
children: [
|
|
3258
|
-
/* @__PURE__ */ jsx(
|
|
3321
|
+
/* @__PURE__ */ jsx(EmptyStateIcon, {
|
|
3259
3322
|
className: "h-12 w-12 text-kumo-subtle mb-4",
|
|
3260
3323
|
"aria-hidden": "true"
|
|
3261
3324
|
}),
|
|
@@ -3271,10 +3334,7 @@ function MediaPickerModal({ open, onOpenChange, onSelect, mimeTypeFilter = "imag
|
|
|
3271
3334
|
children: canSearch && searchQuery ? _t({
|
|
3272
3335
|
id: "jKoZME",
|
|
3273
3336
|
message: "Try a different search term"
|
|
3274
|
-
}) : canUpload ? _t({
|
|
3275
|
-
id: "pzjc9K",
|
|
3276
|
-
message: "Upload an image to get started"
|
|
3277
|
-
}) : _t({
|
|
3337
|
+
}) : canUpload ? emptyStateUploadHint : _t({
|
|
3278
3338
|
id: "IbZjS1",
|
|
3279
3339
|
message: "No media available from this provider"
|
|
3280
3340
|
})
|
|
@@ -3283,10 +3343,7 @@ function MediaPickerModal({ open, onOpenChange, onSelect, mimeTypeFilter = "imag
|
|
|
3283
3343
|
className: "mt-4",
|
|
3284
3344
|
icon: /* @__PURE__ */ jsx(Upload, {}),
|
|
3285
3345
|
onClick: () => fileInputRef.current?.click(),
|
|
3286
|
-
children:
|
|
3287
|
-
id: "lnCMdg",
|
|
3288
|
-
message: "Upload Image"
|
|
3289
|
-
})
|
|
3346
|
+
children: emptyStateUploadCta
|
|
3290
3347
|
})
|
|
3291
3348
|
]
|
|
3292
3349
|
}) : /* @__PURE__ */ jsx("ul", {
|
|
@@ -3384,7 +3441,7 @@ function MediaPickerItem({ item, selected, onClick, onDoubleClick, onDimensionsD
|
|
|
3384
3441
|
const { _: _t2 } = useLingui();
|
|
3385
3442
|
const isImage = item.mimeType.startsWith("image/");
|
|
3386
3443
|
const needsDimensions = isImage && (!item.width || !item.height);
|
|
3387
|
-
const handleImageLoad = React.useCallback((e) => {
|
|
3444
|
+
const handleImageLoad = React$1.useCallback((e) => {
|
|
3388
3445
|
if (needsDimensions && onDimensionsDetected) {
|
|
3389
3446
|
const img = e.currentTarget;
|
|
3390
3447
|
if (img.naturalWidth && img.naturalHeight) onDimensionsDetected(item.id, img.naturalWidth, img.naturalHeight);
|
|
@@ -3451,7 +3508,7 @@ function ProviderMediaItem({ item, selected, onClick, onDoubleClick, onDimension
|
|
|
3451
3508
|
const { _: _t3 } = useLingui();
|
|
3452
3509
|
const isImage = item.mimeType.startsWith("image/");
|
|
3453
3510
|
const needsDimensions = isImage && (!item.width || !item.height);
|
|
3454
|
-
const handleImageLoad = React.useCallback((e) => {
|
|
3511
|
+
const handleImageLoad = React$1.useCallback((e) => {
|
|
3455
3512
|
if (needsDimensions && onDimensionsLoaded) {
|
|
3456
3513
|
const img = e.currentTarget;
|
|
3457
3514
|
if (img.naturalWidth && img.naturalHeight) onDimensionsLoaded(img.naturalWidth, img.naturalHeight);
|
|
@@ -3524,7 +3581,7 @@ function ProviderMediaItem({ item, selected, onClick, onDoubleClick, onDimension
|
|
|
3524
3581
|
*/
|
|
3525
3582
|
function BlockKitMediaPickerField({ actionId, label, placeholder, mimeTypeFilter, value, onChange }) {
|
|
3526
3583
|
const { _: _t } = useLingui();
|
|
3527
|
-
const [pickerOpen, setPickerOpen] = React.useState(false);
|
|
3584
|
+
const [pickerOpen, setPickerOpen] = React$1.useState(false);
|
|
3528
3585
|
const url = typeof value === "string" && value.length > 0 ? value : "";
|
|
3529
3586
|
const filter = mimeTypeFilter ?? "image/";
|
|
3530
3587
|
const canPreview = isSafePreviewUrl(url);
|
|
@@ -3625,9 +3682,9 @@ function isSafePreviewUrl(url) {
|
|
|
3625
3682
|
*/
|
|
3626
3683
|
function BlockKitFieldWidget({ label, elements, value, onChange }) {
|
|
3627
3684
|
const obj = value && typeof value === "object" ? value : {};
|
|
3628
|
-
const objRef = React.useRef(obj);
|
|
3685
|
+
const objRef = React$1.useRef(obj);
|
|
3629
3686
|
objRef.current = obj;
|
|
3630
|
-
const handleElementChange = React.useCallback((actionId, elementValue) => {
|
|
3687
|
+
const handleElementChange = React$1.useCallback((actionId, elementValue) => {
|
|
3631
3688
|
onChange({
|
|
3632
3689
|
...objRef.current,
|
|
3633
3690
|
[actionId]: elementValue
|
|
@@ -3765,10 +3822,10 @@ function findCurrentHeading(headings, cursorPos) {
|
|
|
3765
3822
|
*/
|
|
3766
3823
|
function DocumentOutline({ editor, className }) {
|
|
3767
3824
|
const { _: _t } = useLingui();
|
|
3768
|
-
const [isExpanded, setIsExpanded] = React.useState(true);
|
|
3769
|
-
const [headings, setHeadings] = React.useState([]);
|
|
3770
|
-
const [currentPos, setCurrentPos] = React.useState(0);
|
|
3771
|
-
React.useEffect(() => {
|
|
3825
|
+
const [isExpanded, setIsExpanded] = React$1.useState(true);
|
|
3826
|
+
const [headings, setHeadings] = React$1.useState([]);
|
|
3827
|
+
const [currentPos, setCurrentPos] = React$1.useState(0);
|
|
3828
|
+
React$1.useEffect(() => {
|
|
3772
3829
|
if (!editor) return;
|
|
3773
3830
|
const updateHeadings = () => {
|
|
3774
3831
|
setHeadings(extractHeadings(editor));
|
|
@@ -3779,7 +3836,7 @@ function DocumentOutline({ editor, className }) {
|
|
|
3779
3836
|
editor.off("update", updateHeadings);
|
|
3780
3837
|
};
|
|
3781
3838
|
}, [editor]);
|
|
3782
|
-
React.useEffect(() => {
|
|
3839
|
+
React$1.useEffect(() => {
|
|
3783
3840
|
if (!editor) return;
|
|
3784
3841
|
const updatePosition = () => {
|
|
3785
3842
|
const { from } = editor.state.selection;
|
|
@@ -3841,7 +3898,7 @@ function DocumentOutline({ editor, className }) {
|
|
|
3841
3898
|
* Error boundary that wraps trusted plugin field widgets.
|
|
3842
3899
|
* On render error, shows a warning with a retry button instead of crashing the editor.
|
|
3843
3900
|
*/
|
|
3844
|
-
var PluginFieldErrorBoundary = class extends React.Component {
|
|
3901
|
+
var PluginFieldErrorBoundary = class extends React$1.Component {
|
|
3845
3902
|
constructor(props) {
|
|
3846
3903
|
super(props);
|
|
3847
3904
|
this.state = { hasError: false };
|
|
@@ -3902,9 +3959,9 @@ function stripKeys$1(items) {
|
|
|
3902
3959
|
function RepeaterField({ label, id, value, onChange, subFields, minItems = 0, maxItems }) {
|
|
3903
3960
|
const { _: _t } = useLingui();
|
|
3904
3961
|
const rawItems = Array.isArray(value) ? value : [];
|
|
3905
|
-
const [items, setItems] = React.useState(() => ensureKeys$1(rawItems));
|
|
3906
|
-
const [collapsedItems, setCollapsedItems] = React.useState(/* @__PURE__ */ new Set());
|
|
3907
|
-
React.useEffect(() => {
|
|
3962
|
+
const [items, setItems] = React$1.useState(() => ensureKeys$1(rawItems));
|
|
3963
|
+
const [collapsedItems, setCollapsedItems] = React$1.useState(/* @__PURE__ */ new Set());
|
|
3964
|
+
React$1.useEffect(() => {
|
|
3908
3965
|
const incoming = Array.isArray(value) ? value : [];
|
|
3909
3966
|
setItems((prev) => incoming.map((item, i) => {
|
|
3910
3967
|
const obj = typeof item === "object" && item !== null ? item : {};
|
|
@@ -4157,11 +4214,11 @@ function SubFieldInput({ subField, value, onChange }) {
|
|
|
4157
4214
|
* callback identity changes.
|
|
4158
4215
|
*/
|
|
4159
4216
|
function useStableCallback(callback) {
|
|
4160
|
-
const ref = React.useRef(callback);
|
|
4161
|
-
React.useLayoutEffect(() => {
|
|
4217
|
+
const ref = React$1.useRef(callback);
|
|
4218
|
+
React$1.useLayoutEffect(() => {
|
|
4162
4219
|
ref.current = callback;
|
|
4163
4220
|
});
|
|
4164
|
-
return React.useCallback((...args) => ref.current(...args), []);
|
|
4221
|
+
return React$1.useCallback((...args) => ref.current(...args), []);
|
|
4165
4222
|
}
|
|
4166
4223
|
/**
|
|
4167
4224
|
* Returns a debounced version of a value that only updates after the
|
|
@@ -4169,8 +4226,8 @@ function useStableCallback(callback) {
|
|
|
4169
4226
|
* inputs that trigger API calls.
|
|
4170
4227
|
*/
|
|
4171
4228
|
function useDebouncedValue$1(value, delay) {
|
|
4172
|
-
const [debouncedValue, setDebouncedValue] = React.useState(value);
|
|
4173
|
-
React.useEffect(() => {
|
|
4229
|
+
const [debouncedValue, setDebouncedValue] = React$1.useState(value);
|
|
4230
|
+
React$1.useEffect(() => {
|
|
4174
4231
|
const timer = setTimeout(setDebouncedValue, delay, value);
|
|
4175
4232
|
return () => clearTimeout(timer);
|
|
4176
4233
|
}, [value, delay]);
|
|
@@ -4192,13 +4249,13 @@ function useDebouncedValue$1(value, delay) {
|
|
|
4192
4249
|
*/
|
|
4193
4250
|
function ImageDetailPanel({ attributes, onUpdate, onReplace, onDelete, onClose, inline = false }) {
|
|
4194
4251
|
const { _: _t } = useLingui();
|
|
4195
|
-
const [alt, setAlt] = React.useState(attributes.alt ?? "");
|
|
4196
|
-
const [caption, setCaption] = React.useState(attributes.caption ?? "");
|
|
4197
|
-
const [title, setTitle] = React.useState(attributes.title ?? "");
|
|
4198
|
-
const [showMediaPicker, setShowMediaPicker] = React.useState(false);
|
|
4199
|
-
const [displayWidth, setDisplayWidth] = React.useState(attributes.displayWidth ?? attributes.width);
|
|
4200
|
-
const [displayHeight, setDisplayHeight] = React.useState(attributes.displayHeight ?? attributes.height);
|
|
4201
|
-
const [lockAspectRatio, setLockAspectRatio] = React.useState(true);
|
|
4252
|
+
const [alt, setAlt] = React$1.useState(attributes.alt ?? "");
|
|
4253
|
+
const [caption, setCaption] = React$1.useState(attributes.caption ?? "");
|
|
4254
|
+
const [title, setTitle] = React$1.useState(attributes.title ?? "");
|
|
4255
|
+
const [showMediaPicker, setShowMediaPicker] = React$1.useState(false);
|
|
4256
|
+
const [displayWidth, setDisplayWidth] = React$1.useState(attributes.displayWidth ?? attributes.width);
|
|
4257
|
+
const [displayHeight, setDisplayHeight] = React$1.useState(attributes.displayHeight ?? attributes.height);
|
|
4258
|
+
const [lockAspectRatio, setLockAspectRatio] = React$1.useState(true);
|
|
4202
4259
|
const aspectRatio = attributes.width && attributes.height ? attributes.width / attributes.height : void 0;
|
|
4203
4260
|
const handleWidthChange = (value) => {
|
|
4204
4261
|
const newWidth = value ? parseInt(value, 10) : void 0;
|
|
@@ -4227,7 +4284,7 @@ function ImageDetailPanel({ attributes, onUpdate, onReplace, onDelete, onClose,
|
|
|
4227
4284
|
setShowMediaPicker(false);
|
|
4228
4285
|
onClose();
|
|
4229
4286
|
};
|
|
4230
|
-
const hasChanges = React.useMemo(() => {
|
|
4287
|
+
const hasChanges = React$1.useMemo(() => {
|
|
4231
4288
|
const originalDisplayWidth = attributes.displayWidth ?? attributes.width;
|
|
4232
4289
|
const originalDisplayHeight = attributes.displayHeight ?? attributes.height;
|
|
4233
4290
|
return alt !== (attributes.alt ?? "") || caption !== (attributes.caption ?? "") || title !== (attributes.title ?? "") || displayWidth !== originalDisplayWidth || displayHeight !== originalDisplayHeight;
|
|
@@ -4249,13 +4306,13 @@ function ImageDetailPanel({ attributes, onUpdate, onReplace, onDelete, onClose,
|
|
|
4249
4306
|
});
|
|
4250
4307
|
onClose();
|
|
4251
4308
|
};
|
|
4252
|
-
const [showDeleteConfirm, setShowDeleteConfirm] = React.useState(false);
|
|
4309
|
+
const [showDeleteConfirm, setShowDeleteConfirm] = React$1.useState(false);
|
|
4253
4310
|
const handleDelete = () => {
|
|
4254
4311
|
setShowDeleteConfirm(true);
|
|
4255
4312
|
};
|
|
4256
4313
|
const stableOnClose = useStableCallback(onClose);
|
|
4257
4314
|
const stableHandleSave = useStableCallback(handleSave);
|
|
4258
|
-
React.useEffect(() => {
|
|
4315
|
+
React$1.useEffect(() => {
|
|
4259
4316
|
const handleKeyDown = (e) => {
|
|
4260
4317
|
if (e.key === "Escape") stableOnClose();
|
|
4261
4318
|
if ((e.metaKey || e.ctrlKey) && e.key === "s") {
|
|
@@ -5197,8 +5254,8 @@ const blockTransforms = [
|
|
|
5197
5254
|
*/
|
|
5198
5255
|
function BlockMenu({ editor, anchorElement, isOpen, onClose }) {
|
|
5199
5256
|
const { _: _t } = useLingui();
|
|
5200
|
-
const [showTransforms, setShowTransforms] = React.useState(false);
|
|
5201
|
-
const menuRef = React.useRef(null);
|
|
5257
|
+
const [showTransforms, setShowTransforms] = React$1.useState(false);
|
|
5258
|
+
const menuRef = React$1.useRef(null);
|
|
5202
5259
|
const stableOnClose = useStableCallback(onClose);
|
|
5203
5260
|
const { refs, floatingStyles } = useFloating({
|
|
5204
5261
|
open: isOpen,
|
|
@@ -5213,10 +5270,10 @@ function BlockMenu({ editor, anchorElement, isOpen, onClose }) {
|
|
|
5213
5270
|
],
|
|
5214
5271
|
whileElementsMounted: autoUpdate
|
|
5215
5272
|
});
|
|
5216
|
-
React.useEffect(() => {
|
|
5273
|
+
React$1.useEffect(() => {
|
|
5217
5274
|
if (anchorElement) refs.setReference(anchorElement);
|
|
5218
5275
|
}, [anchorElement, refs]);
|
|
5219
|
-
React.useEffect(() => {
|
|
5276
|
+
React$1.useEffect(() => {
|
|
5220
5277
|
if (!isOpen) return;
|
|
5221
5278
|
const handleKeyDown = (e) => {
|
|
5222
5279
|
if (e.key === "Escape") {
|
|
@@ -5232,7 +5289,7 @@ function BlockMenu({ editor, anchorElement, isOpen, onClose }) {
|
|
|
5232
5289
|
stableOnClose,
|
|
5233
5290
|
showTransforms
|
|
5234
5291
|
]);
|
|
5235
|
-
React.useEffect(() => {
|
|
5292
|
+
React$1.useEffect(() => {
|
|
5236
5293
|
if (!isOpen) return;
|
|
5237
5294
|
const handleClickOutside = (e) => {
|
|
5238
5295
|
const target = e.target;
|
|
@@ -5248,7 +5305,7 @@ function BlockMenu({ editor, anchorElement, isOpen, onClose }) {
|
|
|
5248
5305
|
document.removeEventListener("mousedown", handleClickOutside);
|
|
5249
5306
|
};
|
|
5250
5307
|
}, [isOpen, stableOnClose]);
|
|
5251
|
-
React.useEffect(() => {
|
|
5308
|
+
React$1.useEffect(() => {
|
|
5252
5309
|
if (!isOpen) setShowTransforms(false);
|
|
5253
5310
|
}, [isOpen]);
|
|
5254
5311
|
const handleDuplicate = () => {
|
|
@@ -5341,11 +5398,11 @@ function BlockMenu({ editor, anchorElement, isOpen, onClose }) {
|
|
|
5341
5398
|
* DragHandleWrapper - Official TipTap drag handle with BlockMenu integration
|
|
5342
5399
|
*/
|
|
5343
5400
|
function DragHandleWrapper({ editor }) {
|
|
5344
|
-
const [hoveredNode, setHoveredNode] = React.useState(null);
|
|
5345
|
-
const [menuOpen, setMenuOpen] = React.useState(false);
|
|
5346
|
-
const [menuAnchor, setMenuAnchor] = React.useState(null);
|
|
5347
|
-
const handleRef = React.useRef(null);
|
|
5348
|
-
const handleClick = React.useCallback((e) => {
|
|
5401
|
+
const [hoveredNode, setHoveredNode] = React$1.useState(null);
|
|
5402
|
+
const [menuOpen, setMenuOpen] = React$1.useState(false);
|
|
5403
|
+
const [menuAnchor, setMenuAnchor] = React$1.useState(null);
|
|
5404
|
+
const handleRef = React$1.useRef(null);
|
|
5405
|
+
const handleClick = React$1.useCallback((e) => {
|
|
5349
5406
|
e.preventDefault();
|
|
5350
5407
|
e.stopPropagation();
|
|
5351
5408
|
if (!hoveredNode) return;
|
|
@@ -5354,21 +5411,21 @@ function DragHandleWrapper({ editor }) {
|
|
|
5354
5411
|
setMenuOpen(true);
|
|
5355
5412
|
editor.commands.lockDragHandle();
|
|
5356
5413
|
}, [editor, hoveredNode]);
|
|
5357
|
-
const handleCloseMenu = React.useCallback(() => {
|
|
5414
|
+
const handleCloseMenu = React$1.useCallback(() => {
|
|
5358
5415
|
setMenuOpen(false);
|
|
5359
5416
|
setMenuAnchor(null);
|
|
5360
5417
|
editor.commands.unlockDragHandle();
|
|
5361
5418
|
}, [editor]);
|
|
5362
5419
|
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(DragHandle, {
|
|
5363
5420
|
editor,
|
|
5364
|
-
onNodeChange: React.useCallback((data) => {
|
|
5421
|
+
onNodeChange: React$1.useCallback((data) => {
|
|
5365
5422
|
if (data.node) setHoveredNode({
|
|
5366
5423
|
node: data.node,
|
|
5367
5424
|
pos: data.pos
|
|
5368
5425
|
});
|
|
5369
5426
|
else if (!menuOpen) setHoveredNode(null);
|
|
5370
5427
|
}, [menuOpen]),
|
|
5371
|
-
computePositionConfig: React.useMemo(() => ({
|
|
5428
|
+
computePositionConfig: React$1.useMemo(() => ({
|
|
5372
5429
|
placement: "left-start",
|
|
5373
5430
|
strategy: "absolute"
|
|
5374
5431
|
}), []),
|
|
@@ -5402,10 +5459,10 @@ function DragHandleWrapper({ editor }) {
|
|
|
5402
5459
|
* - Delete/replace options
|
|
5403
5460
|
*/
|
|
5404
5461
|
function ImageNodeView({ node, updateAttributes, selected, deleteNode, editor }) {
|
|
5405
|
-
const [isEditingAlt, setIsEditingAlt] = React.useState(false);
|
|
5406
|
-
const [altText, setAltText] = React.useState(node.attrs.alt || "");
|
|
5462
|
+
const [isEditingAlt, setIsEditingAlt] = React$1.useState(false);
|
|
5463
|
+
const [altText, setAltText] = React$1.useState(node.attrs.alt || "");
|
|
5407
5464
|
/** Whether this node currently has its sidebar panel open */
|
|
5408
|
-
const sidebarOpenRef = React.useRef(false);
|
|
5465
|
+
const sidebarOpenRef = React$1.useRef(false);
|
|
5409
5466
|
const handleSaveAlt = () => {
|
|
5410
5467
|
updateAttributes({ alt: altText });
|
|
5411
5468
|
setIsEditingAlt(false);
|
|
@@ -5419,7 +5476,7 @@ function ImageNodeView({ node, updateAttributes, selected, deleteNode, editor })
|
|
|
5419
5476
|
setIsEditingAlt(false);
|
|
5420
5477
|
}
|
|
5421
5478
|
};
|
|
5422
|
-
React.useEffect(() => {
|
|
5479
|
+
React$1.useEffect(() => {
|
|
5423
5480
|
setAltText(node.attrs.alt || "");
|
|
5424
5481
|
}, [node.attrs.alt]);
|
|
5425
5482
|
const getImageAttrs = () => ({
|
|
@@ -5461,7 +5518,7 @@ function ImageNodeView({ node, updateAttributes, selected, deleteNode, editor })
|
|
|
5461
5518
|
if (sidebarOpenRef.current) closeSidebar();
|
|
5462
5519
|
else openSidebar();
|
|
5463
5520
|
};
|
|
5464
|
-
React.useEffect(() => {
|
|
5521
|
+
React$1.useEffect(() => {
|
|
5465
5522
|
if (!selected) closeSidebar();
|
|
5466
5523
|
}, [selected]);
|
|
5467
5524
|
return /* @__PURE__ */ jsx(NodeViewWrapper, {
|
|
@@ -5782,10 +5839,10 @@ function PluginBlockNodeView({ node, updateAttributes, selected, deleteNode, edi
|
|
|
5782
5839
|
const { Icon, label, color, placeholder } = getEmbedMeta(blockType, registry);
|
|
5783
5840
|
const blockDef = registry.get(blockType);
|
|
5784
5841
|
const hasFields = blockDef?.fields && blockDef.fields.length > 0;
|
|
5785
|
-
const [isEditing, setIsEditing] = React.useState(false);
|
|
5786
|
-
const [editValue, setEditValue] = React.useState(id || "");
|
|
5787
|
-
const inputRef = React.useRef(null);
|
|
5788
|
-
React.useEffect(() => {
|
|
5842
|
+
const [isEditing, setIsEditing] = React$1.useState(false);
|
|
5843
|
+
const [editValue, setEditValue] = React$1.useState(id || "");
|
|
5844
|
+
const inputRef = React$1.useRef(null);
|
|
5845
|
+
React$1.useEffect(() => {
|
|
5789
5846
|
if (isEditing) {
|
|
5790
5847
|
setEditValue(id || "");
|
|
5791
5848
|
setTimeout(() => inputRef.current?.focus(), 0);
|
|
@@ -6006,7 +6063,7 @@ const PluginBlockExtension = Node$1.create({
|
|
|
6006
6063
|
*/
|
|
6007
6064
|
function SectionPickerModal({ open, onOpenChange, onSelect }) {
|
|
6008
6065
|
const { _: _t } = useLingui();
|
|
6009
|
-
const [searchQuery, setSearchQuery] = React.useState("");
|
|
6066
|
+
const [searchQuery, setSearchQuery] = React$1.useState("");
|
|
6010
6067
|
const debouncedSearch = useDebouncedValue$1(searchQuery, 300);
|
|
6011
6068
|
const { data: sectionsData, isLoading: sectionsLoading } = useQuery({
|
|
6012
6069
|
queryKey: ["sections", { search: debouncedSearch }],
|
|
@@ -6014,7 +6071,7 @@ function SectionPickerModal({ open, onOpenChange, onSelect }) {
|
|
|
6014
6071
|
enabled: open
|
|
6015
6072
|
});
|
|
6016
6073
|
const sections = sectionsData?.items ?? [];
|
|
6017
|
-
React.useEffect(() => {
|
|
6074
|
+
React$1.useEffect(() => {
|
|
6018
6075
|
if (open) setSearchQuery("");
|
|
6019
6076
|
}, [open]);
|
|
6020
6077
|
const handleSelect = (section) => {
|
|
@@ -6805,7 +6862,7 @@ function createSlashCommandsExtension(options) {
|
|
|
6805
6862
|
*/
|
|
6806
6863
|
function SlashCommandMenu({ state, onCommand, onClose: _onClose, setSelectedIndex }) {
|
|
6807
6864
|
const { _: _t } = useLingui();
|
|
6808
|
-
const containerRef = React.useRef(null);
|
|
6865
|
+
const containerRef = React$1.useRef(null);
|
|
6809
6866
|
const { refs, floatingStyles } = useFloating({
|
|
6810
6867
|
open: state.isOpen,
|
|
6811
6868
|
placement: "bottom-start",
|
|
@@ -6816,13 +6873,13 @@ function SlashCommandMenu({ state, onCommand, onClose: _onClose, setSelectedInde
|
|
|
6816
6873
|
],
|
|
6817
6874
|
whileElementsMounted: autoUpdate
|
|
6818
6875
|
});
|
|
6819
|
-
React.useEffect(() => {
|
|
6876
|
+
React$1.useEffect(() => {
|
|
6820
6877
|
if (state.clientRect) {
|
|
6821
6878
|
const clientRectFn = state.clientRect;
|
|
6822
6879
|
refs.setReference({ getBoundingClientRect: () => clientRectFn() ?? new DOMRect() });
|
|
6823
6880
|
}
|
|
6824
6881
|
}, [state.clientRect, refs]);
|
|
6825
|
-
React.useEffect(() => {
|
|
6882
|
+
React$1.useEffect(() => {
|
|
6826
6883
|
if (!state.isOpen) return;
|
|
6827
6884
|
const container = containerRef.current;
|
|
6828
6885
|
if (!container) return;
|
|
@@ -6886,9 +6943,9 @@ function hasPluginBlockFormData(values) {
|
|
|
6886
6943
|
* Otherwise falls back to a simple URL input.
|
|
6887
6944
|
*/
|
|
6888
6945
|
function PluginBlockModal({ block, initialValues, onClose, onInsert }) {
|
|
6889
|
-
const [formValues, setFormValues] = React.useState({});
|
|
6890
|
-
const inputRef = React.useRef(null);
|
|
6891
|
-
React.useEffect(() => {
|
|
6946
|
+
const [formValues, setFormValues] = React$1.useState({});
|
|
6947
|
+
const inputRef = React$1.useRef(null);
|
|
6948
|
+
React$1.useEffect(() => {
|
|
6892
6949
|
if (block) {
|
|
6893
6950
|
setFormValues(buildPluginBlockFormValues(block, initialValues));
|
|
6894
6951
|
if (!block.fields || block.fields.length === 0) setTimeout(() => inputRef.current?.focus(), 0);
|
|
@@ -7074,12 +7131,12 @@ function stripKeys(items) {
|
|
|
7074
7131
|
}
|
|
7075
7132
|
function BlockKitRepeater({ field, pluginId, value, onChange }) {
|
|
7076
7133
|
const { _: _t2 } = useLingui();
|
|
7077
|
-
const rawItems = React.useMemo(() => Array.isArray(value) ? value : [], [value]);
|
|
7078
|
-
const [items, setItems] = React.useState(() => ensureKeys(rawItems));
|
|
7079
|
-
const [expanded, setExpanded] = React.useState(/* @__PURE__ */ new Set());
|
|
7134
|
+
const rawItems = React$1.useMemo(() => Array.isArray(value) ? value : [], [value]);
|
|
7135
|
+
const [items, setItems] = React$1.useState(() => ensureKeys(rawItems));
|
|
7136
|
+
const [expanded, setExpanded] = React$1.useState(/* @__PURE__ */ new Set());
|
|
7080
7137
|
const sensors = useSensors(useSensor(PointerSensor), useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }));
|
|
7081
|
-
const lastEmittedRef = React.useRef(null);
|
|
7082
|
-
React.useEffect(() => {
|
|
7138
|
+
const lastEmittedRef = React$1.useRef(null);
|
|
7139
|
+
React$1.useEffect(() => {
|
|
7083
7140
|
if (lastEmittedRef.current === rawItems) return;
|
|
7084
7141
|
setItems((prev) => rawItems.map((item, i) => {
|
|
7085
7142
|
const obj = typeof item === "object" && item !== null ? item : {};
|
|
@@ -7291,9 +7348,9 @@ function BlockKitRepeaterItem({ item, index, fields, pluginId, isCollapsed, onTo
|
|
|
7291
7348
|
* When `optionsRoute` is set, fetches `{ items: [{ id, name }] }` from the plugin route.
|
|
7292
7349
|
*/
|
|
7293
7350
|
function DynamicSelect({ field, pluginId, value, onChange }) {
|
|
7294
|
-
const [dynamicOptions, setDynamicOptions] = React.useState(null);
|
|
7295
|
-
const [loading, setLoading] = React.useState(false);
|
|
7296
|
-
React.useEffect(() => {
|
|
7351
|
+
const [dynamicOptions, setDynamicOptions] = React$1.useState(null);
|
|
7352
|
+
const [loading, setLoading] = React$1.useState(false);
|
|
7353
|
+
React$1.useEffect(() => {
|
|
7297
7354
|
if (!field.optionsRoute || !pluginId) return;
|
|
7298
7355
|
const controller = new AbortController();
|
|
7299
7356
|
setLoading(true);
|
|
@@ -7385,34 +7442,34 @@ function EditorFooter({ editor }) {
|
|
|
7385
7442
|
*/
|
|
7386
7443
|
function PortableTextEditor({ value, onChange, placeholder = "Start writing...", className, editable = true, "aria-labelledby": ariaLabelledby, pluginBlocks = [], focusMode: controlledFocusMode, onFocusModeChange, onEditorReady, minimal = false, onBlockSidebarOpen, onBlockSidebarClose }) {
|
|
7387
7444
|
const { _: _t4 } = useLingui();
|
|
7388
|
-
const onChangeRef = React.useRef(onChange);
|
|
7389
|
-
React.useEffect(() => {
|
|
7445
|
+
const onChangeRef = React$1.useRef(onChange);
|
|
7446
|
+
React$1.useEffect(() => {
|
|
7390
7447
|
onChangeRef.current = onChange;
|
|
7391
7448
|
}, [onChange]);
|
|
7392
|
-
const [internalFocusMode, setInternalFocusMode] = React.useState("normal");
|
|
7449
|
+
const [internalFocusMode, setInternalFocusMode] = React$1.useState("normal");
|
|
7393
7450
|
const focusMode = controlledFocusMode ?? internalFocusMode;
|
|
7394
7451
|
const setFocusMode = (mode) => {
|
|
7395
7452
|
if (onFocusModeChange) onFocusModeChange(mode);
|
|
7396
7453
|
else setInternalFocusMode(mode);
|
|
7397
7454
|
};
|
|
7398
|
-
const [mediaPickerOpen, setMediaPickerOpen] = React.useState(false);
|
|
7399
|
-
const [pluginBlockModal, setPluginBlockModal] = React.useState(null);
|
|
7400
|
-
const [pluginBlockInitialValues, setPluginBlockInitialValues] = React.useState(void 0);
|
|
7455
|
+
const [mediaPickerOpen, setMediaPickerOpen] = React$1.useState(false);
|
|
7456
|
+
const [pluginBlockModal, setPluginBlockModal] = React$1.useState(null);
|
|
7457
|
+
const [pluginBlockInitialValues, setPluginBlockInitialValues] = React$1.useState(void 0);
|
|
7401
7458
|
/** When editing an existing block, store the node position for updateAttributes */
|
|
7402
|
-
const editingBlockPosRef = React.useRef(null);
|
|
7403
|
-
const [sectionPickerOpen, setSectionPickerOpen] = React.useState(false);
|
|
7404
|
-
const [slashMenuState, setSlashMenuState] = React.useState({
|
|
7459
|
+
const editingBlockPosRef = React$1.useRef(null);
|
|
7460
|
+
const [sectionPickerOpen, setSectionPickerOpen] = React$1.useState(false);
|
|
7461
|
+
const [slashMenuState, setSlashMenuState] = React$1.useState({
|
|
7405
7462
|
isOpen: false,
|
|
7406
7463
|
items: [],
|
|
7407
7464
|
selectedIndex: 0,
|
|
7408
7465
|
clientRect: null,
|
|
7409
7466
|
range: null
|
|
7410
7467
|
});
|
|
7411
|
-
const slashMenuStateRef = React.useRef(slashMenuState);
|
|
7412
|
-
React.useEffect(() => {
|
|
7468
|
+
const slashMenuStateRef = React$1.useRef(slashMenuState);
|
|
7469
|
+
React$1.useEffect(() => {
|
|
7413
7470
|
slashMenuStateRef.current = slashMenuState;
|
|
7414
7471
|
}, [slashMenuState]);
|
|
7415
|
-
const slashCommands = React.useMemo(() => {
|
|
7472
|
+
const slashCommands = React$1.useMemo(() => {
|
|
7416
7473
|
const cmds = [...defaultSlashCommands];
|
|
7417
7474
|
cmds.push({
|
|
7418
7475
|
id: "image",
|
|
@@ -7486,7 +7543,7 @@ function PortableTextEditor({ value, onChange, placeholder = "Start writing...",
|
|
|
7486
7543
|
});
|
|
7487
7544
|
return cmds;
|
|
7488
7545
|
}, [pluginBlocks, _t4]);
|
|
7489
|
-
const filterCommandsRef = React.useRef((_q) => []);
|
|
7546
|
+
const filterCommandsRef = React$1.useRef((_q) => []);
|
|
7490
7547
|
filterCommandsRef.current = (query) => {
|
|
7491
7548
|
if (!query) return slashCommands;
|
|
7492
7549
|
const searchText = query.toLowerCase();
|
|
@@ -7500,9 +7557,9 @@ function PortableTextEditor({ value, onChange, placeholder = "Start writing...",
|
|
|
7500
7557
|
}
|
|
7501
7558
|
return [...titleMatches, ...otherMatches];
|
|
7502
7559
|
};
|
|
7503
|
-
const initialContent = React.useMemo(() => portableTextToProsemirror(value || []), []);
|
|
7560
|
+
const initialContent = React$1.useMemo(() => portableTextToProsemirror(value || []), []);
|
|
7504
7561
|
const editor = useEditor({
|
|
7505
|
-
extensions: React.useMemo(() => [
|
|
7562
|
+
extensions: React$1.useMemo(() => [
|
|
7506
7563
|
StarterKit.configure({
|
|
7507
7564
|
heading: { levels: [
|
|
7508
7565
|
1,
|
|
@@ -7546,7 +7603,7 @@ function PortableTextEditor({ value, onChange, placeholder = "Start writing...",
|
|
|
7546
7603
|
content: initialContent,
|
|
7547
7604
|
editable,
|
|
7548
7605
|
immediatelyRender: true,
|
|
7549
|
-
editorProps: React.useMemo(() => ({ attributes: {
|
|
7606
|
+
editorProps: React$1.useMemo(() => ({ attributes: {
|
|
7550
7607
|
class: "prose prose-sm sm:prose-base dark:prose-invert max-w-none focus:outline-none min-h-[200px] p-4",
|
|
7551
7608
|
dir: "auto"
|
|
7552
7609
|
} }), []),
|
|
@@ -7555,7 +7612,7 @@ function PortableTextEditor({ value, onChange, placeholder = "Start writing...",
|
|
|
7555
7612
|
if (cb) cb(prosemirrorToPortableText(updatedEditor.getJSON()));
|
|
7556
7613
|
}
|
|
7557
7614
|
});
|
|
7558
|
-
React.useEffect(() => {
|
|
7615
|
+
React$1.useEffect(() => {
|
|
7559
7616
|
if (editor && onEditorReady) {
|
|
7560
7617
|
onEditorReady(editor);
|
|
7561
7618
|
return () => {
|
|
@@ -7563,10 +7620,10 @@ function PortableTextEditor({ value, onChange, placeholder = "Start writing...",
|
|
|
7563
7620
|
};
|
|
7564
7621
|
}
|
|
7565
7622
|
}, [editor, onEditorReady]);
|
|
7566
|
-
React.useEffect(() => {
|
|
7623
|
+
React$1.useEffect(() => {
|
|
7567
7624
|
if (editor) registerPluginBlocks(editor, pluginBlocks);
|
|
7568
7625
|
}, [editor, pluginBlocks]);
|
|
7569
|
-
React.useEffect(() => {
|
|
7626
|
+
React$1.useEffect(() => {
|
|
7570
7627
|
if (!editor) return;
|
|
7571
7628
|
const storage = editor.storage.pluginBlock;
|
|
7572
7629
|
if (!storage) return;
|
|
@@ -7584,11 +7641,11 @@ function PortableTextEditor({ value, onChange, placeholder = "Start writing...",
|
|
|
7584
7641
|
storage.onEditBlock = null;
|
|
7585
7642
|
};
|
|
7586
7643
|
}, [editor, pluginBlocks]);
|
|
7587
|
-
const onBlockSidebarOpenRef = React.useRef(onBlockSidebarOpen);
|
|
7644
|
+
const onBlockSidebarOpenRef = React$1.useRef(onBlockSidebarOpen);
|
|
7588
7645
|
onBlockSidebarOpenRef.current = onBlockSidebarOpen;
|
|
7589
|
-
const onBlockSidebarCloseRef = React.useRef(onBlockSidebarClose);
|
|
7646
|
+
const onBlockSidebarCloseRef = React$1.useRef(onBlockSidebarClose);
|
|
7590
7647
|
onBlockSidebarCloseRef.current = onBlockSidebarClose;
|
|
7591
|
-
React.useEffect(() => {
|
|
7648
|
+
React$1.useEffect(() => {
|
|
7592
7649
|
if (!editor) return;
|
|
7593
7650
|
const storage = editor.storage.image;
|
|
7594
7651
|
if (!storage) return;
|
|
@@ -7603,7 +7660,7 @@ function PortableTextEditor({ value, onChange, placeholder = "Start writing...",
|
|
|
7603
7660
|
storage.onCloseBlockSidebar = null;
|
|
7604
7661
|
};
|
|
7605
7662
|
}, [editor]);
|
|
7606
|
-
const handleImageSelect = React.useCallback((item) => {
|
|
7663
|
+
const handleImageSelect = React$1.useCallback((item) => {
|
|
7607
7664
|
if (editor) editor.chain().focus().setImage({
|
|
7608
7665
|
src: item.url,
|
|
7609
7666
|
alt: item.alt || item.filename,
|
|
@@ -7614,7 +7671,7 @@ function PortableTextEditor({ value, onChange, placeholder = "Start writing...",
|
|
|
7614
7671
|
}).run();
|
|
7615
7672
|
setMediaPickerOpen(false);
|
|
7616
7673
|
}, [editor]);
|
|
7617
|
-
const handlePluginBlockInsert = React.useCallback((values) => {
|
|
7674
|
+
const handlePluginBlockInsert = React$1.useCallback((values) => {
|
|
7618
7675
|
if (!editor || !pluginBlockModal) return;
|
|
7619
7676
|
const { id, ...data } = values;
|
|
7620
7677
|
const editPos = editingBlockPosRef.current;
|
|
@@ -7641,7 +7698,7 @@ function PortableTextEditor({ value, onChange, placeholder = "Start writing...",
|
|
|
7641
7698
|
setPluginBlockInitialValues(void 0);
|
|
7642
7699
|
editingBlockPosRef.current = null;
|
|
7643
7700
|
}, [editor, pluginBlockModal]);
|
|
7644
|
-
const handleSlashCommand = React.useCallback((item) => {
|
|
7701
|
+
const handleSlashCommand = React$1.useCallback((item) => {
|
|
7645
7702
|
if (editor && slashMenuState.range) {
|
|
7646
7703
|
item.command({
|
|
7647
7704
|
editor,
|
|
@@ -7653,7 +7710,7 @@ function PortableTextEditor({ value, onChange, placeholder = "Start writing...",
|
|
|
7653
7710
|
}));
|
|
7654
7711
|
}
|
|
7655
7712
|
}, [editor, slashMenuState.range]);
|
|
7656
|
-
const handleSectionSelect = React.useCallback((section) => {
|
|
7713
|
+
const handleSectionSelect = React$1.useCallback((section) => {
|
|
7657
7714
|
if (!editor || !section.content || section.content.length === 0) return;
|
|
7658
7715
|
const { content: prosemirrorContent } = portableTextToProsemirror(Array.isArray(section.content) ? section.content : []);
|
|
7659
7716
|
editor.chain().focus().insertContent(prosemirrorContent).run();
|
|
@@ -7722,10 +7779,10 @@ function PortableTextEditor({ value, onChange, placeholder = "Start writing...",
|
|
|
7722
7779
|
* Shows inline formatting options and link editing
|
|
7723
7780
|
*/
|
|
7724
7781
|
function EditorBubbleMenu({ editor }) {
|
|
7725
|
-
const [showLinkInput, setShowLinkInput] = React.useState(false);
|
|
7726
|
-
const [linkUrl, setLinkUrl] = React.useState("");
|
|
7727
|
-
const inputRef = React.useRef(null);
|
|
7728
|
-
React.useEffect(() => {
|
|
7782
|
+
const [showLinkInput, setShowLinkInput] = React$1.useState(false);
|
|
7783
|
+
const [linkUrl, setLinkUrl] = React$1.useState("");
|
|
7784
|
+
const inputRef = React$1.useRef(null);
|
|
7785
|
+
React$1.useEffect(() => {
|
|
7729
7786
|
if (showLinkInput) {
|
|
7730
7787
|
setLinkUrl(editor.getAttributes("link").href || "");
|
|
7731
7788
|
setTimeout(() => inputRef.current?.focus(), 0);
|
|
@@ -7854,11 +7911,11 @@ function BubbleButton({ onClick, active, title, children }) {
|
|
|
7854
7911
|
* Arrow keys move focus between buttons, Home/End jump to first/last.
|
|
7855
7912
|
*/
|
|
7856
7913
|
function EditorToolbar({ editor, focusMode, onFocusModeChange }) {
|
|
7857
|
-
const [mediaPickerOpen, setMediaPickerOpen] = React.useState(false);
|
|
7858
|
-
const [showLinkPopover, setShowLinkPopover] = React.useState(false);
|
|
7859
|
-
const [linkUrl, setLinkUrl] = React.useState("");
|
|
7860
|
-
const toolbarRef = React.useRef(null);
|
|
7861
|
-
const linkInputRef = React.useRef(null);
|
|
7914
|
+
const [mediaPickerOpen, setMediaPickerOpen] = React$1.useState(false);
|
|
7915
|
+
const [showLinkPopover, setShowLinkPopover] = React$1.useState(false);
|
|
7916
|
+
const [linkUrl, setLinkUrl] = React$1.useState("");
|
|
7917
|
+
const toolbarRef = React$1.useRef(null);
|
|
7918
|
+
const linkInputRef = React$1.useRef(null);
|
|
7862
7919
|
const editorState = useEditorState({
|
|
7863
7920
|
editor,
|
|
7864
7921
|
selector: (ctx) => ({
|
|
@@ -7882,7 +7939,7 @@ function EditorToolbar({ editor, focusMode, onFocusModeChange }) {
|
|
|
7882
7939
|
canRedo: ctx.editor.can().redo()
|
|
7883
7940
|
})
|
|
7884
7941
|
});
|
|
7885
|
-
React.useEffect(() => {
|
|
7942
|
+
React$1.useEffect(() => {
|
|
7886
7943
|
if (showLinkPopover) {
|
|
7887
7944
|
setLinkUrl(editor.getAttributes("link").href || "");
|
|
7888
7945
|
setTimeout(() => linkInputRef.current?.focus(), 0);
|
|
@@ -7909,7 +7966,7 @@ function EditorToolbar({ editor, focusMode, onFocusModeChange }) {
|
|
|
7909
7966
|
editor.commands.focus();
|
|
7910
7967
|
}
|
|
7911
7968
|
};
|
|
7912
|
-
const handleImageSelect = React.useCallback((item) => {
|
|
7969
|
+
const handleImageSelect = React$1.useCallback((item) => {
|
|
7913
7970
|
editor.chain().focus().setImage({
|
|
7914
7971
|
src: item.url,
|
|
7915
7972
|
alt: item.alt || item.filename,
|
|
@@ -7918,7 +7975,7 @@ function EditorToolbar({ editor, focusMode, onFocusModeChange }) {
|
|
|
7918
7975
|
height: item.height
|
|
7919
7976
|
}).run();
|
|
7920
7977
|
}, [editor]);
|
|
7921
|
-
const handleKeyDown = React.useCallback((e) => {
|
|
7978
|
+
const handleKeyDown = React$1.useCallback((e) => {
|
|
7922
7979
|
const toolbar = toolbarRef.current;
|
|
7923
7980
|
if (!toolbar) return;
|
|
7924
7981
|
const buttons = [...toolbar.querySelectorAll("button:not([disabled]), [role=\"button\"]:not([disabled])")];
|
|
@@ -8316,9 +8373,9 @@ function formatFullDate(dateString) {
|
|
|
8316
8373
|
*/
|
|
8317
8374
|
function RevisionHistory({ collection, entryId, onRestored }) {
|
|
8318
8375
|
const { _: _t } = useLingui();
|
|
8319
|
-
const [isExpanded, setIsExpanded] = React.useState(false);
|
|
8320
|
-
const [selectedRevision, setSelectedRevision] = React.useState(null);
|
|
8321
|
-
const [restoreTarget, setRestoreTarget] = React.useState(null);
|
|
8376
|
+
const [isExpanded, setIsExpanded] = React$1.useState(false);
|
|
8377
|
+
const [selectedRevision, setSelectedRevision] = React$1.useState(null);
|
|
8378
|
+
const [restoreTarget, setRestoreTarget] = React$1.useState(null);
|
|
8322
8379
|
const queryClient = useQueryClient();
|
|
8323
8380
|
const toastManager = Toast.useToastManager();
|
|
8324
8381
|
const { data, isLoading, error } = useQuery({
|
|
@@ -8526,8 +8583,8 @@ function RevisionItem({ revision, compareRevision, isLatest, isRestoring, isSele
|
|
|
8526
8583
|
}
|
|
8527
8584
|
function RevisionDiffView({ older, newer }) {
|
|
8528
8585
|
const { _: _t3 } = useLingui();
|
|
8529
|
-
const [showUnchanged, setShowUnchanged] = React.useState(false);
|
|
8530
|
-
const diffs = React.useMemo(() => computeFieldDiff(older, newer), [older, newer]);
|
|
8586
|
+
const [showUnchanged, setShowUnchanged] = React$1.useState(false);
|
|
8587
|
+
const diffs = React$1.useMemo(() => computeFieldDiff(older, newer), [older, newer]);
|
|
8531
8588
|
const changedCount = diffs.filter((d) => d.kind !== "unchanged").length;
|
|
8532
8589
|
const unchangedCount = diffs.length - changedCount;
|
|
8533
8590
|
if (diffs.length === 0) return /* @__PURE__ */ jsx("div", {
|
|
@@ -8698,7 +8755,7 @@ function SaveButton({ isDirty, isSaving, className, disabled, ...props }) {
|
|
|
8698
8755
|
*/
|
|
8699
8756
|
function SeoImageField({ seo, onChange }) {
|
|
8700
8757
|
const { _: _t } = useLingui();
|
|
8701
|
-
const [pickerOpen, setPickerOpen] = React.useState(false);
|
|
8758
|
+
const [pickerOpen, setPickerOpen] = React$1.useState(false);
|
|
8702
8759
|
const imageUrl = seo?.image || null;
|
|
8703
8760
|
const handleSelect = (item) => {
|
|
8704
8761
|
onChange({ image: !item.provider || item.provider === "local" ? `/_emdash/api/media/file/${item.storageKey || item.id}` : item.url });
|
|
@@ -8805,33 +8862,33 @@ function serializeDraft(draft) {
|
|
|
8805
8862
|
}
|
|
8806
8863
|
function SeoPanel({ contentKey, seo, onChange }) {
|
|
8807
8864
|
const { _: _t } = useLingui();
|
|
8808
|
-
const propDraft = React.useMemo(() => toDraft(seo), [seo]);
|
|
8809
|
-
const propSnapshot = React.useMemo(() => serializeDraft(propDraft), [propDraft]);
|
|
8810
|
-
const [draft, setDraft] = React.useState(propDraft);
|
|
8811
|
-
const currentDraftRef = React.useRef(draft);
|
|
8865
|
+
const propDraft = React$1.useMemo(() => toDraft(seo), [seo]);
|
|
8866
|
+
const propSnapshot = React$1.useMemo(() => serializeDraft(propDraft), [propDraft]);
|
|
8867
|
+
const [draft, setDraft] = React$1.useState(propDraft);
|
|
8868
|
+
const currentDraftRef = React$1.useRef(draft);
|
|
8812
8869
|
currentDraftRef.current = draft;
|
|
8813
|
-
const lastPropSnapshotRef = React.useRef(propSnapshot);
|
|
8814
|
-
const lastEmittedSnapshotRef = React.useRef(propSnapshot);
|
|
8815
|
-
const activeContentKeyRef = React.useRef(contentKey);
|
|
8816
|
-
const activeOnChangeRef = React.useRef(onChange);
|
|
8817
|
-
const pendingTextFlushTimerRef = React.useRef(null);
|
|
8818
|
-
const emitChange = React.useCallback((nextDraft) => {
|
|
8870
|
+
const lastPropSnapshotRef = React$1.useRef(propSnapshot);
|
|
8871
|
+
const lastEmittedSnapshotRef = React$1.useRef(propSnapshot);
|
|
8872
|
+
const activeContentKeyRef = React$1.useRef(contentKey);
|
|
8873
|
+
const activeOnChangeRef = React$1.useRef(onChange);
|
|
8874
|
+
const pendingTextFlushTimerRef = React$1.useRef(null);
|
|
8875
|
+
const emitChange = React$1.useCallback((nextDraft) => {
|
|
8819
8876
|
const nextSnapshot = serializeDraft(nextDraft);
|
|
8820
8877
|
if (nextSnapshot === lastEmittedSnapshotRef.current) return;
|
|
8821
8878
|
lastEmittedSnapshotRef.current = nextSnapshot;
|
|
8822
8879
|
activeOnChangeRef.current(toInput(nextDraft));
|
|
8823
8880
|
}, []);
|
|
8824
|
-
const clearPendingTextFlush = React.useCallback(() => {
|
|
8881
|
+
const clearPendingTextFlush = React$1.useCallback(() => {
|
|
8825
8882
|
if (pendingTextFlushTimerRef.current) {
|
|
8826
8883
|
clearTimeout(pendingTextFlushTimerRef.current);
|
|
8827
8884
|
pendingTextFlushTimerRef.current = null;
|
|
8828
8885
|
}
|
|
8829
8886
|
}, []);
|
|
8830
|
-
const flushPendingDraft = React.useCallback(() => {
|
|
8887
|
+
const flushPendingDraft = React$1.useCallback(() => {
|
|
8831
8888
|
clearPendingTextFlush();
|
|
8832
8889
|
emitChange(currentDraftRef.current);
|
|
8833
8890
|
}, [clearPendingTextFlush, emitChange]);
|
|
8834
|
-
React.useEffect(() => {
|
|
8891
|
+
React$1.useEffect(() => {
|
|
8835
8892
|
if (activeContentKeyRef.current === contentKey) {
|
|
8836
8893
|
activeOnChangeRef.current = onChange;
|
|
8837
8894
|
return;
|
|
@@ -8850,12 +8907,12 @@ function SeoPanel({ contentKey, seo, onChange }) {
|
|
|
8850
8907
|
propDraft,
|
|
8851
8908
|
propSnapshot
|
|
8852
8909
|
]);
|
|
8853
|
-
React.useEffect(() => {
|
|
8910
|
+
React$1.useEffect(() => {
|
|
8854
8911
|
return () => {
|
|
8855
8912
|
flushPendingDraft();
|
|
8856
8913
|
};
|
|
8857
8914
|
}, [flushPendingDraft]);
|
|
8858
|
-
React.useEffect(() => {
|
|
8915
|
+
React$1.useEffect(() => {
|
|
8859
8916
|
const previousPropSnapshot = lastPropSnapshotRef.current;
|
|
8860
8917
|
if (propSnapshot === previousPropSnapshot) return;
|
|
8861
8918
|
const currentDraftSnapshot = serializeDraft(currentDraftRef.current);
|
|
@@ -8866,7 +8923,7 @@ function SeoPanel({ contentKey, seo, onChange }) {
|
|
|
8866
8923
|
}
|
|
8867
8924
|
lastPropSnapshotRef.current = propSnapshot;
|
|
8868
8925
|
}, [propDraft, propSnapshot]);
|
|
8869
|
-
React.useEffect(() => {
|
|
8926
|
+
React$1.useEffect(() => {
|
|
8870
8927
|
clearPendingTextFlush();
|
|
8871
8928
|
if (serializeDraft(currentDraftRef.current) === lastEmittedSnapshotRef.current) return;
|
|
8872
8929
|
pendingTextFlushTimerRef.current = setTimeout(() => {
|
|
@@ -9090,10 +9147,10 @@ function CategoryCheckboxTree({ term, level = 0, selectedIds, onToggle }) {
|
|
|
9090
9147
|
*/
|
|
9091
9148
|
function TagInput({ terms, selectedIds, onAdd, onRemove, onCreate, isCreating, label }) {
|
|
9092
9149
|
const { _: _t } = useLingui();
|
|
9093
|
-
const [input, setInput] = React.useState("");
|
|
9150
|
+
const [input, setInput] = React$1.useState("");
|
|
9094
9151
|
const selectedTerms = terms.filter((term) => selectedIds.has(term.id));
|
|
9095
9152
|
const trimmedInput = input.trim();
|
|
9096
|
-
const suggestions = React.useMemo(() => {
|
|
9153
|
+
const suggestions = React$1.useMemo(() => {
|
|
9097
9154
|
if (!trimmedInput) return [];
|
|
9098
9155
|
return terms.filter((term) => !selectedIds.has(term.id) && termMatches(term, trimmedInput)).slice(0, 5);
|
|
9099
9156
|
}, [
|
|
@@ -9101,7 +9158,7 @@ function TagInput({ terms, selectedIds, onAdd, onRemove, onCreate, isCreating, l
|
|
|
9101
9158
|
terms,
|
|
9102
9159
|
selectedIds
|
|
9103
9160
|
]);
|
|
9104
|
-
const hasExactMatch = React.useMemo(() => {
|
|
9161
|
+
const hasExactMatch = React$1.useMemo(() => {
|
|
9105
9162
|
if (!trimmedInput) return false;
|
|
9106
9163
|
return terms.some((term) => termExactMatches(term, trimmedInput));
|
|
9107
9164
|
}, [trimmedInput, terms]);
|
|
@@ -9181,8 +9238,8 @@ function TaxonomySection({ taxonomy, collection, entryId, onChange }) {
|
|
|
9181
9238
|
const { _: _t2 } = useLingui();
|
|
9182
9239
|
const queryClient = useQueryClient();
|
|
9183
9240
|
const toastManager = Toast.useToastManager();
|
|
9184
|
-
const [newCategoryLabel, setNewCategoryLabel] = React.useState("");
|
|
9185
|
-
const [showCategoryInput, setShowCategoryInput] = React.useState(false);
|
|
9241
|
+
const [newCategoryLabel, setNewCategoryLabel] = React$1.useState("");
|
|
9242
|
+
const [showCategoryInput, setShowCategoryInput] = React$1.useState(false);
|
|
9186
9243
|
const { data: terms = [] } = useQuery({
|
|
9187
9244
|
queryKey: ["taxonomy-terms", taxonomy.name],
|
|
9188
9245
|
queryFn: () => fetchTerms$1(taxonomy.name)
|
|
@@ -9250,8 +9307,8 @@ function TaxonomySection({ taxonomy, collection, entryId, onChange }) {
|
|
|
9250
9307
|
setShowCategoryInput(false);
|
|
9251
9308
|
}
|
|
9252
9309
|
});
|
|
9253
|
-
const [selectedIds, setSelectedIds] = React.useState(/* @__PURE__ */ new Set());
|
|
9254
|
-
React.useEffect(() => {
|
|
9310
|
+
const [selectedIds, setSelectedIds] = React$1.useState(/* @__PURE__ */ new Set());
|
|
9311
|
+
React$1.useEffect(() => {
|
|
9255
9312
|
setSelectedIds(new Set(entryTerms.map((term) => term.id)));
|
|
9256
9313
|
}, [entryTerms]);
|
|
9257
9314
|
const handleToggle = (termId) => {
|
|
@@ -9387,6 +9444,81 @@ function TaxonomySidebar({ collection, entryId, onChange }) {
|
|
|
9387
9444
|
});
|
|
9388
9445
|
}
|
|
9389
9446
|
|
|
9447
|
+
//#endregion
|
|
9448
|
+
//#region src/components/TranslationsPanel.tsx
|
|
9449
|
+
/**
|
|
9450
|
+
* Shared "Translations" sidebar panel. Matches the look of the translations
|
|
9451
|
+
* section in ContentEditor — reused across content edit, menu edit and
|
|
9452
|
+
* taxonomy term edit so the admin shows one consistent affordance.
|
|
9453
|
+
*/
|
|
9454
|
+
function TranslationsPanel({ title, locales, defaultLocale, currentLocale, translations, onOpen, onCreate, pendingLocale }) {
|
|
9455
|
+
const { _: _t } = useLingui();
|
|
9456
|
+
const byLocale = React$1.useMemo(() => new Map(translations.map((tr) => [tr.locale, tr])), [translations]);
|
|
9457
|
+
return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h3", {
|
|
9458
|
+
className: "mb-4 font-semibold",
|
|
9459
|
+
children: title ?? _t({
|
|
9460
|
+
id: "kAy5R9",
|
|
9461
|
+
message: "Translations"
|
|
9462
|
+
})
|
|
9463
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
9464
|
+
className: "space-y-2",
|
|
9465
|
+
children: locales.map((locale) => {
|
|
9466
|
+
const translation = byLocale.get(locale);
|
|
9467
|
+
const isCurrent = locale === currentLocale;
|
|
9468
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
9469
|
+
className: cn("flex items-center justify-between rounded-md px-3 py-2 text-sm", isCurrent ? "bg-kumo-brand/10 font-medium" : translation ? "hover:bg-kumo-tint/50" : "text-kumo-subtle"),
|
|
9470
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
9471
|
+
className: "flex items-center gap-2",
|
|
9472
|
+
children: [
|
|
9473
|
+
/* @__PURE__ */ jsx("span", {
|
|
9474
|
+
className: "text-xs font-semibold uppercase",
|
|
9475
|
+
children: locale
|
|
9476
|
+
}),
|
|
9477
|
+
locale === defaultLocale && /* @__PURE__ */ jsx("span", {
|
|
9478
|
+
className: "text-[10px] text-kumo-subtle",
|
|
9479
|
+
children: _t({
|
|
9480
|
+
id: "FozKV6",
|
|
9481
|
+
message: " (default)"
|
|
9482
|
+
})
|
|
9483
|
+
}),
|
|
9484
|
+
isCurrent && /* @__PURE__ */ jsx("span", {
|
|
9485
|
+
className: "text-[10px] text-kumo-brand",
|
|
9486
|
+
children: _t({
|
|
9487
|
+
id: "7vEC4B",
|
|
9488
|
+
message: "current"
|
|
9489
|
+
})
|
|
9490
|
+
})
|
|
9491
|
+
]
|
|
9492
|
+
}), isCurrent ? null : translation && onOpen ? /* @__PURE__ */ jsx(Button, {
|
|
9493
|
+
type: "button",
|
|
9494
|
+
variant: "ghost",
|
|
9495
|
+
size: "sm",
|
|
9496
|
+
className: "h-auto px-2 py-1 text-xs",
|
|
9497
|
+
onClick: () => onOpen(translation),
|
|
9498
|
+
children: _t({
|
|
9499
|
+
id: "ePK91l",
|
|
9500
|
+
message: "Edit"
|
|
9501
|
+
})
|
|
9502
|
+
}) : !translation && onCreate ? /* @__PURE__ */ jsx(Button, {
|
|
9503
|
+
type: "button",
|
|
9504
|
+
variant: "ghost",
|
|
9505
|
+
size: "sm",
|
|
9506
|
+
className: "h-auto px-2 py-1 text-xs",
|
|
9507
|
+
disabled: pendingLocale === locale,
|
|
9508
|
+
onClick: () => onCreate(locale),
|
|
9509
|
+
children: pendingLocale === locale ? _t({
|
|
9510
|
+
id: "wvgKtH",
|
|
9511
|
+
message: "Translating..."
|
|
9512
|
+
}) : _t({
|
|
9513
|
+
id: "pi8x/S",
|
|
9514
|
+
message: "Translate"
|
|
9515
|
+
})
|
|
9516
|
+
}) : null]
|
|
9517
|
+
}, locale);
|
|
9518
|
+
})
|
|
9519
|
+
})] });
|
|
9520
|
+
}
|
|
9521
|
+
|
|
9390
9522
|
//#endregion
|
|
9391
9523
|
//#region src/components/ContentEditor.tsx
|
|
9392
9524
|
/** Autosave debounce delay in milliseconds */
|
|
@@ -9409,29 +9541,30 @@ function formatScheduledDate(dateStr) {
|
|
|
9409
9541
|
*/
|
|
9410
9542
|
function ContentEditor({ collection, collectionLabel, item, fields, isNew, isSaving, onSave, onAutosave, isAutosaving, lastAutosaveAt, onPublish, onUnpublish, onDiscardDraft, onSchedule, onUnschedule, isScheduling, supportsDrafts = false, supportsRevisions = false, supportsPreview = false, currentUser, users, onAuthorChange, availableBylines, selectedBylines, onBylinesChange, onQuickCreateByline, onQuickEditByline, onDelete, isDeleting, i18n, translations, onTranslate, pluginBlocks, hasSeo = false, onSeoChange, manifest }) {
|
|
9411
9543
|
const { _: _t } = useLingui();
|
|
9412
|
-
const
|
|
9413
|
-
const [
|
|
9414
|
-
const [
|
|
9415
|
-
const [
|
|
9416
|
-
const [
|
|
9544
|
+
const navigate = useNavigate$1();
|
|
9545
|
+
const [formData, setFormData] = React$1.useState(item?.data || {});
|
|
9546
|
+
const [slug, setSlug] = React$1.useState(item?.slug || "");
|
|
9547
|
+
const [slugTouched, setSlugTouched] = React$1.useState(!!item?.slug);
|
|
9548
|
+
const [status, setStatus] = React$1.useState(item?.status || "draft");
|
|
9549
|
+
const [internalBylines, setInternalBylines] = React$1.useState(item?.bylines?.map((entry) => ({
|
|
9417
9550
|
bylineId: entry.byline.id,
|
|
9418
9551
|
roleLabel: entry.roleLabel
|
|
9419
9552
|
})) ?? []);
|
|
9420
|
-
const [portableTextEditor, setPortableTextEditor] = React.useState(null);
|
|
9421
|
-
const [blockSidebarPanel, setBlockSidebarPanel] = React.useState(null);
|
|
9422
|
-
const handleBlockSidebarOpen = React.useCallback((panel) => {
|
|
9553
|
+
const [portableTextEditor, setPortableTextEditor] = React$1.useState(null);
|
|
9554
|
+
const [blockSidebarPanel, setBlockSidebarPanel] = React$1.useState(null);
|
|
9555
|
+
const handleBlockSidebarOpen = React$1.useCallback((panel) => {
|
|
9423
9556
|
setBlockSidebarPanel(panel);
|
|
9424
9557
|
}, []);
|
|
9425
|
-
const handleBlockSidebarClose = React.useCallback(() => {
|
|
9558
|
+
const handleBlockSidebarClose = React$1.useCallback(() => {
|
|
9426
9559
|
setBlockSidebarPanel((prev) => {
|
|
9427
9560
|
prev?.onClose();
|
|
9428
9561
|
return null;
|
|
9429
9562
|
});
|
|
9430
9563
|
}, []);
|
|
9431
|
-
const handleSeoChange = React.useCallback((seo) => {
|
|
9564
|
+
const handleSeoChange = React$1.useCallback((seo) => {
|
|
9432
9565
|
onSeoChange?.(seo);
|
|
9433
9566
|
}, [onSeoChange]);
|
|
9434
|
-
const [lastSavedData, setLastSavedData] = React.useState(serializeEditorState({
|
|
9567
|
+
const [lastSavedData, setLastSavedData] = React$1.useState(serializeEditorState({
|
|
9435
9568
|
data: item?.data || {},
|
|
9436
9569
|
slug: item?.slug || "",
|
|
9437
9570
|
bylines: item?.bylines?.map((entry) => ({
|
|
@@ -9439,8 +9572,8 @@ function ContentEditor({ collection, collectionLabel, item, fields, isNew, isSav
|
|
|
9439
9572
|
roleLabel: entry.roleLabel
|
|
9440
9573
|
})) ?? []
|
|
9441
9574
|
}));
|
|
9442
|
-
const pendingAutosaveStateRef = React.useRef(null);
|
|
9443
|
-
const [previousItemId, setPreviousItemId] = React.useState(item?.id ?? null);
|
|
9575
|
+
const pendingAutosaveStateRef = React$1.useRef(null);
|
|
9576
|
+
const [previousItemId, setPreviousItemId] = React$1.useState(item?.id ?? null);
|
|
9444
9577
|
if (item && item.id !== previousItemId) {
|
|
9445
9578
|
setPreviousItemId(item.id);
|
|
9446
9579
|
setFormData(item.data);
|
|
@@ -9459,8 +9592,8 @@ function ContentEditor({ collection, collectionLabel, item, fields, isNew, isSav
|
|
|
9459
9592
|
}));
|
|
9460
9593
|
pendingAutosaveStateRef.current = null;
|
|
9461
9594
|
}
|
|
9462
|
-
const itemDataString = React.useMemo(() => item ? JSON.stringify(item.data) : "", [item?.data]);
|
|
9463
|
-
React.useEffect(() => {
|
|
9595
|
+
const itemDataString = React$1.useMemo(() => item ? JSON.stringify(item.data) : "", [item?.data]);
|
|
9596
|
+
React$1.useEffect(() => {
|
|
9464
9597
|
if (item) {
|
|
9465
9598
|
setFormData(item.data);
|
|
9466
9599
|
setSlug(item.slug || "");
|
|
@@ -9487,7 +9620,7 @@ function ContentEditor({ collection, collectionLabel, item, fields, isNew, isSav
|
|
|
9487
9620
|
item?.status
|
|
9488
9621
|
]);
|
|
9489
9622
|
const activeBylines = isNew ? selectedBylines ?? [] : internalBylines;
|
|
9490
|
-
const handleBylinesChange = React.useCallback((next) => {
|
|
9623
|
+
const handleBylinesChange = React$1.useCallback((next) => {
|
|
9491
9624
|
if (isNew) {
|
|
9492
9625
|
onBylinesChange?.(next);
|
|
9493
9626
|
return;
|
|
@@ -9495,7 +9628,7 @@ function ContentEditor({ collection, collectionLabel, item, fields, isNew, isSav
|
|
|
9495
9628
|
setInternalBylines(next);
|
|
9496
9629
|
onBylinesChange?.(next);
|
|
9497
9630
|
}, [isNew, onBylinesChange]);
|
|
9498
|
-
const currentData = React.useMemo(() => serializeEditorState({
|
|
9631
|
+
const currentData = React$1.useMemo(() => serializeEditorState({
|
|
9499
9632
|
data: formData,
|
|
9500
9633
|
slug,
|
|
9501
9634
|
bylines: activeBylines
|
|
@@ -9505,24 +9638,24 @@ function ContentEditor({ collection, collectionLabel, item, fields, isNew, isSav
|
|
|
9505
9638
|
activeBylines
|
|
9506
9639
|
]);
|
|
9507
9640
|
const isDirty = isNew || currentData !== lastSavedData;
|
|
9508
|
-
const autosaveTimeoutRef = React.useRef(null);
|
|
9509
|
-
const formDataRef = React.useRef(formData);
|
|
9641
|
+
const autosaveTimeoutRef = React$1.useRef(null);
|
|
9642
|
+
const formDataRef = React$1.useRef(formData);
|
|
9510
9643
|
formDataRef.current = formData;
|
|
9511
|
-
const slugRef = React.useRef(slug);
|
|
9644
|
+
const slugRef = React$1.useRef(slug);
|
|
9512
9645
|
slugRef.current = slug;
|
|
9513
|
-
React.useEffect(() => {
|
|
9646
|
+
React$1.useEffect(() => {
|
|
9514
9647
|
if (!lastAutosaveAt || !pendingAutosaveStateRef.current) return;
|
|
9515
9648
|
setLastSavedData(pendingAutosaveStateRef.current);
|
|
9516
9649
|
pendingAutosaveStateRef.current = null;
|
|
9517
9650
|
}, [lastAutosaveAt]);
|
|
9518
|
-
const hasInvalidUrls = React.useCallback((data) => {
|
|
9651
|
+
const hasInvalidUrls = React$1.useCallback((data) => {
|
|
9519
9652
|
for (const [name, field] of Object.entries(fields)) if (field.kind === "url") {
|
|
9520
9653
|
const val = typeof data[name] === "string" ? data[name].trim() : "";
|
|
9521
9654
|
if (val && !isValidUrl(val)) return true;
|
|
9522
9655
|
}
|
|
9523
9656
|
return false;
|
|
9524
9657
|
}, [fields]);
|
|
9525
|
-
React.useEffect(() => {
|
|
9658
|
+
React$1.useEffect(() => {
|
|
9526
9659
|
if (isNew || !onAutosave || !item?.id) return;
|
|
9527
9660
|
if (!isDirty || isSaving || isAutosaving) return;
|
|
9528
9661
|
if (autosaveTimeoutRef.current) clearTimeout(autosaveTimeoutRef.current);
|
|
@@ -9567,7 +9700,7 @@ function ContentEditor({ collection, collectionLabel, item, fields, isNew, isSav
|
|
|
9567
9700
|
bylines: activeBylines
|
|
9568
9701
|
});
|
|
9569
9702
|
};
|
|
9570
|
-
const [isLoadingPreview, setIsLoadingPreview] = React.useState(false);
|
|
9703
|
+
const [isLoadingPreview, setIsLoadingPreview] = React$1.useState(false);
|
|
9571
9704
|
const urlPattern = manifest?.collections[collection]?.urlPattern;
|
|
9572
9705
|
const handlePreview = async () => {
|
|
9573
9706
|
if (!item?.id) return;
|
|
@@ -9582,7 +9715,7 @@ function ContentEditor({ collection, collectionLabel, item, fields, isNew, isSav
|
|
|
9582
9715
|
setIsLoadingPreview(false);
|
|
9583
9716
|
}
|
|
9584
9717
|
};
|
|
9585
|
-
const handleFieldChange = React.useCallback((name, value) => {
|
|
9718
|
+
const handleFieldChange = React$1.useCallback((name, value) => {
|
|
9586
9719
|
setFormData((prev) => ({
|
|
9587
9720
|
...prev,
|
|
9588
9721
|
[name]: value
|
|
@@ -9599,10 +9732,10 @@ function ContentEditor({ collection, collectionLabel, item, fields, isNew, isSav
|
|
|
9599
9732
|
const isLive = draftStatus === "published" || draftStatus === "published_with_changes";
|
|
9600
9733
|
const hasSchedule = Boolean(item?.scheduledAt);
|
|
9601
9734
|
const canSchedule = !isNew && !hasSchedule && Boolean(onSchedule) && (!isPublished || hasPendingChanges);
|
|
9602
|
-
const [scheduleDate, setScheduleDate] = React.useState("");
|
|
9603
|
-
const [showScheduler, setShowScheduler] = React.useState(false);
|
|
9604
|
-
const [isDistractionFree, setIsDistractionFree] = React.useState(false);
|
|
9605
|
-
React.useEffect(() => {
|
|
9735
|
+
const [scheduleDate, setScheduleDate] = React$1.useState("");
|
|
9736
|
+
const [showScheduler, setShowScheduler] = React$1.useState(false);
|
|
9737
|
+
const [isDistractionFree, setIsDistractionFree] = React$1.useState(false);
|
|
9738
|
+
React$1.useEffect(() => {
|
|
9606
9739
|
if (!isDistractionFree) return;
|
|
9607
9740
|
const handleKeyDown = (e) => {
|
|
9608
9741
|
if (e.key === "Escape") {
|
|
@@ -10111,68 +10244,22 @@ function ContentEditor({ collection, collectionLabel, item, fields, isNew, isSav
|
|
|
10111
10244
|
onQuickEdit: onQuickEditByline
|
|
10112
10245
|
})]
|
|
10113
10246
|
}),
|
|
10114
|
-
i18n && item && !isNew && /* @__PURE__ */
|
|
10247
|
+
i18n && item && !isNew && /* @__PURE__ */ jsx("div", {
|
|
10115
10248
|
className: "p-4 border-t",
|
|
10116
|
-
children:
|
|
10117
|
-
|
|
10118
|
-
|
|
10119
|
-
|
|
10120
|
-
|
|
10121
|
-
|
|
10122
|
-
|
|
10123
|
-
|
|
10124
|
-
|
|
10125
|
-
|
|
10126
|
-
|
|
10127
|
-
|
|
10128
|
-
|
|
10129
|
-
|
|
10130
|
-
className: "flex items-center gap-2",
|
|
10131
|
-
children: [
|
|
10132
|
-
/* @__PURE__ */ jsx("span", {
|
|
10133
|
-
className: "text-xs font-semibold uppercase",
|
|
10134
|
-
children: locale
|
|
10135
|
-
}),
|
|
10136
|
-
locale === i18n.defaultLocale && /* @__PURE__ */ jsx("span", {
|
|
10137
|
-
className: "text-[10px] text-kumo-subtle",
|
|
10138
|
-
children: _t({
|
|
10139
|
-
id: "FozKV6",
|
|
10140
|
-
message: " (default)"
|
|
10141
|
-
})
|
|
10142
|
-
}),
|
|
10143
|
-
isCurrent && /* @__PURE__ */ jsx("span", {
|
|
10144
|
-
className: "text-[10px] text-kumo-brand",
|
|
10145
|
-
children: _t({
|
|
10146
|
-
id: "7vEC4B",
|
|
10147
|
-
message: "current"
|
|
10148
|
-
})
|
|
10149
|
-
})
|
|
10150
|
-
]
|
|
10151
|
-
}), translation && !isCurrent ? /* @__PURE__ */ jsx(Link$1, {
|
|
10152
|
-
to: "/content/$collection/$id",
|
|
10153
|
-
params: {
|
|
10154
|
-
collection,
|
|
10155
|
-
id: translation.id
|
|
10156
|
-
},
|
|
10157
|
-
className: "text-xs text-kumo-brand hover:underline",
|
|
10158
|
-
children: _t({
|
|
10159
|
-
id: "ePK91l",
|
|
10160
|
-
message: "Edit"
|
|
10161
|
-
})
|
|
10162
|
-
}) : !translation && onTranslate ? /* @__PURE__ */ jsx(Button, {
|
|
10163
|
-
type: "button",
|
|
10164
|
-
variant: "ghost",
|
|
10165
|
-
size: "sm",
|
|
10166
|
-
className: "h-auto px-2 py-1 text-xs",
|
|
10167
|
-
onClick: () => onTranslate(locale),
|
|
10168
|
-
children: _t({
|
|
10169
|
-
id: "pi8x/S",
|
|
10170
|
-
message: "Translate"
|
|
10171
|
-
})
|
|
10172
|
-
}) : null]
|
|
10173
|
-
}, locale);
|
|
10174
|
-
})
|
|
10175
|
-
})]
|
|
10249
|
+
children: /* @__PURE__ */ jsx(TranslationsPanel, {
|
|
10250
|
+
locales: i18n.locales,
|
|
10251
|
+
defaultLocale: i18n.defaultLocale,
|
|
10252
|
+
currentLocale: item.locale ?? void 0,
|
|
10253
|
+
translations: translations ?? [],
|
|
10254
|
+
onOpen: (tr) => navigate({
|
|
10255
|
+
to: "/content/$collection/$id",
|
|
10256
|
+
params: {
|
|
10257
|
+
collection,
|
|
10258
|
+
id: tr.id
|
|
10259
|
+
}
|
|
10260
|
+
}),
|
|
10261
|
+
onCreate: onTranslate
|
|
10262
|
+
})
|
|
10176
10263
|
}),
|
|
10177
10264
|
item && /* @__PURE__ */ jsx("div", {
|
|
10178
10265
|
className: "p-4 border-t",
|
|
@@ -10221,7 +10308,7 @@ function FieldRenderer({ name, field, value, onChange, onEditorReady, minimal, p
|
|
|
10221
10308
|
const label = field.label || name.charAt(0).toUpperCase() + name.slice(1);
|
|
10222
10309
|
const id = `field-${name}`;
|
|
10223
10310
|
const labelClass = minimal ? "text-kumo-subtle/50 text-xs font-normal" : void 0;
|
|
10224
|
-
const handleChange = React.useCallback((v) => onChange(name, v), [onChange, name]);
|
|
10311
|
+
const handleChange = React$1.useCallback((v) => onChange(name, v), [onChange, name]);
|
|
10225
10312
|
if (field.widget) {
|
|
10226
10313
|
const sepIdx = field.widget.indexOf(":");
|
|
10227
10314
|
if (sepIdx <= 0) console.warn(`[emdash] Field "${name}" has widget "${field.widget}" but it should use the format "pluginId:widgetName". Falling back to default editor.`);
|
|
@@ -10380,6 +10467,13 @@ function FieldRenderer({ name, field, value, onChange, onEditorReady, minimal, p
|
|
|
10380
10467
|
required: field.required
|
|
10381
10468
|
});
|
|
10382
10469
|
}
|
|
10470
|
+
case "file": return /* @__PURE__ */ jsx(FileFieldRenderer, {
|
|
10471
|
+
id,
|
|
10472
|
+
label,
|
|
10473
|
+
value: value != null && typeof value === "object" ? value : void 0,
|
|
10474
|
+
onChange: handleChange,
|
|
10475
|
+
required: field.required
|
|
10476
|
+
});
|
|
10383
10477
|
case "repeater": {
|
|
10384
10478
|
const validation = field.validation;
|
|
10385
10479
|
const subFields = validation?.subFields ?? [];
|
|
@@ -10437,7 +10531,7 @@ function isValidUrl(val) {
|
|
|
10437
10531
|
*/
|
|
10438
10532
|
function UrlFieldEditor({ label, labelClass, id, value, onChange, required, placeholder }) {
|
|
10439
10533
|
const { _: _t3 } = useLingui();
|
|
10440
|
-
const [error, setError] = React.useState(null);
|
|
10534
|
+
const [error, setError] = React$1.useState(null);
|
|
10441
10535
|
const handleBlur = (e) => {
|
|
10442
10536
|
const val = e.target.value.trim();
|
|
10443
10537
|
if (!val) {
|
|
@@ -10475,9 +10569,9 @@ function UrlFieldEditor({ label, labelClass, id, value, onChange, required, plac
|
|
|
10475
10569
|
*/
|
|
10476
10570
|
function JsonFieldEditor({ label, id, value, onChange, required }) {
|
|
10477
10571
|
const { _: _t4 } = useLingui();
|
|
10478
|
-
const [text, setText] = React.useState(value);
|
|
10479
|
-
const [error, setError] = React.useState(null);
|
|
10480
|
-
React.useEffect(() => {
|
|
10572
|
+
const [text, setText] = React$1.useState(value);
|
|
10573
|
+
const [error, setError] = React$1.useState(null);
|
|
10574
|
+
React$1.useEffect(() => {
|
|
10481
10575
|
setText(value);
|
|
10482
10576
|
setError(null);
|
|
10483
10577
|
}, [value]);
|
|
@@ -10520,7 +10614,7 @@ function JsonFieldEditor({ label, id, value, onChange, required }) {
|
|
|
10520
10614
|
}
|
|
10521
10615
|
function ImageFieldRenderer({ id, label, description, value, onChange, required }) {
|
|
10522
10616
|
const { _: _t5 } = useLingui();
|
|
10523
|
-
const [pickerOpen, setPickerOpen] = React.useState(false);
|
|
10617
|
+
const [pickerOpen, setPickerOpen] = React$1.useState(false);
|
|
10524
10618
|
const displayUrl = typeof value === "string" ? value : value?.previewUrl || value?.src || (value && (!value.provider || value.provider === "local") ? `/_emdash/api/media/file/${typeof value.meta?.storageKey === "string" ? value.meta.storageKey : value.id}` : void 0);
|
|
10525
10619
|
const handleSelect = (item) => {
|
|
10526
10620
|
const isLocalProvider = !item.provider || item.provider === "local";
|
|
@@ -10612,19 +10706,165 @@ function ImageFieldRenderer({ id, label, description, value, onChange, required
|
|
|
10612
10706
|
]
|
|
10613
10707
|
});
|
|
10614
10708
|
}
|
|
10615
|
-
|
|
10709
|
+
/**
|
|
10710
|
+
* File field with media picker
|
|
10711
|
+
*
|
|
10712
|
+
* Like ImageFieldRenderer but for arbitrary file types. Shows a mime-type-appropriate
|
|
10713
|
+
* icon, filename, and size instead of an image preview.
|
|
10714
|
+
*/
|
|
10715
|
+
function FileFieldRenderer({ id, label, value, onChange, required }) {
|
|
10616
10716
|
const { _: _t6 } = useLingui();
|
|
10617
|
-
const [
|
|
10618
|
-
const
|
|
10619
|
-
|
|
10620
|
-
|
|
10621
|
-
|
|
10622
|
-
|
|
10623
|
-
|
|
10624
|
-
|
|
10625
|
-
|
|
10626
|
-
|
|
10627
|
-
|
|
10717
|
+
const [pickerOpen, setPickerOpen] = React$1.useState(false);
|
|
10718
|
+
const normalized = React$1.useMemo(() => {
|
|
10719
|
+
if (!value) return null;
|
|
10720
|
+
const isLocal = !value.provider || value.provider === "local";
|
|
10721
|
+
const storageKey = typeof value.meta?.storageKey === "string" ? value.meta.storageKey : void 0;
|
|
10722
|
+
const localSrc = typeof value.src === "string" && value.src.startsWith("/_emdash/") ? value.src : void 0;
|
|
10723
|
+
const localUrl = isLocal ? storageKey ? `/_emdash/api/media/file/${encodeURIComponent(storageKey)}` : localSrc ?? `/_emdash/api/media/file/${encodeURIComponent(value.id)}` : void 0;
|
|
10724
|
+
const externalUrl = !isLocal && value.src && isSafeUrl$1(value.src) ? value.src : void 0;
|
|
10725
|
+
return {
|
|
10726
|
+
displayUrl: localUrl ?? externalUrl,
|
|
10727
|
+
filename: value.filename || _t6({
|
|
10728
|
+
id: "cChtk1",
|
|
10729
|
+
message: "Untitled file"
|
|
10730
|
+
}),
|
|
10731
|
+
mimeType: value.mimeType || "",
|
|
10732
|
+
size: value.size
|
|
10733
|
+
};
|
|
10734
|
+
}, [value, _t6]);
|
|
10735
|
+
const handleSelect = (item) => {
|
|
10736
|
+
const isLocalProvider = !item.provider || item.provider === "local";
|
|
10737
|
+
onChange({
|
|
10738
|
+
id: item.id,
|
|
10739
|
+
provider: item.provider || "local",
|
|
10740
|
+
src: isLocalProvider ? void 0 : item.url,
|
|
10741
|
+
filename: item.filename,
|
|
10742
|
+
mimeType: item.mimeType,
|
|
10743
|
+
size: item.size,
|
|
10744
|
+
meta: isLocalProvider ? {
|
|
10745
|
+
...item.meta,
|
|
10746
|
+
storageKey: item.storageKey
|
|
10747
|
+
} : item.meta
|
|
10748
|
+
});
|
|
10749
|
+
};
|
|
10750
|
+
const handleRemove = () => {
|
|
10751
|
+
onChange(null);
|
|
10752
|
+
};
|
|
10753
|
+
const hasMime = !!normalized?.mimeType;
|
|
10754
|
+
const size = typeof normalized?.size === "number" ? normalized.size : void 0;
|
|
10755
|
+
const hasSize = size !== void 0;
|
|
10756
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
10757
|
+
id,
|
|
10758
|
+
children: [
|
|
10759
|
+
/* @__PURE__ */ jsx(Label, { children: label }),
|
|
10760
|
+
normalized ? /* @__PURE__ */ jsxs("div", {
|
|
10761
|
+
className: "mt-2 flex items-center gap-3 rounded-lg border p-3",
|
|
10762
|
+
children: [
|
|
10763
|
+
/* @__PURE__ */ jsx("span", {
|
|
10764
|
+
className: "text-3xl",
|
|
10765
|
+
"aria-hidden": "true",
|
|
10766
|
+
children: getFileIcon(normalized.mimeType)
|
|
10767
|
+
}),
|
|
10768
|
+
/* @__PURE__ */ jsxs("div", {
|
|
10769
|
+
className: "flex-1 min-w-0",
|
|
10770
|
+
children: [normalized.displayUrl ? /* @__PURE__ */ jsx("a", {
|
|
10771
|
+
href: normalized.displayUrl,
|
|
10772
|
+
target: "_blank",
|
|
10773
|
+
rel: "noopener noreferrer",
|
|
10774
|
+
className: "text-sm font-medium truncate block hover:underline",
|
|
10775
|
+
children: normalized.filename
|
|
10776
|
+
}) : /* @__PURE__ */ jsx("p", {
|
|
10777
|
+
className: "text-sm font-medium truncate",
|
|
10778
|
+
children: normalized.filename
|
|
10779
|
+
}), (hasMime || hasSize) && /* @__PURE__ */ jsxs("p", {
|
|
10780
|
+
className: "text-xs text-kumo-subtle",
|
|
10781
|
+
children: [
|
|
10782
|
+
hasMime ? normalized.mimeType : null,
|
|
10783
|
+
hasMime && hasSize ? " • " : null,
|
|
10784
|
+
hasSize ? formatFileSize(size) : null
|
|
10785
|
+
]
|
|
10786
|
+
})]
|
|
10787
|
+
}),
|
|
10788
|
+
/* @__PURE__ */ jsxs("div", {
|
|
10789
|
+
className: "flex gap-1",
|
|
10790
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
10791
|
+
type: "button",
|
|
10792
|
+
size: "sm",
|
|
10793
|
+
variant: "secondary",
|
|
10794
|
+
onClick: () => setPickerOpen(true),
|
|
10795
|
+
children: _t6({
|
|
10796
|
+
id: "o+XJ9D",
|
|
10797
|
+
message: "Change"
|
|
10798
|
+
})
|
|
10799
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
10800
|
+
type: "button",
|
|
10801
|
+
shape: "square",
|
|
10802
|
+
variant: "destructive",
|
|
10803
|
+
className: "h-8 w-8",
|
|
10804
|
+
onClick: handleRemove,
|
|
10805
|
+
"aria-label": _t6({
|
|
10806
|
+
id: "HND1q3",
|
|
10807
|
+
message: "Remove {label}",
|
|
10808
|
+
values: { label }
|
|
10809
|
+
}),
|
|
10810
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" })
|
|
10811
|
+
})]
|
|
10812
|
+
})
|
|
10813
|
+
]
|
|
10814
|
+
}) : /* @__PURE__ */ jsx(Button, {
|
|
10815
|
+
type: "button",
|
|
10816
|
+
variant: "outline",
|
|
10817
|
+
className: "mt-2 w-full h-32 border-dashed",
|
|
10818
|
+
onClick: () => setPickerOpen(true),
|
|
10819
|
+
"aria-label": _t6({
|
|
10820
|
+
id: "pov/PW",
|
|
10821
|
+
message: "Select {label}",
|
|
10822
|
+
values: { label }
|
|
10823
|
+
}),
|
|
10824
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
10825
|
+
className: "flex flex-col items-center gap-2 text-kumo-subtle",
|
|
10826
|
+
children: [/* @__PURE__ */ jsx(Paperclip, { className: "h-8 w-8" }), /* @__PURE__ */ jsx("span", { children: _t6({
|
|
10827
|
+
id: "J6WI1B",
|
|
10828
|
+
message: "Select file"
|
|
10829
|
+
}) })]
|
|
10830
|
+
})
|
|
10831
|
+
}),
|
|
10832
|
+
/* @__PURE__ */ jsx(MediaPickerModal, {
|
|
10833
|
+
open: pickerOpen,
|
|
10834
|
+
onOpenChange: setPickerOpen,
|
|
10835
|
+
onSelect: handleSelect,
|
|
10836
|
+
mimeTypeFilter: "",
|
|
10837
|
+
hideUrlInput: true,
|
|
10838
|
+
mediaKind: "file",
|
|
10839
|
+
title: _t6({
|
|
10840
|
+
id: "pov/PW",
|
|
10841
|
+
message: "Select {label}",
|
|
10842
|
+
values: { label }
|
|
10843
|
+
})
|
|
10844
|
+
}),
|
|
10845
|
+
required && !normalized && /* @__PURE__ */ jsx("p", {
|
|
10846
|
+
className: "text-sm text-kumo-danger mt-1",
|
|
10847
|
+
children: _t6({
|
|
10848
|
+
id: "B8AaMI",
|
|
10849
|
+
message: "This field is required"
|
|
10850
|
+
})
|
|
10851
|
+
})
|
|
10852
|
+
]
|
|
10853
|
+
});
|
|
10854
|
+
}
|
|
10855
|
+
function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuickEdit }) {
|
|
10856
|
+
const { _: _t7 } = useLingui();
|
|
10857
|
+
const [selectedBylineId, setSelectedBylineId] = React$1.useState("");
|
|
10858
|
+
const [quickName, setQuickName] = React$1.useState("");
|
|
10859
|
+
const [quickSlug, setQuickSlug] = React$1.useState("");
|
|
10860
|
+
const [quickError, setQuickError] = React$1.useState(null);
|
|
10861
|
+
const [isCreating, setIsCreating] = React$1.useState(false);
|
|
10862
|
+
const [editBylineId, setEditBylineId] = React$1.useState(null);
|
|
10863
|
+
const [editName, setEditName] = React$1.useState("");
|
|
10864
|
+
const [editSlug, setEditSlug] = React$1.useState("");
|
|
10865
|
+
const [editError, setEditError] = React$1.useState(null);
|
|
10866
|
+
const [isEditing, setIsEditing] = React$1.useState(false);
|
|
10867
|
+
const bylineMap = React$1.useMemo(() => new Map(bylines.map((b) => [b.id, b])), [bylines]);
|
|
10628
10868
|
const availableToAdd = bylines.filter((b) => !credits.some((c) => c.bylineId === b.id));
|
|
10629
10869
|
const move = (index, direction) => {
|
|
10630
10870
|
const target = index + direction;
|
|
@@ -10663,7 +10903,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
|
|
|
10663
10903
|
className: "w-full rounded border bg-kumo-base px-3 py-2 text-sm",
|
|
10664
10904
|
children: [/* @__PURE__ */ jsx("option", {
|
|
10665
10905
|
value: "",
|
|
10666
|
-
children:
|
|
10906
|
+
children: _t7({
|
|
10667
10907
|
id: "r5zcIE",
|
|
10668
10908
|
message: "Select byline..."
|
|
10669
10909
|
})
|
|
@@ -10683,7 +10923,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
|
|
|
10683
10923
|
setSelectedBylineId("");
|
|
10684
10924
|
},
|
|
10685
10925
|
disabled: !selectedBylineId,
|
|
10686
|
-
children:
|
|
10926
|
+
children: _t7({
|
|
10687
10927
|
id: "m16xKo",
|
|
10688
10928
|
message: "Add"
|
|
10689
10929
|
})
|
|
@@ -10712,7 +10952,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
|
|
|
10712
10952
|
variant: "ghost",
|
|
10713
10953
|
size: "sm",
|
|
10714
10954
|
onClick: () => move(index, -1),
|
|
10715
|
-
children:
|
|
10955
|
+
children: _t7({
|
|
10716
10956
|
id: "n+PHuv",
|
|
10717
10957
|
message: "Up"
|
|
10718
10958
|
})
|
|
@@ -10722,7 +10962,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
|
|
|
10722
10962
|
variant: "ghost",
|
|
10723
10963
|
size: "sm",
|
|
10724
10964
|
onClick: () => move(index, 1),
|
|
10725
|
-
children:
|
|
10965
|
+
children: _t7({
|
|
10726
10966
|
id: "gUjkl/",
|
|
10727
10967
|
message: "Down"
|
|
10728
10968
|
})
|
|
@@ -10732,7 +10972,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
|
|
|
10732
10972
|
variant: "ghost",
|
|
10733
10973
|
size: "sm",
|
|
10734
10974
|
onClick: () => openEditByline(byline),
|
|
10735
|
-
children:
|
|
10975
|
+
children: _t7({
|
|
10736
10976
|
id: "ePK91l",
|
|
10737
10977
|
message: "Edit"
|
|
10738
10978
|
})
|
|
@@ -10742,7 +10982,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
|
|
|
10742
10982
|
variant: "destructive",
|
|
10743
10983
|
size: "sm",
|
|
10744
10984
|
onClick: () => onChange(credits.filter((_, i) => i !== index)),
|
|
10745
|
-
children:
|
|
10985
|
+
children: _t7({
|
|
10746
10986
|
id: "t/YqKh",
|
|
10747
10987
|
message: "Remove"
|
|
10748
10988
|
})
|
|
@@ -10750,7 +10990,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
|
|
|
10750
10990
|
]
|
|
10751
10991
|
})]
|
|
10752
10992
|
}), /* @__PURE__ */ jsx(Input, {
|
|
10753
|
-
label:
|
|
10993
|
+
label: _t7({
|
|
10754
10994
|
id: "QeScoL",
|
|
10755
10995
|
message: "Role label"
|
|
10756
10996
|
}),
|
|
@@ -10770,7 +11010,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
|
|
|
10770
11010
|
})
|
|
10771
11011
|
}) : /* @__PURE__ */ jsx("p", {
|
|
10772
11012
|
className: "text-sm text-kumo-subtle",
|
|
10773
|
-
children:
|
|
11013
|
+
children: _t7({
|
|
10774
11014
|
id: "dyZY24",
|
|
10775
11015
|
message: "No bylines selected."
|
|
10776
11016
|
})
|
|
@@ -10779,7 +11019,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
|
|
|
10779
11019
|
...p,
|
|
10780
11020
|
type: "button",
|
|
10781
11021
|
variant: "secondary",
|
|
10782
|
-
children:
|
|
11022
|
+
children: _t7({
|
|
10783
11023
|
id: "gqa8eq",
|
|
10784
11024
|
message: "Quick create byline"
|
|
10785
11025
|
})
|
|
@@ -10789,7 +11029,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
|
|
|
10789
11029
|
children: [
|
|
10790
11030
|
/* @__PURE__ */ jsx(Dialog.Title, {
|
|
10791
11031
|
className: "text-lg font-semibold",
|
|
10792
|
-
children:
|
|
11032
|
+
children: _t7({
|
|
10793
11033
|
id: "d6HWlw",
|
|
10794
11034
|
message: "Create byline"
|
|
10795
11035
|
})
|
|
@@ -10798,7 +11038,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
|
|
|
10798
11038
|
className: "mt-4 space-y-3",
|
|
10799
11039
|
children: [
|
|
10800
11040
|
/* @__PURE__ */ jsx(Input, {
|
|
10801
|
-
label:
|
|
11041
|
+
label: _t7({
|
|
10802
11042
|
id: "pfa8F0",
|
|
10803
11043
|
message: "Display name"
|
|
10804
11044
|
}),
|
|
@@ -10809,7 +11049,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
|
|
|
10809
11049
|
}
|
|
10810
11050
|
}),
|
|
10811
11051
|
/* @__PURE__ */ jsx(Input, {
|
|
10812
|
-
label:
|
|
11052
|
+
label: _t7({
|
|
10813
11053
|
id: "L85WcV",
|
|
10814
11054
|
message: "Slug"
|
|
10815
11055
|
}),
|
|
@@ -10831,7 +11071,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
|
|
|
10831
11071
|
resetQuickCreate();
|
|
10832
11072
|
p.onClick?.(e);
|
|
10833
11073
|
},
|
|
10834
|
-
children:
|
|
11074
|
+
children: _t7({
|
|
10835
11075
|
id: "dEgA5A",
|
|
10836
11076
|
message: "Cancel"
|
|
10837
11077
|
})
|
|
@@ -10852,7 +11092,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
|
|
|
10852
11092
|
}]);
|
|
10853
11093
|
resetQuickCreate();
|
|
10854
11094
|
} catch (err) {
|
|
10855
|
-
setQuickError(err instanceof Error ? err.message :
|
|
11095
|
+
setQuickError(err instanceof Error ? err.message : _t7({
|
|
10856
11096
|
id: "Kd9Ewv",
|
|
10857
11097
|
message: "Failed to create byline"
|
|
10858
11098
|
}));
|
|
@@ -10860,10 +11100,10 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
|
|
|
10860
11100
|
setIsCreating(false);
|
|
10861
11101
|
}
|
|
10862
11102
|
},
|
|
10863
|
-
children: isCreating ?
|
|
11103
|
+
children: isCreating ? _t7({
|
|
10864
11104
|
id: "HM56Bx",
|
|
10865
11105
|
message: "Creating..."
|
|
10866
|
-
}) :
|
|
11106
|
+
}) : _t7({
|
|
10867
11107
|
id: "hYgDIe",
|
|
10868
11108
|
message: "Create"
|
|
10869
11109
|
})
|
|
@@ -10880,7 +11120,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
|
|
|
10880
11120
|
children: [
|
|
10881
11121
|
/* @__PURE__ */ jsx(Dialog.Title, {
|
|
10882
11122
|
className: "text-lg font-semibold",
|
|
10883
|
-
children:
|
|
11123
|
+
children: _t7({
|
|
10884
11124
|
id: "d9lVyw",
|
|
10885
11125
|
message: "Edit byline"
|
|
10886
11126
|
})
|
|
@@ -10889,7 +11129,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
|
|
|
10889
11129
|
className: "mt-4 space-y-3",
|
|
10890
11130
|
children: [
|
|
10891
11131
|
/* @__PURE__ */ jsx(Input, {
|
|
10892
|
-
label:
|
|
11132
|
+
label: _t7({
|
|
10893
11133
|
id: "pfa8F0",
|
|
10894
11134
|
message: "Display name"
|
|
10895
11135
|
}),
|
|
@@ -10900,7 +11140,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
|
|
|
10900
11140
|
}
|
|
10901
11141
|
}),
|
|
10902
11142
|
/* @__PURE__ */ jsx(Input, {
|
|
10903
|
-
label:
|
|
11143
|
+
label: _t7({
|
|
10904
11144
|
id: "L85WcV",
|
|
10905
11145
|
message: "Slug"
|
|
10906
11146
|
}),
|
|
@@ -10919,7 +11159,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
|
|
|
10919
11159
|
type: "button",
|
|
10920
11160
|
variant: "secondary",
|
|
10921
11161
|
onClick: resetQuickEdit,
|
|
10922
|
-
children:
|
|
11162
|
+
children: _t7({
|
|
10923
11163
|
id: "dEgA5A",
|
|
10924
11164
|
message: "Cancel"
|
|
10925
11165
|
})
|
|
@@ -10936,7 +11176,7 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
|
|
|
10936
11176
|
});
|
|
10937
11177
|
resetQuickEdit();
|
|
10938
11178
|
} catch (err) {
|
|
10939
|
-
setEditError(err instanceof Error ? err.message :
|
|
11179
|
+
setEditError(err instanceof Error ? err.message : _t7({
|
|
10940
11180
|
id: "fd6o+d",
|
|
10941
11181
|
message: "Failed to update byline"
|
|
10942
11182
|
}));
|
|
@@ -10944,10 +11184,10 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
|
|
|
10944
11184
|
setIsEditing(false);
|
|
10945
11185
|
}
|
|
10946
11186
|
},
|
|
10947
|
-
children: isEditing ?
|
|
11187
|
+
children: isEditing ? _t7({
|
|
10948
11188
|
id: "XvjC4F",
|
|
10949
11189
|
message: "Saving..."
|
|
10950
|
-
}) :
|
|
11190
|
+
}) : _t7({
|
|
10951
11191
|
id: "tfDRzk",
|
|
10952
11192
|
message: "Save"
|
|
10953
11193
|
})
|
|
@@ -10960,9 +11200,9 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
|
|
|
10960
11200
|
});
|
|
10961
11201
|
}
|
|
10962
11202
|
function AuthorSelector({ authorId, users, onChange }) {
|
|
10963
|
-
const { _:
|
|
11203
|
+
const { _: _t8 } = useLingui();
|
|
10964
11204
|
const currentAuthor = users.find((u) => u.id === authorId);
|
|
10965
|
-
const authorItems = { unassigned:
|
|
11205
|
+
const authorItems = { unassigned: _t8({
|
|
10966
11206
|
id: "EbMPZJ",
|
|
10967
11207
|
message: "Unassigned"
|
|
10968
11208
|
}) };
|
|
@@ -10977,7 +11217,7 @@ function AuthorSelector({ authorId, users, onChange }) {
|
|
|
10977
11217
|
value: "unassigned",
|
|
10978
11218
|
children: /* @__PURE__ */ jsx("span", {
|
|
10979
11219
|
className: "text-kumo-subtle",
|
|
10980
|
-
children:
|
|
11220
|
+
children: _t8({
|
|
10981
11221
|
id: "EbMPZJ",
|
|
10982
11222
|
message: "Unassigned"
|
|
10983
11223
|
})
|
|
@@ -11044,6 +11284,16 @@ function LocaleSwitcher({ locales, defaultLocale, value, onChange, showAll = fal
|
|
|
11044
11284
|
})]
|
|
11045
11285
|
});
|
|
11046
11286
|
}
|
|
11287
|
+
/**
|
|
11288
|
+
* Hook to get i18n config from the manifest query.
|
|
11289
|
+
* Returns null if i18n is not configured.
|
|
11290
|
+
*/
|
|
11291
|
+
function useI18nConfig(manifest) {
|
|
11292
|
+
return React.useMemo(() => {
|
|
11293
|
+
if (!manifest?.i18n) return null;
|
|
11294
|
+
return manifest.i18n;
|
|
11295
|
+
}, [manifest?.i18n]);
|
|
11296
|
+
}
|
|
11047
11297
|
|
|
11048
11298
|
//#endregion
|
|
11049
11299
|
//#region src/components/ContentList.tsx
|
|
@@ -11058,21 +11308,21 @@ function getItemTitle$1(item) {
|
|
|
11058
11308
|
*/
|
|
11059
11309
|
function ContentList({ collection, collectionLabel, items, trashedItems = [], isLoading, isTrashedLoading, onDelete, onDuplicate, onRestore, onPermanentDelete, onLoadMore, onLoadMoreTrashed, hasMore, hasMoreTrashed, trashedCount = 0, i18n: i18n$1, activeLocale, onLocaleChange, urlPattern, sort, onSortChange }) {
|
|
11060
11310
|
const { _: _t } = useLingui();
|
|
11061
|
-
const [activeTab, setActiveTab] = React.useState("all");
|
|
11062
|
-
const [searchQuery, setSearchQuery] = React.useState("");
|
|
11063
|
-
const [page, setPage] = React.useState(0);
|
|
11311
|
+
const [activeTab, setActiveTab] = React$1.useState("all");
|
|
11312
|
+
const [searchQuery, setSearchQuery] = React$1.useState("");
|
|
11313
|
+
const [page, setPage] = React$1.useState(0);
|
|
11064
11314
|
const handleSearchChange = (e) => {
|
|
11065
11315
|
setSearchQuery(e.target.value);
|
|
11066
11316
|
setPage(0);
|
|
11067
11317
|
};
|
|
11068
|
-
const filteredItems = React.useMemo(() => {
|
|
11318
|
+
const filteredItems = React$1.useMemo(() => {
|
|
11069
11319
|
if (!searchQuery) return items;
|
|
11070
11320
|
const query = searchQuery.toLowerCase();
|
|
11071
11321
|
return items.filter((item) => getItemTitle$1(item).toLowerCase().includes(query));
|
|
11072
11322
|
}, [items, searchQuery]);
|
|
11073
11323
|
const totalPages = Math.max(1, Math.ceil(filteredItems.length / PAGE_SIZE));
|
|
11074
11324
|
const paginatedItems = filteredItems.slice(page * PAGE_SIZE, (page + 1) * PAGE_SIZE);
|
|
11075
|
-
React.useEffect(() => {
|
|
11325
|
+
React$1.useEffect(() => {
|
|
11076
11326
|
if (page >= totalPages - 1 && hasMore && onLoadMore && !searchQuery) onLoadMore();
|
|
11077
11327
|
}, [
|
|
11078
11328
|
page,
|
|
@@ -11822,8 +12072,8 @@ function getInitialFormState(field) {
|
|
|
11822
12072
|
*/
|
|
11823
12073
|
function FieldEditor({ open, onOpenChange, field, onSave, isSaving }) {
|
|
11824
12074
|
const { _: _t } = useLingui();
|
|
11825
|
-
const [formState, setFormState] = React.useState(() => getInitialFormState(field));
|
|
11826
|
-
React.useEffect(() => {
|
|
12075
|
+
const [formState, setFormState] = React$1.useState(() => getInitialFormState(field));
|
|
12076
|
+
React$1.useEffect(() => {
|
|
11827
12077
|
if (open) setFormState(getInitialFormState(field));
|
|
11828
12078
|
}, [open, field]);
|
|
11829
12079
|
const { step, selectedType, slug, label, required, unique, searchable } = formState;
|
|
@@ -12709,23 +12959,23 @@ const SYSTEM_FIELDS = [
|
|
|
12709
12959
|
function ContentTypeEditor({ collection, isNew, isSaving, onSave, onAddField, onUpdateField, onDeleteField, onReorderFields }) {
|
|
12710
12960
|
const { _: _t } = useLingui();
|
|
12711
12961
|
useNavigate$1();
|
|
12712
|
-
const [slug, setSlug] = React.useState(collection?.slug ?? "");
|
|
12713
|
-
const [label, setLabel] = React.useState(collection?.label ?? "");
|
|
12714
|
-
const [labelSingular, setLabelSingular] = React.useState(collection?.labelSingular ?? "");
|
|
12715
|
-
const [description, setDescription] = React.useState(collection?.description ?? "");
|
|
12716
|
-
const [urlPattern, setUrlPattern] = React.useState(collection?.urlPattern ?? "");
|
|
12717
|
-
const [supports, setSupports] = React.useState((collection?.supports ?? ["drafts", "revisions"]).filter((s) => s !== "seo"));
|
|
12718
|
-
const [hasSeo, setHasSeo] = React.useState(collection?.hasSeo ?? false);
|
|
12719
|
-
const [commentsEnabled, setCommentsEnabled] = React.useState(collection?.commentsEnabled ?? false);
|
|
12720
|
-
const [commentsModeration, setCommentsModeration] = React.useState(collection?.commentsModeration ?? "first_time");
|
|
12721
|
-
const [commentsClosedAfterDays, setCommentsClosedAfterDays] = React.useState(collection?.commentsClosedAfterDays ?? 90);
|
|
12722
|
-
const [commentsAutoApproveUsers, setCommentsAutoApproveUsers] = React.useState(collection?.commentsAutoApproveUsers ?? true);
|
|
12723
|
-
const [fieldEditorOpen, setFieldEditorOpen] = React.useState(false);
|
|
12724
|
-
const [editingField, setEditingField] = React.useState();
|
|
12725
|
-
const [fieldSaving, setFieldSaving] = React.useState(false);
|
|
12726
|
-
const [deleteFieldTarget, setDeleteFieldTarget] = React.useState(null);
|
|
12962
|
+
const [slug, setSlug] = React$1.useState(collection?.slug ?? "");
|
|
12963
|
+
const [label, setLabel] = React$1.useState(collection?.label ?? "");
|
|
12964
|
+
const [labelSingular, setLabelSingular] = React$1.useState(collection?.labelSingular ?? "");
|
|
12965
|
+
const [description, setDescription] = React$1.useState(collection?.description ?? "");
|
|
12966
|
+
const [urlPattern, setUrlPattern] = React$1.useState(collection?.urlPattern ?? "");
|
|
12967
|
+
const [supports, setSupports] = React$1.useState((collection?.supports ?? ["drafts", "revisions"]).filter((s) => s !== "seo"));
|
|
12968
|
+
const [hasSeo, setHasSeo] = React$1.useState(collection?.hasSeo ?? false);
|
|
12969
|
+
const [commentsEnabled, setCommentsEnabled] = React$1.useState(collection?.commentsEnabled ?? false);
|
|
12970
|
+
const [commentsModeration, setCommentsModeration] = React$1.useState(collection?.commentsModeration ?? "first_time");
|
|
12971
|
+
const [commentsClosedAfterDays, setCommentsClosedAfterDays] = React$1.useState(collection?.commentsClosedAfterDays ?? 90);
|
|
12972
|
+
const [commentsAutoApproveUsers, setCommentsAutoApproveUsers] = React$1.useState(collection?.commentsAutoApproveUsers ?? true);
|
|
12973
|
+
const [fieldEditorOpen, setFieldEditorOpen] = React$1.useState(false);
|
|
12974
|
+
const [editingField, setEditingField] = React$1.useState();
|
|
12975
|
+
const [fieldSaving, setFieldSaving] = React$1.useState(false);
|
|
12976
|
+
const [deleteFieldTarget, setDeleteFieldTarget] = React$1.useState(null);
|
|
12727
12977
|
const urlPatternValid = !urlPattern || urlPattern.includes("{slug}");
|
|
12728
|
-
const hasChanges = React.useMemo(() => {
|
|
12978
|
+
const hasChanges = React$1.useMemo(() => {
|
|
12729
12979
|
if (isNew) return slug && label;
|
|
12730
12980
|
if (!collection) return false;
|
|
12731
12981
|
return label !== collection.label || labelSingular !== (collection.labelSingular ?? "") || description !== (collection.description ?? "") || urlPattern !== (collection.urlPattern ?? "") || JSON.stringify([...supports].toSorted()) !== JSON.stringify(collection.supports.filter((s) => s !== "seo").toSorted()) || hasSeo !== collection.hasSeo || commentsEnabled !== collection.commentsEnabled || commentsModeration !== collection.commentsModeration || commentsClosedAfterDays !== collection.commentsClosedAfterDays || commentsAutoApproveUsers !== collection.commentsAutoApproveUsers;
|
|
@@ -13267,7 +13517,7 @@ function SystemFieldRow({ field }) {
|
|
|
13267
13517
|
*/
|
|
13268
13518
|
function ContentTypeList({ collections, orphanedTables, isLoading, onDelete, onRegisterOrphan }) {
|
|
13269
13519
|
const { _: _t } = useLingui();
|
|
13270
|
-
const [deleteTarget, setDeleteTarget] = React.useState(null);
|
|
13520
|
+
const [deleteTarget, setDeleteTarget] = React$1.useState(null);
|
|
13271
13521
|
const hasOrphans = orphanedTables && orphanedTables.length > 0;
|
|
13272
13522
|
return /* @__PURE__ */ jsxs("div", {
|
|
13273
13523
|
className: "space-y-4",
|
|
@@ -13942,9 +14192,9 @@ const ROLE_NAMES = {
|
|
|
13942
14192
|
const DEVICE_CODE_INVALID_CHARS_REGEX = /[^A-Z0-9-]/g;
|
|
13943
14193
|
const DEVICE_CODE_HYPHEN_REGEX = /-/g;
|
|
13944
14194
|
function DeviceAuthorizePage() {
|
|
13945
|
-
const [code, setCode] = React.useState("");
|
|
13946
|
-
const [pageState, setPageState] = React.useState("input");
|
|
13947
|
-
const [errorMessage, setErrorMessage] = React.useState("");
|
|
14195
|
+
const [code, setCode] = React$1.useState("");
|
|
14196
|
+
const [pageState, setPageState] = React$1.useState("input");
|
|
14197
|
+
const [errorMessage, setErrorMessage] = React$1.useState("");
|
|
13948
14198
|
const { data: user, isLoading, error: authError } = useQuery({
|
|
13949
14199
|
queryKey: ["auth-me"],
|
|
13950
14200
|
queryFn: async () => {
|
|
@@ -13952,11 +14202,11 @@ function DeviceAuthorizePage() {
|
|
|
13952
14202
|
},
|
|
13953
14203
|
retry: false
|
|
13954
14204
|
});
|
|
13955
|
-
React.useEffect(() => {
|
|
14205
|
+
React$1.useEffect(() => {
|
|
13956
14206
|
const urlCode = new URLSearchParams(window.location.search).get("code");
|
|
13957
14207
|
if (urlCode) setCode(urlCode);
|
|
13958
14208
|
}, []);
|
|
13959
|
-
React.useEffect(() => {
|
|
14209
|
+
React$1.useEffect(() => {
|
|
13960
14210
|
if (!isLoading && (authError || !user)) {
|
|
13961
14211
|
const returnUrl = encodeURIComponent(window.location.pathname + window.location.search);
|
|
13962
14212
|
window.location.href = `/_emdash/admin/login?redirect=${returnUrl}`;
|
|
@@ -14313,11 +14563,11 @@ function PasskeyRegistration({ optionsEndpoint, verifyEndpoint, onSuccess, onErr
|
|
|
14313
14563
|
id: "0QF2SD",
|
|
14314
14564
|
message: "Register Passkey"
|
|
14315
14565
|
});
|
|
14316
|
-
const [state, setState] = React.useState({ status: "idle" });
|
|
14317
|
-
const [passkeyName, setPasskeyName] = React.useState("");
|
|
14318
|
-
const isSupported = React.useMemo(() => isPasskeyEnvironmentUsable(), []);
|
|
14319
|
-
const insecureContext = React.useMemo(() => typeof window !== "undefined" && !isWebAuthnSecureContext(), []);
|
|
14320
|
-
const handleRegister = React.useCallback(async () => {
|
|
14566
|
+
const [state, setState] = React$1.useState({ status: "idle" });
|
|
14567
|
+
const [passkeyName, setPasskeyName] = React$1.useState("");
|
|
14568
|
+
const isSupported = React$1.useMemo(() => isPasskeyEnvironmentUsable(), []);
|
|
14569
|
+
const insecureContext = React$1.useMemo(() => typeof window !== "undefined" && !isWebAuthnSecureContext(), []);
|
|
14570
|
+
const handleRegister = React$1.useCallback(async () => {
|
|
14321
14571
|
if (!isSupported) {
|
|
14322
14572
|
setState({
|
|
14323
14573
|
status: "error",
|
|
@@ -14849,7 +15099,7 @@ function handleInviteSuccess() {
|
|
|
14849
15099
|
window.location.href = "/_emdash/admin";
|
|
14850
15100
|
}
|
|
14851
15101
|
function RegisterStep({ inviteData, token }) {
|
|
14852
|
-
const [name, setName] = React.useState("");
|
|
15102
|
+
const [name, setName] = React$1.useState("");
|
|
14853
15103
|
return /* @__PURE__ */ jsxs("div", {
|
|
14854
15104
|
className: "space-y-6",
|
|
14855
15105
|
children: [
|
|
@@ -14980,13 +15230,13 @@ function ErrorStep$1({ message, code }) {
|
|
|
14980
15230
|
}
|
|
14981
15231
|
function InviteAcceptPage() {
|
|
14982
15232
|
const { token: urlToken } = useSearch({ strict: false });
|
|
14983
|
-
const [step, setStep] = React.useState("verify");
|
|
14984
|
-
const [error, setError] = React.useState();
|
|
14985
|
-
const [errorCode, setErrorCode] = React.useState();
|
|
14986
|
-
const [isLoading, setIsLoading] = React.useState(true);
|
|
14987
|
-
const [inviteData, setInviteData] = React.useState(null);
|
|
14988
|
-
const [token, setToken] = React.useState(null);
|
|
14989
|
-
React.useEffect(() => {
|
|
15233
|
+
const [step, setStep] = React$1.useState("verify");
|
|
15234
|
+
const [error, setError] = React$1.useState();
|
|
15235
|
+
const [errorCode, setErrorCode] = React$1.useState();
|
|
15236
|
+
const [isLoading, setIsLoading] = React$1.useState(true);
|
|
15237
|
+
const [inviteData, setInviteData] = React$1.useState(null);
|
|
15238
|
+
const [token, setToken] = React$1.useState(null);
|
|
15239
|
+
React$1.useEffect(() => {
|
|
14990
15240
|
if (!urlToken) {
|
|
14991
15241
|
setError("No invite token provided");
|
|
14992
15242
|
setStep("error");
|
|
@@ -15105,15 +15355,15 @@ function PasskeyLogin({ optionsEndpoint, verifyEndpoint, onSuccess, onError, sho
|
|
|
15105
15355
|
id: "QjsOMP",
|
|
15106
15356
|
message: "Sign in with Passkey"
|
|
15107
15357
|
});
|
|
15108
|
-
const [state, setState] = React.useState({ status: "idle" });
|
|
15109
|
-
const [email, setEmail] = React.useState("");
|
|
15110
|
-
const [supportsConditional, setSupportsConditional] = React.useState(false);
|
|
15111
|
-
const isSupported = React.useMemo(() => isPasskeyEnvironmentUsable(), []);
|
|
15112
|
-
const insecureContext = React.useMemo(() => typeof window !== "undefined" && !isWebAuthnSecureContext(), []);
|
|
15113
|
-
React.useEffect(() => {
|
|
15358
|
+
const [state, setState] = React$1.useState({ status: "idle" });
|
|
15359
|
+
const [email, setEmail] = React$1.useState("");
|
|
15360
|
+
const [supportsConditional, setSupportsConditional] = React$1.useState(false);
|
|
15361
|
+
const isSupported = React$1.useMemo(() => isPasskeyEnvironmentUsable(), []);
|
|
15362
|
+
const insecureContext = React$1.useMemo(() => typeof window !== "undefined" && !isWebAuthnSecureContext(), []);
|
|
15363
|
+
React$1.useEffect(() => {
|
|
15114
15364
|
isConditionalMediationSupported().then(setSupportsConditional);
|
|
15115
15365
|
}, []);
|
|
15116
|
-
const handleLogin = React.useCallback(async (useConditional = false) => {
|
|
15366
|
+
const handleLogin = React$1.useCallback(async (useConditional = false) => {
|
|
15117
15367
|
if (!isSupported) {
|
|
15118
15368
|
setState({
|
|
15119
15369
|
status: "error",
|
|
@@ -15385,10 +15635,10 @@ function PasskeyLogin({ optionsEndpoint, verifyEndpoint, onSuccess, onError, sho
|
|
|
15385
15635
|
*/
|
|
15386
15636
|
function MagicLinkForm({ onBack }) {
|
|
15387
15637
|
const { _: _t } = useLingui();
|
|
15388
|
-
const [email, setEmail] = React.useState("");
|
|
15389
|
-
const [isLoading, setIsLoading] = React.useState(false);
|
|
15390
|
-
const [error, setError] = React.useState(null);
|
|
15391
|
-
const [sent, setSent] = React.useState(false);
|
|
15638
|
+
const [email, setEmail] = React$1.useState("");
|
|
15639
|
+
const [isLoading, setIsLoading] = React$1.useState(false);
|
|
15640
|
+
const [error, setError] = React$1.useState(null);
|
|
15641
|
+
const [sent, setSent] = React$1.useState(false);
|
|
15392
15642
|
const handleSubmit = async (e) => {
|
|
15393
15643
|
e.preventDefault();
|
|
15394
15644
|
setError(null);
|
|
@@ -15527,18 +15777,18 @@ function LoginPage({ redirectUrl = "/_emdash/admin" }) {
|
|
|
15527
15777
|
const safeRedirectUrl = sanitizeRedirectUrl(redirectUrl);
|
|
15528
15778
|
const { _: _t2 } = useLingui();
|
|
15529
15779
|
const { locale, setLocale } = useLocale();
|
|
15530
|
-
const [method, setMethod] = React.useState("passkey");
|
|
15531
|
-
const [urlError, setUrlError] = React.useState(null);
|
|
15532
|
-
const [activeProvider, setActiveProvider] = React.useState(null);
|
|
15780
|
+
const [method, setMethod] = React$1.useState("passkey");
|
|
15781
|
+
const [urlError, setUrlError] = React$1.useState(null);
|
|
15782
|
+
const [activeProvider, setActiveProvider] = React$1.useState(null);
|
|
15533
15783
|
const authProviderList = useAuthProviderList();
|
|
15534
15784
|
const { data: authInfo, isLoading: authModeLoading } = useQuery({
|
|
15535
15785
|
queryKey: ["authMode"],
|
|
15536
15786
|
queryFn: fetchAuthMode
|
|
15537
15787
|
});
|
|
15538
|
-
React.useEffect(() => {
|
|
15788
|
+
React$1.useEffect(() => {
|
|
15539
15789
|
if (authInfo?.authMode && authInfo.authMode !== "passkey") window.location.href = safeRedirectUrl;
|
|
15540
15790
|
}, [authInfo, safeRedirectUrl]);
|
|
15541
|
-
React.useEffect(() => {
|
|
15791
|
+
React$1.useEffect(() => {
|
|
15542
15792
|
const params = new URLSearchParams(window.location.search);
|
|
15543
15793
|
const error = params.get("error");
|
|
15544
15794
|
const message = params.get("message");
|
|
@@ -15731,11 +15981,11 @@ const SORT_LABELS$1 = {
|
|
|
15731
15981
|
};
|
|
15732
15982
|
function MarketplaceBrowse({ installedPluginIds = /* @__PURE__ */ new Set() }) {
|
|
15733
15983
|
const { _: _t } = useLingui();
|
|
15734
|
-
const [searchQuery, setSearchQuery] = React.useState("");
|
|
15735
|
-
const [sort, setSort] = React.useState("installs");
|
|
15736
|
-
const [capability, setCapability] = React.useState("");
|
|
15737
|
-
const [debouncedQuery, setDebouncedQuery] = React.useState("");
|
|
15738
|
-
React.useEffect(() => {
|
|
15984
|
+
const [searchQuery, setSearchQuery] = React$1.useState("");
|
|
15985
|
+
const [sort, setSort] = React$1.useState("installs");
|
|
15986
|
+
const [capability, setCapability] = React$1.useState("");
|
|
15987
|
+
const [debouncedQuery, setDebouncedQuery] = React$1.useState("");
|
|
15988
|
+
React$1.useEffect(() => {
|
|
15739
15989
|
const timer = setTimeout(setDebouncedQuery, 300, searchQuery);
|
|
15740
15990
|
return () => clearTimeout(timer);
|
|
15741
15991
|
}, [searchQuery]);
|
|
@@ -16248,7 +16498,7 @@ function PluginManager({ manifest }) {
|
|
|
16248
16498
|
});
|
|
16249
16499
|
}
|
|
16250
16500
|
});
|
|
16251
|
-
const updateMap = React.useMemo(() => {
|
|
16501
|
+
const updateMap = React$1.useMemo(() => {
|
|
16252
16502
|
if (!updates) return /* @__PURE__ */ new Map();
|
|
16253
16503
|
return new Map(updates.map((u) => [u.pluginId, u]));
|
|
16254
16504
|
}, [updates]);
|
|
@@ -16392,9 +16642,9 @@ function PluginManager({ manifest }) {
|
|
|
16392
16642
|
}
|
|
16393
16643
|
function PluginCard({ plugin, updateInfo, onEnable, onDisable, isToggling, hasMarketplace }) {
|
|
16394
16644
|
const { _: _t2 } = useLingui();
|
|
16395
|
-
const [expanded, setExpanded] = React.useState(false);
|
|
16396
|
-
const [showUpdateConsent, setShowUpdateConsent] = React.useState(false);
|
|
16397
|
-
const [showUninstallConfirm, setShowUninstallConfirm] = React.useState(false);
|
|
16645
|
+
const [expanded, setExpanded] = React$1.useState(false);
|
|
16646
|
+
const [showUpdateConsent, setShowUpdateConsent] = React$1.useState(false);
|
|
16647
|
+
const [showUninstallConfirm, setShowUninstallConfirm] = React$1.useState(false);
|
|
16398
16648
|
const queryClient = useQueryClient();
|
|
16399
16649
|
const toastManager = Toast.useToastManager();
|
|
16400
16650
|
const isMarketplace = plugin.source === "marketplace";
|
|
@@ -16761,7 +17011,7 @@ function PluginCard({ plugin, updateInfo, onEnable, onDisable, isToggling, hasMa
|
|
|
16761
17011
|
}
|
|
16762
17012
|
function UninstallConfirmDialog({ pluginName, isPending, error, onConfirm, onCancel }) {
|
|
16763
17013
|
const { _: _t3 } = useLingui();
|
|
16764
|
-
const [deleteData, setDeleteData] = React.useState(false);
|
|
17014
|
+
const [deleteData, setDeleteData] = React$1.useState(false);
|
|
16765
17015
|
return /* @__PURE__ */ jsxs("div", {
|
|
16766
17016
|
className: "fixed inset-0 z-50 flex items-center justify-center",
|
|
16767
17017
|
role: "dialog",
|
|
@@ -16850,9 +17100,9 @@ function UninstallConfirmDialog({ pluginName, isPending, error, onConfirm, onCan
|
|
|
16850
17100
|
function MarketplacePluginDetail({ pluginId, installedPluginIds = /* @__PURE__ */ new Set() }) {
|
|
16851
17101
|
const { _: _t } = useLingui();
|
|
16852
17102
|
const queryClient = useQueryClient();
|
|
16853
|
-
const [showConsent, setShowConsent] = React.useState(false);
|
|
16854
|
-
const [showUninstallConfirm, setShowUninstallConfirm] = React.useState(false);
|
|
16855
|
-
const [lightboxIndex, setLightboxIndex] = React.useState(null);
|
|
17103
|
+
const [showConsent, setShowConsent] = React$1.useState(false);
|
|
17104
|
+
const [showUninstallConfirm, setShowUninstallConfirm] = React$1.useState(false);
|
|
17105
|
+
const [lightboxIndex, setLightboxIndex] = React$1.useState(null);
|
|
16856
17106
|
const { data: plugin, isLoading, error } = useQuery({
|
|
16857
17107
|
queryKey: [
|
|
16858
17108
|
"marketplace",
|
|
@@ -17229,7 +17479,7 @@ function BackLink() {
|
|
|
17229
17479
|
}
|
|
17230
17480
|
function ScreenshotLightbox({ screenshots, index, isBlurred = false, onClose, onNavigate }) {
|
|
17231
17481
|
const { _: _t3 } = useLingui();
|
|
17232
|
-
const handleKeyDown = React.useCallback((e) => {
|
|
17482
|
+
const handleKeyDown = React$1.useCallback((e) => {
|
|
17233
17483
|
if (e.key === "Escape") onClose();
|
|
17234
17484
|
if (e.key === "ArrowLeft" && index > 0) onNavigate(index - 1);
|
|
17235
17485
|
if (e.key === "ArrowRight" && index < screenshots.length - 1) onNavigate(index + 1);
|
|
@@ -17239,7 +17489,7 @@ function ScreenshotLightbox({ screenshots, index, isBlurred = false, onClose, on
|
|
|
17239
17489
|
onClose,
|
|
17240
17490
|
onNavigate
|
|
17241
17491
|
]);
|
|
17242
|
-
React.useEffect(() => {
|
|
17492
|
+
React$1.useEffect(() => {
|
|
17243
17493
|
document.addEventListener("keydown", handleKeyDown);
|
|
17244
17494
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
17245
17495
|
}, [handleKeyDown]);
|
|
@@ -17388,17 +17638,17 @@ function formatBytes(bytes) {
|
|
|
17388
17638
|
function MediaDetailPanel({ item, onClose, onDeleted }) {
|
|
17389
17639
|
const { _: _t } = useLingui();
|
|
17390
17640
|
const queryClient = useQueryClient();
|
|
17391
|
-
const [filename, setFilename] = React.useState(item?.filename ?? "");
|
|
17392
|
-
const [alt, setAlt] = React.useState(item?.alt ?? "");
|
|
17393
|
-
const [caption, setCaption] = React.useState(item?.caption ?? "");
|
|
17394
|
-
React.useEffect(() => {
|
|
17641
|
+
const [filename, setFilename] = React$1.useState(item?.filename ?? "");
|
|
17642
|
+
const [alt, setAlt] = React$1.useState(item?.alt ?? "");
|
|
17643
|
+
const [caption, setCaption] = React$1.useState(item?.caption ?? "");
|
|
17644
|
+
React$1.useEffect(() => {
|
|
17395
17645
|
if (item) {
|
|
17396
17646
|
setFilename(item.filename);
|
|
17397
17647
|
setAlt(item.alt ?? "");
|
|
17398
17648
|
setCaption(item.caption ?? "");
|
|
17399
17649
|
}
|
|
17400
17650
|
}, [item]);
|
|
17401
|
-
const hasChanges = React.useMemo(() => {
|
|
17651
|
+
const hasChanges = React$1.useMemo(() => {
|
|
17402
17652
|
if (!item) return false;
|
|
17403
17653
|
return filename !== item.filename || alt !== (item.alt ?? "") || caption !== (item.caption ?? "");
|
|
17404
17654
|
}, [
|
|
@@ -17434,14 +17684,14 @@ function MediaDetailPanel({ item, onClose, onDeleted }) {
|
|
|
17434
17684
|
caption: caption || void 0
|
|
17435
17685
|
});
|
|
17436
17686
|
};
|
|
17437
|
-
const [showDeleteConfirm, setShowDeleteConfirm] = React.useState(false);
|
|
17687
|
+
const [showDeleteConfirm, setShowDeleteConfirm] = React$1.useState(false);
|
|
17438
17688
|
const handleDelete = () => {
|
|
17439
17689
|
if (!item) return;
|
|
17440
17690
|
setShowDeleteConfirm(true);
|
|
17441
17691
|
};
|
|
17442
17692
|
const stableOnClose = useStableCallback(onClose);
|
|
17443
17693
|
const stableHandleSave = useStableCallback(handleSave);
|
|
17444
|
-
React.useEffect(() => {
|
|
17694
|
+
React$1.useEffect(() => {
|
|
17445
17695
|
const handleKeyDown = (e) => {
|
|
17446
17696
|
if (e.key === "Escape") stableOnClose();
|
|
17447
17697
|
if ((e.metaKey || e.ctrlKey) && e.key === "s") {
|
|
@@ -17698,13 +17948,13 @@ function formatDate(isoString) {
|
|
|
17698
17948
|
*/
|
|
17699
17949
|
function MediaLibrary({ items = [], isLoading, onUpload, onDelete, onItemUpdated }) {
|
|
17700
17950
|
const { _: _t } = useLingui();
|
|
17701
|
-
const [viewMode, setViewMode] = React.useState("grid");
|
|
17702
|
-
const [selectedItem, setSelectedItem] = React.useState(null);
|
|
17703
|
-
const [activeProvider, setActiveProvider] = React.useState("local");
|
|
17704
|
-
const [searchQuery, setSearchQuery] = React.useState("");
|
|
17705
|
-
const [uploadState, setUploadState] = React.useState({ status: "idle" });
|
|
17706
|
-
const fileInputRef = React.useRef(null);
|
|
17707
|
-
const [loadedDimensions, setLoadedDimensions] = React.useState({});
|
|
17951
|
+
const [viewMode, setViewMode] = React$1.useState("grid");
|
|
17952
|
+
const [selectedItem, setSelectedItem] = React$1.useState(null);
|
|
17953
|
+
const [activeProvider, setActiveProvider] = React$1.useState("local");
|
|
17954
|
+
const [searchQuery, setSearchQuery] = React$1.useState("");
|
|
17955
|
+
const [uploadState, setUploadState] = React$1.useState({ status: "idle" });
|
|
17956
|
+
const fileInputRef = React$1.useRef(null);
|
|
17957
|
+
const [loadedDimensions, setLoadedDimensions] = React$1.useState({});
|
|
17708
17958
|
const { data: providers } = useQuery({
|
|
17709
17959
|
queryKey: ["media-providers"],
|
|
17710
17960
|
queryFn: fetchMediaProviders,
|
|
@@ -17722,7 +17972,7 @@ function MediaLibrary({ items = [], isLoading, onUpload, onDelete, onItemUpdated
|
|
|
17722
17972
|
}),
|
|
17723
17973
|
enabled: activeProvider !== "local"
|
|
17724
17974
|
});
|
|
17725
|
-
const activeProviderInfo = React.useMemo(() => {
|
|
17975
|
+
const activeProviderInfo = React$1.useMemo(() => {
|
|
17726
17976
|
if (activeProvider === "local") return {
|
|
17727
17977
|
id: "local",
|
|
17728
17978
|
name: "Library",
|
|
@@ -17735,7 +17985,7 @@ function MediaLibrary({ items = [], isLoading, onUpload, onDelete, onItemUpdated
|
|
|
17735
17985
|
};
|
|
17736
17986
|
return providers?.find((p) => p.id === activeProvider);
|
|
17737
17987
|
}, [activeProvider, providers]);
|
|
17738
|
-
React.useEffect(() => {
|
|
17988
|
+
React$1.useEffect(() => {
|
|
17739
17989
|
if (selectedItem && activeProvider === "local") {
|
|
17740
17990
|
const updated = items.find((i) => i.id === selectedItem.id);
|
|
17741
17991
|
if (updated) setSelectedItem(updated);
|
|
@@ -17746,7 +17996,7 @@ function MediaLibrary({ items = [], isLoading, onUpload, onDelete, onItemUpdated
|
|
|
17746
17996
|
selectedItem?.id,
|
|
17747
17997
|
activeProvider
|
|
17748
17998
|
]);
|
|
17749
|
-
React.useEffect(() => {
|
|
17999
|
+
React$1.useEffect(() => {
|
|
17750
18000
|
if (uploadState.status === "success" || uploadState.status === "error") {
|
|
17751
18001
|
const timer = setTimeout(() => {
|
|
17752
18002
|
setUploadState({ status: "idle" });
|
|
@@ -17870,7 +18120,7 @@ function MediaLibrary({ items = [], isLoading, onUpload, onDelete, onItemUpdated
|
|
|
17870
18120
|
}
|
|
17871
18121
|
if (fileInputRef.current) fileInputRef.current.value = "";
|
|
17872
18122
|
};
|
|
17873
|
-
const providerTabs = React.useMemo(() => {
|
|
18123
|
+
const providerTabs = React$1.useMemo(() => {
|
|
17874
18124
|
const tabs = [{
|
|
17875
18125
|
id: "local",
|
|
17876
18126
|
name: "Library",
|
|
@@ -18384,18 +18634,18 @@ function getItemTitle(item) {
|
|
|
18384
18634
|
}
|
|
18385
18635
|
function ContentPickerModal({ open, onOpenChange, onSelect }) {
|
|
18386
18636
|
const { _: _t } = useLingui();
|
|
18387
|
-
const [searchQuery, setSearchQuery] = React.useState("");
|
|
18637
|
+
const [searchQuery, setSearchQuery] = React$1.useState("");
|
|
18388
18638
|
const debouncedSearch = useDebouncedValue$1(searchQuery, 300);
|
|
18389
|
-
const [selectedCollection, setSelectedCollection] = React.useState("");
|
|
18390
|
-
const [allItems, setAllItems] = React.useState([]);
|
|
18391
|
-
const [nextCursor, setNextCursor] = React.useState();
|
|
18392
|
-
const [isLoadingMore, setIsLoadingMore] = React.useState(false);
|
|
18639
|
+
const [selectedCollection, setSelectedCollection] = React$1.useState("");
|
|
18640
|
+
const [allItems, setAllItems] = React$1.useState([]);
|
|
18641
|
+
const [nextCursor, setNextCursor] = React$1.useState();
|
|
18642
|
+
const [isLoadingMore, setIsLoadingMore] = React$1.useState(false);
|
|
18393
18643
|
const { data: collections = [] } = useQuery({
|
|
18394
18644
|
queryKey: ["collections"],
|
|
18395
18645
|
queryFn: fetchCollections,
|
|
18396
18646
|
enabled: open
|
|
18397
18647
|
});
|
|
18398
|
-
React.useEffect(() => {
|
|
18648
|
+
React$1.useEffect(() => {
|
|
18399
18649
|
if (collections.length > 0 && !selectedCollection) setSelectedCollection(collections[0].slug);
|
|
18400
18650
|
}, [collections, selectedCollection]);
|
|
18401
18651
|
const { data: contentResult, isLoading: contentLoading } = useQuery({
|
|
@@ -18407,7 +18657,7 @@ function ContentPickerModal({ open, onOpenChange, onSelect }) {
|
|
|
18407
18657
|
queryFn: () => fetchContentList(selectedCollection, { limit: 50 }),
|
|
18408
18658
|
enabled: open && !!selectedCollection
|
|
18409
18659
|
});
|
|
18410
|
-
React.useEffect(() => {
|
|
18660
|
+
React$1.useEffect(() => {
|
|
18411
18661
|
if (contentResult) {
|
|
18412
18662
|
setAllItems(contentResult.items);
|
|
18413
18663
|
setNextCursor(contentResult.nextCursor);
|
|
@@ -18427,12 +18677,12 @@ function ContentPickerModal({ open, onOpenChange, onSelect }) {
|
|
|
18427
18677
|
setIsLoadingMore(false);
|
|
18428
18678
|
}
|
|
18429
18679
|
};
|
|
18430
|
-
const filteredItems = React.useMemo(() => {
|
|
18680
|
+
const filteredItems = React$1.useMemo(() => {
|
|
18431
18681
|
if (!debouncedSearch) return allItems;
|
|
18432
18682
|
const query = debouncedSearch.toLowerCase();
|
|
18433
18683
|
return allItems.filter((item) => getItemTitle(item).toLowerCase().includes(query));
|
|
18434
18684
|
}, [allItems, debouncedSearch]);
|
|
18435
|
-
React.useEffect(() => {
|
|
18685
|
+
React$1.useEffect(() => {
|
|
18436
18686
|
if (open) {
|
|
18437
18687
|
setSearchQuery("");
|
|
18438
18688
|
setSelectedCollection("");
|
|
@@ -18631,25 +18881,85 @@ function ContentPickerModal({ open, onOpenChange, onSelect }) {
|
|
|
18631
18881
|
function MenuEditor() {
|
|
18632
18882
|
const { _: _t } = useLingui();
|
|
18633
18883
|
const { name } = useParams$1({ from: "/_admin/menus/$name" });
|
|
18884
|
+
const routeLocale = useSearch({ from: "/_admin/menus/$name" }).locale;
|
|
18634
18885
|
const navigate = useNavigate$1();
|
|
18635
18886
|
const queryClient = useQueryClient();
|
|
18636
18887
|
const toastManager = Toast.useToastManager();
|
|
18637
|
-
const [isAddOpen, setIsAddOpen] = React.useState(false);
|
|
18638
|
-
const [isContentPickerOpen, setIsContentPickerOpen] = React.useState(false);
|
|
18639
|
-
const [editingItem, setEditingItem] = React.useState(null);
|
|
18640
|
-
const [localItems, setLocalItems] = React.useState([]);
|
|
18641
|
-
const [addError, setAddError] = React.useState(null);
|
|
18642
|
-
const [editError, setEditError] = React.useState(null);
|
|
18888
|
+
const [isAddOpen, setIsAddOpen] = React$1.useState(false);
|
|
18889
|
+
const [isContentPickerOpen, setIsContentPickerOpen] = React$1.useState(false);
|
|
18890
|
+
const [editingItem, setEditingItem] = React$1.useState(null);
|
|
18891
|
+
const [localItems, setLocalItems] = React$1.useState([]);
|
|
18892
|
+
const [addError, setAddError] = React$1.useState(null);
|
|
18893
|
+
const [editError, setEditError] = React$1.useState(null);
|
|
18894
|
+
const { data: manifest } = useQuery({
|
|
18895
|
+
queryKey: ["manifest"],
|
|
18896
|
+
queryFn: fetchManifest
|
|
18897
|
+
});
|
|
18898
|
+
const i18n = useI18nConfig(manifest);
|
|
18643
18899
|
const { data: menu, isLoading } = useQuery({
|
|
18644
|
-
queryKey: [
|
|
18645
|
-
|
|
18900
|
+
queryKey: [
|
|
18901
|
+
"menu",
|
|
18902
|
+
name,
|
|
18903
|
+
routeLocale ?? null
|
|
18904
|
+
],
|
|
18905
|
+
queryFn: () => fetchMenu(name, { locale: routeLocale }),
|
|
18646
18906
|
staleTime: Infinity
|
|
18647
18907
|
});
|
|
18648
|
-
|
|
18908
|
+
const menuLocale = routeLocale ?? menu?.locale;
|
|
18909
|
+
const { data: translationsData } = useQuery({
|
|
18910
|
+
queryKey: [
|
|
18911
|
+
"menu-translations",
|
|
18912
|
+
name,
|
|
18913
|
+
menuLocale ?? null
|
|
18914
|
+
],
|
|
18915
|
+
queryFn: () => fetchMenuTranslations(name, { locale: menuLocale }),
|
|
18916
|
+
enabled: !!menu && !!i18n && i18n.locales.length > 1
|
|
18917
|
+
});
|
|
18918
|
+
const translateMutation = useMutation({
|
|
18919
|
+
mutationFn: (targetLocale) => createMenuTranslation(name, {
|
|
18920
|
+
locale: targetLocale,
|
|
18921
|
+
label: menu?.label
|
|
18922
|
+
}, { locale: menuLocale }),
|
|
18923
|
+
onSuccess: (translated) => {
|
|
18924
|
+
queryClient.invalidateQueries({ queryKey: ["menus"] });
|
|
18925
|
+
queryClient.invalidateQueries({ queryKey: ["menu", name] });
|
|
18926
|
+
queryClient.invalidateQueries({ queryKey: ["menu-translations", name] });
|
|
18927
|
+
toastManager.add({
|
|
18928
|
+
title: _t({
|
|
18929
|
+
id: "pBdGCu",
|
|
18930
|
+
message: "Translation created"
|
|
18931
|
+
}),
|
|
18932
|
+
description: _t({
|
|
18933
|
+
id: "RKdeOp",
|
|
18934
|
+
message: "Menu \"{0}\" ({1}) created.",
|
|
18935
|
+
values: {
|
|
18936
|
+
0: translated.label,
|
|
18937
|
+
1: translated.locale.toUpperCase()
|
|
18938
|
+
}
|
|
18939
|
+
})
|
|
18940
|
+
});
|
|
18941
|
+
navigate({
|
|
18942
|
+
to: "/menus/$name",
|
|
18943
|
+
params: { name },
|
|
18944
|
+
search: { locale: translated.locale }
|
|
18945
|
+
});
|
|
18946
|
+
},
|
|
18947
|
+
onError: (error) => {
|
|
18948
|
+
toastManager.add({
|
|
18949
|
+
title: _t({
|
|
18950
|
+
id: "SlfejT",
|
|
18951
|
+
message: "Error"
|
|
18952
|
+
}),
|
|
18953
|
+
description: error.message,
|
|
18954
|
+
type: "error"
|
|
18955
|
+
});
|
|
18956
|
+
}
|
|
18957
|
+
});
|
|
18958
|
+
React$1.useEffect(() => {
|
|
18649
18959
|
if (menu?.items) setLocalItems(menu.items);
|
|
18650
18960
|
}, [menu]);
|
|
18651
18961
|
const createMutation = useMutation({
|
|
18652
|
-
mutationFn: (input) => createMenuItem(name, input),
|
|
18962
|
+
mutationFn: (input) => createMenuItem(name, input, { locale: menuLocale }),
|
|
18653
18963
|
onSuccess: () => {
|
|
18654
18964
|
queryClient.invalidateQueries({ queryKey: ["menu", name] });
|
|
18655
18965
|
setIsAddOpen(false);
|
|
@@ -18669,7 +18979,7 @@ function MenuEditor() {
|
|
|
18669
18979
|
}
|
|
18670
18980
|
});
|
|
18671
18981
|
const deleteMutation = useMutation({
|
|
18672
|
-
mutationFn: (itemId) => deleteMenuItem(name, itemId),
|
|
18982
|
+
mutationFn: (itemId) => deleteMenuItem(name, itemId, { locale: menuLocale }),
|
|
18673
18983
|
onSuccess: () => {
|
|
18674
18984
|
queryClient.invalidateQueries({ queryKey: ["menu", name] });
|
|
18675
18985
|
toastManager.add({
|
|
@@ -18695,7 +19005,7 @@ function MenuEditor() {
|
|
|
18695
19005
|
}
|
|
18696
19006
|
});
|
|
18697
19007
|
const updateMutation = useMutation({
|
|
18698
|
-
mutationFn: ({ itemId, input }) => updateMenuItem(name, itemId, input),
|
|
19008
|
+
mutationFn: ({ itemId, input }) => updateMenuItem(name, itemId, input, { locale: menuLocale }),
|
|
18699
19009
|
onSuccess: () => {
|
|
18700
19010
|
queryClient.invalidateQueries({ queryKey: ["menu", name] });
|
|
18701
19011
|
setEditingItem(null);
|
|
@@ -18715,7 +19025,7 @@ function MenuEditor() {
|
|
|
18715
19025
|
}
|
|
18716
19026
|
});
|
|
18717
19027
|
const reorderMutation = useMutation({
|
|
18718
|
-
mutationFn: (input) => reorderMenuItems(name, input),
|
|
19028
|
+
mutationFn: (input) => reorderMenuItems(name, input, { locale: menuLocale }),
|
|
18719
19029
|
onSuccess: () => {
|
|
18720
19030
|
queryClient.invalidateQueries({ queryKey: ["menu", name] });
|
|
18721
19031
|
toastManager.add({
|
|
@@ -18998,6 +19308,28 @@ function MenuEditor() {
|
|
|
18998
19308
|
onOpenChange: setIsContentPickerOpen,
|
|
18999
19309
|
onSelect: handleAddContent
|
|
19000
19310
|
}),
|
|
19311
|
+
i18n && i18n.locales.length > 1 && menu ? /* @__PURE__ */ jsx("div", {
|
|
19312
|
+
className: "border rounded-lg p-4",
|
|
19313
|
+
children: /* @__PURE__ */ jsx(TranslationsPanel, {
|
|
19314
|
+
locales: i18n.locales,
|
|
19315
|
+
defaultLocale: i18n.defaultLocale,
|
|
19316
|
+
currentLocale: menu.locale,
|
|
19317
|
+
translations: translationsData?.translations.map((tr) => ({
|
|
19318
|
+
id: tr.id,
|
|
19319
|
+
locale: tr.locale
|
|
19320
|
+
})) ?? [{
|
|
19321
|
+
id: menu.id,
|
|
19322
|
+
locale: menu.locale
|
|
19323
|
+
}],
|
|
19324
|
+
onOpen: (tr) => navigate({
|
|
19325
|
+
to: "/menus/$name",
|
|
19326
|
+
params: { name },
|
|
19327
|
+
search: { locale: tr.locale }
|
|
19328
|
+
}),
|
|
19329
|
+
onCreate: (target) => translateMutation.mutate(target),
|
|
19330
|
+
pendingLocale: translateMutation.isPending ? translateMutation.variables ?? null : null
|
|
19331
|
+
})
|
|
19332
|
+
}) : null,
|
|
19001
19333
|
localItems.length === 0 ? /* @__PURE__ */ jsxs("div", {
|
|
19002
19334
|
className: "border rounded-lg p-12 text-center",
|
|
19003
19335
|
children: [
|
|
@@ -19247,12 +19579,21 @@ function MenuList() {
|
|
|
19247
19579
|
const queryClient = useQueryClient();
|
|
19248
19580
|
const navigate = useNavigate$1();
|
|
19249
19581
|
const toastManager = Toast.useToastManager();
|
|
19250
|
-
const [isCreateOpen, setIsCreateOpen] = React.useState(false);
|
|
19251
|
-
const [deleteMenuName, setDeleteMenuName] = React.useState(null);
|
|
19252
|
-
const [createError, setCreateError] = React.useState(null);
|
|
19582
|
+
const [isCreateOpen, setIsCreateOpen] = React$1.useState(false);
|
|
19583
|
+
const [deleteMenuName, setDeleteMenuName] = React$1.useState(null);
|
|
19584
|
+
const [createError, setCreateError] = React$1.useState(null);
|
|
19585
|
+
const { data: manifest } = useQuery({
|
|
19586
|
+
queryKey: ["manifest"],
|
|
19587
|
+
queryFn: fetchManifest
|
|
19588
|
+
});
|
|
19589
|
+
const i18n = useI18nConfig(manifest);
|
|
19590
|
+
const [activeLocale, setActiveLocale] = React$1.useState(void 0);
|
|
19591
|
+
React$1.useEffect(() => {
|
|
19592
|
+
if (i18n && !activeLocale) setActiveLocale(i18n.defaultLocale);
|
|
19593
|
+
}, [i18n, activeLocale]);
|
|
19253
19594
|
const { data: menus, isLoading } = useQuery({
|
|
19254
|
-
queryKey: ["menus"],
|
|
19255
|
-
queryFn: fetchMenus
|
|
19595
|
+
queryKey: ["menus", activeLocale],
|
|
19596
|
+
queryFn: () => fetchMenus({ locale: activeLocale })
|
|
19256
19597
|
});
|
|
19257
19598
|
const createMutation = useMutation({
|
|
19258
19599
|
mutationFn: createMenu,
|
|
@@ -19272,7 +19613,8 @@ function MenuList() {
|
|
|
19272
19613
|
});
|
|
19273
19614
|
navigate({
|
|
19274
19615
|
to: "/menus/$name",
|
|
19275
|
-
params: { name: menu.name }
|
|
19616
|
+
params: { name: menu.name },
|
|
19617
|
+
search: { locale: menu.locale }
|
|
19276
19618
|
});
|
|
19277
19619
|
},
|
|
19278
19620
|
onError: (error) => {
|
|
@@ -19280,7 +19622,7 @@ function MenuList() {
|
|
|
19280
19622
|
}
|
|
19281
19623
|
});
|
|
19282
19624
|
const deleteMutation = useMutation({
|
|
19283
|
-
mutationFn: deleteMenu,
|
|
19625
|
+
mutationFn: (name) => deleteMenu(name, { locale: activeLocale }),
|
|
19284
19626
|
onSuccess: () => {
|
|
19285
19627
|
queryClient.invalidateQueries({ queryKey: ["menus"] });
|
|
19286
19628
|
setDeleteMenuName(null);
|
|
@@ -19306,7 +19648,8 @@ function MenuList() {
|
|
|
19306
19648
|
const label = typeof labelVal === "string" ? labelVal : "";
|
|
19307
19649
|
createMutation.mutate({
|
|
19308
19650
|
name,
|
|
19309
|
-
label
|
|
19651
|
+
label,
|
|
19652
|
+
locale: activeLocale
|
|
19310
19653
|
});
|
|
19311
19654
|
};
|
|
19312
19655
|
if (isLoading) return /* @__PURE__ */ jsx("div", {
|
|
@@ -19323,135 +19666,147 @@ function MenuList() {
|
|
|
19323
19666
|
className: "space-y-6",
|
|
19324
19667
|
children: [
|
|
19325
19668
|
/* @__PURE__ */ jsxs("div", {
|
|
19326
|
-
className: "flex items-center justify-between",
|
|
19327
|
-
children: [
|
|
19328
|
-
|
|
19329
|
-
|
|
19330
|
-
id: "NXjnVQ",
|
|
19331
|
-
message: "Menus"
|
|
19332
|
-
})
|
|
19333
|
-
}), /* @__PURE__ */ jsx("p", {
|
|
19334
|
-
className: "text-kumo-subtle",
|
|
19335
|
-
children: _t({
|
|
19336
|
-
id: "+2SUVL",
|
|
19337
|
-
message: "Manage navigation menus for your site"
|
|
19338
|
-
})
|
|
19339
|
-
})] }), /* @__PURE__ */ jsxs(Dialog.Root, {
|
|
19340
|
-
open: isCreateOpen,
|
|
19341
|
-
onOpenChange: (open) => {
|
|
19342
|
-
setIsCreateOpen(open);
|
|
19343
|
-
if (!open) setCreateError(null);
|
|
19344
|
-
},
|
|
19345
|
-
children: [/* @__PURE__ */ jsx(Dialog.Trigger, { render: (props) => /* @__PURE__ */ jsx(Button, {
|
|
19346
|
-
...props,
|
|
19347
|
-
icon: /* @__PURE__ */ jsx(Plus, {}),
|
|
19669
|
+
className: "flex items-center justify-between gap-4 flex-wrap",
|
|
19670
|
+
children: [
|
|
19671
|
+
/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h1", {
|
|
19672
|
+
className: "text-3xl font-bold",
|
|
19348
19673
|
children: _t({
|
|
19349
|
-
id: "
|
|
19350
|
-
message: "
|
|
19674
|
+
id: "NXjnVQ",
|
|
19675
|
+
message: "Menus"
|
|
19351
19676
|
})
|
|
19352
|
-
})
|
|
19353
|
-
className: "
|
|
19354
|
-
|
|
19355
|
-
|
|
19356
|
-
|
|
19357
|
-
|
|
19358
|
-
|
|
19359
|
-
|
|
19360
|
-
|
|
19361
|
-
|
|
19362
|
-
|
|
19363
|
-
|
|
19364
|
-
|
|
19365
|
-
|
|
19366
|
-
|
|
19367
|
-
|
|
19368
|
-
|
|
19369
|
-
|
|
19370
|
-
|
|
19371
|
-
|
|
19677
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
19678
|
+
className: "text-kumo-subtle",
|
|
19679
|
+
children: _t({
|
|
19680
|
+
id: "+2SUVL",
|
|
19681
|
+
message: "Manage navigation menus for your site"
|
|
19682
|
+
})
|
|
19683
|
+
})] }),
|
|
19684
|
+
/* @__PURE__ */ jsx("div", {
|
|
19685
|
+
className: "flex items-center gap-2",
|
|
19686
|
+
children: i18n && activeLocale ? /* @__PURE__ */ jsx(LocaleSwitcher, {
|
|
19687
|
+
locales: i18n.locales,
|
|
19688
|
+
defaultLocale: i18n.defaultLocale,
|
|
19689
|
+
value: activeLocale,
|
|
19690
|
+
onChange: setActiveLocale
|
|
19691
|
+
}) : null
|
|
19692
|
+
}),
|
|
19693
|
+
/* @__PURE__ */ jsxs(Dialog.Root, {
|
|
19694
|
+
open: isCreateOpen,
|
|
19695
|
+
onOpenChange: (open) => {
|
|
19696
|
+
setIsCreateOpen(open);
|
|
19697
|
+
if (!open) setCreateError(null);
|
|
19698
|
+
},
|
|
19699
|
+
children: [/* @__PURE__ */ jsx(Dialog.Trigger, { render: (props) => /* @__PURE__ */ jsx(Button, {
|
|
19700
|
+
...props,
|
|
19701
|
+
icon: /* @__PURE__ */ jsx(Plus, {}),
|
|
19702
|
+
children: _t({
|
|
19703
|
+
id: "89ONdL",
|
|
19704
|
+
message: "Create Menu"
|
|
19705
|
+
})
|
|
19706
|
+
}) }), /* @__PURE__ */ jsxs(Dialog, {
|
|
19707
|
+
className: "p-6",
|
|
19708
|
+
size: "lg",
|
|
19709
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
19710
|
+
className: "flex items-start justify-between gap-4 mb-4",
|
|
19711
|
+
children: [/* @__PURE__ */ jsx(Dialog.Title, {
|
|
19712
|
+
className: "text-lg font-semibold leading-none tracking-tight",
|
|
19713
|
+
children: _t({
|
|
19714
|
+
id: "7P7UXw",
|
|
19715
|
+
message: "Create New Menu"
|
|
19716
|
+
})
|
|
19717
|
+
}), /* @__PURE__ */ jsx(Dialog.Close, {
|
|
19372
19718
|
"aria-label": _t({
|
|
19373
19719
|
id: "yz7wBu",
|
|
19374
19720
|
message: "Close"
|
|
19375
19721
|
}),
|
|
19376
|
-
|
|
19377
|
-
|
|
19378
|
-
|
|
19379
|
-
|
|
19722
|
+
render: (props) => /* @__PURE__ */ jsxs(Button, {
|
|
19723
|
+
...props,
|
|
19724
|
+
variant: "ghost",
|
|
19725
|
+
shape: "square",
|
|
19726
|
+
"aria-label": _t({
|
|
19380
19727
|
id: "yz7wBu",
|
|
19381
19728
|
message: "Close"
|
|
19382
|
-
})
|
|
19383
|
-
|
|
19384
|
-
|
|
19385
|
-
|
|
19386
|
-
|
|
19387
|
-
|
|
19388
|
-
|
|
19389
|
-
|
|
19390
|
-
|
|
19391
|
-
label: _t({
|
|
19392
|
-
id: "6YtxFj",
|
|
19393
|
-
message: "Name"
|
|
19394
|
-
}),
|
|
19395
|
-
name: "name",
|
|
19396
|
-
required: true,
|
|
19397
|
-
placeholder: "primary",
|
|
19398
|
-
pattern: "[a-z0-9\\-]+",
|
|
19399
|
-
title: _t({
|
|
19400
|
-
id: "6ZQzu/",
|
|
19401
|
-
message: "Only lowercase letters, numbers, and hyphens"
|
|
19402
|
-
})
|
|
19403
|
-
}), /* @__PURE__ */ jsx("p", {
|
|
19404
|
-
className: "text-sm text-kumo-subtle mt-1",
|
|
19405
|
-
children: _t({
|
|
19406
|
-
id: "P5zbwF",
|
|
19407
|
-
message: "URL-friendly identifier (e.g., \"primary\", \"footer\")"
|
|
19408
|
-
})
|
|
19409
|
-
})] }),
|
|
19410
|
-
/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(Input, {
|
|
19411
|
-
label: _t({
|
|
19412
|
-
id: "87a/t/",
|
|
19413
|
-
message: "Label"
|
|
19414
|
-
}),
|
|
19415
|
-
name: "label",
|
|
19416
|
-
required: true,
|
|
19417
|
-
placeholder: _t({
|
|
19418
|
-
id: "9xZvwS",
|
|
19419
|
-
message: "Primary Navigation"
|
|
19420
|
-
})
|
|
19421
|
-
}), /* @__PURE__ */ jsx("p", {
|
|
19422
|
-
className: "text-sm text-kumo-subtle mt-1",
|
|
19423
|
-
children: _t({
|
|
19424
|
-
id: "1jYgRd",
|
|
19425
|
-
message: "Display name for admin interface"
|
|
19729
|
+
}),
|
|
19730
|
+
className: "absolute end-4 top-4",
|
|
19731
|
+
children: [/* @__PURE__ */ jsx(X, { className: "h-4 w-4" }), /* @__PURE__ */ jsx("span", {
|
|
19732
|
+
className: "sr-only",
|
|
19733
|
+
children: _t({
|
|
19734
|
+
id: "yz7wBu",
|
|
19735
|
+
message: "Close"
|
|
19736
|
+
})
|
|
19737
|
+
})]
|
|
19426
19738
|
})
|
|
19427
|
-
})]
|
|
19428
|
-
|
|
19429
|
-
|
|
19430
|
-
|
|
19431
|
-
|
|
19432
|
-
|
|
19433
|
-
|
|
19434
|
-
|
|
19739
|
+
})]
|
|
19740
|
+
}), /* @__PURE__ */ jsxs("form", {
|
|
19741
|
+
onSubmit: handleCreate,
|
|
19742
|
+
className: "space-y-4",
|
|
19743
|
+
children: [
|
|
19744
|
+
/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(Input, {
|
|
19745
|
+
label: _t({
|
|
19746
|
+
id: "6YtxFj",
|
|
19747
|
+
message: "Name"
|
|
19748
|
+
}),
|
|
19749
|
+
name: "name",
|
|
19750
|
+
required: true,
|
|
19751
|
+
placeholder: "primary",
|
|
19752
|
+
pattern: "[a-z0-9\\-]+",
|
|
19753
|
+
title: _t({
|
|
19754
|
+
id: "6ZQzu/",
|
|
19755
|
+
message: "Only lowercase letters, numbers, and hyphens"
|
|
19756
|
+
})
|
|
19757
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
19758
|
+
className: "text-sm text-kumo-subtle mt-1",
|
|
19435
19759
|
children: _t({
|
|
19436
|
-
id: "
|
|
19437
|
-
message: "
|
|
19760
|
+
id: "P5zbwF",
|
|
19761
|
+
message: "URL-friendly identifier (e.g., \"primary\", \"footer\")"
|
|
19438
19762
|
})
|
|
19439
|
-
})
|
|
19440
|
-
|
|
19441
|
-
|
|
19442
|
-
|
|
19443
|
-
|
|
19444
|
-
|
|
19445
|
-
|
|
19446
|
-
|
|
19447
|
-
|
|
19763
|
+
})] }),
|
|
19764
|
+
/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(Input, {
|
|
19765
|
+
label: _t({
|
|
19766
|
+
id: "87a/t/",
|
|
19767
|
+
message: "Label"
|
|
19768
|
+
}),
|
|
19769
|
+
name: "label",
|
|
19770
|
+
required: true,
|
|
19771
|
+
placeholder: _t({
|
|
19772
|
+
id: "9xZvwS",
|
|
19773
|
+
message: "Primary Navigation"
|
|
19448
19774
|
})
|
|
19449
|
-
})
|
|
19450
|
-
|
|
19451
|
-
|
|
19775
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
19776
|
+
className: "text-sm text-kumo-subtle mt-1",
|
|
19777
|
+
children: _t({
|
|
19778
|
+
id: "1jYgRd",
|
|
19779
|
+
message: "Display name for admin interface"
|
|
19780
|
+
})
|
|
19781
|
+
})] }),
|
|
19782
|
+
/* @__PURE__ */ jsx(DialogError, { message: createError || getMutationError(createMutation.error) }),
|
|
19783
|
+
/* @__PURE__ */ jsxs("div", {
|
|
19784
|
+
className: "flex justify-end gap-2",
|
|
19785
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
19786
|
+
type: "button",
|
|
19787
|
+
variant: "outline",
|
|
19788
|
+
onClick: () => setIsCreateOpen(false),
|
|
19789
|
+
children: _t({
|
|
19790
|
+
id: "dEgA5A",
|
|
19791
|
+
message: "Cancel"
|
|
19792
|
+
})
|
|
19793
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
19794
|
+
type: "submit",
|
|
19795
|
+
disabled: createMutation.isPending,
|
|
19796
|
+
children: createMutation.isPending ? _t({
|
|
19797
|
+
id: "HM56Bx",
|
|
19798
|
+
message: "Creating..."
|
|
19799
|
+
}) : _t({
|
|
19800
|
+
id: "hYgDIe",
|
|
19801
|
+
message: "Create"
|
|
19802
|
+
})
|
|
19803
|
+
})]
|
|
19804
|
+
})
|
|
19805
|
+
]
|
|
19806
|
+
})]
|
|
19452
19807
|
})]
|
|
19453
|
-
})
|
|
19454
|
-
|
|
19808
|
+
})
|
|
19809
|
+
]
|
|
19455
19810
|
}),
|
|
19456
19811
|
!menus || menus.length === 0 ? /* @__PURE__ */ jsxs("div", {
|
|
19457
19812
|
className: "border rounded-lg p-12 text-center",
|
|
@@ -19487,10 +19842,14 @@ function MenuList() {
|
|
|
19487
19842
|
children: [/* @__PURE__ */ jsx(Link$1, {
|
|
19488
19843
|
to: "/menus/$name",
|
|
19489
19844
|
params: { name: menu.name },
|
|
19845
|
+
search: { locale: menu.locale },
|
|
19490
19846
|
className: "flex-1",
|
|
19491
|
-
children: /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */
|
|
19847
|
+
children: /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs("h3", {
|
|
19492
19848
|
className: "font-semibold text-lg",
|
|
19493
|
-
children: menu.label
|
|
19849
|
+
children: [menu.label, i18n ? /* @__PURE__ */ jsx("span", {
|
|
19850
|
+
className: "ms-2 text-xs font-mono uppercase text-kumo-subtle",
|
|
19851
|
+
children: menu.locale
|
|
19852
|
+
}) : null]
|
|
19494
19853
|
}), /* @__PURE__ */ jsxs("p", {
|
|
19495
19854
|
className: "text-sm text-kumo-subtle",
|
|
19496
19855
|
children: [
|
|
@@ -19505,6 +19864,7 @@ function MenuList() {
|
|
|
19505
19864
|
children: [/* @__PURE__ */ jsxs(Link$1, {
|
|
19506
19865
|
to: "/menus/$name",
|
|
19507
19866
|
params: { name: menu.name },
|
|
19867
|
+
search: { locale: menu.locale },
|
|
19508
19868
|
className: buttonVariants({
|
|
19509
19869
|
variant: "outline",
|
|
19510
19870
|
size: "sm"
|
|
@@ -20444,27 +20804,27 @@ function SectionEditor() {
|
|
|
20444
20804
|
}
|
|
20445
20805
|
function SectionEditorForm({ section, isSaving, onSave }) {
|
|
20446
20806
|
const { _: _t2 } = useLingui();
|
|
20447
|
-
const [title, setTitle] = React.useState(section.title);
|
|
20448
|
-
const [sectionSlug, setSectionSlug] = React.useState(section.slug);
|
|
20449
|
-
const [slugTouched, setSlugTouched] = React.useState(true);
|
|
20450
|
-
const [description, setDescription] = React.useState(section.description || "");
|
|
20451
|
-
const [keywords, setKeywords] = React.useState(section.keywords.join(", "));
|
|
20452
|
-
const [content, setContent] = React.useState(section.content);
|
|
20453
|
-
const [lastSavedData] = React.useState(() => JSON.stringify({
|
|
20807
|
+
const [title, setTitle] = React$1.useState(section.title);
|
|
20808
|
+
const [sectionSlug, setSectionSlug] = React$1.useState(section.slug);
|
|
20809
|
+
const [slugTouched, setSlugTouched] = React$1.useState(true);
|
|
20810
|
+
const [description, setDescription] = React$1.useState(section.description || "");
|
|
20811
|
+
const [keywords, setKeywords] = React$1.useState(section.keywords.join(", "));
|
|
20812
|
+
const [content, setContent] = React$1.useState(section.content);
|
|
20813
|
+
const [lastSavedData] = React$1.useState(() => JSON.stringify({
|
|
20454
20814
|
title: section.title,
|
|
20455
20815
|
slug: section.slug,
|
|
20456
20816
|
description: section.description || "",
|
|
20457
20817
|
keywords: section.keywords.join(", "),
|
|
20458
20818
|
content: section.content
|
|
20459
20819
|
}));
|
|
20460
|
-
React.useEffect(() => {
|
|
20820
|
+
React$1.useEffect(() => {
|
|
20461
20821
|
if (!slugTouched && title && title !== section.title) setSectionSlug(slugify(title));
|
|
20462
20822
|
}, [
|
|
20463
20823
|
title,
|
|
20464
20824
|
slugTouched,
|
|
20465
20825
|
section.title
|
|
20466
20826
|
]);
|
|
20467
|
-
const isDirty = React.useMemo(() => JSON.stringify({
|
|
20827
|
+
const isDirty = React$1.useMemo(() => JSON.stringify({
|
|
20468
20828
|
title,
|
|
20469
20829
|
slug: sectionSlug,
|
|
20470
20830
|
description,
|
|
@@ -20477,11 +20837,11 @@ function SectionEditorForm({ section, isSaving, onSave }) {
|
|
|
20477
20837
|
keywords,
|
|
20478
20838
|
content
|
|
20479
20839
|
]) !== lastSavedData;
|
|
20480
|
-
const [blockSidebarPanel, setBlockSidebarPanel] = React.useState(null);
|
|
20481
|
-
const handleBlockSidebarOpen = React.useCallback((panel) => {
|
|
20840
|
+
const [blockSidebarPanel, setBlockSidebarPanel] = React$1.useState(null);
|
|
20841
|
+
const handleBlockSidebarOpen = React$1.useCallback((panel) => {
|
|
20482
20842
|
setBlockSidebarPanel(panel);
|
|
20483
20843
|
}, []);
|
|
20484
|
-
const handleBlockSidebarClose = React.useCallback(() => {
|
|
20844
|
+
const handleBlockSidebarClose = React$1.useCallback(() => {
|
|
20485
20845
|
setBlockSidebarPanel((prev) => {
|
|
20486
20846
|
prev?.onClose();
|
|
20487
20847
|
return null;
|
|
@@ -20700,16 +21060,16 @@ function Sections() {
|
|
|
20700
21060
|
const navigate = useNavigate$1();
|
|
20701
21061
|
const queryClient = useQueryClient();
|
|
20702
21062
|
const toastManager = Toast.useToastManager();
|
|
20703
|
-
const [isCreateOpen, setIsCreateOpen] = React.useState(false);
|
|
20704
|
-
const [deleteSlug, setDeleteSlug] = React.useState(null);
|
|
20705
|
-
const [searchQuery, setSearchQuery] = React.useState("");
|
|
20706
|
-
const [selectedSource, setSelectedSource] = React.useState(null);
|
|
20707
|
-
const [createTitle, setCreateTitle] = React.useState("");
|
|
20708
|
-
const [createSlug, setCreateSlug] = React.useState("");
|
|
20709
|
-
const [createDescription, setCreateDescription] = React.useState("");
|
|
20710
|
-
const [slugTouched, setSlugTouched] = React.useState(false);
|
|
20711
|
-
const [createError, setCreateError] = React.useState(null);
|
|
20712
|
-
React.useEffect(() => {
|
|
21063
|
+
const [isCreateOpen, setIsCreateOpen] = React$1.useState(false);
|
|
21064
|
+
const [deleteSlug, setDeleteSlug] = React$1.useState(null);
|
|
21065
|
+
const [searchQuery, setSearchQuery] = React$1.useState("");
|
|
21066
|
+
const [selectedSource, setSelectedSource] = React$1.useState(null);
|
|
21067
|
+
const [createTitle, setCreateTitle] = React$1.useState("");
|
|
21068
|
+
const [createSlug, setCreateSlug] = React$1.useState("");
|
|
21069
|
+
const [createDescription, setCreateDescription] = React$1.useState("");
|
|
21070
|
+
const [slugTouched, setSlugTouched] = React$1.useState(false);
|
|
21071
|
+
const [createError, setCreateError] = React$1.useState(null);
|
|
21072
|
+
React$1.useEffect(() => {
|
|
20713
21073
|
if (!isCreateOpen) {
|
|
20714
21074
|
setCreateTitle("");
|
|
20715
21075
|
setCreateSlug("");
|
|
@@ -21454,15 +21814,15 @@ const MSG_ROLE_UNKNOWN = {
|
|
|
21454
21814
|
*/
|
|
21455
21815
|
function useRolesConfig() {
|
|
21456
21816
|
const { _: _t } = useLingui();
|
|
21457
|
-
const roles = React.useMemo(() => ROLE_ENTRIES.map(({ value, label, description }) => ({
|
|
21817
|
+
const roles = React$1.useMemo(() => ROLE_ENTRIES.map(({ value, label, description }) => ({
|
|
21458
21818
|
value,
|
|
21459
21819
|
label: _t(label),
|
|
21460
21820
|
description: _t(description)
|
|
21461
21821
|
})), [_t]);
|
|
21462
|
-
const roleLabels = React.useMemo(() => Object.fromEntries(ROLE_ENTRIES.map((r) => [String(r.value), _t(r.label)])), [_t]);
|
|
21822
|
+
const roleLabels = React$1.useMemo(() => Object.fromEntries(ROLE_ENTRIES.map((r) => [String(r.value), _t(r.label)])), [_t]);
|
|
21463
21823
|
return {
|
|
21464
21824
|
roleLabels,
|
|
21465
|
-
getRoleLabel: React.useCallback((level) => roleLabels[String(level)] ?? _t(MSG_ROLE_UNKNOWN), [roleLabels, _t]),
|
|
21825
|
+
getRoleLabel: React$1.useCallback((level) => roleLabels[String(level)] ?? _t(MSG_ROLE_UNKNOWN), [roleLabels, _t]),
|
|
21466
21826
|
roles
|
|
21467
21827
|
};
|
|
21468
21828
|
}
|
|
@@ -21477,11 +21837,11 @@ const MAX_SELF_SIGNUP_DEFAULT_ROLE = 40;
|
|
|
21477
21837
|
*/
|
|
21478
21838
|
function useAllowedDomainsRolesConfig() {
|
|
21479
21839
|
const { roleLabels, getRoleLabel, roles } = useRolesConfig();
|
|
21480
|
-
const signupRoles = React.useMemo(() => roles.filter((r) => r.value <= MAX_SELF_SIGNUP_DEFAULT_ROLE), [roles]);
|
|
21840
|
+
const signupRoles = React$1.useMemo(() => roles.filter((r) => r.value <= MAX_SELF_SIGNUP_DEFAULT_ROLE), [roles]);
|
|
21481
21841
|
return {
|
|
21482
21842
|
getRoleLabel,
|
|
21483
21843
|
signupRoles,
|
|
21484
|
-
signupRoleItems: React.useMemo(() => {
|
|
21844
|
+
signupRoleItems: React$1.useMemo(() => {
|
|
21485
21845
|
const entries = signupRoles.map((r) => {
|
|
21486
21846
|
const label = roleLabels[String(r.value)];
|
|
21487
21847
|
return [String(r.value), label ?? getRoleLabel(r.value)];
|
|
@@ -21507,12 +21867,12 @@ function AllowedDomainsSettings() {
|
|
|
21507
21867
|
const { _: _t } = useLingui();
|
|
21508
21868
|
const { getRoleLabel, signupRoles, signupRoleItems } = useAllowedDomainsRolesConfig();
|
|
21509
21869
|
const queryClient = useQueryClient();
|
|
21510
|
-
const [isAddingDomain, setIsAddingDomain] = React.useState(false);
|
|
21511
|
-
const [editingDomain, setEditingDomain] = React.useState(null);
|
|
21512
|
-
const [deletingDomain, setDeletingDomain] = React.useState(null);
|
|
21513
|
-
const [saveStatus, setSaveStatus] = React.useState(null);
|
|
21514
|
-
const [newDomain, setNewDomain] = React.useState("");
|
|
21515
|
-
const [newRole, setNewRole] = React.useState(30);
|
|
21870
|
+
const [isAddingDomain, setIsAddingDomain] = React$1.useState(false);
|
|
21871
|
+
const [editingDomain, setEditingDomain] = React$1.useState(null);
|
|
21872
|
+
const [deletingDomain, setDeletingDomain] = React$1.useState(null);
|
|
21873
|
+
const [saveStatus, setSaveStatus] = React$1.useState(null);
|
|
21874
|
+
const [newDomain, setNewDomain] = React$1.useState("");
|
|
21875
|
+
const [newRole, setNewRole] = React$1.useState(30);
|
|
21516
21876
|
const { data: manifest, isLoading: manifestLoading } = useQuery({
|
|
21517
21877
|
queryKey: ["manifest"],
|
|
21518
21878
|
queryFn: fetchManifest
|
|
@@ -21523,7 +21883,7 @@ function AllowedDomainsSettings() {
|
|
|
21523
21883
|
queryFn: fetchAllowedDomains,
|
|
21524
21884
|
enabled: !isExternalAuth && !manifestLoading
|
|
21525
21885
|
});
|
|
21526
|
-
React.useEffect(() => {
|
|
21886
|
+
React$1.useEffect(() => {
|
|
21527
21887
|
if (saveStatus) {
|
|
21528
21888
|
const timer = setTimeout(setSaveStatus, 3e3, null);
|
|
21529
21889
|
return () => clearTimeout(timer);
|
|
@@ -22160,11 +22520,11 @@ function computeExpiryDate(option) {
|
|
|
22160
22520
|
function ApiTokenSettings() {
|
|
22161
22521
|
const { _: _t } = useLingui();
|
|
22162
22522
|
const queryClient = useQueryClient();
|
|
22163
|
-
const [showCreateForm, setShowCreateForm] = React.useState(false);
|
|
22164
|
-
const [newToken, setNewToken] = React.useState(null);
|
|
22165
|
-
const [tokenVisible, setTokenVisible] = React.useState(false);
|
|
22166
|
-
const [copied, setCopied] = React.useState(false);
|
|
22167
|
-
const [revokeConfirmId, setRevokeConfirmId] = React.useState(null);
|
|
22523
|
+
const [showCreateForm, setShowCreateForm] = React$1.useState(false);
|
|
22524
|
+
const [newToken, setNewToken] = React$1.useState(null);
|
|
22525
|
+
const [tokenVisible, setTokenVisible] = React$1.useState(false);
|
|
22526
|
+
const [copied, setCopied] = React$1.useState(false);
|
|
22527
|
+
const [revokeConfirmId, setRevokeConfirmId] = React$1.useState(null);
|
|
22168
22528
|
const { data: tokens, isLoading } = useQuery({
|
|
22169
22529
|
queryKey: ["api-tokens"],
|
|
22170
22530
|
queryFn: fetchApiTokens
|
|
@@ -22186,8 +22546,8 @@ function ApiTokenSettings() {
|
|
|
22186
22546
|
queryClient.invalidateQueries({ queryKey: ["api-tokens"] });
|
|
22187
22547
|
}
|
|
22188
22548
|
});
|
|
22189
|
-
const copyTimeoutRef = React.useRef(void 0);
|
|
22190
|
-
React.useEffect(() => {
|
|
22549
|
+
const copyTimeoutRef = React$1.useRef(void 0);
|
|
22550
|
+
React$1.useEffect(() => {
|
|
22191
22551
|
return () => {
|
|
22192
22552
|
if (copyTimeoutRef.current) clearTimeout(copyTimeoutRef.current);
|
|
22193
22553
|
};
|
|
@@ -22200,7 +22560,7 @@ function ApiTokenSettings() {
|
|
|
22200
22560
|
copyTimeoutRef.current = setTimeout(setCopied, 2e3, false);
|
|
22201
22561
|
} catch {}
|
|
22202
22562
|
};
|
|
22203
|
-
const expirySelectItems = React.useMemo(() => Object.fromEntries(EXPIRY_OPTIONS.map((o) => [o.value, _t(o.label)])), [_t]);
|
|
22563
|
+
const expirySelectItems = React$1.useMemo(() => Object.fromEntries(EXPIRY_OPTIONS.map((o) => [o.value, _t(o.label)])), [_t]);
|
|
22204
22564
|
return /* @__PURE__ */ jsxs("div", {
|
|
22205
22565
|
className: "space-y-6",
|
|
22206
22566
|
children: [
|
|
@@ -22445,9 +22805,9 @@ function ApiTokenSettings() {
|
|
|
22445
22805
|
}
|
|
22446
22806
|
function CreateTokenForm({ expirySelectItems, isCreating, error, onSubmit, onCancel }) {
|
|
22447
22807
|
const { _: _t2 } = useLingui();
|
|
22448
|
-
const [name, setName] = React.useState("");
|
|
22449
|
-
const [selectedScopes, setSelectedScopes] = React.useState(/* @__PURE__ */ new Set());
|
|
22450
|
-
const [expiry, setExpiry] = React.useState("30d");
|
|
22808
|
+
const [name, setName] = React$1.useState("");
|
|
22809
|
+
const [selectedScopes, setSelectedScopes] = React$1.useState(/* @__PURE__ */ new Set());
|
|
22810
|
+
const [expiry, setExpiry] = React$1.useState("30d");
|
|
22451
22811
|
const toggleScope = (scope) => {
|
|
22452
22812
|
setSelectedScopes((prev) => {
|
|
22453
22813
|
const next = new Set(prev);
|
|
@@ -22572,9 +22932,9 @@ function CreateTokenForm({ expirySelectItems, isCreating, error, onSubmit, onCan
|
|
|
22572
22932
|
*/
|
|
22573
22933
|
function EmailSettings() {
|
|
22574
22934
|
const { _: _t } = useLingui();
|
|
22575
|
-
const [testEmail, setTestEmail] = React.useState("");
|
|
22576
|
-
const [status, setStatus] = React.useState(null);
|
|
22577
|
-
React.useEffect(() => {
|
|
22935
|
+
const [testEmail, setTestEmail] = React$1.useState("");
|
|
22936
|
+
const [status, setStatus] = React$1.useState(null);
|
|
22937
|
+
React$1.useEffect(() => {
|
|
22578
22938
|
if (!status) return;
|
|
22579
22939
|
const timer = setTimeout(setStatus, 5e3, null);
|
|
22580
22940
|
return () => clearTimeout(timer);
|
|
@@ -22866,14 +23226,14 @@ function GeneralSettings() {
|
|
|
22866
23226
|
queryFn: fetchSettings,
|
|
22867
23227
|
staleTime: Infinity
|
|
22868
23228
|
});
|
|
22869
|
-
const [formData, setFormData] = React.useState({});
|
|
22870
|
-
const [saveStatus, setSaveStatus] = React.useState(null);
|
|
22871
|
-
const [logoPickerOpen, setLogoPickerOpen] = React.useState(false);
|
|
22872
|
-
const [faviconPickerOpen, setFaviconPickerOpen] = React.useState(false);
|
|
22873
|
-
React.useEffect(() => {
|
|
23229
|
+
const [formData, setFormData] = React$1.useState({});
|
|
23230
|
+
const [saveStatus, setSaveStatus] = React$1.useState(null);
|
|
23231
|
+
const [logoPickerOpen, setLogoPickerOpen] = React$1.useState(false);
|
|
23232
|
+
const [faviconPickerOpen, setFaviconPickerOpen] = React$1.useState(false);
|
|
23233
|
+
React$1.useEffect(() => {
|
|
22874
23234
|
if (settings) setFormData(settings);
|
|
22875
23235
|
}, [settings]);
|
|
22876
|
-
React.useEffect(() => {
|
|
23236
|
+
React$1.useEffect(() => {
|
|
22877
23237
|
if (saveStatus) {
|
|
22878
23238
|
const timer = setTimeout(setSaveStatus, 3e3, null);
|
|
22879
23239
|
return () => clearTimeout(timer);
|
|
@@ -23284,12 +23644,12 @@ function formatRelativeTime(dateString) {
|
|
|
23284
23644
|
}
|
|
23285
23645
|
function PasskeyItem({ passkey, canDelete, onRename, onDelete, isDeleting, isRenaming }) {
|
|
23286
23646
|
const { _: _t } = useLingui();
|
|
23287
|
-
const [isEditing, setIsEditing] = React.useState(false);
|
|
23288
|
-
const [editName, setEditName] = React.useState(passkey.name || "");
|
|
23289
|
-
const [showDeleteDialog, setShowDeleteDialog] = React.useState(false);
|
|
23290
|
-
const [deleteError, setDeleteError] = React.useState(null);
|
|
23291
|
-
const inputRef = React.useRef(null);
|
|
23292
|
-
React.useEffect(() => {
|
|
23647
|
+
const [isEditing, setIsEditing] = React$1.useState(false);
|
|
23648
|
+
const [editName, setEditName] = React$1.useState(passkey.name || "");
|
|
23649
|
+
const [showDeleteDialog, setShowDeleteDialog] = React$1.useState(false);
|
|
23650
|
+
const [deleteError, setDeleteError] = React$1.useState(null);
|
|
23651
|
+
const inputRef = React$1.useRef(null);
|
|
23652
|
+
React$1.useEffect(() => {
|
|
23293
23653
|
if (isEditing && inputRef.current) {
|
|
23294
23654
|
inputRef.current.focus();
|
|
23295
23655
|
inputRef.current.select();
|
|
@@ -23509,8 +23869,8 @@ function PasskeyList({ passkeys, onRename, onDelete, isDeleting, isRenaming }) {
|
|
|
23509
23869
|
function SecuritySettings() {
|
|
23510
23870
|
const { _: _t } = useLingui();
|
|
23511
23871
|
const queryClient = useQueryClient();
|
|
23512
|
-
const [isAdding, setIsAdding] = React.useState(false);
|
|
23513
|
-
const [saveStatus, setSaveStatus] = React.useState(null);
|
|
23872
|
+
const [isAdding, setIsAdding] = React$1.useState(false);
|
|
23873
|
+
const [saveStatus, setSaveStatus] = React$1.useState(null);
|
|
23514
23874
|
const { data: manifest, isLoading: manifestLoading } = useQuery({
|
|
23515
23875
|
queryKey: ["manifest"],
|
|
23516
23876
|
queryFn: fetchManifest
|
|
@@ -23521,7 +23881,7 @@ function SecuritySettings() {
|
|
|
23521
23881
|
queryFn: fetchPasskeys,
|
|
23522
23882
|
enabled: !isExternalAuth && !manifestLoading
|
|
23523
23883
|
});
|
|
23524
|
-
React.useEffect(() => {
|
|
23884
|
+
React$1.useEffect(() => {
|
|
23525
23885
|
if (saveStatus) {
|
|
23526
23886
|
const timer = setTimeout(setSaveStatus, 3e3, null);
|
|
23527
23887
|
return () => clearTimeout(timer);
|
|
@@ -23764,12 +24124,12 @@ function SeoSettings() {
|
|
|
23764
24124
|
queryFn: fetchSettings,
|
|
23765
24125
|
staleTime: Infinity
|
|
23766
24126
|
});
|
|
23767
|
-
const [formData, setFormData] = React.useState({});
|
|
23768
|
-
const [saveStatus, setSaveStatus] = React.useState(null);
|
|
23769
|
-
React.useEffect(() => {
|
|
24127
|
+
const [formData, setFormData] = React$1.useState({});
|
|
24128
|
+
const [saveStatus, setSaveStatus] = React$1.useState(null);
|
|
24129
|
+
React$1.useEffect(() => {
|
|
23770
24130
|
if (settings) setFormData(settings);
|
|
23771
24131
|
}, [settings]);
|
|
23772
|
-
React.useEffect(() => {
|
|
24132
|
+
React$1.useEffect(() => {
|
|
23773
24133
|
if (saveStatus) {
|
|
23774
24134
|
const timer = setTimeout(setSaveStatus, 3e3, null);
|
|
23775
24135
|
return () => clearTimeout(timer);
|
|
@@ -23985,12 +24345,12 @@ function SocialSettings() {
|
|
|
23985
24345
|
queryFn: fetchSettings,
|
|
23986
24346
|
staleTime: Infinity
|
|
23987
24347
|
});
|
|
23988
|
-
const [formData, setFormData] = React.useState({});
|
|
23989
|
-
const [saveStatus, setSaveStatus] = React.useState(null);
|
|
23990
|
-
React.useEffect(() => {
|
|
24348
|
+
const [formData, setFormData] = React$1.useState({});
|
|
24349
|
+
const [saveStatus, setSaveStatus] = React$1.useState(null);
|
|
24350
|
+
React$1.useEffect(() => {
|
|
23991
24351
|
if (settings) setFormData(settings);
|
|
23992
24352
|
}, [settings]);
|
|
23993
|
-
React.useEffect(() => {
|
|
24353
|
+
React$1.useEffect(() => {
|
|
23994
24354
|
if (saveStatus) {
|
|
23995
24355
|
const timer = setTimeout(setSaveStatus, 3e3, null);
|
|
23996
24356
|
return () => clearTimeout(timer);
|
|
@@ -24257,10 +24617,10 @@ async function executeAdminSetup(data) {
|
|
|
24257
24617
|
}
|
|
24258
24618
|
function SiteStep({ seedInfo, onNext, isLoading, error }) {
|
|
24259
24619
|
const { _: _t } = useLingui();
|
|
24260
|
-
const [title, setTitle] = React.useState(seedInfo?.title ?? "");
|
|
24261
|
-
const [tagline, setTagline] = React.useState(seedInfo?.tagline ?? "");
|
|
24262
|
-
const [includeContent, setIncludeContent] = React.useState(true);
|
|
24263
|
-
const [errors, setErrors] = React.useState({});
|
|
24620
|
+
const [title, setTitle] = React$1.useState(seedInfo?.title ?? "");
|
|
24621
|
+
const [tagline, setTagline] = React$1.useState(seedInfo?.tagline ?? "");
|
|
24622
|
+
const [includeContent, setIncludeContent] = React$1.useState(true);
|
|
24623
|
+
const [errors, setErrors] = React$1.useState({});
|
|
24264
24624
|
const validate = () => {
|
|
24265
24625
|
const newErrors = {};
|
|
24266
24626
|
if (!title.trim()) newErrors.title = _t({
|
|
@@ -24370,9 +24730,9 @@ function SiteStep({ seedInfo, onNext, isLoading, error }) {
|
|
|
24370
24730
|
}
|
|
24371
24731
|
function AdminStep({ onNext, onBack, isLoading, error }) {
|
|
24372
24732
|
const { _: _t2 } = useLingui();
|
|
24373
|
-
const [email, setEmail] = React.useState("");
|
|
24374
|
-
const [name, setName] = React.useState("");
|
|
24375
|
-
const [errors, setErrors] = React.useState({});
|
|
24733
|
+
const [email, setEmail] = React$1.useState("");
|
|
24734
|
+
const [name, setName] = React$1.useState("");
|
|
24735
|
+
const [errors, setErrors] = React$1.useState({});
|
|
24376
24736
|
const validate = () => {
|
|
24377
24737
|
const newErrors = {};
|
|
24378
24738
|
if (!email.trim()) newErrors.email = _t2({
|
|
@@ -24475,7 +24835,7 @@ function handleSetupSuccess() {
|
|
|
24475
24835
|
}
|
|
24476
24836
|
function AuthMethodStep({ adminData, providers, onBack }) {
|
|
24477
24837
|
const { _: _t3 } = useLingui();
|
|
24478
|
-
const [activeProvider, setActiveProvider] = React.useState(null);
|
|
24838
|
+
const [activeProvider, setActiveProvider] = React$1.useState(null);
|
|
24479
24839
|
const buttonProviders = providers.filter((p) => p.LoginButton);
|
|
24480
24840
|
const hasProviders = buttonProviders.length > 0;
|
|
24481
24841
|
if (activeProvider) {
|
|
@@ -24608,7 +24968,7 @@ function StepIndicator$1({ currentStep, useAccessAuth }) {
|
|
|
24608
24968
|
const currentIndex = steps.findIndex((s) => s.key === currentStep);
|
|
24609
24969
|
return /* @__PURE__ */ jsx("div", {
|
|
24610
24970
|
className: "flex items-center justify-center mb-8",
|
|
24611
|
-
children: steps.map((step, index) => /* @__PURE__ */ jsxs(React.Fragment, { children: [/* @__PURE__ */ jsxs("div", {
|
|
24971
|
+
children: steps.map((step, index) => /* @__PURE__ */ jsxs(React$1.Fragment, { children: [/* @__PURE__ */ jsxs("div", {
|
|
24612
24972
|
className: "flex items-center",
|
|
24613
24973
|
children: [/* @__PURE__ */ jsx("div", {
|
|
24614
24974
|
className: `
|
|
@@ -24635,13 +24995,13 @@ function StepIndicator$1({ currentStep, useAccessAuth }) {
|
|
|
24635
24995
|
});
|
|
24636
24996
|
}
|
|
24637
24997
|
function SetupWizard() {
|
|
24638
|
-
const [currentStep, setCurrentStep] = React.useState("site");
|
|
24639
|
-
const [_siteData, setSiteData] = React.useState(null);
|
|
24640
|
-
const [adminData, setAdminData] = React.useState(null);
|
|
24641
|
-
const [error, setError] = React.useState();
|
|
24642
|
-
const [urlError, setUrlError] = React.useState(null);
|
|
24998
|
+
const [currentStep, setCurrentStep] = React$1.useState("site");
|
|
24999
|
+
const [_siteData, setSiteData] = React$1.useState(null);
|
|
25000
|
+
const [adminData, setAdminData] = React$1.useState(null);
|
|
25001
|
+
const [error, setError] = React$1.useState();
|
|
25002
|
+
const [urlError, setUrlError] = React$1.useState(null);
|
|
24643
25003
|
const authProviderList = useAuthProviderList();
|
|
24644
|
-
React.useEffect(() => {
|
|
25004
|
+
React$1.useEffect(() => {
|
|
24645
25005
|
const params = new URLSearchParams(window.location.search);
|
|
24646
25006
|
const errorParam = params.get("error");
|
|
24647
25007
|
const message = params.get("message");
|
|
@@ -24826,8 +25186,8 @@ const IS_MAC = typeof navigator !== "undefined" && /Mac|iPhone|iPad|iPod/.test(n
|
|
|
24826
25186
|
* Custom hook for debouncing a value
|
|
24827
25187
|
*/
|
|
24828
25188
|
function useDebouncedValue(value, delay) {
|
|
24829
|
-
const [debouncedValue, setDebouncedValue] = React.useState(value);
|
|
24830
|
-
React.useEffect(() => {
|
|
25189
|
+
const [debouncedValue, setDebouncedValue] = React$1.useState(value);
|
|
25190
|
+
React$1.useEffect(() => {
|
|
24831
25191
|
const timer = setTimeout(() => {
|
|
24832
25192
|
setDebouncedValue(value);
|
|
24833
25193
|
}, delay);
|
|
@@ -25020,8 +25380,8 @@ function filterNavItems(items, query, translate) {
|
|
|
25020
25380
|
}
|
|
25021
25381
|
function AdminCommandPalette({ manifest }) {
|
|
25022
25382
|
const { _: _t } = useLingui();
|
|
25023
|
-
const [open, setOpen] = React.useState(false);
|
|
25024
|
-
const [query, setQuery] = React.useState("");
|
|
25383
|
+
const [open, setOpen] = React$1.useState(false);
|
|
25384
|
+
const [query, setQuery] = React$1.useState("");
|
|
25025
25385
|
const navigate = useNavigate$1();
|
|
25026
25386
|
const debouncedQuery = useDebouncedValue(query, SEARCH_DEBOUNCE_MS);
|
|
25027
25387
|
const { data: user } = useCurrentUser();
|
|
@@ -25033,13 +25393,13 @@ function AdminCommandPalette({ manifest }) {
|
|
|
25033
25393
|
staleTime: 30 * 1e3
|
|
25034
25394
|
});
|
|
25035
25395
|
const isPendingSearch = query.length >= 2 && query !== debouncedQuery || isSearching;
|
|
25036
|
-
const allNavItems = React.useMemo(() => buildNavItems(manifest, userRole), [manifest, userRole]);
|
|
25037
|
-
const filteredNavItems = React.useMemo(() => filterNavItems(allNavItems, query, _t), [
|
|
25396
|
+
const allNavItems = React$1.useMemo(() => buildNavItems(manifest, userRole), [manifest, userRole]);
|
|
25397
|
+
const filteredNavItems = React$1.useMemo(() => filterNavItems(allNavItems, query, _t), [
|
|
25038
25398
|
allNavItems,
|
|
25039
25399
|
query,
|
|
25040
25400
|
_t
|
|
25041
25401
|
]);
|
|
25042
|
-
const resultGroups = React.useMemo(() => {
|
|
25402
|
+
const resultGroups = React$1.useMemo(() => {
|
|
25043
25403
|
const groups = [];
|
|
25044
25404
|
if (filteredNavItems.length > 0) groups.push({
|
|
25045
25405
|
id: "navigation",
|
|
@@ -25091,10 +25451,10 @@ function AdminCommandPalette({ manifest }) {
|
|
|
25091
25451
|
e.preventDefault();
|
|
25092
25452
|
setOpen(true);
|
|
25093
25453
|
});
|
|
25094
|
-
React.useEffect(() => {
|
|
25454
|
+
React$1.useEffect(() => {
|
|
25095
25455
|
if (!open) setQuery("");
|
|
25096
25456
|
}, [open]);
|
|
25097
|
-
const handleSelect = React.useCallback((item, options) => {
|
|
25457
|
+
const handleSelect = React$1.useCallback((item, options) => {
|
|
25098
25458
|
setOpen(false);
|
|
25099
25459
|
if (options.newTab) {
|
|
25100
25460
|
const path = item.params ? item.to.replace(ROUTE_PARAM_REGEX, (_, key) => item.params?.[key] ?? "") : item.to;
|
|
@@ -25104,7 +25464,7 @@ function AdminCommandPalette({ manifest }) {
|
|
|
25104
25464
|
params: item.params
|
|
25105
25465
|
});
|
|
25106
25466
|
}, [navigate]);
|
|
25107
|
-
const handleItemClick = React.useCallback((item, e) => {
|
|
25467
|
+
const handleItemClick = React$1.useCallback((item, e) => {
|
|
25108
25468
|
handleSelect(item, { newTab: e.metaKey || e.ctrlKey });
|
|
25109
25469
|
}, [handleSelect]);
|
|
25110
25470
|
return /* @__PURE__ */ jsxs(CommandPalette.Root, {
|
|
@@ -25688,7 +26048,7 @@ async function handleLogout() {
|
|
|
25688
26048
|
*/
|
|
25689
26049
|
function Header() {
|
|
25690
26050
|
const { _: _t } = useLingui();
|
|
25691
|
-
const [userMenuOpen, setUserMenuOpen] = React.useState(false);
|
|
26051
|
+
const [userMenuOpen, setUserMenuOpen] = React$1.useState(false);
|
|
25692
26052
|
const { data: user } = useCurrentUser();
|
|
25693
26053
|
const displayName = user?.name || user?.email || _t({
|
|
25694
26054
|
id: "7PzzBU",
|
|
@@ -25991,9 +26351,9 @@ function WelcomeModal({ open, onClose, userName, userRole }) {
|
|
|
25991
26351
|
* handling collapse state, mobile detection, and layout transitions.
|
|
25992
26352
|
*/
|
|
25993
26353
|
function Shell({ children, manifest }) {
|
|
25994
|
-
const [welcomeModalOpen, setWelcomeModalOpen] = React.useState(false);
|
|
26354
|
+
const [welcomeModalOpen, setWelcomeModalOpen] = React$1.useState(false);
|
|
25995
26355
|
const { data: user } = useCurrentUser();
|
|
25996
|
-
React.useEffect(() => {
|
|
26356
|
+
React$1.useEffect(() => {
|
|
25997
26357
|
if (user?.isFirstLogin) setWelcomeModalOpen(true);
|
|
25998
26358
|
}, [user?.isFirstLogin]);
|
|
25999
26359
|
return /* @__PURE__ */ jsxs(KumoSidebar.Provider, {
|
|
@@ -26039,8 +26399,8 @@ function Shell({ children, manifest }) {
|
|
|
26039
26399
|
*/
|
|
26040
26400
|
function EmailStep({ onSubmit, isLoading, error }) {
|
|
26041
26401
|
const { _: _t } = useLingui();
|
|
26042
|
-
const [email, setEmail] = React.useState("");
|
|
26043
|
-
const [validationError, setValidationError] = React.useState(null);
|
|
26402
|
+
const [email, setEmail] = React$1.useState("");
|
|
26403
|
+
const [validationError, setValidationError] = React$1.useState(null);
|
|
26044
26404
|
const handleSubmit = (e) => {
|
|
26045
26405
|
e.preventDefault();
|
|
26046
26406
|
setValidationError(null);
|
|
@@ -26200,7 +26560,7 @@ function handleSignupSuccess() {
|
|
|
26200
26560
|
}
|
|
26201
26561
|
function VerifyStep({ verifyResult, token, onBack: _onBack }) {
|
|
26202
26562
|
const { _: _t3 } = useLingui();
|
|
26203
|
-
const [name, setName] = React.useState("");
|
|
26563
|
+
const [name, setName] = React$1.useState("");
|
|
26204
26564
|
return /* @__PURE__ */ jsxs("div", {
|
|
26205
26565
|
className: "space-y-6",
|
|
26206
26566
|
children: [
|
|
@@ -26376,22 +26736,22 @@ function ErrorStep({ message, code, onRetry }) {
|
|
|
26376
26736
|
});
|
|
26377
26737
|
}
|
|
26378
26738
|
function SignupPage() {
|
|
26379
|
-
const [step, setStep] = React.useState("email");
|
|
26380
|
-
const [email, setEmail] = React.useState("");
|
|
26381
|
-
const [error, setError] = React.useState();
|
|
26382
|
-
const [errorCode, setErrorCode] = React.useState();
|
|
26383
|
-
const [isLoading, setIsLoading] = React.useState(false);
|
|
26384
|
-
const [verifyResult, setVerifyResult] = React.useState(null);
|
|
26385
|
-
const [token, setToken] = React.useState(null);
|
|
26386
|
-
const [resendCooldown, setResendCooldown] = React.useState(0);
|
|
26387
|
-
React.useEffect(() => {
|
|
26739
|
+
const [step, setStep] = React$1.useState("email");
|
|
26740
|
+
const [email, setEmail] = React$1.useState("");
|
|
26741
|
+
const [error, setError] = React$1.useState();
|
|
26742
|
+
const [errorCode, setErrorCode] = React$1.useState();
|
|
26743
|
+
const [isLoading, setIsLoading] = React$1.useState(false);
|
|
26744
|
+
const [verifyResult, setVerifyResult] = React$1.useState(null);
|
|
26745
|
+
const [token, setToken] = React$1.useState(null);
|
|
26746
|
+
const [resendCooldown, setResendCooldown] = React$1.useState(0);
|
|
26747
|
+
React$1.useEffect(() => {
|
|
26388
26748
|
const urlToken = new URLSearchParams(window.location.search).get("token");
|
|
26389
26749
|
if (urlToken) {
|
|
26390
26750
|
setToken(urlToken);
|
|
26391
26751
|
verifyToken(urlToken);
|
|
26392
26752
|
}
|
|
26393
26753
|
}, []);
|
|
26394
|
-
React.useEffect(() => {
|
|
26754
|
+
React$1.useEffect(() => {
|
|
26395
26755
|
if (resendCooldown > 0) {
|
|
26396
26756
|
const timer = setTimeout(() => setResendCooldown((c) => c - 1), 1e3);
|
|
26397
26757
|
return () => clearTimeout(timer);
|
|
@@ -26556,7 +26916,7 @@ function flattenTerms(terms) {
|
|
|
26556
26916
|
/**
|
|
26557
26917
|
* Term row component (recursive for hierarchy)
|
|
26558
26918
|
*/
|
|
26559
|
-
function TermRow({ term, level = 0, onEdit, onDelete }) {
|
|
26919
|
+
function TermRow({ term, level = 0, onEdit, onDelete, onTranslate, canTranslate }) {
|
|
26560
26920
|
const { _: _t } = useLingui();
|
|
26561
26921
|
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
|
|
26562
26922
|
className: "flex items-center gap-4 py-2 px-4 border-b hover:bg-kumo-tint/50",
|
|
@@ -26582,49 +26942,154 @@ function TermRow({ term, level = 0, onEdit, onDelete }) {
|
|
|
26582
26942
|
}),
|
|
26583
26943
|
/* @__PURE__ */ jsxs("div", {
|
|
26584
26944
|
className: "flex gap-2",
|
|
26585
|
-
children: [
|
|
26586
|
-
|
|
26587
|
-
|
|
26588
|
-
|
|
26589
|
-
|
|
26590
|
-
|
|
26591
|
-
|
|
26592
|
-
|
|
26593
|
-
|
|
26594
|
-
|
|
26595
|
-
|
|
26596
|
-
|
|
26597
|
-
|
|
26598
|
-
|
|
26599
|
-
|
|
26600
|
-
|
|
26601
|
-
|
|
26945
|
+
children: [
|
|
26946
|
+
canTranslate && onTranslate ? /* @__PURE__ */ jsx(Button, {
|
|
26947
|
+
variant: "ghost",
|
|
26948
|
+
size: "sm",
|
|
26949
|
+
"aria-label": _t({
|
|
26950
|
+
id: "Acyeiz",
|
|
26951
|
+
message: "Translate {0}",
|
|
26952
|
+
values: { 0: term.label }
|
|
26953
|
+
}),
|
|
26954
|
+
onClick: () => onTranslate(term),
|
|
26955
|
+
children: _t({
|
|
26956
|
+
id: "pi8x/S",
|
|
26957
|
+
message: "Translate"
|
|
26958
|
+
})
|
|
26959
|
+
}) : null,
|
|
26960
|
+
/* @__PURE__ */ jsx(Button, {
|
|
26961
|
+
variant: "ghost",
|
|
26962
|
+
size: "sm",
|
|
26963
|
+
"aria-label": _t({
|
|
26964
|
+
id: "N6j2JH",
|
|
26965
|
+
message: "Edit {0}",
|
|
26966
|
+
values: { 0: term.label }
|
|
26967
|
+
}),
|
|
26968
|
+
onClick: () => onEdit(term),
|
|
26969
|
+
children: /* @__PURE__ */ jsx(Pencil, { className: "w-4 h-4" })
|
|
26602
26970
|
}),
|
|
26603
|
-
|
|
26604
|
-
|
|
26605
|
-
|
|
26971
|
+
/* @__PURE__ */ jsx(Button, {
|
|
26972
|
+
variant: "ghost",
|
|
26973
|
+
size: "sm",
|
|
26974
|
+
"aria-label": _t({
|
|
26975
|
+
id: "Y2tU6I",
|
|
26976
|
+
message: "Delete {0}",
|
|
26977
|
+
values: { 0: term.label }
|
|
26978
|
+
}),
|
|
26979
|
+
onClick: () => onDelete(term),
|
|
26980
|
+
children: /* @__PURE__ */ jsx(Trash, { className: "w-4 h-4" })
|
|
26981
|
+
})
|
|
26982
|
+
]
|
|
26606
26983
|
})
|
|
26607
26984
|
]
|
|
26608
26985
|
}), term.children.map((child) => /* @__PURE__ */ jsx(TermRow, {
|
|
26609
26986
|
term: child,
|
|
26610
26987
|
level: level + 1,
|
|
26611
26988
|
onEdit,
|
|
26612
|
-
onDelete
|
|
26989
|
+
onDelete,
|
|
26990
|
+
onTranslate,
|
|
26991
|
+
canTranslate
|
|
26613
26992
|
}, child.id))] });
|
|
26614
26993
|
}
|
|
26615
26994
|
/**
|
|
26616
|
-
*
|
|
26995
|
+
* Dialog to pick a target locale for creating a term translation.
|
|
26617
26996
|
*/
|
|
26618
|
-
function
|
|
26997
|
+
function TranslateTermDialog({ term, taxonomyName, locales, activeLocale, isPending, error, onClose, onSubmit }) {
|
|
26619
26998
|
const { _: _t2 } = useLingui();
|
|
26999
|
+
const otherLocales = locales.filter((l) => l !== activeLocale);
|
|
27000
|
+
const [selected, setSelected] = React$1.useState(otherLocales[0] ?? "");
|
|
27001
|
+
return /* @__PURE__ */ jsx(Dialog.Root, {
|
|
27002
|
+
open: true,
|
|
27003
|
+
onOpenChange: (isOpen) => {
|
|
27004
|
+
if (!isOpen) onClose();
|
|
27005
|
+
},
|
|
27006
|
+
children: /* @__PURE__ */ jsxs(Dialog, {
|
|
27007
|
+
className: "p-6",
|
|
27008
|
+
size: "sm",
|
|
27009
|
+
children: [
|
|
27010
|
+
/* @__PURE__ */ jsxs("div", {
|
|
27011
|
+
className: "flex items-start justify-between gap-4 mb-4",
|
|
27012
|
+
children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(Dialog.Title, {
|
|
27013
|
+
className: "text-lg font-semibold",
|
|
27014
|
+
children: _t2({
|
|
27015
|
+
id: "aCu6FM",
|
|
27016
|
+
message: "Translate \"{0}\"",
|
|
27017
|
+
values: { 0: term.label }
|
|
27018
|
+
})
|
|
27019
|
+
}), /* @__PURE__ */ jsx(Dialog.Description, {
|
|
27020
|
+
className: "text-sm text-kumo-subtle",
|
|
27021
|
+
children: _t2({
|
|
27022
|
+
id: "J1hptc",
|
|
27023
|
+
message: "Taxonomy: {taxonomyName}",
|
|
27024
|
+
values: { taxonomyName }
|
|
27025
|
+
})
|
|
27026
|
+
})] }), /* @__PURE__ */ jsx(Dialog.Close, { render: (props) => /* @__PURE__ */ jsx(Button, {
|
|
27027
|
+
...props,
|
|
27028
|
+
variant: "ghost",
|
|
27029
|
+
shape: "square",
|
|
27030
|
+
"aria-label": _t2({
|
|
27031
|
+
id: "yz7wBu",
|
|
27032
|
+
message: "Close"
|
|
27033
|
+
}),
|
|
27034
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" })
|
|
27035
|
+
}) })]
|
|
27036
|
+
}),
|
|
27037
|
+
/* @__PURE__ */ jsxs("div", {
|
|
27038
|
+
className: "space-y-4 py-2",
|
|
27039
|
+
children: [/* @__PURE__ */ jsx(Select, {
|
|
27040
|
+
label: _t2({
|
|
27041
|
+
id: "qxt3cN",
|
|
27042
|
+
message: "Target locale"
|
|
27043
|
+
}),
|
|
27044
|
+
value: selected,
|
|
27045
|
+
onValueChange: (v) => setSelected(v ?? ""),
|
|
27046
|
+
items: Object.fromEntries(otherLocales.map((l) => [l, l.toUpperCase()])),
|
|
27047
|
+
children: otherLocales.map((l) => /* @__PURE__ */ jsx(Select.Option, {
|
|
27048
|
+
value: l,
|
|
27049
|
+
children: l.toUpperCase()
|
|
27050
|
+
}, l))
|
|
27051
|
+
}), /* @__PURE__ */ jsx(DialogError, { message: error ? error.message : null })]
|
|
27052
|
+
}),
|
|
27053
|
+
/* @__PURE__ */ jsxs("div", {
|
|
27054
|
+
className: "flex justify-end gap-2",
|
|
27055
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
27056
|
+
variant: "outline",
|
|
27057
|
+
type: "button",
|
|
27058
|
+
onClick: onClose,
|
|
27059
|
+
children: _t2({
|
|
27060
|
+
id: "dEgA5A",
|
|
27061
|
+
message: "Cancel"
|
|
27062
|
+
})
|
|
27063
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
27064
|
+
type: "button",
|
|
27065
|
+
disabled: !selected || isPending,
|
|
27066
|
+
onClick: () => onSubmit(selected),
|
|
27067
|
+
children: isPending ? _t2({
|
|
27068
|
+
id: "wvgKtH",
|
|
27069
|
+
message: "Translating..."
|
|
27070
|
+
}) : _t2({
|
|
27071
|
+
id: "pi8x/S",
|
|
27072
|
+
message: "Translate"
|
|
27073
|
+
})
|
|
27074
|
+
})]
|
|
27075
|
+
})
|
|
27076
|
+
]
|
|
27077
|
+
})
|
|
27078
|
+
});
|
|
27079
|
+
}
|
|
27080
|
+
/**
|
|
27081
|
+
* Term form dialog
|
|
27082
|
+
*/
|
|
27083
|
+
function TermFormDialog({ open, onClose, taxonomyName, taxonomyDef, term, allTerms, locale, i18n, onOpenTranslation }) {
|
|
27084
|
+
const { _: _t3 } = useLingui();
|
|
26620
27085
|
const queryClient = useQueryClient();
|
|
26621
|
-
const [label, setLabel] = React.useState(term?.label || "");
|
|
26622
|
-
const [slug, setSlug] = React.useState(term?.slug || "");
|
|
26623
|
-
const [parentId, setParentId] = React.useState(term?.parentId || "");
|
|
26624
|
-
const [description, setDescription] = React.useState(term?.description || "");
|
|
26625
|
-
const [autoSlug, setAutoSlug] = React.useState(!term);
|
|
26626
|
-
const [error, setError] = React.useState(null);
|
|
26627
|
-
React.useEffect(() => {
|
|
27086
|
+
const [label, setLabel] = React$1.useState(term?.label || "");
|
|
27087
|
+
const [slug, setSlug] = React$1.useState(term?.slug || "");
|
|
27088
|
+
const [parentId, setParentId] = React$1.useState(term?.parentId || "");
|
|
27089
|
+
const [description, setDescription] = React$1.useState(term?.description || "");
|
|
27090
|
+
const [autoSlug, setAutoSlug] = React$1.useState(!term);
|
|
27091
|
+
const [error, setError] = React$1.useState(null);
|
|
27092
|
+
React$1.useEffect(() => {
|
|
26628
27093
|
setLabel(term?.label || "");
|
|
26629
27094
|
setSlug(term?.slug || "");
|
|
26630
27095
|
setParentId(term?.parentId || "");
|
|
@@ -26632,7 +27097,7 @@ function TermFormDialog({ open, onClose, taxonomyName, taxonomyDef, term, allTer
|
|
|
26632
27097
|
setAutoSlug(!term);
|
|
26633
27098
|
setError(null);
|
|
26634
27099
|
}, [term]);
|
|
26635
|
-
React.useEffect(() => {
|
|
27100
|
+
React$1.useEffect(() => {
|
|
26636
27101
|
if (autoSlug && label) setSlug(slugify(label));
|
|
26637
27102
|
}, [label, autoSlug]);
|
|
26638
27103
|
const createMutation = useMutation({
|
|
@@ -26640,7 +27105,8 @@ function TermFormDialog({ open, onClose, taxonomyName, taxonomyDef, term, allTer
|
|
|
26640
27105
|
slug,
|
|
26641
27106
|
label,
|
|
26642
27107
|
parentId: parentId || void 0,
|
|
26643
|
-
description: description || void 0
|
|
27108
|
+
description: description || void 0,
|
|
27109
|
+
locale
|
|
26644
27110
|
}),
|
|
26645
27111
|
onSuccess: () => {
|
|
26646
27112
|
queryClient.invalidateQueries({ queryKey: ["taxonomy-terms", taxonomyName] });
|
|
@@ -26658,7 +27124,7 @@ function TermFormDialog({ open, onClose, taxonomyName, taxonomyDef, term, allTer
|
|
|
26658
27124
|
label,
|
|
26659
27125
|
parentId: parentId || void 0,
|
|
26660
27126
|
description: description || void 0
|
|
26661
|
-
});
|
|
27127
|
+
}, { locale: term.locale ?? locale });
|
|
26662
27128
|
},
|
|
26663
27129
|
onSuccess: () => {
|
|
26664
27130
|
queryClient.invalidateQueries({ queryKey: ["taxonomy-terms", taxonomyName] });
|
|
@@ -26668,6 +27134,40 @@ function TermFormDialog({ open, onClose, taxonomyName, taxonomyDef, term, allTer
|
|
|
26668
27134
|
setError(err.message);
|
|
26669
27135
|
}
|
|
26670
27136
|
});
|
|
27137
|
+
const { data: translationsData } = useQuery({
|
|
27138
|
+
queryKey: [
|
|
27139
|
+
"term-translations",
|
|
27140
|
+
taxonomyName,
|
|
27141
|
+
term?.id ?? null
|
|
27142
|
+
],
|
|
27143
|
+
queryFn: () => {
|
|
27144
|
+
if (!term) throw new Error("No term");
|
|
27145
|
+
return fetchTermTranslations(taxonomyName, term.slug, { locale: term.locale ?? locale });
|
|
27146
|
+
},
|
|
27147
|
+
enabled: !!term && !!i18n && i18n.locales.length > 1
|
|
27148
|
+
});
|
|
27149
|
+
const translateMutation = useMutation({
|
|
27150
|
+
mutationFn: (targetLocale) => {
|
|
27151
|
+
if (!term) throw new Error("No term");
|
|
27152
|
+
return createTermTranslation(taxonomyName, term.slug, {
|
|
27153
|
+
locale: targetLocale,
|
|
27154
|
+
label: term.label,
|
|
27155
|
+
slug: term.slug
|
|
27156
|
+
}, { locale: term.locale ?? locale });
|
|
27157
|
+
},
|
|
27158
|
+
onSuccess: (translated) => {
|
|
27159
|
+
queryClient.invalidateQueries({ queryKey: ["taxonomy-terms", taxonomyName] });
|
|
27160
|
+
queryClient.invalidateQueries({ queryKey: ["term-translations", taxonomyName] });
|
|
27161
|
+
onClose();
|
|
27162
|
+
onOpenTranslation?.({
|
|
27163
|
+
slug: translated.slug,
|
|
27164
|
+
locale: translated.locale
|
|
27165
|
+
});
|
|
27166
|
+
},
|
|
27167
|
+
onError: (err) => {
|
|
27168
|
+
setError(err.message);
|
|
27169
|
+
}
|
|
27170
|
+
});
|
|
26671
27171
|
const handleSubmit = (e) => {
|
|
26672
27172
|
e.preventDefault();
|
|
26673
27173
|
setError(null);
|
|
@@ -26697,33 +27197,33 @@ function TermFormDialog({ open, onClose, taxonomyName, taxonomyDef, term, allTer
|
|
|
26697
27197
|
children: [/* @__PURE__ */ jsxs(Dialog.Title, {
|
|
26698
27198
|
className: "text-lg font-semibold leading-none tracking-tight",
|
|
26699
27199
|
children: [
|
|
26700
|
-
term ?
|
|
27200
|
+
term ? _t3({
|
|
26701
27201
|
id: "ePK91l",
|
|
26702
27202
|
message: "Edit"
|
|
26703
|
-
}) :
|
|
27203
|
+
}) : _t3({
|
|
26704
27204
|
id: "m16xKo",
|
|
26705
27205
|
message: "Add"
|
|
26706
27206
|
}),
|
|
26707
27207
|
" ",
|
|
26708
|
-
taxonomyDef.labelSingular ||
|
|
27208
|
+
taxonomyDef.labelSingular || _t3({
|
|
26709
27209
|
id: "k3xOSk",
|
|
26710
27210
|
message: "Term"
|
|
26711
27211
|
})
|
|
26712
27212
|
]
|
|
26713
27213
|
}), /* @__PURE__ */ jsx(Dialog.Description, {
|
|
26714
27214
|
className: "text-sm text-kumo-subtle",
|
|
26715
|
-
children: term ?
|
|
27215
|
+
children: term ? _t3({
|
|
26716
27216
|
id: "EWH8E/",
|
|
26717
27217
|
message: "Update the {0} details",
|
|
26718
27218
|
values: { 0: taxonomyDef.labelSingular?.toLowerCase() || "term" }
|
|
26719
|
-
}) :
|
|
27219
|
+
}) : _t3({
|
|
26720
27220
|
id: "bwUFyt",
|
|
26721
27221
|
message: "Create a new {0}",
|
|
26722
27222
|
values: { 0: taxonomyDef.labelSingular?.toLowerCase() || "term" }
|
|
26723
27223
|
})
|
|
26724
27224
|
})]
|
|
26725
27225
|
}), /* @__PURE__ */ jsx(Dialog.Close, {
|
|
26726
|
-
"aria-label":
|
|
27226
|
+
"aria-label": _t3({
|
|
26727
27227
|
id: "yz7wBu",
|
|
26728
27228
|
message: "Close"
|
|
26729
27229
|
}),
|
|
@@ -26731,14 +27231,14 @@ function TermFormDialog({ open, onClose, taxonomyName, taxonomyDef, term, allTer
|
|
|
26731
27231
|
...props,
|
|
26732
27232
|
variant: "ghost",
|
|
26733
27233
|
shape: "square",
|
|
26734
|
-
"aria-label":
|
|
27234
|
+
"aria-label": _t3({
|
|
26735
27235
|
id: "yz7wBu",
|
|
26736
27236
|
message: "Close"
|
|
26737
27237
|
}),
|
|
26738
27238
|
className: "absolute end-4 top-4",
|
|
26739
27239
|
children: [/* @__PURE__ */ jsx(X, { className: "h-4 w-4" }), /* @__PURE__ */ jsx("span", {
|
|
26740
27240
|
className: "sr-only",
|
|
26741
|
-
children:
|
|
27241
|
+
children: _t3({
|
|
26742
27242
|
id: "yz7wBu",
|
|
26743
27243
|
message: "Close"
|
|
26744
27244
|
})
|
|
@@ -26750,7 +27250,7 @@ function TermFormDialog({ open, onClose, taxonomyName, taxonomyDef, term, allTer
|
|
|
26750
27250
|
className: "space-y-4 py-4",
|
|
26751
27251
|
children: [
|
|
26752
27252
|
/* @__PURE__ */ jsx(Input, {
|
|
26753
|
-
label:
|
|
27253
|
+
label: _t3({
|
|
26754
27254
|
id: "6YtxFj",
|
|
26755
27255
|
message: "Name"
|
|
26756
27256
|
}),
|
|
@@ -26760,7 +27260,7 @@ function TermFormDialog({ open, onClose, taxonomyName, taxonomyDef, term, allTer
|
|
|
26760
27260
|
required: true
|
|
26761
27261
|
}),
|
|
26762
27262
|
/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(Input, {
|
|
26763
|
-
label:
|
|
27263
|
+
label: _t3({
|
|
26764
27264
|
id: "L85WcV",
|
|
26765
27265
|
message: "Slug"
|
|
26766
27266
|
}),
|
|
@@ -26773,20 +27273,20 @@ function TermFormDialog({ open, onClose, taxonomyName, taxonomyDef, term, allTer
|
|
|
26773
27273
|
required: true
|
|
26774
27274
|
}), /* @__PURE__ */ jsx("p", {
|
|
26775
27275
|
className: "text-sm text-kumo-subtle mt-1",
|
|
26776
|
-
children:
|
|
27276
|
+
children: _t3({
|
|
26777
27277
|
id: "WA0tbJ",
|
|
26778
27278
|
message: "Auto-generated from name (you can edit)"
|
|
26779
27279
|
})
|
|
26780
27280
|
})] }),
|
|
26781
27281
|
taxonomyDef.hierarchical && /* @__PURE__ */ jsxs(Select, {
|
|
26782
|
-
label:
|
|
27282
|
+
label: _t3({
|
|
26783
27283
|
id: "sujToP",
|
|
26784
27284
|
message: "Parent"
|
|
26785
27285
|
}),
|
|
26786
27286
|
value: parentId,
|
|
26787
27287
|
onValueChange: (v) => setParentId(v ?? ""),
|
|
26788
27288
|
items: {
|
|
26789
|
-
"":
|
|
27289
|
+
"": _t3({
|
|
26790
27290
|
id: "0KpSnU",
|
|
26791
27291
|
message: "None (top level)"
|
|
26792
27292
|
}),
|
|
@@ -26794,7 +27294,7 @@ function TermFormDialog({ open, onClose, taxonomyName, taxonomyDef, term, allTer
|
|
|
26794
27294
|
},
|
|
26795
27295
|
children: [/* @__PURE__ */ jsx(Select.Option, {
|
|
26796
27296
|
value: "",
|
|
26797
|
-
children:
|
|
27297
|
+
children: _t3({
|
|
26798
27298
|
id: "0KpSnU",
|
|
26799
27299
|
message: "None (top level)"
|
|
26800
27300
|
})
|
|
@@ -26804,19 +27304,37 @@ function TermFormDialog({ open, onClose, taxonomyName, taxonomyDef, term, allTer
|
|
|
26804
27304
|
}, parentTerm.id))]
|
|
26805
27305
|
}),
|
|
26806
27306
|
/* @__PURE__ */ jsx(InputArea, {
|
|
26807
|
-
label:
|
|
27307
|
+
label: _t3({
|
|
26808
27308
|
id: "Fxf4jq",
|
|
26809
27309
|
message: "Description (optional)"
|
|
26810
27310
|
}),
|
|
26811
27311
|
value: description,
|
|
26812
27312
|
onChange: (e) => setDescription(e.target.value),
|
|
26813
|
-
placeholder:
|
|
27313
|
+
placeholder: _t3({
|
|
26814
27314
|
id: "pbzA+s",
|
|
26815
27315
|
message: "Optional description"
|
|
26816
27316
|
}),
|
|
26817
27317
|
rows: 3
|
|
26818
27318
|
}),
|
|
26819
|
-
/* @__PURE__ */ jsx(DialogError, { message: error || getMutationError(createMutation.error) || getMutationError(updateMutation.error) })
|
|
27319
|
+
/* @__PURE__ */ jsx(DialogError, { message: error || getMutationError(createMutation.error) || getMutationError(updateMutation.error) || getMutationError(translateMutation.error) }),
|
|
27320
|
+
term && i18n && i18n.locales.length > 1 ? /* @__PURE__ */ jsx("div", {
|
|
27321
|
+
className: "pt-4 border-t",
|
|
27322
|
+
children: /* @__PURE__ */ jsx(TranslationsPanel, {
|
|
27323
|
+
locales: i18n.locales,
|
|
27324
|
+
defaultLocale: i18n.defaultLocale,
|
|
27325
|
+
currentLocale: term.locale,
|
|
27326
|
+
translations: translationsData?.translations ?? [],
|
|
27327
|
+
onOpen: (tr) => {
|
|
27328
|
+
onClose();
|
|
27329
|
+
onOpenTranslation?.({
|
|
27330
|
+
slug: term.slug,
|
|
27331
|
+
locale: tr.locale
|
|
27332
|
+
});
|
|
27333
|
+
},
|
|
27334
|
+
onCreate: (target) => translateMutation.mutate(target),
|
|
27335
|
+
pendingLocale: translateMutation.isPending ? translateMutation.variables ?? null : null
|
|
27336
|
+
})
|
|
27337
|
+
}) : null
|
|
26820
27338
|
]
|
|
26821
27339
|
}),
|
|
26822
27340
|
/* @__PURE__ */ jsxs("div", {
|
|
@@ -26825,20 +27343,20 @@ function TermFormDialog({ open, onClose, taxonomyName, taxonomyDef, term, allTer
|
|
|
26825
27343
|
type: "button",
|
|
26826
27344
|
variant: "outline",
|
|
26827
27345
|
onClick: onClose,
|
|
26828
|
-
children:
|
|
27346
|
+
children: _t3({
|
|
26829
27347
|
id: "dEgA5A",
|
|
26830
27348
|
message: "Cancel"
|
|
26831
27349
|
})
|
|
26832
27350
|
}), /* @__PURE__ */ jsx(Button, {
|
|
26833
27351
|
type: "submit",
|
|
26834
27352
|
disabled: createMutation.isPending || updateMutation.isPending,
|
|
26835
|
-
children: createMutation.isPending || updateMutation.isPending ?
|
|
27353
|
+
children: createMutation.isPending || updateMutation.isPending ? _t3({
|
|
26836
27354
|
id: "XvjC4F",
|
|
26837
27355
|
message: "Saving..."
|
|
26838
|
-
}) : term ?
|
|
27356
|
+
}) : term ? _t3({
|
|
26839
27357
|
id: "EkH9pt",
|
|
26840
27358
|
message: "Update"
|
|
26841
|
-
}) :
|
|
27359
|
+
}) : _t3({
|
|
26842
27360
|
id: "hYgDIe",
|
|
26843
27361
|
message: "Create"
|
|
26844
27362
|
})
|
|
@@ -26853,14 +27371,14 @@ function TermFormDialog({ open, onClose, taxonomyName, taxonomyDef, term, allTer
|
|
|
26853
27371
|
* Create Taxonomy dialog
|
|
26854
27372
|
*/
|
|
26855
27373
|
function CreateTaxonomyDialog({ open, onClose, onCreated }) {
|
|
26856
|
-
const { _:
|
|
27374
|
+
const { _: _t4 } = useLingui();
|
|
26857
27375
|
const queryClient = useQueryClient();
|
|
26858
|
-
const [name, setName] = React.useState("");
|
|
26859
|
-
const [label, setLabel] = React.useState("");
|
|
26860
|
-
const [hierarchical, setHierarchical] = React.useState(false);
|
|
26861
|
-
const [selectedCollections, setSelectedCollections] = React.useState([]);
|
|
26862
|
-
const [autoName, setAutoName] = React.useState(true);
|
|
26863
|
-
const [error, setError] = React.useState(null);
|
|
27376
|
+
const [name, setName] = React$1.useState("");
|
|
27377
|
+
const [label, setLabel] = React$1.useState("");
|
|
27378
|
+
const [hierarchical, setHierarchical] = React$1.useState(false);
|
|
27379
|
+
const [selectedCollections, setSelectedCollections] = React$1.useState([]);
|
|
27380
|
+
const [autoName, setAutoName] = React$1.useState(true);
|
|
27381
|
+
const [error, setError] = React$1.useState(null);
|
|
26864
27382
|
const { data: manifest } = useQuery({
|
|
26865
27383
|
queryKey: ["manifest"],
|
|
26866
27384
|
queryFn: fetchManifest
|
|
@@ -26869,7 +27387,7 @@ function CreateTaxonomyDialog({ open, onClose, onCreated }) {
|
|
|
26869
27387
|
slug,
|
|
26870
27388
|
label: config.label
|
|
26871
27389
|
})) : [];
|
|
26872
|
-
React.useEffect(() => {
|
|
27390
|
+
React$1.useEffect(() => {
|
|
26873
27391
|
if (autoName && label) setName(label.toLowerCase().replace(NON_ALPHANUMERIC_PATTERN, "_").replace(LEADING_TRAILING_UNDERSCORE_PATTERN, ""));
|
|
26874
27392
|
}, [label, autoName]);
|
|
26875
27393
|
const createMutation = useMutation({
|
|
@@ -26894,14 +27412,14 @@ function CreateTaxonomyDialog({ open, onClose, onCreated }) {
|
|
|
26894
27412
|
e.preventDefault();
|
|
26895
27413
|
setError(null);
|
|
26896
27414
|
if (!name || !label) {
|
|
26897
|
-
setError(
|
|
27415
|
+
setError(_t4({
|
|
26898
27416
|
id: "6RLorB",
|
|
26899
27417
|
message: "Name and label are required"
|
|
26900
27418
|
}));
|
|
26901
27419
|
return;
|
|
26902
27420
|
}
|
|
26903
27421
|
if (!TAXONOMY_NAME_PATTERN.test(name)) {
|
|
26904
|
-
setError(
|
|
27422
|
+
setError(_t4({
|
|
26905
27423
|
id: "rpb1yP",
|
|
26906
27424
|
message: "Name must start with a letter and contain only lowercase letters, numbers, and underscores"
|
|
26907
27425
|
}));
|
|
@@ -26937,19 +27455,19 @@ function CreateTaxonomyDialog({ open, onClose, onCreated }) {
|
|
|
26937
27455
|
className: "flex flex-col space-y-1.5",
|
|
26938
27456
|
children: [/* @__PURE__ */ jsx(Dialog.Title, {
|
|
26939
27457
|
className: "text-lg font-semibold leading-none tracking-tight",
|
|
26940
|
-
children:
|
|
27458
|
+
children: _t4({
|
|
26941
27459
|
id: "xOmArx",
|
|
26942
27460
|
message: "Create Taxonomy"
|
|
26943
27461
|
})
|
|
26944
27462
|
}), /* @__PURE__ */ jsx(Dialog.Description, {
|
|
26945
27463
|
className: "text-sm text-kumo-subtle",
|
|
26946
|
-
children:
|
|
27464
|
+
children: _t4({
|
|
26947
27465
|
id: "piag2l",
|
|
26948
27466
|
message: "Define a new taxonomy for classifying content"
|
|
26949
27467
|
})
|
|
26950
27468
|
})]
|
|
26951
27469
|
}), /* @__PURE__ */ jsx(Dialog.Close, {
|
|
26952
|
-
"aria-label":
|
|
27470
|
+
"aria-label": _t4({
|
|
26953
27471
|
id: "yz7wBu",
|
|
26954
27472
|
message: "Close"
|
|
26955
27473
|
}),
|
|
@@ -26957,14 +27475,14 @@ function CreateTaxonomyDialog({ open, onClose, onCreated }) {
|
|
|
26957
27475
|
...props,
|
|
26958
27476
|
variant: "ghost",
|
|
26959
27477
|
shape: "square",
|
|
26960
|
-
"aria-label":
|
|
27478
|
+
"aria-label": _t4({
|
|
26961
27479
|
id: "yz7wBu",
|
|
26962
27480
|
message: "Close"
|
|
26963
27481
|
}),
|
|
26964
27482
|
className: "absolute end-4 top-4",
|
|
26965
27483
|
children: [/* @__PURE__ */ jsx(X, { className: "h-4 w-4" }), /* @__PURE__ */ jsx("span", {
|
|
26966
27484
|
className: "sr-only",
|
|
26967
|
-
children:
|
|
27485
|
+
children: _t4({
|
|
26968
27486
|
id: "yz7wBu",
|
|
26969
27487
|
message: "Close"
|
|
26970
27488
|
})
|
|
@@ -26976,7 +27494,7 @@ function CreateTaxonomyDialog({ open, onClose, onCreated }) {
|
|
|
26976
27494
|
className: "space-y-4 py-4",
|
|
26977
27495
|
children: [
|
|
26978
27496
|
/* @__PURE__ */ jsx(Input, {
|
|
26979
|
-
label:
|
|
27497
|
+
label: _t4({
|
|
26980
27498
|
id: "87a/t/",
|
|
26981
27499
|
message: "Label"
|
|
26982
27500
|
}),
|
|
@@ -26986,7 +27504,7 @@ function CreateTaxonomyDialog({ open, onClose, onCreated }) {
|
|
|
26986
27504
|
required: true
|
|
26987
27505
|
}),
|
|
26988
27506
|
/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(Input, {
|
|
26989
|
-
label:
|
|
27507
|
+
label: _t4({
|
|
26990
27508
|
id: "6YtxFj",
|
|
26991
27509
|
message: "Name"
|
|
26992
27510
|
}),
|
|
@@ -26998,19 +27516,19 @@ function CreateTaxonomyDialog({ open, onClose, onCreated }) {
|
|
|
26998
27516
|
placeholder: "genre",
|
|
26999
27517
|
required: true,
|
|
27000
27518
|
pattern: "[a-z][a-z0-9_]*",
|
|
27001
|
-
title:
|
|
27519
|
+
title: _t4({
|
|
27002
27520
|
id: "vVZq2l",
|
|
27003
27521
|
message: "Lowercase letters, numbers, and underscores only, starting with a letter"
|
|
27004
27522
|
})
|
|
27005
27523
|
}), /* @__PURE__ */ jsx("p", {
|
|
27006
27524
|
className: "text-xs text-kumo-subtle mt-1",
|
|
27007
|
-
children:
|
|
27525
|
+
children: _t4({
|
|
27008
27526
|
id: "eEF9iG",
|
|
27009
27527
|
message: "Used as the identifier. Lowercase letters, numbers, and underscores only."
|
|
27010
27528
|
})
|
|
27011
27529
|
})] }),
|
|
27012
27530
|
/* @__PURE__ */ jsx(Checkbox, {
|
|
27013
|
-
label:
|
|
27531
|
+
label: _t4({
|
|
27014
27532
|
id: "BUeYF7",
|
|
27015
27533
|
message: "Hierarchical (like categories, with parent/child relationships)"
|
|
27016
27534
|
}),
|
|
@@ -27020,14 +27538,14 @@ function CreateTaxonomyDialog({ open, onClose, onCreated }) {
|
|
|
27020
27538
|
collectionEntries.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
27021
27539
|
/* @__PURE__ */ jsx("label", {
|
|
27022
27540
|
className: "text-sm font-medium",
|
|
27023
|
-
children:
|
|
27541
|
+
children: _t4({
|
|
27024
27542
|
id: "DoJzLz",
|
|
27025
27543
|
message: "Collections"
|
|
27026
27544
|
})
|
|
27027
27545
|
}),
|
|
27028
27546
|
/* @__PURE__ */ jsx("p", {
|
|
27029
27547
|
className: "text-xs text-kumo-subtle mb-2",
|
|
27030
|
-
children:
|
|
27548
|
+
children: _t4({
|
|
27031
27549
|
id: "STKTcL",
|
|
27032
27550
|
message: "Which content types can use this taxonomy"
|
|
27033
27551
|
})
|
|
@@ -27060,17 +27578,17 @@ function CreateTaxonomyDialog({ open, onClose, onCreated }) {
|
|
|
27060
27578
|
resetForm();
|
|
27061
27579
|
onClose();
|
|
27062
27580
|
},
|
|
27063
|
-
children:
|
|
27581
|
+
children: _t4({
|
|
27064
27582
|
id: "dEgA5A",
|
|
27065
27583
|
message: "Cancel"
|
|
27066
27584
|
})
|
|
27067
27585
|
}), /* @__PURE__ */ jsx(Button, {
|
|
27068
27586
|
type: "submit",
|
|
27069
27587
|
disabled: createMutation.isPending,
|
|
27070
|
-
children: createMutation.isPending ?
|
|
27588
|
+
children: createMutation.isPending ? _t4({
|
|
27071
27589
|
id: "HM56Bx",
|
|
27072
27590
|
message: "Creating..."
|
|
27073
|
-
}) :
|
|
27591
|
+
}) : _t4({
|
|
27074
27592
|
id: "xOmArx",
|
|
27075
27593
|
message: "Create Taxonomy"
|
|
27076
27594
|
})
|
|
@@ -27085,32 +27603,72 @@ function CreateTaxonomyDialog({ open, onClose, onCreated }) {
|
|
|
27085
27603
|
* Main TaxonomyManager component
|
|
27086
27604
|
*/
|
|
27087
27605
|
function TaxonomyManager({ taxonomyName }) {
|
|
27088
|
-
const { _:
|
|
27606
|
+
const { _: _t5 } = useLingui();
|
|
27089
27607
|
const queryClient = useQueryClient();
|
|
27090
27608
|
const toastManager = Toast.useToastManager();
|
|
27091
|
-
const [formOpen, setFormOpen] = React.useState(false);
|
|
27092
|
-
const [editingTerm, setEditingTerm] = React.useState();
|
|
27093
|
-
const [deleteTarget, setDeleteTarget] = React.useState(null);
|
|
27094
|
-
const [createTaxonomyOpen, setCreateTaxonomyOpen] = React.useState(false);
|
|
27609
|
+
const [formOpen, setFormOpen] = React$1.useState(false);
|
|
27610
|
+
const [editingTerm, setEditingTerm] = React$1.useState();
|
|
27611
|
+
const [deleteTarget, setDeleteTarget] = React$1.useState(null);
|
|
27612
|
+
const [createTaxonomyOpen, setCreateTaxonomyOpen] = React$1.useState(false);
|
|
27613
|
+
const [translateTarget, setTranslateTarget] = React$1.useState(null);
|
|
27614
|
+
const { data: manifest } = useQuery({
|
|
27615
|
+
queryKey: ["manifest"],
|
|
27616
|
+
queryFn: fetchManifest
|
|
27617
|
+
});
|
|
27618
|
+
const i18n = useI18nConfig(manifest);
|
|
27619
|
+
const [activeLocale, setActiveLocale] = React$1.useState(void 0);
|
|
27620
|
+
React$1.useEffect(() => {
|
|
27621
|
+
if (i18n && !activeLocale) setActiveLocale(i18n.defaultLocale);
|
|
27622
|
+
}, [i18n, activeLocale]);
|
|
27095
27623
|
const { data: taxonomyDef, isLoading: defLoading } = useQuery({
|
|
27096
27624
|
queryKey: ["taxonomy-def", taxonomyName],
|
|
27097
27625
|
queryFn: () => fetchTaxonomyDef(taxonomyName)
|
|
27098
27626
|
});
|
|
27099
27627
|
const { data: terms = [], isLoading: termsLoading } = useQuery({
|
|
27100
|
-
queryKey: [
|
|
27101
|
-
|
|
27628
|
+
queryKey: [
|
|
27629
|
+
"taxonomy-terms",
|
|
27630
|
+
taxonomyName,
|
|
27631
|
+
activeLocale
|
|
27632
|
+
],
|
|
27633
|
+
queryFn: () => fetchTerms(taxonomyName, { locale: activeLocale })
|
|
27102
27634
|
});
|
|
27103
27635
|
const deleteMutation = useMutation({
|
|
27104
|
-
mutationFn: (term) => deleteTerm(taxonomyName, term.slug),
|
|
27636
|
+
mutationFn: (term) => deleteTerm(taxonomyName, term.slug, { locale: activeLocale }),
|
|
27105
27637
|
onSuccess: () => {
|
|
27106
27638
|
queryClient.invalidateQueries({ queryKey: ["taxonomy-terms", taxonomyName] });
|
|
27107
27639
|
setDeleteTarget(null);
|
|
27108
|
-
toastManager.add({ title:
|
|
27640
|
+
toastManager.add({ title: _t5({
|
|
27109
27641
|
id: "SXhLSY",
|
|
27110
27642
|
message: "Term deleted"
|
|
27111
27643
|
}) });
|
|
27112
27644
|
}
|
|
27113
27645
|
});
|
|
27646
|
+
const translateMutation = useMutation({
|
|
27647
|
+
mutationFn: ({ term, locale }) => createTermTranslation(taxonomyName, term.slug, {
|
|
27648
|
+
locale,
|
|
27649
|
+
label: term.label,
|
|
27650
|
+
slug: term.slug
|
|
27651
|
+
}, { locale: activeLocale }),
|
|
27652
|
+
onSuccess: (term) => {
|
|
27653
|
+
queryClient.invalidateQueries({ queryKey: ["taxonomy-terms", taxonomyName] });
|
|
27654
|
+
setTranslateTarget(null);
|
|
27655
|
+
setActiveLocale(term.locale);
|
|
27656
|
+
toastManager.add({
|
|
27657
|
+
title: _t5({
|
|
27658
|
+
id: "pBdGCu",
|
|
27659
|
+
message: "Translation created"
|
|
27660
|
+
}),
|
|
27661
|
+
description: _t5({
|
|
27662
|
+
id: "X974Zi",
|
|
27663
|
+
message: "Term \"{0}\" created in {1}.",
|
|
27664
|
+
values: {
|
|
27665
|
+
0: term.label,
|
|
27666
|
+
1: term.locale.toUpperCase()
|
|
27667
|
+
}
|
|
27668
|
+
})
|
|
27669
|
+
});
|
|
27670
|
+
}
|
|
27671
|
+
});
|
|
27114
27672
|
const handleEdit = (term) => {
|
|
27115
27673
|
setEditingTerm(term);
|
|
27116
27674
|
setFormOpen(true);
|
|
@@ -27122,12 +27680,12 @@ function TaxonomyManager({ taxonomyName }) {
|
|
|
27122
27680
|
setFormOpen(false);
|
|
27123
27681
|
setEditingTerm(void 0);
|
|
27124
27682
|
};
|
|
27125
|
-
if (defLoading) return /* @__PURE__ */ jsx("div", { children:
|
|
27683
|
+
if (defLoading) return /* @__PURE__ */ jsx("div", { children: _t5({
|
|
27126
27684
|
id: "Z3FXyt",
|
|
27127
27685
|
message: "Loading..."
|
|
27128
27686
|
}) });
|
|
27129
27687
|
if (!taxonomyDef) return /* @__PURE__ */ jsxs("div", { children: [
|
|
27130
|
-
|
|
27688
|
+
_t5({
|
|
27131
27689
|
id: "8EXwpa",
|
|
27132
27690
|
message: "Taxonomy not found:"
|
|
27133
27691
|
}),
|
|
@@ -27139,13 +27697,13 @@ function TaxonomyManager({ taxonomyName }) {
|
|
|
27139
27697
|
className: "space-y-6",
|
|
27140
27698
|
children: [
|
|
27141
27699
|
/* @__PURE__ */ jsxs("div", {
|
|
27142
|
-
className: "flex items-center justify-between",
|
|
27700
|
+
className: "flex items-center justify-between gap-4 flex-wrap",
|
|
27143
27701
|
children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h1", {
|
|
27144
27702
|
className: "text-3xl font-bold",
|
|
27145
27703
|
children: taxonomyDef.label
|
|
27146
27704
|
}), /* @__PURE__ */ jsx("p", {
|
|
27147
27705
|
className: "text-kumo-subtle mt-1",
|
|
27148
|
-
children:
|
|
27706
|
+
children: _t5({
|
|
27149
27707
|
id: "H1WnmU",
|
|
27150
27708
|
message: "Manage {0} for {1}",
|
|
27151
27709
|
values: {
|
|
@@ -27154,30 +27712,39 @@ function TaxonomyManager({ taxonomyName }) {
|
|
|
27154
27712
|
}
|
|
27155
27713
|
})
|
|
27156
27714
|
})] }), /* @__PURE__ */ jsxs("div", {
|
|
27157
|
-
className: "flex gap-2",
|
|
27158
|
-
children: [
|
|
27159
|
-
|
|
27160
|
-
|
|
27161
|
-
|
|
27162
|
-
|
|
27163
|
-
|
|
27164
|
-
|
|
27165
|
-
|
|
27166
|
-
|
|
27167
|
-
|
|
27168
|
-
|
|
27169
|
-
|
|
27170
|
-
|
|
27171
|
-
|
|
27172
|
-
message: "Add"
|
|
27173
|
-
}),
|
|
27174
|
-
" ",
|
|
27175
|
-
taxonomyDef.labelSingular || _t4({
|
|
27176
|
-
id: "k3xOSk",
|
|
27177
|
-
message: "Term"
|
|
27715
|
+
className: "flex gap-2 items-center",
|
|
27716
|
+
children: [
|
|
27717
|
+
i18n && activeLocale ? /* @__PURE__ */ jsx(LocaleSwitcher, {
|
|
27718
|
+
locales: i18n.locales,
|
|
27719
|
+
defaultLocale: i18n.defaultLocale,
|
|
27720
|
+
value: activeLocale,
|
|
27721
|
+
onChange: setActiveLocale
|
|
27722
|
+
}) : null,
|
|
27723
|
+
/* @__PURE__ */ jsx(Button, {
|
|
27724
|
+
variant: "outline",
|
|
27725
|
+
icon: /* @__PURE__ */ jsx(Plus, {}),
|
|
27726
|
+
onClick: () => setCreateTaxonomyOpen(true),
|
|
27727
|
+
children: _t5({
|
|
27728
|
+
id: "rrNQ2v",
|
|
27729
|
+
message: "New Taxonomy"
|
|
27178
27730
|
})
|
|
27179
|
-
|
|
27180
|
-
|
|
27731
|
+
}),
|
|
27732
|
+
/* @__PURE__ */ jsxs(Button, {
|
|
27733
|
+
icon: /* @__PURE__ */ jsx(Plus, {}),
|
|
27734
|
+
onClick: () => setFormOpen(true),
|
|
27735
|
+
children: [
|
|
27736
|
+
_t5({
|
|
27737
|
+
id: "m16xKo",
|
|
27738
|
+
message: "Add"
|
|
27739
|
+
}),
|
|
27740
|
+
" ",
|
|
27741
|
+
taxonomyDef.labelSingular || _t5({
|
|
27742
|
+
id: "k3xOSk",
|
|
27743
|
+
message: "Term"
|
|
27744
|
+
})
|
|
27745
|
+
]
|
|
27746
|
+
})
|
|
27747
|
+
]
|
|
27181
27748
|
})]
|
|
27182
27749
|
}),
|
|
27183
27750
|
/* @__PURE__ */ jsxs("div", {
|
|
@@ -27187,21 +27754,21 @@ function TaxonomyManager({ taxonomyName }) {
|
|
|
27187
27754
|
children: [
|
|
27188
27755
|
/* @__PURE__ */ jsx("div", {
|
|
27189
27756
|
className: "flex-1",
|
|
27190
|
-
children:
|
|
27757
|
+
children: _t5({
|
|
27191
27758
|
id: "6YtxFj",
|
|
27192
27759
|
message: "Name"
|
|
27193
27760
|
})
|
|
27194
27761
|
}),
|
|
27195
27762
|
/* @__PURE__ */ jsx("div", {
|
|
27196
27763
|
className: "w-16 text-center",
|
|
27197
|
-
children:
|
|
27764
|
+
children: _t5({
|
|
27198
27765
|
id: "wBMjJ2",
|
|
27199
27766
|
message: "Count"
|
|
27200
27767
|
})
|
|
27201
27768
|
}),
|
|
27202
27769
|
/* @__PURE__ */ jsx("div", {
|
|
27203
27770
|
className: "w-24 text-center",
|
|
27204
|
-
children:
|
|
27771
|
+
children: _t5({
|
|
27205
27772
|
id: "7L01XJ",
|
|
27206
27773
|
message: "Actions"
|
|
27207
27774
|
})
|
|
@@ -27209,13 +27776,13 @@ function TaxonomyManager({ taxonomyName }) {
|
|
|
27209
27776
|
]
|
|
27210
27777
|
}), termsLoading ? /* @__PURE__ */ jsx("div", {
|
|
27211
27778
|
className: "p-8 text-center text-kumo-subtle",
|
|
27212
|
-
children:
|
|
27779
|
+
children: _t5({
|
|
27213
27780
|
id: "x/4m9x",
|
|
27214
27781
|
message: "Loading terms..."
|
|
27215
27782
|
})
|
|
27216
27783
|
}) : terms.length === 0 ? /* @__PURE__ */ jsx("div", {
|
|
27217
27784
|
className: "p-8 text-center text-kumo-subtle",
|
|
27218
|
-
children:
|
|
27785
|
+
children: _t5({
|
|
27219
27786
|
id: "R3O8Io",
|
|
27220
27787
|
message: "No {0} yet. Create one to get started.",
|
|
27221
27788
|
values: { 0: taxonomyDef.label.toLowerCase() }
|
|
@@ -27223,7 +27790,9 @@ function TaxonomyManager({ taxonomyName }) {
|
|
|
27223
27790
|
}) : /* @__PURE__ */ jsx("div", { children: terms.map((term) => /* @__PURE__ */ jsx(TermRow, {
|
|
27224
27791
|
term,
|
|
27225
27792
|
onEdit: handleEdit,
|
|
27226
|
-
onDelete: handleDelete
|
|
27793
|
+
onDelete: handleDelete,
|
|
27794
|
+
onTranslate: setTranslateTarget,
|
|
27795
|
+
canTranslate: !!i18n && !!activeLocale && i18n.locales.length > 1
|
|
27227
27796
|
}, term.id)) })]
|
|
27228
27797
|
}),
|
|
27229
27798
|
/* @__PURE__ */ jsx(TermFormDialog, {
|
|
@@ -27232,29 +27801,48 @@ function TaxonomyManager({ taxonomyName }) {
|
|
|
27232
27801
|
taxonomyName,
|
|
27233
27802
|
taxonomyDef,
|
|
27234
27803
|
term: editingTerm,
|
|
27235
|
-
allTerms: flatTerms
|
|
27804
|
+
allTerms: flatTerms,
|
|
27805
|
+
locale: activeLocale,
|
|
27806
|
+
i18n,
|
|
27807
|
+
onOpenTranslation: (tr) => setActiveLocale(tr.locale)
|
|
27236
27808
|
}),
|
|
27809
|
+
i18n && translateTarget ? /* @__PURE__ */ jsx(TranslateTermDialog, {
|
|
27810
|
+
term: translateTarget,
|
|
27811
|
+
taxonomyName,
|
|
27812
|
+
locales: i18n.locales,
|
|
27813
|
+
activeLocale,
|
|
27814
|
+
isPending: translateMutation.isPending,
|
|
27815
|
+
error: translateMutation.error,
|
|
27816
|
+
onClose: () => {
|
|
27817
|
+
setTranslateTarget(null);
|
|
27818
|
+
translateMutation.reset();
|
|
27819
|
+
},
|
|
27820
|
+
onSubmit: (locale) => translateMutation.mutate({
|
|
27821
|
+
term: translateTarget,
|
|
27822
|
+
locale
|
|
27823
|
+
})
|
|
27824
|
+
}) : null,
|
|
27237
27825
|
/* @__PURE__ */ jsx(ConfirmDialog, {
|
|
27238
27826
|
open: !!deleteTarget,
|
|
27239
27827
|
onClose: () => {
|
|
27240
27828
|
setDeleteTarget(null);
|
|
27241
27829
|
deleteMutation.reset();
|
|
27242
27830
|
},
|
|
27243
|
-
title:
|
|
27831
|
+
title: _t5({
|
|
27244
27832
|
id: "Tf88pC",
|
|
27245
27833
|
message: "Delete {0}?",
|
|
27246
27834
|
values: { 0: taxonomyDef.labelSingular || "Term" }
|
|
27247
27835
|
}),
|
|
27248
|
-
description: /* @__PURE__ */ jsx(Fragment, { children:
|
|
27836
|
+
description: /* @__PURE__ */ jsx(Fragment, { children: _t5({
|
|
27249
27837
|
id: "JKi9lM",
|
|
27250
27838
|
message: "This will permanently delete \"{0}\" and remove it from all content.",
|
|
27251
27839
|
values: { 0: deleteTarget?.label }
|
|
27252
27840
|
}) }),
|
|
27253
|
-
confirmLabel:
|
|
27841
|
+
confirmLabel: _t5({
|
|
27254
27842
|
id: "cnGeoo",
|
|
27255
27843
|
message: "Delete"
|
|
27256
27844
|
}),
|
|
27257
|
-
pendingLabel:
|
|
27845
|
+
pendingLabel: _t5({
|
|
27258
27846
|
id: "EF2EU9",
|
|
27259
27847
|
message: "Deleting..."
|
|
27260
27848
|
}),
|
|
@@ -27267,7 +27855,7 @@ function TaxonomyManager({ taxonomyName }) {
|
|
|
27267
27855
|
onClose: () => setCreateTaxonomyOpen(false),
|
|
27268
27856
|
onCreated: () => {
|
|
27269
27857
|
setCreateTaxonomyOpen(false);
|
|
27270
|
-
toastManager.add({ title:
|
|
27858
|
+
toastManager.add({ title: _t5({
|
|
27271
27859
|
id: "pmEpis",
|
|
27272
27860
|
message: "Taxonomy created"
|
|
27273
27861
|
}) });
|
|
@@ -27300,10 +27888,10 @@ function isSortOption(value) {
|
|
|
27300
27888
|
}
|
|
27301
27889
|
function ThemeMarketplaceBrowse() {
|
|
27302
27890
|
const { _: _t } = useLingui();
|
|
27303
|
-
const [searchQuery, setSearchQuery] = React.useState("");
|
|
27304
|
-
const [sort, setSort] = React.useState("updated");
|
|
27305
|
-
const [debouncedQuery, setDebouncedQuery] = React.useState("");
|
|
27306
|
-
React.useEffect(() => {
|
|
27891
|
+
const [searchQuery, setSearchQuery] = React$1.useState("");
|
|
27892
|
+
const [sort, setSort] = React$1.useState("updated");
|
|
27893
|
+
const [debouncedQuery, setDebouncedQuery] = React$1.useState("");
|
|
27894
|
+
React$1.useEffect(() => {
|
|
27307
27895
|
const timer = setTimeout(setDebouncedQuery, 300, searchQuery);
|
|
27308
27896
|
return () => clearTimeout(timer);
|
|
27309
27897
|
}, [searchQuery]);
|
|
@@ -27569,7 +28157,7 @@ function isSafeUrl(url) {
|
|
|
27569
28157
|
}
|
|
27570
28158
|
function ThemeMarketplaceDetail({ themeId }) {
|
|
27571
28159
|
const { _: _t } = useLingui();
|
|
27572
|
-
const [lightboxIndex, setLightboxIndex] = React.useState(null);
|
|
28160
|
+
const [lightboxIndex, setLightboxIndex] = React$1.useState(null);
|
|
27573
28161
|
const { data: theme, isLoading, error } = useQuery({
|
|
27574
28162
|
queryKey: [
|
|
27575
28163
|
"themes",
|
|
@@ -27779,7 +28367,7 @@ function ThemeMarketplaceDetail({ themeId }) {
|
|
|
27779
28367
|
}
|
|
27780
28368
|
function Lightbox({ urls, index, onClose, onPrev, onNext }) {
|
|
27781
28369
|
const { _: _t2 } = useLingui();
|
|
27782
|
-
React.useEffect(() => {
|
|
28370
|
+
React$1.useEffect(() => {
|
|
27783
28371
|
function onKeyDown(e) {
|
|
27784
28372
|
if (e.key === "Escape") onClose();
|
|
27785
28373
|
if (e.key === "ArrowLeft") onPrev();
|
|
@@ -27901,20 +28489,20 @@ function Widgets() {
|
|
|
27901
28489
|
const { _: _t } = useLingui();
|
|
27902
28490
|
const queryClient = useQueryClient();
|
|
27903
28491
|
const toastManager = Toast.useToastManager();
|
|
27904
|
-
const [isCreateAreaOpen, setIsCreateAreaOpen] = React.useState(false);
|
|
27905
|
-
const [createAreaError, setCreateAreaError] = React.useState(null);
|
|
27906
|
-
const [activeId, setActiveId] = React.useState(null);
|
|
27907
|
-
const [activeDragData, setActiveDragData] = React.useState(null);
|
|
27908
|
-
const [expandedWidgets, setExpandedWidgets] = React.useState(/* @__PURE__ */ new Set());
|
|
27909
|
-
const [blockSidebarPanel, setBlockSidebarPanel] = React.useState(null);
|
|
27910
|
-
const draggingFromPaletteRef = React.useRef(false);
|
|
27911
|
-
const handleBlockSidebarOpen = React.useCallback((panel) => {
|
|
28492
|
+
const [isCreateAreaOpen, setIsCreateAreaOpen] = React$1.useState(false);
|
|
28493
|
+
const [createAreaError, setCreateAreaError] = React$1.useState(null);
|
|
28494
|
+
const [activeId, setActiveId] = React$1.useState(null);
|
|
28495
|
+
const [activeDragData, setActiveDragData] = React$1.useState(null);
|
|
28496
|
+
const [expandedWidgets, setExpandedWidgets] = React$1.useState(/* @__PURE__ */ new Set());
|
|
28497
|
+
const [blockSidebarPanel, setBlockSidebarPanel] = React$1.useState(null);
|
|
28498
|
+
const draggingFromPaletteRef = React$1.useRef(false);
|
|
28499
|
+
const handleBlockSidebarOpen = React$1.useCallback((panel) => {
|
|
27912
28500
|
setBlockSidebarPanel((prev) => {
|
|
27913
28501
|
prev?.onClose();
|
|
27914
28502
|
return panel;
|
|
27915
28503
|
});
|
|
27916
28504
|
}, []);
|
|
27917
|
-
const handleBlockSidebarClose = React.useCallback(() => {
|
|
28505
|
+
const handleBlockSidebarClose = React$1.useCallback(() => {
|
|
27918
28506
|
setBlockSidebarPanel((prev) => {
|
|
27919
28507
|
prev?.onClose();
|
|
27920
28508
|
return null;
|
|
@@ -27932,7 +28520,7 @@ function Widgets() {
|
|
|
27932
28520
|
queryKey: ["manifest"],
|
|
27933
28521
|
queryFn: fetchManifest
|
|
27934
28522
|
});
|
|
27935
|
-
const pluginBlocks = React.useMemo(() => manifest ? getPluginBlocks(manifest) : [], [manifest]);
|
|
28523
|
+
const pluginBlocks = React$1.useMemo(() => manifest ? getPluginBlocks(manifest) : [], [manifest]);
|
|
27936
28524
|
const createAreaMutation = useMutation({
|
|
27937
28525
|
mutationFn: createWidgetArea,
|
|
27938
28526
|
onSuccess: () => {
|
|
@@ -27972,7 +28560,7 @@ function Widgets() {
|
|
|
27972
28560
|
});
|
|
27973
28561
|
};
|
|
27974
28562
|
const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 8 } }), useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }));
|
|
27975
|
-
const collisionDetection = React.useCallback((args) => {
|
|
28563
|
+
const collisionDetection = React$1.useCallback((args) => {
|
|
27976
28564
|
const dragData = args.active.data.current;
|
|
27977
28565
|
if (dragData && isPaletteItem(dragData)) {
|
|
27978
28566
|
const areaContainers = args.droppableContainers.filter((c) => String(c.id).startsWith("area:"));
|
|
@@ -28269,7 +28857,7 @@ function DraggablePaletteItem({ id, label, description, widgetInput }) {
|
|
|
28269
28857
|
function WidgetAreaPanel({ area, expandedWidgets, onToggleWidget, isDraggingPalette, components, pluginBlocks, onBlockSidebarOpen, onBlockSidebarClose }) {
|
|
28270
28858
|
const queryClient = useQueryClient();
|
|
28271
28859
|
const toastManager = Toast.useToastManager();
|
|
28272
|
-
const [deleteAreaName, setDeleteAreaName] = React.useState(null);
|
|
28860
|
+
const [deleteAreaName, setDeleteAreaName] = React$1.useState(null);
|
|
28273
28861
|
const { setNodeRef: setDropRef, isOver } = useDroppable({ id: `area:${area.name}` });
|
|
28274
28862
|
const deleteAreaMutation = useMutation({
|
|
28275
28863
|
mutationFn: deleteWidgetArea,
|
|
@@ -28444,14 +29032,14 @@ function WidgetItem({ widget, areaName, isExpanded, onToggle, components, plugin
|
|
|
28444
29032
|
}
|
|
28445
29033
|
/** Inline editor form for a widget, rendered when the widget is expanded */
|
|
28446
29034
|
function WidgetEditor({ widget, components, pluginBlocks, onSave, isSaving, onBlockSidebarOpen, onBlockSidebarClose }) {
|
|
28447
|
-
const [title, setTitle] = React.useState(widget.title ?? "");
|
|
28448
|
-
const [content, setContent] = React.useState(Array.isArray(widget.content) ? widget.content : []);
|
|
28449
|
-
const [menuName, setMenuName] = React.useState(widget.menuName ?? "");
|
|
28450
|
-
const [componentId, setComponentId] = React.useState(widget.componentId ?? "");
|
|
28451
|
-
const [componentProps, setComponentProps] = React.useState(widget.componentProps ?? {});
|
|
29035
|
+
const [title, setTitle] = React$1.useState(widget.title ?? "");
|
|
29036
|
+
const [content, setContent] = React$1.useState(Array.isArray(widget.content) ? widget.content : []);
|
|
29037
|
+
const [menuName, setMenuName] = React$1.useState(widget.menuName ?? "");
|
|
29038
|
+
const [componentId, setComponentId] = React$1.useState(widget.componentId ?? "");
|
|
29039
|
+
const [componentProps, setComponentProps] = React$1.useState(widget.componentProps ?? {});
|
|
28452
29040
|
const { data: menus = [] } = useQuery({
|
|
28453
29041
|
queryKey: ["menus"],
|
|
28454
|
-
queryFn: fetchMenus,
|
|
29042
|
+
queryFn: () => fetchMenus(),
|
|
28455
29043
|
enabled: widget.type === "menu"
|
|
28456
29044
|
});
|
|
28457
29045
|
const selectedComponent = components.find((c) => c.id === componentId);
|
|
@@ -28588,32 +29176,32 @@ function ComponentPropField({ def, value, onChange }) {
|
|
|
28588
29176
|
const TRAILING_SLASH_REGEX = /\/$/;
|
|
28589
29177
|
const WHITESPACE_REGEX = /\s/g;
|
|
28590
29178
|
function WordPressImport() {
|
|
28591
|
-
const [step, setStep] = React.useState("choose");
|
|
28592
|
-
const [urlInput, setUrlInput] = React.useState("");
|
|
28593
|
-
const [probeResult, setProbeResult] = React.useState(null);
|
|
28594
|
-
const [importSource, setImportSource] = React.useState(null);
|
|
28595
|
-
const [_file, setFile] = React.useState(null);
|
|
28596
|
-
const [analysis, setAnalysis] = React.useState(null);
|
|
28597
|
-
const [pluginUsername, setPluginUsername] = React.useState("");
|
|
28598
|
-
const [pluginPassword, setPluginPassword] = React.useState("");
|
|
28599
|
-
const [selections, setSelections] = React.useState({});
|
|
28600
|
-
const [prepareResult, setPrepareResult] = React.useState(null);
|
|
28601
|
-
const [result, setResult] = React.useState(null);
|
|
28602
|
-
const [expandedTypes, setExpandedTypes] = React.useState(/* @__PURE__ */ new Set());
|
|
28603
|
-
const [prepareError, setPrepareError] = React.useState(null);
|
|
28604
|
-
const [importError, setImportError] = React.useState(null);
|
|
28605
|
-
const [mediaResult, setMediaResult] = React.useState(null);
|
|
28606
|
-
const [rewriteResult, setRewriteResult] = React.useState(null);
|
|
28607
|
-
const [mediaError, setMediaError] = React.useState(null);
|
|
28608
|
-
const [skipMedia, setSkipMedia] = React.useState(false);
|
|
28609
|
-
const [mediaProgress, setMediaProgress] = React.useState(null);
|
|
28610
|
-
const [importMenus, setImportMenus] = React.useState(true);
|
|
28611
|
-
const [importSiteTitle, setImportSiteTitle] = React.useState(true);
|
|
28612
|
-
const [importLogo, setImportLogo] = React.useState(true);
|
|
28613
|
-
const [importSeo, setImportSeo] = React.useState(false);
|
|
28614
|
-
const [authorMappings, setAuthorMappings] = React.useState([]);
|
|
28615
|
-
const [emdashUsers, setEmDashUsers] = React.useState([]);
|
|
28616
|
-
const initializeAuthorMappings = React.useCallback((importAnalysis, users) => {
|
|
29179
|
+
const [step, setStep] = React$1.useState("choose");
|
|
29180
|
+
const [urlInput, setUrlInput] = React$1.useState("");
|
|
29181
|
+
const [probeResult, setProbeResult] = React$1.useState(null);
|
|
29182
|
+
const [importSource, setImportSource] = React$1.useState(null);
|
|
29183
|
+
const [_file, setFile] = React$1.useState(null);
|
|
29184
|
+
const [analysis, setAnalysis] = React$1.useState(null);
|
|
29185
|
+
const [pluginUsername, setPluginUsername] = React$1.useState("");
|
|
29186
|
+
const [pluginPassword, setPluginPassword] = React$1.useState("");
|
|
29187
|
+
const [selections, setSelections] = React$1.useState({});
|
|
29188
|
+
const [prepareResult, setPrepareResult] = React$1.useState(null);
|
|
29189
|
+
const [result, setResult] = React$1.useState(null);
|
|
29190
|
+
const [expandedTypes, setExpandedTypes] = React$1.useState(/* @__PURE__ */ new Set());
|
|
29191
|
+
const [prepareError, setPrepareError] = React$1.useState(null);
|
|
29192
|
+
const [importError, setImportError] = React$1.useState(null);
|
|
29193
|
+
const [mediaResult, setMediaResult] = React$1.useState(null);
|
|
29194
|
+
const [rewriteResult, setRewriteResult] = React$1.useState(null);
|
|
29195
|
+
const [mediaError, setMediaError] = React$1.useState(null);
|
|
29196
|
+
const [skipMedia, setSkipMedia] = React$1.useState(false);
|
|
29197
|
+
const [mediaProgress, setMediaProgress] = React$1.useState(null);
|
|
29198
|
+
const [importMenus, setImportMenus] = React$1.useState(true);
|
|
29199
|
+
const [importSiteTitle, setImportSiteTitle] = React$1.useState(true);
|
|
29200
|
+
const [importLogo, setImportLogo] = React$1.useState(true);
|
|
29201
|
+
const [importSeo, setImportSeo] = React$1.useState(false);
|
|
29202
|
+
const [authorMappings, setAuthorMappings] = React$1.useState([]);
|
|
29203
|
+
const [emdashUsers, setEmDashUsers] = React$1.useState([]);
|
|
29204
|
+
const initializeAuthorMappings = React$1.useCallback((importAnalysis, users) => {
|
|
28617
29205
|
setAuthorMappings(importAnalysis.authors.map((author) => {
|
|
28618
29206
|
const matchedUser = author.email ? users.find((u) => u.email.toLowerCase() === author.email?.toLowerCase()) : void 0;
|
|
28619
29207
|
return {
|
|
@@ -28625,7 +29213,7 @@ function WordPressImport() {
|
|
|
28625
29213
|
};
|
|
28626
29214
|
}));
|
|
28627
29215
|
}, []);
|
|
28628
|
-
React.useEffect(() => {
|
|
29216
|
+
React$1.useEffect(() => {
|
|
28629
29217
|
const params = new URLSearchParams(window.location.search);
|
|
28630
29218
|
const authStatus = params.get("auth");
|
|
28631
29219
|
if (params.get("error") === "auth_rejected") {
|
|
@@ -31163,12 +31751,12 @@ function getUserLabel(user) {
|
|
|
31163
31751
|
}
|
|
31164
31752
|
function BylinesPage() {
|
|
31165
31753
|
const queryClient = useQueryClient();
|
|
31166
|
-
const [search, setSearch] = React.useState("");
|
|
31167
|
-
const [guestFilter, setGuestFilter] = React.useState("all");
|
|
31168
|
-
const [selectedId, setSelectedId] = React.useState(null);
|
|
31169
|
-
const [showDeleteConfirm, setShowDeleteConfirm] = React.useState(false);
|
|
31170
|
-
const [allItems, setAllItems] = React.useState([]);
|
|
31171
|
-
const [nextCursor, setNextCursor] = React.useState(void 0);
|
|
31754
|
+
const [search, setSearch] = React$1.useState("");
|
|
31755
|
+
const [guestFilter, setGuestFilter] = React$1.useState("all");
|
|
31756
|
+
const [selectedId, setSelectedId] = React$1.useState(null);
|
|
31757
|
+
const [showDeleteConfirm, setShowDeleteConfirm] = React$1.useState(false);
|
|
31758
|
+
const [allItems, setAllItems] = React$1.useState([]);
|
|
31759
|
+
const [nextCursor, setNextCursor] = React$1.useState(void 0);
|
|
31172
31760
|
const { data, isLoading, error } = useQuery({
|
|
31173
31761
|
queryKey: [
|
|
31174
31762
|
"bylines",
|
|
@@ -31181,7 +31769,7 @@ function BylinesPage() {
|
|
|
31181
31769
|
limit: 50
|
|
31182
31770
|
})
|
|
31183
31771
|
});
|
|
31184
|
-
React.useEffect(() => {
|
|
31772
|
+
React$1.useEffect(() => {
|
|
31185
31773
|
if (data) {
|
|
31186
31774
|
setAllItems(data.items);
|
|
31187
31775
|
setNextCursor(data.nextCursor);
|
|
@@ -31211,8 +31799,8 @@ function BylinesPage() {
|
|
|
31211
31799
|
});
|
|
31212
31800
|
const items = allItems;
|
|
31213
31801
|
const selected = items.find((item) => item.id === selectedId) ?? null;
|
|
31214
|
-
const [form, setForm] = React.useState(() => toFormState(null));
|
|
31215
|
-
React.useEffect(() => {
|
|
31802
|
+
const [form, setForm] = React$1.useState(() => toFormState(null));
|
|
31803
|
+
React$1.useEffect(() => {
|
|
31216
31804
|
setForm(toFormState(selected));
|
|
31217
31805
|
}, [selectedId, selected]);
|
|
31218
31806
|
const createMutation = useMutation({
|
|
@@ -31480,14 +32068,14 @@ function RoleBadge({ role, size = "sm", showDescription = false, className }) {
|
|
|
31480
32068
|
function UserList({ users, isLoading, hasMore, searchQuery, roleFilter, onSearchChange, onRoleFilterChange, onSelectUser, onInviteUser, onLoadMore }) {
|
|
31481
32069
|
const { _: _t } = useLingui();
|
|
31482
32070
|
const { roles, roleLabels } = useRolesConfig();
|
|
31483
|
-
const roleFilterSelectItems = React.useMemo(() => ({
|
|
32071
|
+
const roleFilterSelectItems = React$1.useMemo(() => ({
|
|
31484
32072
|
all: _t({
|
|
31485
32073
|
id: "Hm90t3",
|
|
31486
32074
|
message: "All roles"
|
|
31487
32075
|
}),
|
|
31488
32076
|
...roleLabels
|
|
31489
32077
|
}), [_t, roleLabels]);
|
|
31490
|
-
const roleFilterSelectOptions = React.useMemo(() => [{
|
|
32078
|
+
const roleFilterSelectOptions = React$1.useMemo(() => [{
|
|
31491
32079
|
value: "all",
|
|
31492
32080
|
label: _t({
|
|
31493
32081
|
id: "Hm90t3",
|
|
@@ -31710,10 +32298,10 @@ function UserListSkeleton() {
|
|
|
31710
32298
|
function UserDetail({ user, isLoading, isOpen, isSaving, isSendingRecovery, recoverySent, recoveryError, currentUserId, onClose, onSave, onDisable, onEnable, onSendRecovery }) {
|
|
31711
32299
|
const { _: _t } = useLingui();
|
|
31712
32300
|
const { roles, roleLabels, getRoleLabel } = useRolesConfig();
|
|
31713
|
-
const [name, setName] = React.useState(user?.name ?? "");
|
|
31714
|
-
const [email, setEmail] = React.useState(user?.email ?? "");
|
|
31715
|
-
const [role, setRole] = React.useState(user?.role ?? 30);
|
|
31716
|
-
const userIdRef = React.useRef(user?.id);
|
|
32301
|
+
const [name, setName] = React$1.useState(user?.name ?? "");
|
|
32302
|
+
const [email, setEmail] = React$1.useState(user?.email ?? "");
|
|
32303
|
+
const [role, setRole] = React$1.useState(user?.role ?? 30);
|
|
32304
|
+
const userIdRef = React$1.useRef(user?.id);
|
|
31717
32305
|
if (user?.id !== userIdRef.current) {
|
|
31718
32306
|
userIdRef.current = user?.id;
|
|
31719
32307
|
if (user) {
|
|
@@ -32127,12 +32715,12 @@ function UserDetailSkeleton() {
|
|
|
32127
32715
|
function InviteUserModal({ open, isSending, error, inviteUrl, onOpenChange, onInvite }) {
|
|
32128
32716
|
const { _: _t } = useLingui();
|
|
32129
32717
|
const { roles, roleLabels } = useRolesConfig();
|
|
32130
|
-
const [email, setEmail] = React.useState("");
|
|
32131
|
-
const [role, setRole] = React.useState(30);
|
|
32132
|
-
const [copied, setCopied] = React.useState(false);
|
|
32133
|
-
const [copyError, setCopyError] = React.useState(false);
|
|
32134
|
-
const copyTimeoutRef = React.useRef(void 0);
|
|
32135
|
-
React.useEffect(() => {
|
|
32718
|
+
const [email, setEmail] = React$1.useState("");
|
|
32719
|
+
const [role, setRole] = React$1.useState(30);
|
|
32720
|
+
const [copied, setCopied] = React$1.useState(false);
|
|
32721
|
+
const [copyError, setCopyError] = React$1.useState(false);
|
|
32722
|
+
const copyTimeoutRef = React$1.useRef(void 0);
|
|
32723
|
+
React$1.useEffect(() => {
|
|
32136
32724
|
if (open) {
|
|
32137
32725
|
setEmail("");
|
|
32138
32726
|
setRole(30);
|
|
@@ -32140,7 +32728,7 @@ function InviteUserModal({ open, isSending, error, inviteUrl, onOpenChange, onIn
|
|
|
32140
32728
|
setCopyError(false);
|
|
32141
32729
|
}
|
|
32142
32730
|
}, [open]);
|
|
32143
|
-
React.useEffect(() => {
|
|
32731
|
+
React$1.useEffect(() => {
|
|
32144
32732
|
return () => {
|
|
32145
32733
|
if (copyTimeoutRef.current) clearTimeout(copyTimeoutRef.current);
|
|
32146
32734
|
};
|
|
@@ -32362,8 +32950,8 @@ function InviteUserModal({ open, isSending, error, inviteUrl, onOpenChange, onIn
|
|
|
32362
32950
|
* Debounce hook for search input
|
|
32363
32951
|
*/
|
|
32364
32952
|
function useDebounce(value, delay) {
|
|
32365
|
-
const [debouncedValue, setDebouncedValue] = React.useState(value);
|
|
32366
|
-
React.useEffect(() => {
|
|
32953
|
+
const [debouncedValue, setDebouncedValue] = React$1.useState(value);
|
|
32954
|
+
React$1.useEffect(() => {
|
|
32367
32955
|
const timer = setTimeout(setDebouncedValue, delay, value);
|
|
32368
32956
|
return () => clearTimeout(timer);
|
|
32369
32957
|
}, [value, delay]);
|
|
@@ -32372,16 +32960,16 @@ function useDebounce(value, delay) {
|
|
|
32372
32960
|
function UsersPage() {
|
|
32373
32961
|
const { getRoleLabel } = useRolesConfig();
|
|
32374
32962
|
const queryClient = useQueryClient();
|
|
32375
|
-
const [searchQuery, setSearchQuery] = React.useState("");
|
|
32376
|
-
const [roleFilter, setRoleFilter] = React.useState();
|
|
32377
|
-
const [selectedUserId, setSelectedUserId] = React.useState(null);
|
|
32378
|
-
const [isDetailOpen, setIsDetailOpen] = React.useState(false);
|
|
32379
|
-
const [isInviteOpen, setIsInviteOpen] = React.useState(false);
|
|
32380
|
-
const [showDisableConfirm, setShowDisableConfirm] = React.useState(false);
|
|
32381
|
-
const [showDemoteConfirm, setShowDemoteConfirm] = React.useState(false);
|
|
32382
|
-
const [pendingSaveData, setPendingSaveData] = React.useState(null);
|
|
32383
|
-
const [inviteError, setInviteError] = React.useState(null);
|
|
32384
|
-
const [inviteUrl, setInviteUrl] = React.useState(null);
|
|
32963
|
+
const [searchQuery, setSearchQuery] = React$1.useState("");
|
|
32964
|
+
const [roleFilter, setRoleFilter] = React$1.useState();
|
|
32965
|
+
const [selectedUserId, setSelectedUserId] = React$1.useState(null);
|
|
32966
|
+
const [isDetailOpen, setIsDetailOpen] = React$1.useState(false);
|
|
32967
|
+
const [isInviteOpen, setIsInviteOpen] = React$1.useState(false);
|
|
32968
|
+
const [showDisableConfirm, setShowDisableConfirm] = React$1.useState(false);
|
|
32969
|
+
const [showDemoteConfirm, setShowDemoteConfirm] = React$1.useState(false);
|
|
32970
|
+
const [pendingSaveData, setPendingSaveData] = React$1.useState(null);
|
|
32971
|
+
const [inviteError, setInviteError] = React$1.useState(null);
|
|
32972
|
+
const [inviteUrl, setInviteUrl] = React$1.useState(null);
|
|
32385
32973
|
const debouncedSearch = useDebounce(searchQuery, 300);
|
|
32386
32974
|
const usersQuery = useInfiniteQuery({
|
|
32387
32975
|
queryKey: [
|
|
@@ -32702,7 +33290,7 @@ function ContentListPage() {
|
|
|
32702
33290
|
});
|
|
32703
33291
|
const i18n = manifest?.i18n;
|
|
32704
33292
|
const activeLocale = i18n ? localeParam ?? i18n.defaultLocale : void 0;
|
|
32705
|
-
const [sort, setSort] = React.useState({
|
|
33293
|
+
const [sort, setSort] = React$1.useState({
|
|
32706
33294
|
field: "updatedAt",
|
|
32707
33295
|
direction: "desc"
|
|
32708
33296
|
});
|
|
@@ -32800,7 +33388,7 @@ function ContentListPage() {
|
|
|
32800
33388
|
});
|
|
32801
33389
|
}
|
|
32802
33390
|
});
|
|
32803
|
-
const items = React.useMemo(() => {
|
|
33391
|
+
const items = React$1.useMemo(() => {
|
|
32804
33392
|
return data?.pages.flatMap((page) => page.items) || [];
|
|
32805
33393
|
}, [data]);
|
|
32806
33394
|
if (!manifest) return /* @__PURE__ */ jsx(LoadingScreen, {});
|
|
@@ -32822,7 +33410,7 @@ function ContentListPage() {
|
|
|
32822
33410
|
isLoading: isLoading || isFetchingNextPage,
|
|
32823
33411
|
isTrashedLoading,
|
|
32824
33412
|
hasMore: !!hasNextPage,
|
|
32825
|
-
onLoadMore: React.useCallback(() => void fetchNextPage(), [fetchNextPage]),
|
|
33413
|
+
onLoadMore: React$1.useCallback(() => void fetchNextPage(), [fetchNextPage]),
|
|
32826
33414
|
trashedCount: trashedData?.items?.length || 0,
|
|
32827
33415
|
onDelete: (id) => deleteMutation.mutate(id),
|
|
32828
33416
|
onRestore: (id) => restoreMutation.mutate(id),
|
|
@@ -32847,7 +33435,7 @@ function ContentNewPage() {
|
|
|
32847
33435
|
const { locale } = useSearch({ from: "/_admin/content/$collection/new" });
|
|
32848
33436
|
const navigate = useNavigate();
|
|
32849
33437
|
const queryClient = useQueryClient();
|
|
32850
|
-
const [selectedBylines, setSelectedBylines] = React.useState([]);
|
|
33438
|
+
const [selectedBylines, setSelectedBylines] = React$1.useState([]);
|
|
32851
33439
|
const { data: manifest } = useQuery({
|
|
32852
33440
|
queryKey: ["manifest"],
|
|
32853
33441
|
queryFn: fetchManifest
|
|
@@ -32868,7 +33456,7 @@ function ContentNewPage() {
|
|
|
32868
33456
|
});
|
|
32869
33457
|
}
|
|
32870
33458
|
});
|
|
32871
|
-
const pluginBlocks = React.useMemo(() => manifest ? getPluginBlocks(manifest) : [], [manifest]);
|
|
33459
|
+
const pluginBlocks = React$1.useMemo(() => manifest ? getPluginBlocks(manifest) : [], [manifest]);
|
|
32872
33460
|
const { data: bylinesData } = useQuery({
|
|
32873
33461
|
queryKey: ["bylines"],
|
|
32874
33462
|
queryFn: () => fetchBylines({ limit: 100 })
|
|
@@ -32946,7 +33534,7 @@ function ContentEditPage() {
|
|
|
32946
33534
|
],
|
|
32947
33535
|
queryFn: () => fetchContent(collection, id)
|
|
32948
33536
|
});
|
|
32949
|
-
React.useEffect(() => {
|
|
33537
|
+
React$1.useEffect(() => {
|
|
32950
33538
|
if (typeof searchParams.field !== "string" || isLoading) return;
|
|
32951
33539
|
const timeoutId = requestIdleCallback(() => {
|
|
32952
33540
|
const el = document.getElementById(`field-${searchParams.field}`);
|
|
@@ -32983,7 +33571,7 @@ function ContentEditPage() {
|
|
|
32983
33571
|
queryFn: () => fetchRevision(rawItem.draftRevisionId),
|
|
32984
33572
|
enabled: !!rawItem?.draftRevisionId
|
|
32985
33573
|
});
|
|
32986
|
-
const item = React.useMemo(() => {
|
|
33574
|
+
const item = React$1.useMemo(() => {
|
|
32987
33575
|
if (!rawItem) return void 0;
|
|
32988
33576
|
if (!draftRevision?.data) return rawItem;
|
|
32989
33577
|
const draftData = {};
|
|
@@ -33056,7 +33644,7 @@ function ContentEditPage() {
|
|
|
33056
33644
|
});
|
|
33057
33645
|
}
|
|
33058
33646
|
});
|
|
33059
|
-
const [lastAutosaveAt, setLastAutosaveAt] = React.useState(null);
|
|
33647
|
+
const [lastAutosaveAt, setLastAutosaveAt] = React$1.useState(null);
|
|
33060
33648
|
const autosaveMutation = useMutation({
|
|
33061
33649
|
mutationFn: (data) => updateContent(collection, id, {
|
|
33062
33650
|
...data,
|
|
@@ -33259,7 +33847,7 @@ function ContentEditPage() {
|
|
|
33259
33847
|
});
|
|
33260
33848
|
}
|
|
33261
33849
|
});
|
|
33262
|
-
const pluginBlocks = React.useMemo(() => manifest ? getPluginBlocks(manifest) : [], [manifest]);
|
|
33850
|
+
const pluginBlocks = React$1.useMemo(() => manifest ? getPluginBlocks(manifest) : [], [manifest]);
|
|
33263
33851
|
if (!manifest) return /* @__PURE__ */ jsx(LoadingScreen, {});
|
|
33264
33852
|
const collectionConfig = manifest.collections[collection];
|
|
33265
33853
|
if (!collectionConfig) return /* @__PURE__ */ jsx(NotFoundPage, { message: `Collection "${collection}" not found` });
|
|
@@ -33370,11 +33958,11 @@ function CommentsPage() {
|
|
|
33370
33958
|
},
|
|
33371
33959
|
staleTime: 300 * 1e3
|
|
33372
33960
|
});
|
|
33373
|
-
const [activeStatus, setActiveStatus] = React.useState("pending");
|
|
33374
|
-
const [collectionFilter, setCollectionFilter] = React.useState("");
|
|
33375
|
-
const [searchQuery, setSearchQuery] = React.useState("");
|
|
33376
|
-
const [debouncedSearch, setDebouncedSearch] = React.useState("");
|
|
33377
|
-
React.useEffect(() => {
|
|
33961
|
+
const [activeStatus, setActiveStatus] = React$1.useState("pending");
|
|
33962
|
+
const [collectionFilter, setCollectionFilter] = React$1.useState("");
|
|
33963
|
+
const [searchQuery, setSearchQuery] = React$1.useState("");
|
|
33964
|
+
const [debouncedSearch, setDebouncedSearch] = React$1.useState("");
|
|
33965
|
+
React$1.useEffect(() => {
|
|
33378
33966
|
const timer = setTimeout(setDebouncedSearch, 300, searchQuery);
|
|
33379
33967
|
return () => clearTimeout(timer);
|
|
33380
33968
|
}, [searchQuery]);
|
|
@@ -33557,7 +34145,7 @@ function MarketplaceBrowsePage() {
|
|
|
33557
34145
|
return fetchPlugins();
|
|
33558
34146
|
}
|
|
33559
34147
|
});
|
|
33560
|
-
return /* @__PURE__ */ jsx(MarketplaceBrowse, { installedPluginIds: React.useMemo(() => {
|
|
34148
|
+
return /* @__PURE__ */ jsx(MarketplaceBrowse, { installedPluginIds: React$1.useMemo(() => {
|
|
33561
34149
|
if (!plugins) return /* @__PURE__ */ new Set();
|
|
33562
34150
|
return new Set(plugins.map((p) => p.id));
|
|
33563
34151
|
}, [plugins]) });
|
|
@@ -33578,7 +34166,7 @@ function MarketplaceDetailPage() {
|
|
|
33578
34166
|
});
|
|
33579
34167
|
return /* @__PURE__ */ jsx(MarketplacePluginDetail, {
|
|
33580
34168
|
pluginId,
|
|
33581
|
-
installedPluginIds: React.useMemo(() => {
|
|
34169
|
+
installedPluginIds: React$1.useMemo(() => {
|
|
33582
34170
|
if (!plugins) return /* @__PURE__ */ new Set();
|
|
33583
34171
|
return new Set(plugins.map((p) => p.id));
|
|
33584
34172
|
}, [plugins])
|
|
@@ -33611,7 +34199,10 @@ const menuListRoute = createRoute({
|
|
|
33611
34199
|
const menuEditorRoute = createRoute({
|
|
33612
34200
|
getParentRoute: () => adminLayoutRoute,
|
|
33613
34201
|
path: "/menus/$name",
|
|
33614
|
-
component: MenuEditor
|
|
34202
|
+
component: MenuEditor,
|
|
34203
|
+
validateSearch: (search) => {
|
|
34204
|
+
return { locale: typeof search.locale === "string" ? search.locale : void 0 };
|
|
34205
|
+
}
|
|
33615
34206
|
});
|
|
33616
34207
|
const taxonomyRoute = createRoute({
|
|
33617
34208
|
getParentRoute: () => adminLayoutRoute,
|
|
@@ -33987,10 +34578,10 @@ const router = createAdminRouter(queryClient);
|
|
|
33987
34578
|
const EMPTY_PLUGINS = {};
|
|
33988
34579
|
const EMPTY_AUTH_PROVIDERS = {};
|
|
33989
34580
|
function AdminApp({ pluginAdmins = EMPTY_PLUGINS, authProviders = EMPTY_AUTH_PROVIDERS, locale = "en", messages = {} }) {
|
|
33990
|
-
React.useEffect(() => {
|
|
34581
|
+
React$1.useEffect(() => {
|
|
33991
34582
|
document.getElementById("emdash-boot-loader")?.remove();
|
|
33992
34583
|
}, []);
|
|
33993
|
-
const i18nInitialized = React.useRef(false);
|
|
34584
|
+
const i18nInitialized = React$1.useRef(false);
|
|
33994
34585
|
if (!i18nInitialized.current) {
|
|
33995
34586
|
i18n.loadAndActivate({
|
|
33996
34587
|
locale,
|
|
@@ -34014,5 +34605,5 @@ function AdminApp({ pluginAdmins = EMPTY_PLUGINS, authProviders = EMPTY_AUTH_PRO
|
|
|
34014
34605
|
}
|
|
34015
34606
|
|
|
34016
34607
|
//#endregion
|
|
34017
|
-
export { API_BASE, API_TOKEN_SCOPES, AdminApp, AdminApp as App, AuthProviderProvider, CAPABILITY_LABELS, ContentEditor, ContentList, DEFAULT_LOCALE, Dashboard, EditorHeader, Header, Link, LoginPage, MediaLibrary, MediaPickerModal, PasskeyLogin, PasskeyRegistration, PluginAdminProvider, PortableTextEditor, SUPPORTED_LOCALES, SUPPORTED_LOCALE_CODES, SaveButton, Settings, SetupWizard, Shell, KumoSidebar as Sidebar, SidebarNav, analyzeWpPluginSite, analyzeWxr, apiFetch, bulkCommentAction, checkPluginUpdates, cn, compareRevisions, completeSignup, createAdminRouter, createAllowedDomain, createApiToken, createByline, createCollection, createContent, createField, createMenu, createMenuItem, createRedirect, createSection, createTaxonomy, createTerm, createWidget, createWidgetArea, deleteAllowedDomain, deleteByline, deleteCollection, deleteComment, deleteContent, deleteField, deleteFromProvider, deleteMedia, deleteMenu, deleteMenuItem, deletePasskey, deleteRedirect, deleteSection, deleteTerm, deleteWidget, deleteWidgetArea, describeCapability, disablePlugin, disableUser, discardDraft, duplicateContent, enablePlugin, enableUser, executeWpPluginImport, executeWxrImport, fetch404Summary, fetchAllowedDomains, fetchApiTokens, fetchAuthMode, fetchByline, fetchBylines, fetchCollection, fetchCollections, fetchComment, fetchCommentCounts, fetchComments, fetchContent, fetchContentList, fetchDashboardStats, fetchEmailSettings, fetchFields, fetchManifest, fetchMarketplacePlugin, fetchMediaList, fetchMediaProviders, fetchMenu, fetchMenus, fetchOrphanedTables, fetchPasskeys, fetchPlugin, fetchPlugins, fetchProviderMedia, fetchRedirects, fetchRevision, fetchRevisions, fetchSection, fetchSections, fetchSettings, fetchTaxonomyDef, fetchTaxonomyDefs, fetchTerms, fetchTheme, fetchTranslations, fetchTrashedContent, fetchUser, fetchUsers, fetchWidgetArea, fetchWidgetAreas, fetchWidgetComponents, generatePreviewUrl, getDraftStatus, getPreviewUrl, hasAllowedDomains, importWxrMedia, installMarketplacePlugin, inviteUser, parseApiResponse, permanentDeleteContent, prepareWxrImport, probeImportUrl, publishContent, registerOrphanedTable, renamePasskey, reorderFields, reorderMenuItems, reorderWidgets, requestSignup, resolveLocale, restoreContent, restoreRevision, revokeApiToken, rewriteContentUrls, scheduleContent, searchMarketplace, searchThemes, sendRecoveryLink, sendTestEmail, setSearchEnabled, throwResponseError, uninstallMarketplacePlugin, unpublishContent, unscheduleContent, updateAllowedDomain, updateByline, updateCollection, updateCommentStatus, updateContent, updateField, updateMarketplacePlugin, updateMedia, updateMenu, updateMenuItem, updateRedirect, updateSection, updateSettings, updateTerm, updateUser, updateWidget, uploadMedia, uploadToProvider, useAuthProviderList, useAuthProviders, useCurrentUser, useLocale, useNavigate, useParams, usePluginAdmins, usePluginField, usePluginHasPages, usePluginHasWidgets, usePluginPage, usePluginWidget, validateInviteToken, verifySignupToken };
|
|
34608
|
+
export { API_BASE, API_TOKEN_SCOPES, AdminApp, AdminApp as App, AuthProviderProvider, CAPABILITY_LABELS, ContentEditor, ContentList, DEFAULT_LOCALE, Dashboard, EditorHeader, Header, Link, LoginPage, MediaLibrary, MediaPickerModal, PasskeyLogin, PasskeyRegistration, PluginAdminProvider, PortableTextEditor, SUPPORTED_LOCALES, SUPPORTED_LOCALE_CODES, SaveButton, Settings, SetupWizard, Shell, KumoSidebar as Sidebar, SidebarNav, analyzeWpPluginSite, analyzeWxr, apiFetch, bulkCommentAction, checkPluginUpdates, cn, compareRevisions, completeSignup, createAdminRouter, createAllowedDomain, createApiToken, createByline, createCollection, createContent, createField, createMenu, createMenuItem, createMenuTranslation, createRedirect, createSection, createTaxonomy, createTerm, createTermTranslation, createWidget, createWidgetArea, deleteAllowedDomain, deleteByline, deleteCollection, deleteComment, deleteContent, deleteField, deleteFromProvider, deleteMedia, deleteMenu, deleteMenuItem, deletePasskey, deleteRedirect, deleteSection, deleteTerm, deleteWidget, deleteWidgetArea, describeCapability, disablePlugin, disableUser, discardDraft, duplicateContent, enablePlugin, enableUser, executeWpPluginImport, executeWxrImport, fetch404Summary, fetchAllowedDomains, fetchApiTokens, fetchAuthMode, fetchByline, fetchBylines, fetchCollection, fetchCollections, fetchComment, fetchCommentCounts, fetchComments, fetchContent, fetchContentList, fetchDashboardStats, fetchEmailSettings, fetchFields, fetchManifest, fetchMarketplacePlugin, fetchMediaList, fetchMediaProviders, fetchMenu, fetchMenuTranslations, fetchMenus, fetchOrphanedTables, fetchPasskeys, fetchPlugin, fetchPlugins, fetchProviderMedia, fetchRedirects, fetchRevision, fetchRevisions, fetchSection, fetchSections, fetchSettings, fetchTaxonomyDef, fetchTaxonomyDefs, fetchTermTranslations, fetchTerms, fetchTheme, fetchTranslations, fetchTrashedContent, fetchUser, fetchUsers, fetchWidgetArea, fetchWidgetAreas, fetchWidgetComponents, generatePreviewUrl, getDraftStatus, getPreviewUrl, hasAllowedDomains, importWxrMedia, installMarketplacePlugin, inviteUser, parseApiResponse, permanentDeleteContent, prepareWxrImport, probeImportUrl, publishContent, registerOrphanedTable, renamePasskey, reorderFields, reorderMenuItems, reorderWidgets, requestSignup, resolveLocale, restoreContent, restoreRevision, revokeApiToken, rewriteContentUrls, scheduleContent, searchMarketplace, searchThemes, sendRecoveryLink, sendTestEmail, setSearchEnabled, throwResponseError, uninstallMarketplacePlugin, unpublishContent, unscheduleContent, updateAllowedDomain, updateByline, updateCollection, updateCommentStatus, updateContent, updateField, updateMarketplacePlugin, updateMedia, updateMenu, updateMenuItem, updateRedirect, updateSection, updateSettings, updateTerm, updateUser, updateWidget, uploadMedia, uploadToProvider, useAuthProviderList, useAuthProviders, useCurrentUser, useLocale, useNavigate, useParams, usePluginAdmins, usePluginField, usePluginHasPages, usePluginHasWidgets, usePluginPage, usePluginWidget, validateInviteToken, verifySignupToken };
|
|
34018
34609
|
//# sourceMappingURL=index.js.map
|