@emdash-cms/admin 0.19.0 → 0.20.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-xsHb49dm.js → LocaleDirectionProvider-D701o676.js} +25 -19
- package/dist/LocaleDirectionProvider-D701o676.js.map +1 -0
- package/dist/{config-76UcBWeH.d.ts → config-CPRInh7U.d.ts} +1 -1
- package/dist/{config-76UcBWeH.d.ts.map → config-CPRInh7U.d.ts.map} +1 -1
- package/dist/index.d.ts +9 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +667 -306
- 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/en-GB/messages.mjs +1 -0
- package/dist/locales/es-419/messages.mjs +1 -1
- package/dist/locales/es-ES/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/nb/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/th/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-BCdr0vs6.js +6 -0
- package/dist/messages-BCdr0vs6.js.map +1 -0
- package/dist/messages-BEba-i5h.js +6 -0
- package/dist/messages-BEba-i5h.js.map +1 -0
- package/dist/messages-BOJU79wz.js +6 -0
- package/dist/messages-BOJU79wz.js.map +1 -0
- package/dist/messages-B_776u_s.js +6 -0
- package/dist/messages-B_776u_s.js.map +1 -0
- package/dist/messages-BuTB8H87.js +6 -0
- package/dist/messages-BuTB8H87.js.map +1 -0
- package/dist/messages-BxxGIhf4.js +6 -0
- package/dist/messages-BxxGIhf4.js.map +1 -0
- package/dist/messages-CBkzQcd-.js +6 -0
- package/dist/messages-CBkzQcd-.js.map +1 -0
- package/dist/messages-CNCPtLaI.js +6 -0
- package/dist/messages-CNCPtLaI.js.map +1 -0
- package/dist/messages-CY65b3kz.js +6 -0
- package/dist/messages-CY65b3kz.js.map +1 -0
- package/dist/messages-CvaPem7G.js +6 -0
- package/dist/messages-CvaPem7G.js.map +1 -0
- package/dist/messages-DHo2mVqL.js +6 -0
- package/dist/messages-DHo2mVqL.js.map +1 -0
- package/dist/messages-DHqYoT8m.js +6 -0
- package/dist/messages-DHqYoT8m.js.map +1 -0
- package/dist/messages-DUYqNIID.js +6 -0
- package/dist/messages-DUYqNIID.js.map +1 -0
- package/dist/messages-DflNUNOT.js +6 -0
- package/dist/messages-DflNUNOT.js.map +1 -0
- package/dist/messages-DfrYsR2M.js +6 -0
- package/dist/messages-DfrYsR2M.js.map +1 -0
- package/dist/messages-DiOQ8Er0.js +6 -0
- package/dist/messages-DiOQ8Er0.js.map +1 -0
- package/dist/messages-MtFRSNif.js +6 -0
- package/dist/messages-MtFRSNif.js.map +1 -0
- package/dist/messages-TCMOQPXZ.js +6 -0
- package/dist/messages-TCMOQPXZ.js.map +1 -0
- package/dist/messages-Z5LBofRQ.js +6 -0
- package/dist/messages-Z5LBofRQ.js.map +1 -0
- package/dist/{plugins-BZzztFdK.js → plugins-G9Z9NQ7n.js} +26 -7
- package/dist/{plugins-BZzztFdK.js.map → plugins-G9Z9NQ7n.js.map} +1 -1
- package/package.json +8 -7
- package/dist/LocaleDirectionProvider-xsHb49dm.js.map +0 -1
- package/dist/messages-BMitdYCD.js +0 -6
- package/dist/messages-BMitdYCD.js.map +0 -1
- package/dist/messages-BQ-MRpT8.js +0 -6
- package/dist/messages-BQ-MRpT8.js.map +0 -1
- package/dist/messages-BXYYYOd2.js +0 -6
- package/dist/messages-BXYYYOd2.js.map +0 -1
- package/dist/messages-Bg8kLtZI.js +0 -6
- package/dist/messages-Bg8kLtZI.js.map +0 -1
- package/dist/messages-BwRtFSRk.js +0 -6
- package/dist/messages-BwRtFSRk.js.map +0 -1
- package/dist/messages-C1IVcXec.js +0 -6
- package/dist/messages-C1IVcXec.js.map +0 -1
- package/dist/messages-C5P0RJYN.js +0 -6
- package/dist/messages-C5P0RJYN.js.map +0 -1
- package/dist/messages-CH9Gmcpo.js +0 -6
- package/dist/messages-CH9Gmcpo.js.map +0 -1
- package/dist/messages-CJgGf1T1.js +0 -6
- package/dist/messages-CJgGf1T1.js.map +0 -1
- package/dist/messages-CWew0hcG.js +0 -6
- package/dist/messages-CWew0hcG.js.map +0 -1
- package/dist/messages-CmMy_HWT.js +0 -6
- package/dist/messages-CmMy_HWT.js.map +0 -1
- package/dist/messages-CzJu5dYn.js +0 -6
- package/dist/messages-CzJu5dYn.js.map +0 -1
- package/dist/messages-DQ5ZXmj9.js +0 -6
- package/dist/messages-DQ5ZXmj9.js.map +0 -1
- package/dist/messages-DYT85mDk.js +0 -6
- package/dist/messages-DYT85mDk.js.map +0 -1
- package/dist/messages-DinvbD0I.js +0 -6
- package/dist/messages-DinvbD0I.js.map +0 -1
- package/dist/messages-Dj-5xKz6.js +0 -6
- package/dist/messages-Dj-5xKz6.js.map +0 -1
- package/dist/messages-DnhGgBnH.js +0 -6
- package/dist/messages-DnhGgBnH.js.map +0 -1
- package/dist/messages-Tf8h9nIJ.js +0 -6
- package/dist/messages-Tf8h9nIJ.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
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-
|
|
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-
|
|
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-G9Z9NQ7n.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-D701o676.js";
|
|
3
3
|
import "./locales/index.js";
|
|
4
|
-
import { Autocomplete, 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";
|
|
4
|
+
import { Autocomplete, Badge, Button, Checkbox, ClipboardText, 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, keepPreviousData, useInfiniteQuery, useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
@@ -40,6 +40,7 @@ import { BlockRenderer } from "@emdash-cms/blocks";
|
|
|
40
40
|
import DOMPurify from "dompurify";
|
|
41
41
|
import { Marked, Renderer } from "marked";
|
|
42
42
|
import { checkEnvCompatibility, hostEnvFromVersions } from "@emdash-cms/registry-client/env";
|
|
43
|
+
import { declaredAccessToCapabilities } from "@emdash-cms/plugin-types";
|
|
43
44
|
import { useHotkeys } from "react-hotkeys-hook";
|
|
44
45
|
|
|
45
46
|
//#region src/components/ThemeProvider.tsx
|
|
@@ -279,7 +280,10 @@ function ArrowPrev({ className, ...props }) {
|
|
|
279
280
|
function getMutationError(error) {
|
|
280
281
|
if (!error) return null;
|
|
281
282
|
if (error instanceof Error) return error.message;
|
|
282
|
-
return
|
|
283
|
+
return i18n._({
|
|
284
|
+
id: "Vw8l6h",
|
|
285
|
+
message: "An error occurred"
|
|
286
|
+
});
|
|
283
287
|
}
|
|
284
288
|
/** Inline error banner for use inside dialogs. */
|
|
285
289
|
function DialogError({ message, className }) {
|
|
@@ -1437,7 +1441,22 @@ async function fetchMediaList(options) {
|
|
|
1437
1441
|
const q = normalizeMediaSearch(options.search);
|
|
1438
1442
|
if (q) params.set("q", q);
|
|
1439
1443
|
}
|
|
1440
|
-
return parseApiResponse(await apiFetch(`${API_BASE}/media${params.toString() ? `?${params}` : ""}`),
|
|
1444
|
+
return parseApiResponse(await apiFetch(`${API_BASE}/media${params.toString() ? `?${params}` : ""}`), i18n._({
|
|
1445
|
+
id: "gtFAk8",
|
|
1446
|
+
message: "Failed to fetch media"
|
|
1447
|
+
}));
|
|
1448
|
+
}
|
|
1449
|
+
/**
|
|
1450
|
+
* Fetch a single media item by id.
|
|
1451
|
+
*
|
|
1452
|
+
* Used to resolve an id-only reference (e.g. a byline's `avatarMediaId`)
|
|
1453
|
+
* back into a full media item for display.
|
|
1454
|
+
*/
|
|
1455
|
+
async function fetchMediaItem(id) {
|
|
1456
|
+
return (await parseApiResponse(await apiFetch(`${API_BASE}/media/${id}`), i18n._({
|
|
1457
|
+
id: "8rtatN",
|
|
1458
|
+
message: "Failed to fetch media item"
|
|
1459
|
+
}))).item;
|
|
1441
1460
|
}
|
|
1442
1461
|
/**
|
|
1443
1462
|
* Try to get a signed upload URL
|
|
@@ -1456,7 +1475,10 @@ async function getUploadUrl(file, opts) {
|
|
|
1456
1475
|
})
|
|
1457
1476
|
});
|
|
1458
1477
|
if (response.status === 501) return null;
|
|
1459
|
-
return parseApiResponse(response,
|
|
1478
|
+
return parseApiResponse(response, i18n._({
|
|
1479
|
+
id: "YTKTMb",
|
|
1480
|
+
message: "Failed to get upload URL"
|
|
1481
|
+
}));
|
|
1460
1482
|
} catch (error) {
|
|
1461
1483
|
if (error instanceof TypeError && error.message.includes("fetch")) return null;
|
|
1462
1484
|
throw error;
|
|
@@ -1470,7 +1492,10 @@ async function confirmUpload(mediaId, metadata) {
|
|
|
1470
1492
|
method: "POST",
|
|
1471
1493
|
headers: { "Content-Type": "application/json" },
|
|
1472
1494
|
body: JSON.stringify(metadata || {})
|
|
1473
|
-
}),
|
|
1495
|
+
}), i18n._({
|
|
1496
|
+
id: "QZDXMs",
|
|
1497
|
+
message: "Failed to confirm upload"
|
|
1498
|
+
}))).item;
|
|
1474
1499
|
}
|
|
1475
1500
|
/**
|
|
1476
1501
|
* Upload directly to signed URL
|
|
@@ -1523,7 +1548,10 @@ async function uploadMediaDirect(file, opts) {
|
|
|
1523
1548
|
return (await parseApiResponse(await apiFetch(`${API_BASE}/media`, {
|
|
1524
1549
|
method: "POST",
|
|
1525
1550
|
body: formData
|
|
1526
|
-
}),
|
|
1551
|
+
}), i18n._({
|
|
1552
|
+
id: "5IFNMM",
|
|
1553
|
+
message: "Failed to upload media"
|
|
1554
|
+
}))).item;
|
|
1527
1555
|
}
|
|
1528
1556
|
/**
|
|
1529
1557
|
* Upload media file
|
|
@@ -1560,13 +1588,19 @@ async function updateMedia(id, input) {
|
|
|
1560
1588
|
method: "PUT",
|
|
1561
1589
|
headers: { "Content-Type": "application/json" },
|
|
1562
1590
|
body: JSON.stringify(input)
|
|
1563
|
-
}),
|
|
1591
|
+
}), i18n._({
|
|
1592
|
+
id: "nr0Bxd",
|
|
1593
|
+
message: "Failed to update media"
|
|
1594
|
+
}))).item;
|
|
1564
1595
|
}
|
|
1565
1596
|
/**
|
|
1566
1597
|
* Fetch all configured media providers
|
|
1567
1598
|
*/
|
|
1568
1599
|
async function fetchMediaProviders() {
|
|
1569
|
-
return (await parseApiResponse(await apiFetch(`${API_BASE}/media/providers`),
|
|
1600
|
+
return (await parseApiResponse(await apiFetch(`${API_BASE}/media/providers`), i18n._({
|
|
1601
|
+
id: "sj4xOB",
|
|
1602
|
+
message: "Failed to fetch media providers"
|
|
1603
|
+
}))).items;
|
|
1570
1604
|
}
|
|
1571
1605
|
/**
|
|
1572
1606
|
* Fetch media items from a specific provider
|
|
@@ -1580,7 +1614,10 @@ async function fetchProviderMedia(providerId, options) {
|
|
|
1580
1614
|
const value = Array.isArray(options.mimeType) ? options.mimeType.join(",") : options.mimeType;
|
|
1581
1615
|
if (value) params.set("mimeType", value);
|
|
1582
1616
|
}
|
|
1583
|
-
return parseApiResponse(await apiFetch(`${API_BASE}/media/providers/${providerId}${params.toString() ? `?${params}` : ""}`),
|
|
1617
|
+
return parseApiResponse(await apiFetch(`${API_BASE}/media/providers/${providerId}${params.toString() ? `?${params}` : ""}`), i18n._({
|
|
1618
|
+
id: "ZrDiVv",
|
|
1619
|
+
message: "Failed to fetch provider media"
|
|
1620
|
+
}));
|
|
1584
1621
|
}
|
|
1585
1622
|
/**
|
|
1586
1623
|
* Upload media to a specific provider
|
|
@@ -1592,7 +1629,10 @@ async function uploadToProvider(providerId, file, alt) {
|
|
|
1592
1629
|
return (await parseApiResponse(await apiFetch(`${API_BASE}/media/providers/${providerId}`, {
|
|
1593
1630
|
method: "POST",
|
|
1594
1631
|
body: formData
|
|
1595
|
-
}),
|
|
1632
|
+
}), i18n._({
|
|
1633
|
+
id: "j66jlb",
|
|
1634
|
+
message: "Failed to upload to provider"
|
|
1635
|
+
}))).item;
|
|
1596
1636
|
}
|
|
1597
1637
|
/**
|
|
1598
1638
|
* Delete media from a specific provider
|
|
@@ -1739,7 +1779,10 @@ async function registerOrphanedTable(slug, options) {
|
|
|
1739
1779
|
* Fetch site settings
|
|
1740
1780
|
*/
|
|
1741
1781
|
async function fetchSettings() {
|
|
1742
|
-
return parseApiResponse(await apiFetch(`${API_BASE}/settings`),
|
|
1782
|
+
return parseApiResponse(await apiFetch(`${API_BASE}/settings`), i18n._({
|
|
1783
|
+
id: "naCprc",
|
|
1784
|
+
message: "Failed to fetch settings"
|
|
1785
|
+
}));
|
|
1743
1786
|
}
|
|
1744
1787
|
/**
|
|
1745
1788
|
* Update site settings
|
|
@@ -1749,7 +1792,10 @@ async function updateSettings(settings) {
|
|
|
1749
1792
|
method: "POST",
|
|
1750
1793
|
headers: { "Content-Type": "application/json" },
|
|
1751
1794
|
body: JSON.stringify(settings)
|
|
1752
|
-
}),
|
|
1795
|
+
}), i18n._({
|
|
1796
|
+
id: "tOcErW",
|
|
1797
|
+
message: "Failed to update settings"
|
|
1798
|
+
}));
|
|
1753
1799
|
}
|
|
1754
1800
|
|
|
1755
1801
|
//#endregion
|
|
@@ -2339,13 +2385,19 @@ async function fetchSections(options) {
|
|
|
2339
2385
|
if (options?.search) params.set("search", options.search);
|
|
2340
2386
|
if (options?.limit) params.set("limit", String(options.limit));
|
|
2341
2387
|
if (options?.cursor) params.set("cursor", options.cursor);
|
|
2342
|
-
return parseApiResponse(await apiFetch(params.toString() ? `${API_BASE}/sections?${params}` : `${API_BASE}/sections`),
|
|
2388
|
+
return parseApiResponse(await apiFetch(params.toString() ? `${API_BASE}/sections?${params}` : `${API_BASE}/sections`), i18n._({
|
|
2389
|
+
id: "CEv4Y+",
|
|
2390
|
+
message: "Failed to fetch sections"
|
|
2391
|
+
}));
|
|
2343
2392
|
}
|
|
2344
2393
|
/**
|
|
2345
2394
|
* Fetch a single section by slug
|
|
2346
2395
|
*/
|
|
2347
2396
|
async function fetchSection(slug) {
|
|
2348
|
-
return parseApiResponse(await apiFetch(`${API_BASE}/sections/${slug}`),
|
|
2397
|
+
return parseApiResponse(await apiFetch(`${API_BASE}/sections/${slug}`), i18n._({
|
|
2398
|
+
id: "FZmyhf",
|
|
2399
|
+
message: "Failed to fetch section"
|
|
2400
|
+
}));
|
|
2349
2401
|
}
|
|
2350
2402
|
/**
|
|
2351
2403
|
* Create a section
|
|
@@ -2355,7 +2407,10 @@ async function createSection(input) {
|
|
|
2355
2407
|
method: "POST",
|
|
2356
2408
|
headers: { "Content-Type": "application/json" },
|
|
2357
2409
|
body: JSON.stringify(input)
|
|
2358
|
-
}),
|
|
2410
|
+
}), i18n._({
|
|
2411
|
+
id: "NL9xsV",
|
|
2412
|
+
message: "Failed to create section"
|
|
2413
|
+
}));
|
|
2359
2414
|
}
|
|
2360
2415
|
/**
|
|
2361
2416
|
* Update a section
|
|
@@ -2365,7 +2420,10 @@ async function updateSection(slug, input) {
|
|
|
2365
2420
|
method: "PUT",
|
|
2366
2421
|
headers: { "Content-Type": "application/json" },
|
|
2367
2422
|
body: JSON.stringify(input)
|
|
2368
|
-
}),
|
|
2423
|
+
}), i18n._({
|
|
2424
|
+
id: "cCyATW",
|
|
2425
|
+
message: "Failed to update section"
|
|
2426
|
+
}));
|
|
2369
2427
|
}
|
|
2370
2428
|
/**
|
|
2371
2429
|
* Delete a section
|
|
@@ -2727,7 +2785,10 @@ async function bulkCommentAction(ids, action) {
|
|
|
2727
2785
|
* Fetch dashboard statistics
|
|
2728
2786
|
*/
|
|
2729
2787
|
async function fetchDashboardStats() {
|
|
2730
|
-
return parseApiResponse(await apiFetch(`${API_BASE}/dashboard`),
|
|
2788
|
+
return parseApiResponse(await apiFetch(`${API_BASE}/dashboard`), i18n._({
|
|
2789
|
+
id: "IZPHXp",
|
|
2790
|
+
message: "Failed to fetch dashboard stats"
|
|
2791
|
+
}));
|
|
2731
2792
|
}
|
|
2732
2793
|
|
|
2733
2794
|
//#endregion
|
|
@@ -2747,7 +2808,13 @@ async function setSearchEnabled(collection, enabled, weights) {
|
|
|
2747
2808
|
enabled,
|
|
2748
2809
|
weights
|
|
2749
2810
|
})
|
|
2750
|
-
}),
|
|
2811
|
+
}), enabled ? i18n._({
|
|
2812
|
+
id: "2DwuuY",
|
|
2813
|
+
message: "Failed to enable search"
|
|
2814
|
+
}) : i18n._({
|
|
2815
|
+
id: "5YQYqs",
|
|
2816
|
+
message: "Failed to disable search"
|
|
2817
|
+
}));
|
|
2751
2818
|
}
|
|
2752
2819
|
|
|
2753
2820
|
//#endregion
|
|
@@ -2924,14 +2991,20 @@ function describeCapability(capability, allowedHosts) {
|
|
|
2924
2991
|
* Email settings API client functions
|
|
2925
2992
|
*/
|
|
2926
2993
|
async function fetchEmailSettings() {
|
|
2927
|
-
return parseApiResponse(await apiFetch(`${API_BASE}/settings/email`),
|
|
2994
|
+
return parseApiResponse(await apiFetch(`${API_BASE}/settings/email`), i18n._({
|
|
2995
|
+
id: "QxS/sM",
|
|
2996
|
+
message: "Failed to fetch email settings"
|
|
2997
|
+
}));
|
|
2928
2998
|
}
|
|
2929
2999
|
async function sendTestEmail(to) {
|
|
2930
3000
|
return parseApiResponse(await apiFetch(`${API_BASE}/settings/email`, {
|
|
2931
3001
|
method: "POST",
|
|
2932
3002
|
headers: { "Content-Type": "application/json" },
|
|
2933
3003
|
body: JSON.stringify({ to })
|
|
2934
|
-
}),
|
|
3004
|
+
}), i18n._({
|
|
3005
|
+
id: "aH/q8K",
|
|
3006
|
+
message: "Failed to send test email"
|
|
3007
|
+
}));
|
|
2935
3008
|
}
|
|
2936
3009
|
|
|
2937
3010
|
//#endregion
|
|
@@ -3042,7 +3115,10 @@ async function fetch404Summary(limit) {
|
|
|
3042
3115
|
* Current user query — shared across Shell, Header, Sidebar, and CommandPalette.
|
|
3043
3116
|
*/
|
|
3044
3117
|
async function fetchCurrentUser() {
|
|
3045
|
-
return parseApiResponse(await apiFetch("/_emdash/api/auth/me"),
|
|
3118
|
+
return parseApiResponse(await apiFetch("/_emdash/api/auth/me"), i18n._({
|
|
3119
|
+
id: "z7Mflq",
|
|
3120
|
+
message: "Failed to fetch user"
|
|
3121
|
+
}));
|
|
3046
3122
|
}
|
|
3047
3123
|
function useCurrentUser() {
|
|
3048
3124
|
return useQuery({
|
|
@@ -3126,6 +3202,57 @@ function providerItemToMediaItem(providerId, item) {
|
|
|
3126
3202
|
meta: item.meta
|
|
3127
3203
|
};
|
|
3128
3204
|
}
|
|
3205
|
+
/** Root-absolute path prefix for locally stored media served by EmDash. */
|
|
3206
|
+
const INTERNAL_MEDIA_PREFIX = "/_emdash/api/media/file/";
|
|
3207
|
+
/**
|
|
3208
|
+
* Default rendered width (CSS px) for admin grid thumbnails, requested at ~2x
|
|
3209
|
+
* the largest grid cell (200px) so they stay crisp on HiDPI displays.
|
|
3210
|
+
*/
|
|
3211
|
+
const MEDIA_THUMBNAIL_WIDTH = 400;
|
|
3212
|
+
/**
|
|
3213
|
+
* Build a display URL for a media thumbnail in the admin grid/list views.
|
|
3214
|
+
*
|
|
3215
|
+
* Large libraries were slow to browse and search because every grid cell loaded
|
|
3216
|
+
* the full-size original through the media proxy (#1488). This routes
|
|
3217
|
+
* same-origin raster images through Astro's runtime image endpoint (`/_image`)
|
|
3218
|
+
* to request a small resized rendition instead.
|
|
3219
|
+
*
|
|
3220
|
+
* Where a runtime image service transforms — sharp on Node, or the Cloudflare
|
|
3221
|
+
* Images binding on Workers (the `@astrojs/cloudflare` v13 default) — the grid
|
|
3222
|
+
* gets a lightweight thumbnail. Where none does (a `passthrough` config, or
|
|
3223
|
+
* behind Cloudflare Access where the endpoint's same-origin source fetch is
|
|
3224
|
+
* blocked) `/_image` streams the original, so this never renders worse than
|
|
3225
|
+
* before. Callers should still fall back to the original on image `error` for
|
|
3226
|
+
* the rare case where the endpoint rejects the request (e.g. a site whose
|
|
3227
|
+
* configured origin differs from the admin's).
|
|
3228
|
+
*
|
|
3229
|
+
* Returns the URL unchanged for non-raster media (an icon renders instead),
|
|
3230
|
+
* SVGs (vector — nothing to downscale, and some services reject them), and
|
|
3231
|
+
* anything not served from the local media route (external/provider URLs are
|
|
3232
|
+
* already remote renditions, not same-origin originals).
|
|
3233
|
+
*/
|
|
3234
|
+
function getMediaThumbnailUrl(originalUrl, mimeType, width = MEDIA_THUMBNAIL_WIDTH) {
|
|
3235
|
+
if (!mimeType.startsWith("image/") || mimeType === "image/svg+xml") return originalUrl;
|
|
3236
|
+
if (!originalUrl.startsWith(INTERNAL_MEDIA_PREFIX)) return originalUrl;
|
|
3237
|
+
const origin = typeof window === "undefined" ? "" : window.location.origin;
|
|
3238
|
+
if (!origin) return originalUrl;
|
|
3239
|
+
return `/_image?${new URLSearchParams({
|
|
3240
|
+
href: `${origin}${originalUrl}`,
|
|
3241
|
+
w: String(width),
|
|
3242
|
+
f: "webp"
|
|
3243
|
+
}).toString()}`;
|
|
3244
|
+
}
|
|
3245
|
+
/**
|
|
3246
|
+
* `onError` fallback for grid thumbnails: if a `/_image` rendition fails to
|
|
3247
|
+
* load (e.g. the endpoint rejects the request on a site whose configured origin
|
|
3248
|
+
* differs from the admin's), swap in the original URL once. Guarded with a data
|
|
3249
|
+
* attribute so a failing original can't trigger a reload loop.
|
|
3250
|
+
*/
|
|
3251
|
+
function fallbackToOriginalThumbnail(img, originalUrl) {
|
|
3252
|
+
if (img.dataset.thumbFallback) return;
|
|
3253
|
+
img.dataset.thumbFallback = "1";
|
|
3254
|
+
img.src = originalUrl;
|
|
3255
|
+
}
|
|
3129
3256
|
function getFileIcon(mimeType) {
|
|
3130
3257
|
if (mimeType.startsWith("video/")) return "🎬";
|
|
3131
3258
|
if (mimeType.startsWith("audio/")) return "🎵";
|
|
@@ -3352,7 +3479,10 @@ function MediaPickerModal({ open, onOpenChange, onSelect, mimeTypeFilter = "imag
|
|
|
3352
3479
|
const activeProviderInfo = React$1.useMemo(() => {
|
|
3353
3480
|
if (activeProvider === "local") return {
|
|
3354
3481
|
id: "local",
|
|
3355
|
-
name:
|
|
3482
|
+
name: _t({
|
|
3483
|
+
id: "exYcTF",
|
|
3484
|
+
message: "Library"
|
|
3485
|
+
}),
|
|
3356
3486
|
icon: void 0,
|
|
3357
3487
|
capabilities: {
|
|
3358
3488
|
browse: true,
|
|
@@ -3362,7 +3492,11 @@ function MediaPickerModal({ open, onOpenChange, onSelect, mimeTypeFilter = "imag
|
|
|
3362
3492
|
}
|
|
3363
3493
|
};
|
|
3364
3494
|
return providers?.find((p) => p.id === activeProvider);
|
|
3365
|
-
}, [
|
|
3495
|
+
}, [
|
|
3496
|
+
activeProvider,
|
|
3497
|
+
providers,
|
|
3498
|
+
_t
|
|
3499
|
+
]);
|
|
3366
3500
|
const mediaQueryKey = [
|
|
3367
3501
|
"media",
|
|
3368
3502
|
filters?.join(",") ?? "",
|
|
@@ -3580,7 +3714,10 @@ function MediaPickerModal({ open, onOpenChange, onSelect, mimeTypeFilter = "imag
|
|
|
3580
3714
|
const providerTabs = React$1.useMemo(() => {
|
|
3581
3715
|
const tabs = [{
|
|
3582
3716
|
id: "local",
|
|
3583
|
-
name:
|
|
3717
|
+
name: _t({
|
|
3718
|
+
id: "exYcTF",
|
|
3719
|
+
message: "Library"
|
|
3720
|
+
}),
|
|
3584
3721
|
icon: void 0
|
|
3585
3722
|
}];
|
|
3586
3723
|
if (providers && !localOnly) {
|
|
@@ -3591,7 +3728,11 @@ function MediaPickerModal({ open, onOpenChange, onSelect, mimeTypeFilter = "imag
|
|
|
3591
3728
|
});
|
|
3592
3729
|
}
|
|
3593
3730
|
return tabs;
|
|
3594
|
-
}, [
|
|
3731
|
+
}, [
|
|
3732
|
+
providers,
|
|
3733
|
+
localOnly,
|
|
3734
|
+
_t
|
|
3735
|
+
]);
|
|
3595
3736
|
return /* @__PURE__ */ jsx(Dialog.Root, {
|
|
3596
3737
|
open,
|
|
3597
3738
|
onOpenChange: handleClose,
|
|
@@ -3915,6 +4056,7 @@ function MediaPickerItem({ item, selected, onClick, onDoubleClick, onDimensionsD
|
|
|
3915
4056
|
const { _: _t2 } = useLingui();
|
|
3916
4057
|
const isImage = item.mimeType.startsWith("image/");
|
|
3917
4058
|
const needsDimensions = isImage && (!item.width || !item.height);
|
|
4059
|
+
const displayUrl = needsDimensions ? item.url : getMediaThumbnailUrl(item.url, item.mimeType);
|
|
3918
4060
|
const handleImageLoad = React$1.useCallback((e) => {
|
|
3919
4061
|
if (needsDimensions && onDimensionsDetected) {
|
|
3920
4062
|
const img = e.currentTarget;
|
|
@@ -3946,10 +4088,11 @@ function MediaPickerItem({ item, selected, onClick, onDoubleClick, onDimensionsD
|
|
|
3946
4088
|
}),
|
|
3947
4089
|
children: [
|
|
3948
4090
|
isImage ? /* @__PURE__ */ jsx("img", {
|
|
3949
|
-
src:
|
|
4091
|
+
src: displayUrl,
|
|
3950
4092
|
alt: "",
|
|
3951
4093
|
className: "h-full w-full object-cover",
|
|
3952
|
-
onLoad: handleImageLoad
|
|
4094
|
+
onLoad: handleImageLoad,
|
|
4095
|
+
onError: (e) => fallbackToOriginalThumbnail(e.currentTarget, item.url)
|
|
3953
4096
|
}) : /* @__PURE__ */ jsx("div", {
|
|
3954
4097
|
className: "flex h-full w-full items-center justify-center bg-kumo-tint",
|
|
3955
4098
|
children: /* @__PURE__ */ jsx("span", {
|
|
@@ -4408,6 +4551,153 @@ function DocumentOutline({ editor, className }) {
|
|
|
4408
4551
|
});
|
|
4409
4552
|
}
|
|
4410
4553
|
|
|
4554
|
+
//#endregion
|
|
4555
|
+
//#region src/components/ImageFieldRenderer.tsx
|
|
4556
|
+
/**
|
|
4557
|
+
* Image field with media picker
|
|
4558
|
+
*
|
|
4559
|
+
* Stores full image metadata including dimensions for responsive images.
|
|
4560
|
+
* Handles backwards compatibility with legacy string URLs.
|
|
4561
|
+
*
|
|
4562
|
+
* Extracted from ContentEditor so non-top-level field UIs (e.g. repeater
|
|
4563
|
+
* sub-fields) can reuse the same picker without a circular import.
|
|
4564
|
+
*/
|
|
4565
|
+
function ImageFieldRenderer({ id, label, description, value, onChange, required, allowedMimeTypes, fieldId }) {
|
|
4566
|
+
const { _: _t } = useLingui();
|
|
4567
|
+
const [pickerOpen, setPickerOpen] = React$1.useState(false);
|
|
4568
|
+
const [imageBroken, setImageBroken] = React$1.useState(false);
|
|
4569
|
+
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);
|
|
4570
|
+
React$1.useEffect(() => {
|
|
4571
|
+
setImageBroken(false);
|
|
4572
|
+
}, [displayUrl]);
|
|
4573
|
+
const handleSelect = (item) => {
|
|
4574
|
+
const isLocalProvider = !item.provider || item.provider === "local";
|
|
4575
|
+
onChange({
|
|
4576
|
+
id: item.id,
|
|
4577
|
+
provider: item.provider || "local",
|
|
4578
|
+
previewUrl: isLocalProvider ? void 0 : item.url,
|
|
4579
|
+
alt: item.alt || "",
|
|
4580
|
+
width: item.width,
|
|
4581
|
+
height: item.height,
|
|
4582
|
+
meta: isLocalProvider ? {
|
|
4583
|
+
...item.meta,
|
|
4584
|
+
storageKey: item.storageKey
|
|
4585
|
+
} : item.meta
|
|
4586
|
+
});
|
|
4587
|
+
};
|
|
4588
|
+
const handleRemove = () => {
|
|
4589
|
+
onChange(null);
|
|
4590
|
+
};
|
|
4591
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
4592
|
+
id,
|
|
4593
|
+
children: [
|
|
4594
|
+
/* @__PURE__ */ jsx(Label, { children: label }),
|
|
4595
|
+
displayUrl ? imageBroken ? /* @__PURE__ */ jsxs("div", {
|
|
4596
|
+
className: "mt-2 relative group",
|
|
4597
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
4598
|
+
className: "min-h-20 rounded-lg border bg-kumo-muted flex items-center justify-center gap-2 text-kumo-subtle",
|
|
4599
|
+
children: [/* @__PURE__ */ jsx(ImageBroken, { className: "h-5 w-5" }), /* @__PURE__ */ jsx("span", {
|
|
4600
|
+
className: "text-sm",
|
|
4601
|
+
children: _t({
|
|
4602
|
+
id: "1pdLQw",
|
|
4603
|
+
message: "Image not found"
|
|
4604
|
+
})
|
|
4605
|
+
})]
|
|
4606
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
4607
|
+
className: "absolute top-2 end-2 opacity-0 group-hover:opacity-100 transition-opacity flex gap-1",
|
|
4608
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
4609
|
+
type: "button",
|
|
4610
|
+
size: "sm",
|
|
4611
|
+
variant: "secondary",
|
|
4612
|
+
onClick: () => setPickerOpen(true),
|
|
4613
|
+
children: _t({
|
|
4614
|
+
id: "o+XJ9D",
|
|
4615
|
+
message: "Change"
|
|
4616
|
+
})
|
|
4617
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
4618
|
+
type: "button",
|
|
4619
|
+
shape: "square",
|
|
4620
|
+
variant: "destructive",
|
|
4621
|
+
className: "h-8 w-8",
|
|
4622
|
+
onClick: handleRemove,
|
|
4623
|
+
"aria-label": _t({
|
|
4624
|
+
id: "5ywtDz",
|
|
4625
|
+
message: "Remove image"
|
|
4626
|
+
}),
|
|
4627
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" })
|
|
4628
|
+
})]
|
|
4629
|
+
})]
|
|
4630
|
+
}) : /* @__PURE__ */ jsxs("div", {
|
|
4631
|
+
className: "mt-2 relative group",
|
|
4632
|
+
children: [/* @__PURE__ */ jsx("img", {
|
|
4633
|
+
src: displayUrl,
|
|
4634
|
+
alt: "",
|
|
4635
|
+
className: "max-h-48 min-h-20 rounded-lg border object-cover",
|
|
4636
|
+
onError: () => setImageBroken(true)
|
|
4637
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
4638
|
+
className: "absolute top-2 end-2 opacity-0 group-hover:opacity-100 transition-opacity flex gap-1",
|
|
4639
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
4640
|
+
type: "button",
|
|
4641
|
+
size: "sm",
|
|
4642
|
+
variant: "secondary",
|
|
4643
|
+
onClick: () => setPickerOpen(true),
|
|
4644
|
+
children: _t({
|
|
4645
|
+
id: "o+XJ9D",
|
|
4646
|
+
message: "Change"
|
|
4647
|
+
})
|
|
4648
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
4649
|
+
type: "button",
|
|
4650
|
+
shape: "square",
|
|
4651
|
+
variant: "destructive",
|
|
4652
|
+
className: "h-8 w-8",
|
|
4653
|
+
onClick: handleRemove,
|
|
4654
|
+
"aria-label": _t({
|
|
4655
|
+
id: "5ywtDz",
|
|
4656
|
+
message: "Remove image"
|
|
4657
|
+
}),
|
|
4658
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" })
|
|
4659
|
+
})]
|
|
4660
|
+
})]
|
|
4661
|
+
}) : /* @__PURE__ */ jsx(Button, {
|
|
4662
|
+
type: "button",
|
|
4663
|
+
variant: "outline",
|
|
4664
|
+
className: "mt-2 w-full h-32 border-dashed",
|
|
4665
|
+
onClick: () => setPickerOpen(true),
|
|
4666
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
4667
|
+
className: "flex flex-col items-center gap-2 text-kumo-subtle",
|
|
4668
|
+
children: [/* @__PURE__ */ jsx(Image$1, { className: "h-8 w-8" }), /* @__PURE__ */ jsx("span", { children: _t({
|
|
4669
|
+
id: "oDodff",
|
|
4670
|
+
message: "Select image"
|
|
4671
|
+
}) })]
|
|
4672
|
+
})
|
|
4673
|
+
}),
|
|
4674
|
+
/* @__PURE__ */ jsx(MediaPickerModal, {
|
|
4675
|
+
open: pickerOpen,
|
|
4676
|
+
onOpenChange: setPickerOpen,
|
|
4677
|
+
onSelect: handleSelect,
|
|
4678
|
+
mimeTypeFilters: allowedMimeTypes && allowedMimeTypes.length > 0 ? allowedMimeTypes : ["image/"],
|
|
4679
|
+
fieldId,
|
|
4680
|
+
title: _t({
|
|
4681
|
+
id: "pov/PW",
|
|
4682
|
+
message: "Select {label}",
|
|
4683
|
+
values: { label }
|
|
4684
|
+
})
|
|
4685
|
+
}),
|
|
4686
|
+
description && /* @__PURE__ */ jsx("p", {
|
|
4687
|
+
className: "text-xs text-kumo-subtle mt-1",
|
|
4688
|
+
children: description
|
|
4689
|
+
}),
|
|
4690
|
+
required && !displayUrl && /* @__PURE__ */ jsx("p", {
|
|
4691
|
+
className: "text-sm text-kumo-danger mt-1",
|
|
4692
|
+
children: _t({
|
|
4693
|
+
id: "B8AaMI",
|
|
4694
|
+
message: "This field is required"
|
|
4695
|
+
})
|
|
4696
|
+
})
|
|
4697
|
+
]
|
|
4698
|
+
});
|
|
4699
|
+
}
|
|
4700
|
+
|
|
4411
4701
|
//#endregion
|
|
4412
4702
|
//#region src/components/PluginFieldErrorBoundary.tsx
|
|
4413
4703
|
/**
|
|
@@ -4431,11 +4721,17 @@ var PluginFieldErrorBoundary = class extends React$1.Component {
|
|
|
4431
4721
|
children: [
|
|
4432
4722
|
/* @__PURE__ */ jsx("p", {
|
|
4433
4723
|
className: "text-sm font-medium text-kumo-danger",
|
|
4434
|
-
children:
|
|
4724
|
+
children: /* @__PURE__ */ jsx(Trans, {
|
|
4725
|
+
id: "zyTWI0",
|
|
4726
|
+
message: "Plugin widget error"
|
|
4727
|
+
})
|
|
4435
4728
|
}),
|
|
4436
4729
|
/* @__PURE__ */ jsx("p", {
|
|
4437
4730
|
className: "mt-1 text-xs text-kumo-subtle",
|
|
4438
|
-
children: this.state.error?.message ||
|
|
4731
|
+
children: this.state.error?.message || /* @__PURE__ */ jsx(Trans, {
|
|
4732
|
+
id: "Q/HIiC",
|
|
4733
|
+
message: "The plugin field widget failed to render."
|
|
4734
|
+
})
|
|
4439
4735
|
}),
|
|
4440
4736
|
/* @__PURE__ */ jsx("button", {
|
|
4441
4737
|
type: "button",
|
|
@@ -4444,7 +4740,10 @@ var PluginFieldErrorBoundary = class extends React$1.Component {
|
|
|
4444
4740
|
hasError: false,
|
|
4445
4741
|
error: void 0
|
|
4446
4742
|
}),
|
|
4447
|
-
children:
|
|
4743
|
+
children: /* @__PURE__ */ jsx(Trans, {
|
|
4744
|
+
id: "6gRgw8",
|
|
4745
|
+
message: "Retry"
|
|
4746
|
+
})
|
|
4448
4747
|
})
|
|
4449
4748
|
]
|
|
4450
4749
|
});
|
|
@@ -4495,7 +4794,7 @@ function RepeaterField({ label, id, value, onChange, subFields, minItems = 0, ma
|
|
|
4495
4794
|
const handleAdd = () => {
|
|
4496
4795
|
if (maxItems && items.length >= maxItems) return;
|
|
4497
4796
|
const newItem = { _key: `item-${Date.now()}` };
|
|
4498
|
-
for (const sf of subFields) newItem[sf.slug] = sf.type === "boolean" ? false : sf.type === "number" || sf.type === "integer" ? null : "";
|
|
4797
|
+
for (const sf of subFields) newItem[sf.slug] = sf.type === "boolean" ? false : sf.type === "number" || sf.type === "integer" || sf.type === "image" ? null : "";
|
|
4499
4798
|
emitChange([...items, newItem]);
|
|
4500
4799
|
};
|
|
4501
4800
|
const handleRemove = (key) => {
|
|
@@ -4703,6 +5002,12 @@ function SubFieldInput({ subField, value, onChange }) {
|
|
|
4703
5002
|
...Object.fromEntries((subField.options ?? []).map((opt) => [opt, opt]))
|
|
4704
5003
|
}
|
|
4705
5004
|
});
|
|
5005
|
+
case "image": return /* @__PURE__ */ jsx(ImageFieldRenderer, {
|
|
5006
|
+
label: subField.label,
|
|
5007
|
+
value: value != null && typeof value === "object" ? value : typeof value === "string" && value ? value : void 0,
|
|
5008
|
+
onChange: (v) => onChange(v),
|
|
5009
|
+
required: subField.required
|
|
5010
|
+
});
|
|
4706
5011
|
default: return /* @__PURE__ */ jsx(Input, {
|
|
4707
5012
|
label: subField.label,
|
|
4708
5013
|
value: typeof value === "string" ? value : "",
|
|
@@ -5683,7 +5988,10 @@ var index_default = Suggestion;
|
|
|
5683
5988
|
const CODE_BLOCK_LANGUAGES = [
|
|
5684
5989
|
{
|
|
5685
5990
|
id: "plaintext",
|
|
5686
|
-
label:
|
|
5991
|
+
label: {
|
|
5992
|
+
id: "pOo4Aa",
|
|
5993
|
+
message: "Plain text"
|
|
5994
|
+
},
|
|
5687
5995
|
aliases: [
|
|
5688
5996
|
"text",
|
|
5689
5997
|
"plain",
|
|
@@ -5692,11 +6000,17 @@ const CODE_BLOCK_LANGUAGES = [
|
|
|
5692
6000
|
},
|
|
5693
6001
|
{
|
|
5694
6002
|
id: "astro",
|
|
5695
|
-
label:
|
|
6003
|
+
label: {
|
|
6004
|
+
id: "2qNhQ4",
|
|
6005
|
+
message: "Astro"
|
|
6006
|
+
}
|
|
5696
6007
|
},
|
|
5697
6008
|
{
|
|
5698
6009
|
id: "bash",
|
|
5699
|
-
label:
|
|
6010
|
+
label: {
|
|
6011
|
+
id: "DjECRV",
|
|
6012
|
+
message: "Bash"
|
|
6013
|
+
},
|
|
5700
6014
|
aliases: [
|
|
5701
6015
|
"sh",
|
|
5702
6016
|
"shell",
|
|
@@ -5705,137 +6019,227 @@ const CODE_BLOCK_LANGUAGES = [
|
|
|
5705
6019
|
},
|
|
5706
6020
|
{
|
|
5707
6021
|
id: "c",
|
|
5708
|
-
label:
|
|
6022
|
+
label: {
|
|
6023
|
+
id: "qvh3Th",
|
|
6024
|
+
message: "C"
|
|
6025
|
+
}
|
|
5709
6026
|
},
|
|
5710
6027
|
{
|
|
5711
6028
|
id: "cpp",
|
|
5712
|
-
label:
|
|
6029
|
+
label: {
|
|
6030
|
+
id: "ZfVDhL",
|
|
6031
|
+
message: "C++"
|
|
6032
|
+
},
|
|
5713
6033
|
aliases: ["c++"]
|
|
5714
6034
|
},
|
|
5715
6035
|
{
|
|
5716
6036
|
id: "csharp",
|
|
5717
|
-
label:
|
|
6037
|
+
label: {
|
|
6038
|
+
id: "JMN/Cx",
|
|
6039
|
+
message: "C#"
|
|
6040
|
+
},
|
|
5718
6041
|
aliases: ["cs", "c#"]
|
|
5719
6042
|
},
|
|
5720
6043
|
{
|
|
5721
6044
|
id: "css",
|
|
5722
|
-
label:
|
|
6045
|
+
label: {
|
|
6046
|
+
id: "Tfspdu",
|
|
6047
|
+
message: "CSS"
|
|
6048
|
+
}
|
|
5723
6049
|
},
|
|
5724
6050
|
{
|
|
5725
6051
|
id: "diff",
|
|
5726
|
-
label:
|
|
6052
|
+
label: {
|
|
6053
|
+
id: "bspG20",
|
|
6054
|
+
message: "Diff"
|
|
6055
|
+
},
|
|
5727
6056
|
aliases: ["patch"]
|
|
5728
6057
|
},
|
|
5729
6058
|
{
|
|
5730
6059
|
id: "dockerfile",
|
|
5731
|
-
label:
|
|
6060
|
+
label: {
|
|
6061
|
+
id: "xbo2Nv",
|
|
6062
|
+
message: "Dockerfile"
|
|
6063
|
+
},
|
|
5732
6064
|
aliases: ["docker"]
|
|
5733
6065
|
},
|
|
5734
6066
|
{
|
|
5735
6067
|
id: "go",
|
|
5736
|
-
label:
|
|
6068
|
+
label: {
|
|
6069
|
+
id: "4pSxwB",
|
|
6070
|
+
message: "Go"
|
|
6071
|
+
},
|
|
5737
6072
|
aliases: ["golang"]
|
|
5738
6073
|
},
|
|
5739
6074
|
{
|
|
5740
6075
|
id: "graphql",
|
|
5741
|
-
label:
|
|
6076
|
+
label: {
|
|
6077
|
+
id: "gBiL6J",
|
|
6078
|
+
message: "GraphQL"
|
|
6079
|
+
},
|
|
5742
6080
|
aliases: ["gql"]
|
|
5743
6081
|
},
|
|
5744
6082
|
{
|
|
5745
6083
|
id: "html",
|
|
5746
|
-
label:
|
|
6084
|
+
label: {
|
|
6085
|
+
id: "FBknns",
|
|
6086
|
+
message: "HTML"
|
|
6087
|
+
}
|
|
5747
6088
|
},
|
|
5748
6089
|
{
|
|
5749
6090
|
id: "java",
|
|
5750
|
-
label:
|
|
6091
|
+
label: {
|
|
6092
|
+
id: "d/bW+Y",
|
|
6093
|
+
message: "Java"
|
|
6094
|
+
}
|
|
5751
6095
|
},
|
|
5752
6096
|
{
|
|
5753
6097
|
id: "javascript",
|
|
5754
|
-
label:
|
|
6098
|
+
label: {
|
|
6099
|
+
id: "k8pHx9",
|
|
6100
|
+
message: "JavaScript"
|
|
6101
|
+
},
|
|
5755
6102
|
aliases: ["js"]
|
|
5756
6103
|
},
|
|
5757
6104
|
{
|
|
5758
6105
|
id: "json",
|
|
5759
|
-
label:
|
|
6106
|
+
label: {
|
|
6107
|
+
id: "B2Zb/F",
|
|
6108
|
+
message: "JSON"
|
|
6109
|
+
}
|
|
5760
6110
|
},
|
|
5761
6111
|
{
|
|
5762
6112
|
id: "jsx",
|
|
5763
|
-
label:
|
|
6113
|
+
label: {
|
|
6114
|
+
id: "ijupPe",
|
|
6115
|
+
message: "JSX"
|
|
6116
|
+
}
|
|
5764
6117
|
},
|
|
5765
6118
|
{
|
|
5766
6119
|
id: "kotlin",
|
|
5767
|
-
label:
|
|
6120
|
+
label: {
|
|
6121
|
+
id: "ouqXGV",
|
|
6122
|
+
message: "Kotlin"
|
|
6123
|
+
},
|
|
5768
6124
|
aliases: ["kt"]
|
|
5769
6125
|
},
|
|
5770
6126
|
{
|
|
5771
6127
|
id: "markdown",
|
|
5772
|
-
label:
|
|
6128
|
+
label: {
|
|
6129
|
+
id: "u6Hp4N",
|
|
6130
|
+
message: "Markdown"
|
|
6131
|
+
},
|
|
5773
6132
|
aliases: ["md"]
|
|
5774
6133
|
},
|
|
5775
6134
|
{
|
|
5776
6135
|
id: "mdx",
|
|
5777
|
-
label:
|
|
6136
|
+
label: {
|
|
6137
|
+
id: "6TGIsL",
|
|
6138
|
+
message: "MDX"
|
|
6139
|
+
}
|
|
5778
6140
|
},
|
|
5779
6141
|
{
|
|
5780
6142
|
id: "php",
|
|
5781
|
-
label:
|
|
6143
|
+
label: {
|
|
6144
|
+
id: "Zw6ISu",
|
|
6145
|
+
message: "PHP"
|
|
6146
|
+
}
|
|
5782
6147
|
},
|
|
5783
6148
|
{
|
|
5784
6149
|
id: "python",
|
|
5785
|
-
label:
|
|
6150
|
+
label: {
|
|
6151
|
+
id: "zY6PMh",
|
|
6152
|
+
message: "Python"
|
|
6153
|
+
},
|
|
5786
6154
|
aliases: ["py"]
|
|
5787
6155
|
},
|
|
5788
6156
|
{
|
|
5789
6157
|
id: "ruby",
|
|
5790
|
-
label:
|
|
6158
|
+
label: {
|
|
6159
|
+
id: "7jTlsu",
|
|
6160
|
+
message: "Ruby"
|
|
6161
|
+
},
|
|
5791
6162
|
aliases: ["rb"]
|
|
5792
6163
|
},
|
|
5793
6164
|
{
|
|
5794
6165
|
id: "rust",
|
|
5795
|
-
label:
|
|
6166
|
+
label: {
|
|
6167
|
+
id: "Sc8PMh",
|
|
6168
|
+
message: "Rust"
|
|
6169
|
+
},
|
|
5796
6170
|
aliases: ["rs"]
|
|
5797
6171
|
},
|
|
5798
6172
|
{
|
|
5799
6173
|
id: "scss",
|
|
5800
|
-
label:
|
|
6174
|
+
label: {
|
|
6175
|
+
id: "xEGQEX",
|
|
6176
|
+
message: "SCSS"
|
|
6177
|
+
},
|
|
5801
6178
|
aliases: ["sass"]
|
|
5802
6179
|
},
|
|
5803
6180
|
{
|
|
5804
6181
|
id: "sql",
|
|
5805
|
-
label:
|
|
6182
|
+
label: {
|
|
6183
|
+
id: "mZT1Nu",
|
|
6184
|
+
message: "SQL"
|
|
6185
|
+
}
|
|
5806
6186
|
},
|
|
5807
6187
|
{
|
|
5808
6188
|
id: "svelte",
|
|
5809
|
-
label:
|
|
6189
|
+
label: {
|
|
6190
|
+
id: "I0X6aq",
|
|
6191
|
+
message: "Svelte"
|
|
6192
|
+
}
|
|
5810
6193
|
},
|
|
5811
6194
|
{
|
|
5812
6195
|
id: "swift",
|
|
5813
|
-
label:
|
|
6196
|
+
label: {
|
|
6197
|
+
id: "D8sGaA",
|
|
6198
|
+
message: "Swift"
|
|
6199
|
+
}
|
|
5814
6200
|
},
|
|
5815
6201
|
{
|
|
5816
6202
|
id: "toml",
|
|
5817
|
-
label:
|
|
6203
|
+
label: {
|
|
6204
|
+
id: "ZmWJqk",
|
|
6205
|
+
message: "TOML"
|
|
6206
|
+
}
|
|
5818
6207
|
},
|
|
5819
6208
|
{
|
|
5820
6209
|
id: "tsx",
|
|
5821
|
-
label:
|
|
6210
|
+
label: {
|
|
6211
|
+
id: "lFP3br",
|
|
6212
|
+
message: "TSX"
|
|
6213
|
+
}
|
|
5822
6214
|
},
|
|
5823
6215
|
{
|
|
5824
6216
|
id: "typescript",
|
|
5825
|
-
label:
|
|
6217
|
+
label: {
|
|
6218
|
+
id: "49rpnf",
|
|
6219
|
+
message: "TypeScript"
|
|
6220
|
+
},
|
|
5826
6221
|
aliases: ["ts"]
|
|
5827
6222
|
},
|
|
5828
6223
|
{
|
|
5829
6224
|
id: "vue",
|
|
5830
|
-
label:
|
|
6225
|
+
label: {
|
|
6226
|
+
id: "M6Uejz",
|
|
6227
|
+
message: "Vue"
|
|
6228
|
+
}
|
|
5831
6229
|
},
|
|
5832
6230
|
{
|
|
5833
6231
|
id: "xml",
|
|
5834
|
-
label:
|
|
6232
|
+
label: {
|
|
6233
|
+
id: "8W/ILN",
|
|
6234
|
+
message: "XML"
|
|
6235
|
+
}
|
|
5835
6236
|
},
|
|
5836
6237
|
{
|
|
5837
6238
|
id: "yaml",
|
|
5838
|
-
label:
|
|
6239
|
+
label: {
|
|
6240
|
+
id: "h51QFW",
|
|
6241
|
+
message: "YAML"
|
|
6242
|
+
},
|
|
5839
6243
|
aliases: ["yml"]
|
|
5840
6244
|
}
|
|
5841
6245
|
];
|
|
@@ -5845,11 +6249,11 @@ const CODE_BLOCK_LANGUAGES = [
|
|
|
5845
6249
|
*/
|
|
5846
6250
|
function findLanguage(value) {
|
|
5847
6251
|
if (!value) return null;
|
|
5848
|
-
const
|
|
5849
|
-
if (!
|
|
6252
|
+
const searchText = value.trim().toLowerCase();
|
|
6253
|
+
if (!searchText) return null;
|
|
5850
6254
|
for (const lang of CODE_BLOCK_LANGUAGES) {
|
|
5851
|
-
if (lang.id ===
|
|
5852
|
-
if (lang.aliases?.includes(
|
|
6255
|
+
if (lang.id === searchText) return lang;
|
|
6256
|
+
if (lang.aliases?.includes(searchText)) return lang;
|
|
5853
6257
|
}
|
|
5854
6258
|
return null;
|
|
5855
6259
|
}
|
|
@@ -5882,8 +6286,11 @@ function normalizeLanguage(value) {
|
|
|
5882
6286
|
* Human-readable label for a stored language id. Falls back to the id itself
|
|
5883
6287
|
* for unknown values so the editor never shows "undefined".
|
|
5884
6288
|
*/
|
|
5885
|
-
function
|
|
5886
|
-
if (!value) return
|
|
6289
|
+
function languageLabelDescriptor(value) {
|
|
6290
|
+
if (!value) return {
|
|
6291
|
+
id: "pOo4Aa",
|
|
6292
|
+
message: "Plain text"
|
|
6293
|
+
};
|
|
5887
6294
|
const match = findLanguage(value);
|
|
5888
6295
|
if (match) return match.label;
|
|
5889
6296
|
return value;
|
|
@@ -5906,37 +6313,51 @@ function languageLabel(value) {
|
|
|
5906
6313
|
* sanitized to a single safe CSS class token via `normalizeLanguage` so the
|
|
5907
6314
|
* frontend's `language-{id}` class stays well-formed.
|
|
5908
6315
|
*/
|
|
5909
|
-
const LANGUAGE_ITEMS = CODE_BLOCK_LANGUAGES.map((l) => l.label);
|
|
5910
|
-
function filterLanguages(item, query) {
|
|
5911
|
-
if (!query) return true;
|
|
5912
|
-
const needle = query.toLowerCase();
|
|
5913
|
-
const lang = CODE_BLOCK_LANGUAGES.find((l) => l.label === item);
|
|
5914
|
-
if (!lang) return false;
|
|
5915
|
-
if (lang.label.toLowerCase().includes(needle)) return true;
|
|
5916
|
-
if (lang.id.toLowerCase().includes(needle)) return true;
|
|
5917
|
-
return lang.aliases?.some((alias) => alias.toLowerCase().includes(needle)) ?? false;
|
|
5918
|
-
}
|
|
5919
6316
|
function CodeBlockNodeView({ node, updateAttributes, selected }) {
|
|
5920
6317
|
const { _: _t } = useLingui();
|
|
5921
6318
|
const [isEditing, setIsEditing] = React$1.useState(false);
|
|
5922
6319
|
const storedLanguage = typeof node.attrs.language === "string" ? node.attrs.language : "";
|
|
5923
|
-
const
|
|
6320
|
+
const labelText = React$1.useCallback((value) => {
|
|
6321
|
+
const label = languageLabelDescriptor(value);
|
|
6322
|
+
return typeof label === "string" ? label : _t(label);
|
|
6323
|
+
}, [_t]);
|
|
6324
|
+
const languageItems = React$1.useMemo(() => CODE_BLOCK_LANGUAGES.map((language) => _t(language.label)), [_t]);
|
|
6325
|
+
const findLanguageByDisplayLabel = React$1.useCallback((label) => CODE_BLOCK_LANGUAGES.find((language) => _t(language.label) === label), [_t]);
|
|
6326
|
+
const filterLanguages = React$1.useCallback((item, query) => {
|
|
6327
|
+
if (!query) return true;
|
|
6328
|
+
const searchText = query.toLowerCase();
|
|
6329
|
+
const lang = findLanguageByDisplayLabel(item);
|
|
6330
|
+
if (!lang) return false;
|
|
6331
|
+
if (_t(lang.label).toLowerCase().includes(searchText)) return true;
|
|
6332
|
+
if (lang.id.toLowerCase().includes(searchText)) return true;
|
|
6333
|
+
return lang.aliases?.some((alias) => alias.toLowerCase().includes(searchText)) ?? false;
|
|
6334
|
+
}, [findLanguageByDisplayLabel, _t]);
|
|
6335
|
+
const [draft, setDraft] = React$1.useState(() => labelText(storedLanguage));
|
|
5924
6336
|
const popoverRef = React$1.useRef(null);
|
|
5925
6337
|
React$1.useEffect(() => {
|
|
5926
|
-
if (!isEditing) setDraft(
|
|
5927
|
-
}, [
|
|
6338
|
+
if (!isEditing) setDraft(labelText(storedLanguage));
|
|
6339
|
+
}, [
|
|
6340
|
+
storedLanguage,
|
|
6341
|
+
isEditing,
|
|
6342
|
+
labelText
|
|
6343
|
+
]);
|
|
5928
6344
|
const openPicker = React$1.useCallback(() => {
|
|
5929
|
-
setDraft(storedLanguage ?
|
|
6345
|
+
setDraft(storedLanguage ? labelText(storedLanguage) : "");
|
|
5930
6346
|
setIsEditing(true);
|
|
5931
|
-
}, [storedLanguage]);
|
|
6347
|
+
}, [storedLanguage, labelText]);
|
|
5932
6348
|
const closePicker = React$1.useCallback(() => {
|
|
5933
6349
|
setIsEditing(false);
|
|
5934
|
-
setDraft(
|
|
5935
|
-
}, [storedLanguage]);
|
|
6350
|
+
setDraft(labelText(storedLanguage));
|
|
6351
|
+
}, [storedLanguage, labelText]);
|
|
5936
6352
|
const commit = React$1.useCallback((value) => {
|
|
5937
|
-
|
|
6353
|
+
const raw = value ?? draft;
|
|
6354
|
+
updateAttributes({ language: findLanguageByDisplayLabel(raw)?.id ?? normalizeLanguage(raw) ?? null });
|
|
5938
6355
|
setIsEditing(false);
|
|
5939
|
-
}, [
|
|
6356
|
+
}, [
|
|
6357
|
+
draft,
|
|
6358
|
+
findLanguageByDisplayLabel,
|
|
6359
|
+
updateAttributes
|
|
6360
|
+
]);
|
|
5940
6361
|
const handleKeyDown = (e) => {
|
|
5941
6362
|
if (e.key === "Enter") {
|
|
5942
6363
|
e.preventDefault();
|
|
@@ -5955,7 +6376,7 @@ function CodeBlockNodeView({ node, updateAttributes, selected }) {
|
|
|
5955
6376
|
document.addEventListener("mousedown", onMouseDown);
|
|
5956
6377
|
return () => document.removeEventListener("mousedown", onMouseDown);
|
|
5957
6378
|
}, [isEditing, closePicker]);
|
|
5958
|
-
const label =
|
|
6379
|
+
const label = labelText(storedLanguage);
|
|
5959
6380
|
const chipPersistent = isEditing || Boolean(storedLanguage) || selected;
|
|
5960
6381
|
return /* @__PURE__ */ jsxs(NodeViewWrapper, {
|
|
5961
6382
|
className: "group relative my-4",
|
|
@@ -5972,7 +6393,7 @@ function CodeBlockNodeView({ node, updateAttributes, selected }) {
|
|
|
5972
6393
|
onKeyDown: handleKeyDown,
|
|
5973
6394
|
children: [
|
|
5974
6395
|
/* @__PURE__ */ jsxs(Autocomplete, {
|
|
5975
|
-
items:
|
|
6396
|
+
items: languageItems,
|
|
5976
6397
|
value: draft,
|
|
5977
6398
|
onValueChange: (next) => setDraft(next),
|
|
5978
6399
|
filter: filterLanguages,
|
|
@@ -11711,8 +12132,7 @@ function ContentEditor({ collection, collectionLabel, item, fields, isNew, entry
|
|
|
11711
12132
|
className: "mt-1 flex flex-wrap items-center gap-1.5",
|
|
11712
12133
|
children: supportsDrafts ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
11713
12134
|
isLive && /* @__PURE__ */ jsx(Badge, {
|
|
11714
|
-
variant: "
|
|
11715
|
-
className: "text-white",
|
|
12135
|
+
variant: "success",
|
|
11716
12136
|
children: _t({
|
|
11717
12137
|
id: "u3wRF+",
|
|
11718
12138
|
message: "Published"
|
|
@@ -12295,141 +12715,6 @@ function JsonFieldEditor({ label, id, value, onChange, required }) {
|
|
|
12295
12715
|
children: error
|
|
12296
12716
|
})] });
|
|
12297
12717
|
}
|
|
12298
|
-
function ImageFieldRenderer({ id, label, description, value, onChange, required, allowedMimeTypes, fieldId }) {
|
|
12299
|
-
const { _: _t5 } = useLingui();
|
|
12300
|
-
const [pickerOpen, setPickerOpen] = React$1.useState(false);
|
|
12301
|
-
const [imageBroken, setImageBroken] = React$1.useState(false);
|
|
12302
|
-
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);
|
|
12303
|
-
React$1.useEffect(() => {
|
|
12304
|
-
setImageBroken(false);
|
|
12305
|
-
}, [displayUrl]);
|
|
12306
|
-
const handleSelect = (item) => {
|
|
12307
|
-
const isLocalProvider = !item.provider || item.provider === "local";
|
|
12308
|
-
onChange({
|
|
12309
|
-
id: item.id,
|
|
12310
|
-
provider: item.provider || "local",
|
|
12311
|
-
previewUrl: isLocalProvider ? void 0 : item.url,
|
|
12312
|
-
alt: item.alt || "",
|
|
12313
|
-
width: item.width,
|
|
12314
|
-
height: item.height,
|
|
12315
|
-
meta: isLocalProvider ? {
|
|
12316
|
-
...item.meta,
|
|
12317
|
-
storageKey: item.storageKey
|
|
12318
|
-
} : item.meta
|
|
12319
|
-
});
|
|
12320
|
-
};
|
|
12321
|
-
const handleRemove = () => {
|
|
12322
|
-
onChange(null);
|
|
12323
|
-
};
|
|
12324
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
12325
|
-
id,
|
|
12326
|
-
children: [
|
|
12327
|
-
/* @__PURE__ */ jsx(Label, { children: label }),
|
|
12328
|
-
displayUrl ? imageBroken ? /* @__PURE__ */ jsxs("div", {
|
|
12329
|
-
className: "mt-2 relative group",
|
|
12330
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
12331
|
-
className: "min-h-20 rounded-lg border bg-kumo-muted flex items-center justify-center gap-2 text-kumo-subtle",
|
|
12332
|
-
children: [/* @__PURE__ */ jsx(ImageBroken, { className: "h-5 w-5" }), /* @__PURE__ */ jsx("span", {
|
|
12333
|
-
className: "text-sm",
|
|
12334
|
-
children: _t5({
|
|
12335
|
-
id: "1pdLQw",
|
|
12336
|
-
message: "Image not found"
|
|
12337
|
-
})
|
|
12338
|
-
})]
|
|
12339
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
12340
|
-
className: "absolute top-2 end-2 opacity-0 group-hover:opacity-100 transition-opacity flex gap-1",
|
|
12341
|
-
children: [/* @__PURE__ */ jsx(Button, {
|
|
12342
|
-
type: "button",
|
|
12343
|
-
size: "sm",
|
|
12344
|
-
variant: "secondary",
|
|
12345
|
-
onClick: () => setPickerOpen(true),
|
|
12346
|
-
children: _t5({
|
|
12347
|
-
id: "o+XJ9D",
|
|
12348
|
-
message: "Change"
|
|
12349
|
-
})
|
|
12350
|
-
}), /* @__PURE__ */ jsx(Button, {
|
|
12351
|
-
type: "button",
|
|
12352
|
-
shape: "square",
|
|
12353
|
-
variant: "destructive",
|
|
12354
|
-
className: "h-8 w-8",
|
|
12355
|
-
onClick: handleRemove,
|
|
12356
|
-
"aria-label": _t5({
|
|
12357
|
-
id: "5ywtDz",
|
|
12358
|
-
message: "Remove image"
|
|
12359
|
-
}),
|
|
12360
|
-
children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" })
|
|
12361
|
-
})]
|
|
12362
|
-
})]
|
|
12363
|
-
}) : /* @__PURE__ */ jsxs("div", {
|
|
12364
|
-
className: "mt-2 relative group",
|
|
12365
|
-
children: [/* @__PURE__ */ jsx("img", {
|
|
12366
|
-
src: displayUrl,
|
|
12367
|
-
alt: "",
|
|
12368
|
-
className: "max-h-48 min-h-20 rounded-lg border object-cover",
|
|
12369
|
-
onError: () => setImageBroken(true)
|
|
12370
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
12371
|
-
className: "absolute top-2 end-2 opacity-0 group-hover:opacity-100 transition-opacity flex gap-1",
|
|
12372
|
-
children: [/* @__PURE__ */ jsx(Button, {
|
|
12373
|
-
type: "button",
|
|
12374
|
-
size: "sm",
|
|
12375
|
-
variant: "secondary",
|
|
12376
|
-
onClick: () => setPickerOpen(true),
|
|
12377
|
-
children: _t5({
|
|
12378
|
-
id: "o+XJ9D",
|
|
12379
|
-
message: "Change"
|
|
12380
|
-
})
|
|
12381
|
-
}), /* @__PURE__ */ jsx(Button, {
|
|
12382
|
-
type: "button",
|
|
12383
|
-
shape: "square",
|
|
12384
|
-
variant: "destructive",
|
|
12385
|
-
className: "h-8 w-8",
|
|
12386
|
-
onClick: handleRemove,
|
|
12387
|
-
"aria-label": _t5({
|
|
12388
|
-
id: "5ywtDz",
|
|
12389
|
-
message: "Remove image"
|
|
12390
|
-
}),
|
|
12391
|
-
children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" })
|
|
12392
|
-
})]
|
|
12393
|
-
})]
|
|
12394
|
-
}) : /* @__PURE__ */ jsx(Button, {
|
|
12395
|
-
type: "button",
|
|
12396
|
-
variant: "outline",
|
|
12397
|
-
className: "mt-2 w-full h-32 border-dashed",
|
|
12398
|
-
onClick: () => setPickerOpen(true),
|
|
12399
|
-
children: /* @__PURE__ */ jsxs("div", {
|
|
12400
|
-
className: "flex flex-col items-center gap-2 text-kumo-subtle",
|
|
12401
|
-
children: [/* @__PURE__ */ jsx(Image$1, { className: "h-8 w-8" }), /* @__PURE__ */ jsx("span", { children: _t5({
|
|
12402
|
-
id: "oDodff",
|
|
12403
|
-
message: "Select image"
|
|
12404
|
-
}) })]
|
|
12405
|
-
})
|
|
12406
|
-
}),
|
|
12407
|
-
/* @__PURE__ */ jsx(MediaPickerModal, {
|
|
12408
|
-
open: pickerOpen,
|
|
12409
|
-
onOpenChange: setPickerOpen,
|
|
12410
|
-
onSelect: handleSelect,
|
|
12411
|
-
mimeTypeFilters: allowedMimeTypes && allowedMimeTypes.length > 0 ? allowedMimeTypes : ["image/"],
|
|
12412
|
-
fieldId,
|
|
12413
|
-
title: _t5({
|
|
12414
|
-
id: "pov/PW",
|
|
12415
|
-
message: "Select {label}",
|
|
12416
|
-
values: { label }
|
|
12417
|
-
})
|
|
12418
|
-
}),
|
|
12419
|
-
description && /* @__PURE__ */ jsx("p", {
|
|
12420
|
-
className: "text-xs text-kumo-subtle mt-1",
|
|
12421
|
-
children: description
|
|
12422
|
-
}),
|
|
12423
|
-
required && !displayUrl && /* @__PURE__ */ jsx("p", {
|
|
12424
|
-
className: "text-sm text-kumo-danger mt-1",
|
|
12425
|
-
children: _t5({
|
|
12426
|
-
id: "B8AaMI",
|
|
12427
|
-
message: "This field is required"
|
|
12428
|
-
})
|
|
12429
|
-
})
|
|
12430
|
-
]
|
|
12431
|
-
});
|
|
12432
|
-
}
|
|
12433
12718
|
/**
|
|
12434
12719
|
* File field with media picker
|
|
12435
12720
|
*
|
|
@@ -12437,7 +12722,7 @@ function ImageFieldRenderer({ id, label, description, value, onChange, required,
|
|
|
12437
12722
|
* icon, filename, and size instead of an image preview.
|
|
12438
12723
|
*/
|
|
12439
12724
|
function FileFieldRenderer({ id, label, value, onChange, required, allowedMimeTypes, fieldId }) {
|
|
12440
|
-
const { _:
|
|
12725
|
+
const { _: _t5 } = useLingui();
|
|
12441
12726
|
const [pickerOpen, setPickerOpen] = React$1.useState(false);
|
|
12442
12727
|
const normalized = React$1.useMemo(() => {
|
|
12443
12728
|
if (!value) return null;
|
|
@@ -12448,14 +12733,14 @@ function FileFieldRenderer({ id, label, value, onChange, required, allowedMimeTy
|
|
|
12448
12733
|
const externalUrl = !isLocal && value.src && isSafeUrl$1(value.src) ? value.src : void 0;
|
|
12449
12734
|
return {
|
|
12450
12735
|
displayUrl: localUrl ?? externalUrl,
|
|
12451
|
-
filename: value.filename ||
|
|
12736
|
+
filename: value.filename || _t5({
|
|
12452
12737
|
id: "cChtk1",
|
|
12453
12738
|
message: "Untitled file"
|
|
12454
12739
|
}),
|
|
12455
12740
|
mimeType: value.mimeType || "",
|
|
12456
12741
|
size: value.size
|
|
12457
12742
|
};
|
|
12458
|
-
}, [value,
|
|
12743
|
+
}, [value, _t5]);
|
|
12459
12744
|
const handleSelect = (item) => {
|
|
12460
12745
|
const isLocalProvider = !item.provider || item.provider === "local";
|
|
12461
12746
|
onChange({
|
|
@@ -12516,7 +12801,7 @@ function FileFieldRenderer({ id, label, value, onChange, required, allowedMimeTy
|
|
|
12516
12801
|
size: "sm",
|
|
12517
12802
|
variant: "secondary",
|
|
12518
12803
|
onClick: () => setPickerOpen(true),
|
|
12519
|
-
children:
|
|
12804
|
+
children: _t5({
|
|
12520
12805
|
id: "o+XJ9D",
|
|
12521
12806
|
message: "Change"
|
|
12522
12807
|
})
|
|
@@ -12526,7 +12811,7 @@ function FileFieldRenderer({ id, label, value, onChange, required, allowedMimeTy
|
|
|
12526
12811
|
variant: "destructive",
|
|
12527
12812
|
className: "h-8 w-8",
|
|
12528
12813
|
onClick: handleRemove,
|
|
12529
|
-
"aria-label":
|
|
12814
|
+
"aria-label": _t5({
|
|
12530
12815
|
id: "HND1q3",
|
|
12531
12816
|
message: "Remove {label}",
|
|
12532
12817
|
values: { label }
|
|
@@ -12540,14 +12825,14 @@ function FileFieldRenderer({ id, label, value, onChange, required, allowedMimeTy
|
|
|
12540
12825
|
variant: "outline",
|
|
12541
12826
|
className: "mt-2 w-full h-32 border-dashed",
|
|
12542
12827
|
onClick: () => setPickerOpen(true),
|
|
12543
|
-
"aria-label":
|
|
12828
|
+
"aria-label": _t5({
|
|
12544
12829
|
id: "pov/PW",
|
|
12545
12830
|
message: "Select {label}",
|
|
12546
12831
|
values: { label }
|
|
12547
12832
|
}),
|
|
12548
12833
|
children: /* @__PURE__ */ jsxs("div", {
|
|
12549
12834
|
className: "flex flex-col items-center gap-2 text-kumo-subtle",
|
|
12550
|
-
children: [/* @__PURE__ */ jsx(Paperclip, { className: "h-8 w-8" }), /* @__PURE__ */ jsx("span", { children:
|
|
12835
|
+
children: [/* @__PURE__ */ jsx(Paperclip, { className: "h-8 w-8" }), /* @__PURE__ */ jsx("span", { children: _t5({
|
|
12551
12836
|
id: "J6WI1B",
|
|
12552
12837
|
message: "Select file"
|
|
12553
12838
|
}) })]
|
|
@@ -12561,7 +12846,7 @@ function FileFieldRenderer({ id, label, value, onChange, required, allowedMimeTy
|
|
|
12561
12846
|
fieldId,
|
|
12562
12847
|
hideUrlInput: true,
|
|
12563
12848
|
mediaKind: "file",
|
|
12564
|
-
title:
|
|
12849
|
+
title: _t5({
|
|
12565
12850
|
id: "pov/PW",
|
|
12566
12851
|
message: "Select {label}",
|
|
12567
12852
|
values: { label }
|
|
@@ -12569,7 +12854,7 @@ function FileFieldRenderer({ id, label, value, onChange, required, allowedMimeTy
|
|
|
12569
12854
|
}),
|
|
12570
12855
|
required && !normalized && /* @__PURE__ */ jsx("p", {
|
|
12571
12856
|
className: "text-sm text-kumo-danger mt-1",
|
|
12572
|
-
children:
|
|
12857
|
+
children: _t5({
|
|
12573
12858
|
id: "B8AaMI",
|
|
12574
12859
|
message: "This field is required"
|
|
12575
12860
|
})
|
|
@@ -12578,7 +12863,7 @@ function FileFieldRenderer({ id, label, value, onChange, required, allowedMimeTy
|
|
|
12578
12863
|
});
|
|
12579
12864
|
}
|
|
12580
12865
|
function BylineCreditsEditor({ credits, bylines, selectedBylineDetails, onChange, onQuickCreate, onQuickEdit, entryLocale, i18n, bylinesLoaded = true }) {
|
|
12581
|
-
const { _:
|
|
12866
|
+
const { _: _t6 } = useLingui();
|
|
12582
12867
|
const [search, setSearch] = React$1.useState("");
|
|
12583
12868
|
const debouncedSearch = useDebouncedValue$1(search, 300);
|
|
12584
12869
|
const [quickName, setQuickName] = React$1.useState("");
|
|
@@ -12661,7 +12946,7 @@ function BylineCreditsEditor({ credits, bylines, selectedBylineDetails, onChange
|
|
|
12661
12946
|
className: "rounded border border-dashed p-3 text-sm space-y-2",
|
|
12662
12947
|
children: [/* @__PURE__ */ jsx("p", {
|
|
12663
12948
|
className: "text-kumo-subtle",
|
|
12664
|
-
children:
|
|
12949
|
+
children: _t6({
|
|
12665
12950
|
id: "Tmb8Fw",
|
|
12666
12951
|
message: "No bylines available in {entryLocale}. Create a variant from the Bylines page before crediting one on this entry.",
|
|
12667
12952
|
values: { entryLocale }
|
|
@@ -12671,7 +12956,7 @@ function BylineCreditsEditor({ credits, bylines, selectedBylineDetails, onChange
|
|
|
12671
12956
|
search: { locale: entryLocale ?? void 0 },
|
|
12672
12957
|
variant: "secondary",
|
|
12673
12958
|
size: "sm",
|
|
12674
|
-
children:
|
|
12959
|
+
children: _t6({
|
|
12675
12960
|
id: "yXD9HA",
|
|
12676
12961
|
message: "Manage bylines in {entryLocale}",
|
|
12677
12962
|
values: { entryLocale }
|
|
@@ -12684,18 +12969,18 @@ function BylineCreditsEditor({ credits, bylines, selectedBylineDetails, onChange
|
|
|
12684
12969
|
/* @__PURE__ */ jsx(Input, {
|
|
12685
12970
|
value: search,
|
|
12686
12971
|
onChange: (e) => setSearch(e.target.value),
|
|
12687
|
-
placeholder:
|
|
12972
|
+
placeholder: _t6({
|
|
12688
12973
|
id: "96Um6i",
|
|
12689
12974
|
message: "Search bylines to add..."
|
|
12690
12975
|
}),
|
|
12691
|
-
"aria-label":
|
|
12976
|
+
"aria-label": _t6({
|
|
12692
12977
|
id: "4L2LjM",
|
|
12693
12978
|
message: "Search bylines"
|
|
12694
12979
|
})
|
|
12695
12980
|
}),
|
|
12696
12981
|
searchEnabled && searchResults.isLoading ? /* @__PURE__ */ jsx("p", {
|
|
12697
12982
|
className: "text-sm text-kumo-subtle",
|
|
12698
|
-
children:
|
|
12983
|
+
children: _t6({
|
|
12699
12984
|
id: "Du+zn+",
|
|
12700
12985
|
message: "Searching..."
|
|
12701
12986
|
})
|
|
@@ -12716,7 +13001,7 @@ function BylineCreditsEditor({ credits, bylines, selectedBylineDetails, onChange
|
|
|
12716
13001
|
})]
|
|
12717
13002
|
}), /* @__PURE__ */ jsx("span", {
|
|
12718
13003
|
className: "text-xs text-kumo-subtle",
|
|
12719
|
-
children:
|
|
13004
|
+
children: _t6({
|
|
12720
13005
|
id: "m16xKo",
|
|
12721
13006
|
message: "Add"
|
|
12722
13007
|
})
|
|
@@ -12724,20 +13009,20 @@ function BylineCreditsEditor({ credits, bylines, selectedBylineDetails, onChange
|
|
|
12724
13009
|
}) }, b.id))
|
|
12725
13010
|
}) : searchEnabled && searchResults.isError ? /* @__PURE__ */ jsx("p", {
|
|
12726
13011
|
className: "text-sm text-kumo-danger",
|
|
12727
|
-
children:
|
|
13012
|
+
children: _t6({
|
|
12728
13013
|
id: "617r+T",
|
|
12729
13014
|
message: "Couldn't search bylines. Please try again."
|
|
12730
13015
|
})
|
|
12731
13016
|
}) : searchEnabled ? /* @__PURE__ */ jsx("p", {
|
|
12732
13017
|
className: "text-sm text-kumo-subtle",
|
|
12733
|
-
children:
|
|
13018
|
+
children: _t6({
|
|
12734
13019
|
id: "ncgkI9",
|
|
12735
13020
|
message: "No matching bylines."
|
|
12736
13021
|
})
|
|
12737
13022
|
}) : null,
|
|
12738
13023
|
hasMoreResults && /* @__PURE__ */ jsx("p", {
|
|
12739
13024
|
className: "text-xs text-kumo-subtle",
|
|
12740
|
-
children:
|
|
13025
|
+
children: _t6({
|
|
12741
13026
|
id: "7Jpj2/",
|
|
12742
13027
|
message: "Keep typing to narrow down more bylines."
|
|
12743
13028
|
})
|
|
@@ -12767,7 +13052,7 @@ function BylineCreditsEditor({ credits, bylines, selectedBylineDetails, onChange
|
|
|
12767
13052
|
variant: "ghost",
|
|
12768
13053
|
size: "sm",
|
|
12769
13054
|
onClick: () => move(index, -1),
|
|
12770
|
-
children:
|
|
13055
|
+
children: _t6({
|
|
12771
13056
|
id: "n+PHuv",
|
|
12772
13057
|
message: "Up"
|
|
12773
13058
|
})
|
|
@@ -12777,7 +13062,7 @@ function BylineCreditsEditor({ credits, bylines, selectedBylineDetails, onChange
|
|
|
12777
13062
|
variant: "ghost",
|
|
12778
13063
|
size: "sm",
|
|
12779
13064
|
onClick: () => move(index, 1),
|
|
12780
|
-
children:
|
|
13065
|
+
children: _t6({
|
|
12781
13066
|
id: "gUjkl/",
|
|
12782
13067
|
message: "Down"
|
|
12783
13068
|
})
|
|
@@ -12787,7 +13072,7 @@ function BylineCreditsEditor({ credits, bylines, selectedBylineDetails, onChange
|
|
|
12787
13072
|
variant: "ghost",
|
|
12788
13073
|
size: "sm",
|
|
12789
13074
|
onClick: () => openEditByline(byline),
|
|
12790
|
-
children:
|
|
13075
|
+
children: _t6({
|
|
12791
13076
|
id: "ePK91l",
|
|
12792
13077
|
message: "Edit"
|
|
12793
13078
|
})
|
|
@@ -12797,7 +13082,7 @@ function BylineCreditsEditor({ credits, bylines, selectedBylineDetails, onChange
|
|
|
12797
13082
|
variant: "destructive",
|
|
12798
13083
|
size: "sm",
|
|
12799
13084
|
onClick: () => onChange(credits.filter((_, i) => i !== index)),
|
|
12800
|
-
children:
|
|
13085
|
+
children: _t6({
|
|
12801
13086
|
id: "t/YqKh",
|
|
12802
13087
|
message: "Remove"
|
|
12803
13088
|
})
|
|
@@ -12805,7 +13090,7 @@ function BylineCreditsEditor({ credits, bylines, selectedBylineDetails, onChange
|
|
|
12805
13090
|
]
|
|
12806
13091
|
})]
|
|
12807
13092
|
}), /* @__PURE__ */ jsx(Input, {
|
|
12808
|
-
label:
|
|
13093
|
+
label: _t6({
|
|
12809
13094
|
id: "QeScoL",
|
|
12810
13095
|
message: "Role label"
|
|
12811
13096
|
}),
|
|
@@ -12825,7 +13110,7 @@ function BylineCreditsEditor({ credits, bylines, selectedBylineDetails, onChange
|
|
|
12825
13110
|
})
|
|
12826
13111
|
}) : /* @__PURE__ */ jsx("p", {
|
|
12827
13112
|
className: "text-sm text-kumo-subtle",
|
|
12828
|
-
children:
|
|
13113
|
+
children: _t6({
|
|
12829
13114
|
id: "dyZY24",
|
|
12830
13115
|
message: "No bylines selected."
|
|
12831
13116
|
})
|
|
@@ -12834,7 +13119,7 @@ function BylineCreditsEditor({ credits, bylines, selectedBylineDetails, onChange
|
|
|
12834
13119
|
...p,
|
|
12835
13120
|
type: "button",
|
|
12836
13121
|
variant: "secondary",
|
|
12837
|
-
children:
|
|
13122
|
+
children: _t6({
|
|
12838
13123
|
id: "gqa8eq",
|
|
12839
13124
|
message: "Quick create byline"
|
|
12840
13125
|
})
|
|
@@ -12844,7 +13129,7 @@ function BylineCreditsEditor({ credits, bylines, selectedBylineDetails, onChange
|
|
|
12844
13129
|
children: [
|
|
12845
13130
|
/* @__PURE__ */ jsx(Dialog.Title, {
|
|
12846
13131
|
className: "text-lg font-semibold",
|
|
12847
|
-
children:
|
|
13132
|
+
children: _t6({
|
|
12848
13133
|
id: "d6HWlw",
|
|
12849
13134
|
message: "Create byline"
|
|
12850
13135
|
})
|
|
@@ -12853,7 +13138,7 @@ function BylineCreditsEditor({ credits, bylines, selectedBylineDetails, onChange
|
|
|
12853
13138
|
className: "mt-4 space-y-3",
|
|
12854
13139
|
children: [
|
|
12855
13140
|
/* @__PURE__ */ jsx(Input, {
|
|
12856
|
-
label:
|
|
13141
|
+
label: _t6({
|
|
12857
13142
|
id: "pfa8F0",
|
|
12858
13143
|
message: "Display name"
|
|
12859
13144
|
}),
|
|
@@ -12864,7 +13149,7 @@ function BylineCreditsEditor({ credits, bylines, selectedBylineDetails, onChange
|
|
|
12864
13149
|
}
|
|
12865
13150
|
}),
|
|
12866
13151
|
/* @__PURE__ */ jsx(Input, {
|
|
12867
|
-
label:
|
|
13152
|
+
label: _t6({
|
|
12868
13153
|
id: "L85WcV",
|
|
12869
13154
|
message: "Slug"
|
|
12870
13155
|
}),
|
|
@@ -12886,7 +13171,7 @@ function BylineCreditsEditor({ credits, bylines, selectedBylineDetails, onChange
|
|
|
12886
13171
|
resetQuickCreate();
|
|
12887
13172
|
p.onClick?.(e);
|
|
12888
13173
|
},
|
|
12889
|
-
children:
|
|
13174
|
+
children: _t6({
|
|
12890
13175
|
id: "dEgA5A",
|
|
12891
13176
|
message: "Cancel"
|
|
12892
13177
|
})
|
|
@@ -12907,7 +13192,7 @@ function BylineCreditsEditor({ credits, bylines, selectedBylineDetails, onChange
|
|
|
12907
13192
|
}]);
|
|
12908
13193
|
resetQuickCreate();
|
|
12909
13194
|
} catch (err) {
|
|
12910
|
-
setQuickError(err instanceof Error ? err.message :
|
|
13195
|
+
setQuickError(err instanceof Error ? err.message : _t6({
|
|
12911
13196
|
id: "Kd9Ewv",
|
|
12912
13197
|
message: "Failed to create byline"
|
|
12913
13198
|
}));
|
|
@@ -12915,10 +13200,10 @@ function BylineCreditsEditor({ credits, bylines, selectedBylineDetails, onChange
|
|
|
12915
13200
|
setIsCreating(false);
|
|
12916
13201
|
}
|
|
12917
13202
|
},
|
|
12918
|
-
children: isCreating ?
|
|
13203
|
+
children: isCreating ? _t6({
|
|
12919
13204
|
id: "HM56Bx",
|
|
12920
13205
|
message: "Creating..."
|
|
12921
|
-
}) :
|
|
13206
|
+
}) : _t6({
|
|
12922
13207
|
id: "hYgDIe",
|
|
12923
13208
|
message: "Create"
|
|
12924
13209
|
})
|
|
@@ -12935,7 +13220,7 @@ function BylineCreditsEditor({ credits, bylines, selectedBylineDetails, onChange
|
|
|
12935
13220
|
children: [
|
|
12936
13221
|
/* @__PURE__ */ jsx(Dialog.Title, {
|
|
12937
13222
|
className: "text-lg font-semibold",
|
|
12938
|
-
children:
|
|
13223
|
+
children: _t6({
|
|
12939
13224
|
id: "d9lVyw",
|
|
12940
13225
|
message: "Edit byline"
|
|
12941
13226
|
})
|
|
@@ -12944,7 +13229,7 @@ function BylineCreditsEditor({ credits, bylines, selectedBylineDetails, onChange
|
|
|
12944
13229
|
className: "mt-4 space-y-3",
|
|
12945
13230
|
children: [
|
|
12946
13231
|
/* @__PURE__ */ jsx(Input, {
|
|
12947
|
-
label:
|
|
13232
|
+
label: _t6({
|
|
12948
13233
|
id: "pfa8F0",
|
|
12949
13234
|
message: "Display name"
|
|
12950
13235
|
}),
|
|
@@ -12955,7 +13240,7 @@ function BylineCreditsEditor({ credits, bylines, selectedBylineDetails, onChange
|
|
|
12955
13240
|
}
|
|
12956
13241
|
}),
|
|
12957
13242
|
/* @__PURE__ */ jsx(Input, {
|
|
12958
|
-
label:
|
|
13243
|
+
label: _t6({
|
|
12959
13244
|
id: "L85WcV",
|
|
12960
13245
|
message: "Slug"
|
|
12961
13246
|
}),
|
|
@@ -12974,7 +13259,7 @@ function BylineCreditsEditor({ credits, bylines, selectedBylineDetails, onChange
|
|
|
12974
13259
|
type: "button",
|
|
12975
13260
|
variant: "secondary",
|
|
12976
13261
|
onClick: resetQuickEdit,
|
|
12977
|
-
children:
|
|
13262
|
+
children: _t6({
|
|
12978
13263
|
id: "dEgA5A",
|
|
12979
13264
|
message: "Cancel"
|
|
12980
13265
|
})
|
|
@@ -12991,7 +13276,7 @@ function BylineCreditsEditor({ credits, bylines, selectedBylineDetails, onChange
|
|
|
12991
13276
|
});
|
|
12992
13277
|
resetQuickEdit();
|
|
12993
13278
|
} catch (err) {
|
|
12994
|
-
setEditError(err instanceof Error ? err.message :
|
|
13279
|
+
setEditError(err instanceof Error ? err.message : _t6({
|
|
12995
13280
|
id: "fd6o+d",
|
|
12996
13281
|
message: "Failed to update byline"
|
|
12997
13282
|
}));
|
|
@@ -12999,10 +13284,10 @@ function BylineCreditsEditor({ credits, bylines, selectedBylineDetails, onChange
|
|
|
12999
13284
|
setIsEditing(false);
|
|
13000
13285
|
}
|
|
13001
13286
|
},
|
|
13002
|
-
children: isEditing ?
|
|
13287
|
+
children: isEditing ? _t6({
|
|
13003
13288
|
id: "XvjC4F",
|
|
13004
13289
|
message: "Saving..."
|
|
13005
|
-
}) :
|
|
13290
|
+
}) : _t6({
|
|
13006
13291
|
id: "tfDRzk",
|
|
13007
13292
|
message: "Save"
|
|
13008
13293
|
})
|
|
@@ -13015,9 +13300,9 @@ function BylineCreditsEditor({ credits, bylines, selectedBylineDetails, onChange
|
|
|
13015
13300
|
});
|
|
13016
13301
|
}
|
|
13017
13302
|
function AuthorSelector({ authorId, users, onChange }) {
|
|
13018
|
-
const { _:
|
|
13303
|
+
const { _: _t7 } = useLingui();
|
|
13019
13304
|
const currentAuthor = users.find((u) => u.id === authorId);
|
|
13020
|
-
const authorItems = { unassigned:
|
|
13305
|
+
const authorItems = { unassigned: _t7({
|
|
13021
13306
|
id: "EbMPZJ",
|
|
13022
13307
|
message: "Unassigned"
|
|
13023
13308
|
}) };
|
|
@@ -13032,7 +13317,7 @@ function AuthorSelector({ authorId, users, onChange }) {
|
|
|
13032
13317
|
value: "unassigned",
|
|
13033
13318
|
children: /* @__PURE__ */ jsx("span", {
|
|
13034
13319
|
className: "text-kumo-subtle",
|
|
13035
|
-
children:
|
|
13320
|
+
children: _t7({
|
|
13036
13321
|
id: "EbMPZJ",
|
|
13037
13322
|
message: "Unassigned"
|
|
13038
13323
|
})
|
|
@@ -14952,6 +15237,10 @@ function FieldEditor({ open, onOpenChange, field, onSave, isSaving }) {
|
|
|
14952
15237
|
url: _t({
|
|
14953
15238
|
id: "IagCbF",
|
|
14954
15239
|
message: "URL"
|
|
15240
|
+
}),
|
|
15241
|
+
image: _t({
|
|
15242
|
+
id: "hG89Ed",
|
|
15243
|
+
message: "Image"
|
|
14955
15244
|
})
|
|
14956
15245
|
}
|
|
14957
15246
|
}) })]
|
|
@@ -15375,7 +15664,10 @@ function ContentTypeEditor({ collection, isNew, isSaving, onSave, onAddField, on
|
|
|
15375
15664
|
}),
|
|
15376
15665
|
value: labelSingular,
|
|
15377
15666
|
onChange: (e) => handleSingularLabelChange(e.target.value),
|
|
15378
|
-
placeholder:
|
|
15667
|
+
placeholder: _t({
|
|
15668
|
+
id: "y28hnO",
|
|
15669
|
+
message: "Post"
|
|
15670
|
+
}),
|
|
15379
15671
|
disabled: isFromCode
|
|
15380
15672
|
}),
|
|
15381
15673
|
/* @__PURE__ */ jsx(Input, {
|
|
@@ -15385,7 +15677,10 @@ function ContentTypeEditor({ collection, isNew, isSaving, onSave, onAddField, on
|
|
|
15385
15677
|
}),
|
|
15386
15678
|
value: label,
|
|
15387
15679
|
onChange: (e) => handleLabelChange(e.target.value),
|
|
15388
|
-
placeholder:
|
|
15680
|
+
placeholder: _t({
|
|
15681
|
+
id: "+owNNn",
|
|
15682
|
+
message: "Posts"
|
|
15683
|
+
}),
|
|
15389
15684
|
disabled: isFromCode
|
|
15390
15685
|
}),
|
|
15391
15686
|
isNew && /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(Input, {
|
|
@@ -15448,7 +15743,10 @@ function ContentTypeEditor({ collection, isNew, isSaving, onSave, onAddField, on
|
|
|
15448
15743
|
] }),
|
|
15449
15744
|
/* @__PURE__ */ jsxs("div", {
|
|
15450
15745
|
className: "space-y-3",
|
|
15451
|
-
children: [/* @__PURE__ */ jsx(Label, { children:
|
|
15746
|
+
children: [/* @__PURE__ */ jsx(Label, { children: _t({
|
|
15747
|
+
id: "PpZkda",
|
|
15748
|
+
message: "Features"
|
|
15749
|
+
}) }), SUPPORT_OPTIONS.map((option) => /* @__PURE__ */ jsx("div", {
|
|
15452
15750
|
className: cn("p-2 rounded-md hover:bg-kumo-tint/50", isFromCode && "opacity-60"),
|
|
15453
15751
|
children: /* @__PURE__ */ jsx(Checkbox, {
|
|
15454
15752
|
checked: supports.includes(option.value),
|
|
@@ -20613,6 +20911,7 @@ function MediaDetailPanel({ item, onClose, onDeleted }) {
|
|
|
20613
20911
|
setCaption(item.caption ?? "");
|
|
20614
20912
|
}
|
|
20615
20913
|
}, [item]);
|
|
20914
|
+
const fileUrl = item ? new URL(item.url, window.location.origin).href : "";
|
|
20616
20915
|
const hasChanges = React$1.useMemo(() => {
|
|
20617
20916
|
if (!item) return false;
|
|
20618
20917
|
return filename !== item.filename || alt !== (item.alt ?? "") || caption !== (item.caption ?? "");
|
|
@@ -20780,6 +21079,28 @@ function MediaDetailPanel({ item, onClose, onDeleted }) {
|
|
|
20780
21079
|
}),
|
|
20781
21080
|
/* @__PURE__ */ jsx("span", { children: formatDate$1(item.createdAt) })
|
|
20782
21081
|
]
|
|
21082
|
+
}),
|
|
21083
|
+
/* @__PURE__ */ jsxs("div", {
|
|
21084
|
+
className: "flex items-center gap-2 text-sm",
|
|
21085
|
+
children: [
|
|
21086
|
+
/* @__PURE__ */ jsx(LinkSimple, { className: "h-4 w-4 text-kumo-subtle shrink-0" }),
|
|
21087
|
+
/* @__PURE__ */ jsx("span", {
|
|
21088
|
+
className: "text-kumo-subtle shrink-0",
|
|
21089
|
+
children: _t({
|
|
21090
|
+
id: "PQs7eb",
|
|
21091
|
+
message: "URL:"
|
|
21092
|
+
})
|
|
21093
|
+
}),
|
|
21094
|
+
/* @__PURE__ */ jsx(ClipboardText, {
|
|
21095
|
+
text: fileUrl,
|
|
21096
|
+
size: "sm",
|
|
21097
|
+
className: "min-w-0 flex-1",
|
|
21098
|
+
labels: { copyAction: _t({
|
|
21099
|
+
id: "E6nRW7",
|
|
21100
|
+
message: "Copy URL"
|
|
21101
|
+
}) }
|
|
21102
|
+
})
|
|
21103
|
+
]
|
|
20783
21104
|
})
|
|
20784
21105
|
]
|
|
20785
21106
|
}),
|
|
@@ -21513,9 +21834,10 @@ function MediaGridItem({ item, selected, onClick }) {
|
|
|
21513
21834
|
children: [/* @__PURE__ */ jsx("div", {
|
|
21514
21835
|
className: "aspect-square",
|
|
21515
21836
|
children: isImage ? /* @__PURE__ */ jsx("img", {
|
|
21516
|
-
src: item.url,
|
|
21837
|
+
src: getMediaThumbnailUrl(item.url, item.mimeType, MEDIA_THUMBNAIL_WIDTH),
|
|
21517
21838
|
alt: item.alt || item.filename,
|
|
21518
|
-
className: "h-full w-full object-cover"
|
|
21839
|
+
className: "h-full w-full object-cover",
|
|
21840
|
+
onError: (e) => fallbackToOriginalThumbnail(e.currentTarget, item.url)
|
|
21519
21841
|
}) : /* @__PURE__ */ jsx("div", {
|
|
21520
21842
|
className: "flex h-full w-full items-center justify-center bg-kumo-tint",
|
|
21521
21843
|
children: /* @__PURE__ */ jsx("span", {
|
|
@@ -21583,9 +21905,10 @@ function MediaListItem({ item, selected, onClick }) {
|
|
|
21583
21905
|
children: /* @__PURE__ */ jsx("div", {
|
|
21584
21906
|
className: "h-10 w-10 overflow-hidden rounded",
|
|
21585
21907
|
children: isImage ? /* @__PURE__ */ jsx("img", {
|
|
21586
|
-
src: item.url,
|
|
21908
|
+
src: getMediaThumbnailUrl(item.url, item.mimeType, 80),
|
|
21587
21909
|
alt: item.alt || item.filename,
|
|
21588
|
-
className: "h-full w-full object-cover"
|
|
21910
|
+
className: "h-full w-full object-cover",
|
|
21911
|
+
onError: (e) => fallbackToOriginalThumbnail(e.currentTarget, item.url)
|
|
21589
21912
|
}) : /* @__PURE__ */ jsx("div", {
|
|
21590
21913
|
className: "flex h-full w-full items-center justify-center bg-kumo-tint text-xl",
|
|
21591
21914
|
children: getFileIcon(item.mimeType)
|
|
@@ -23975,7 +24298,7 @@ function RegistryPluginDetail({ pluginId, config }) {
|
|
|
23975
24298
|
const { data: installedPlugins } = useQuery({
|
|
23976
24299
|
queryKey: ["plugins"],
|
|
23977
24300
|
queryFn: async () => {
|
|
23978
|
-
const { fetchPlugins } = await import("./plugins-
|
|
24301
|
+
const { fetchPlugins } = await import("./plugins-G9Z9NQ7n.js").then((n) => n.a);
|
|
23979
24302
|
return fetchPlugins();
|
|
23980
24303
|
}
|
|
23981
24304
|
});
|
|
@@ -24038,7 +24361,7 @@ function RegistryPluginDetail({ pluginId, config }) {
|
|
|
24038
24361
|
const release = React$1.useMemo(() => releases.find((r) => r.version === effectiveVersion), [releases, effectiveVersion]);
|
|
24039
24362
|
const isPreRelease = release ? isPreReleaseVersion(release.version) : false;
|
|
24040
24363
|
const ext = (release?.release?.extensions)?.["com.emdashcms.experimental.package.releaseExtension"];
|
|
24041
|
-
const capabilities =
|
|
24364
|
+
const capabilities = ext?.declaredAccess ? canonicalCapabilitiesForDriftCheck(declaredAccessToCapabilities(ext.declaredAccess).capabilities) : [];
|
|
24042
24365
|
const pkgProfile = pkg?.profile ?? null;
|
|
24043
24366
|
const displayName = pkgProfile?.name;
|
|
24044
24367
|
const description = pkgProfile?.description;
|
|
@@ -24623,26 +24946,6 @@ function BackLink() {
|
|
|
24623
24946
|
})]
|
|
24624
24947
|
});
|
|
24625
24948
|
}
|
|
24626
|
-
/**
|
|
24627
|
-
* Flatten an RFC-0001 `declaredAccess` block (`{ content: { read: true },
|
|
24628
|
-
* email: { send: { allowedHosts: [...] } }, ... }`) into the legacy
|
|
24629
|
-
* `capabilities: string[]` shape that the existing sandbox runtime
|
|
24630
|
-
* enforces today. One entry per declared operation under each
|
|
24631
|
-
* category. Unknown values are skipped silently -- the consent dialog
|
|
24632
|
-
* shows only what the current runtime recognises.
|
|
24633
|
-
*/
|
|
24634
|
-
function declaredAccessToCapabilityList(declaredAccess) {
|
|
24635
|
-
if (!declaredAccess || typeof declaredAccess !== "object") return [];
|
|
24636
|
-
const out = [];
|
|
24637
|
-
for (const [category, value] of Object.entries(declaredAccess)) {
|
|
24638
|
-
if (!value || typeof value !== "object") continue;
|
|
24639
|
-
for (const [operation, opValue] of Object.entries(value)) {
|
|
24640
|
-
if (opValue === false) continue;
|
|
24641
|
-
out.push(`${category}:${operation}`);
|
|
24642
|
-
}
|
|
24643
|
-
}
|
|
24644
|
-
return out;
|
|
24645
|
-
}
|
|
24646
24949
|
const PRE_RELEASE_VERSION_RE = /^\d+\.\d+\.\d+-/;
|
|
24647
24950
|
/**
|
|
24648
24951
|
* Detects semver pre-release identifiers (`1.0.0-alpha.1`, `2.0.0-rc.2`). The
|
|
@@ -37013,6 +37316,53 @@ function FieldRow({ field, isFirst, isLast, onMoveUp, onMoveDown, onEdit, onDele
|
|
|
37013
37316
|
});
|
|
37014
37317
|
}
|
|
37015
37318
|
|
|
37319
|
+
//#endregion
|
|
37320
|
+
//#region src/components/BylineAvatarField.tsx
|
|
37321
|
+
/**
|
|
37322
|
+
* Avatar picker for the byline editor (#1250).
|
|
37323
|
+
*
|
|
37324
|
+
* Bylines store only an `avatarMediaId` (the media item's id), not a
|
|
37325
|
+
* URL or embedded media object. This component resolves that id back
|
|
37326
|
+
* into a full media item so it can hand a populated value to the
|
|
37327
|
+
* shared {@link ImageFieldRenderer} — reusing its picker, preview, and
|
|
37328
|
+
* broken-image handling rather than duplicating the markup.
|
|
37329
|
+
*
|
|
37330
|
+
* On change it strips the resolved media back down to the bare id for
|
|
37331
|
+
* the byline update body.
|
|
37332
|
+
*/
|
|
37333
|
+
function BylineAvatarField({ value, onChange }) {
|
|
37334
|
+
const { _: _t } = useLingui();
|
|
37335
|
+
const { data: media, isLoading } = useQuery({
|
|
37336
|
+
queryKey: ["media", value],
|
|
37337
|
+
queryFn: () => value ? fetchMediaItem(value) : Promise.resolve(null),
|
|
37338
|
+
enabled: !!value
|
|
37339
|
+
});
|
|
37340
|
+
if (value && isLoading) return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(Label, { children: _t({
|
|
37341
|
+
id: "kfcRb0",
|
|
37342
|
+
message: "Avatar"
|
|
37343
|
+
}) }), /* @__PURE__ */ jsx("div", {
|
|
37344
|
+
className: "mt-2 flex h-32 items-center justify-center rounded-lg border",
|
|
37345
|
+
children: /* @__PURE__ */ jsx(Loader, {})
|
|
37346
|
+
})] });
|
|
37347
|
+
const fieldValue = value && media ? {
|
|
37348
|
+
id: media.id,
|
|
37349
|
+
provider: media.provider || "local",
|
|
37350
|
+
previewUrl: media.provider && media.provider !== "local" ? media.url : void 0,
|
|
37351
|
+
alt: media.alt ?? "",
|
|
37352
|
+
width: media.width,
|
|
37353
|
+
height: media.height,
|
|
37354
|
+
meta: media.storageKey ? { storageKey: media.storageKey } : void 0
|
|
37355
|
+
} : void 0;
|
|
37356
|
+
return /* @__PURE__ */ jsx(ImageFieldRenderer, {
|
|
37357
|
+
label: _t({
|
|
37358
|
+
id: "kfcRb0",
|
|
37359
|
+
message: "Avatar"
|
|
37360
|
+
}),
|
|
37361
|
+
value: fieldValue,
|
|
37362
|
+
onChange: (next) => onChange(next?.id ?? null)
|
|
37363
|
+
});
|
|
37364
|
+
}
|
|
37365
|
+
|
|
37016
37366
|
//#endregion
|
|
37017
37367
|
//#region src/routes/bylines.tsx
|
|
37018
37368
|
/**
|
|
@@ -37030,6 +37380,7 @@ function toFormState(byline) {
|
|
|
37030
37380
|
websiteUrl: "",
|
|
37031
37381
|
userId: null,
|
|
37032
37382
|
isGuest: false,
|
|
37383
|
+
avatarMediaId: null,
|
|
37033
37384
|
customFields: {}
|
|
37034
37385
|
};
|
|
37035
37386
|
return {
|
|
@@ -37039,6 +37390,7 @@ function toFormState(byline) {
|
|
|
37039
37390
|
websiteUrl: byline.websiteUrl ?? "",
|
|
37040
37391
|
userId: byline.userId,
|
|
37041
37392
|
isGuest: byline.isGuest,
|
|
37393
|
+
avatarMediaId: byline.avatarMediaId ?? null,
|
|
37042
37394
|
customFields: byline.customFields ?? {}
|
|
37043
37395
|
};
|
|
37044
37396
|
}
|
|
@@ -37153,6 +37505,7 @@ function BylinesPage() {
|
|
|
37153
37505
|
websiteUrl: form.websiteUrl || null,
|
|
37154
37506
|
userId: form.userId,
|
|
37155
37507
|
isGuest: form.isGuest,
|
|
37508
|
+
avatarMediaId: form.avatarMediaId,
|
|
37156
37509
|
locale: activeLocale
|
|
37157
37510
|
};
|
|
37158
37511
|
if (!customFieldsError && Object.keys(form.customFields).length > 0) body.customFields = form.customFields;
|
|
@@ -37173,7 +37526,8 @@ function BylinesPage() {
|
|
|
37173
37526
|
bio: form.bio || null,
|
|
37174
37527
|
websiteUrl: form.websiteUrl || null,
|
|
37175
37528
|
userId: form.userId,
|
|
37176
|
-
isGuest: form.isGuest
|
|
37529
|
+
isGuest: form.isGuest,
|
|
37530
|
+
avatarMediaId: form.avatarMediaId
|
|
37177
37531
|
};
|
|
37178
37532
|
if (!customFieldsError) body.customFields = form.customFields;
|
|
37179
37533
|
return updateByline(selectedId, body);
|
|
@@ -37421,6 +37775,13 @@ function BylinesPage() {
|
|
|
37421
37775
|
})),
|
|
37422
37776
|
rows: 5
|
|
37423
37777
|
}),
|
|
37778
|
+
/* @__PURE__ */ jsx(BylineAvatarField, {
|
|
37779
|
+
value: form.avatarMediaId,
|
|
37780
|
+
onChange: (mediaId) => setForm((prev) => ({
|
|
37781
|
+
...prev,
|
|
37782
|
+
avatarMediaId: mediaId
|
|
37783
|
+
}))
|
|
37784
|
+
}),
|
|
37424
37785
|
/* @__PURE__ */ jsx(Select, {
|
|
37425
37786
|
label: _t({
|
|
37426
37787
|
id: "nti0N3",
|
|
@@ -40094,7 +40455,7 @@ function MarketplaceBrowsePage() {
|
|
|
40094
40455
|
const { data: plugins } = useQuery({
|
|
40095
40456
|
queryKey: ["plugins"],
|
|
40096
40457
|
queryFn: async () => {
|
|
40097
|
-
const { fetchPlugins } = await import("./plugins-
|
|
40458
|
+
const { fetchPlugins } = await import("./plugins-G9Z9NQ7n.js").then((n) => n.a);
|
|
40098
40459
|
return fetchPlugins();
|
|
40099
40460
|
}
|
|
40100
40461
|
});
|
|
@@ -40125,7 +40486,7 @@ function MarketplaceDetailPage() {
|
|
|
40125
40486
|
const { data: plugins } = useQuery({
|
|
40126
40487
|
queryKey: ["plugins"],
|
|
40127
40488
|
queryFn: async () => {
|
|
40128
|
-
const { fetchPlugins } = await import("./plugins-
|
|
40489
|
+
const { fetchPlugins } = await import("./plugins-G9Z9NQ7n.js").then((n) => n.a);
|
|
40129
40490
|
return fetchPlugins();
|
|
40130
40491
|
}
|
|
40131
40492
|
});
|
|
@@ -40608,5 +40969,5 @@ function AdminApp({ pluginAdmins = EMPTY_PLUGINS, authProviders = EMPTY_AUTH_PRO
|
|
|
40608
40969
|
}
|
|
40609
40970
|
|
|
40610
40971
|
//#endregion
|
|
40611
|
-
export { API_BASE, API_TOKEN_SCOPES, AdminApp, AdminApp as App, AuthProviderProvider, CAPABILITY_LABELS, ContentEditor, ContentList, DEFAULT_LOCALE, Dashboard, EditorHeader, Header, Link, LoginPage, MEDIA_SEARCH_MAX_LENGTH, 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, createBylineField, createBylineTranslation, createCollection, createContent, createField, createMenu, createMenuItem, createMenuTranslation, createRedirect, createSection, createTaxonomy, createTerm, createTermTranslation, createWidget, createWidgetArea, deleteAllowedDomain, deleteByline, deleteBylineField, 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, fetchBylineTranslations, fetchBylines, fetchCollection, fetchCollections, fetchComment, fetchCommentCounts, fetchComments, fetchContent, fetchContentAuthors, 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, getBylineFieldUsage, getDraftStatus, getPreviewUrl, hasAllowedDomains, importWxrMedia, installMarketplacePlugin, inviteUser, listBylineFields, parseApiResponse, permanentDeleteContent, prepareWxrImport, probeImportUrl, publishContent, registerOrphanedTable, renamePasskey, reorderBylineFields, reorderFields, reorderMenuItems, reorderWidgets, requestSignup, resolveLocale, restoreContent, restoreRevision, revokeApiToken, rewriteContentUrls, scheduleContent, searchMarketplace, searchThemes, sendRecoveryLink, sendTestEmail, setSearchEnabled, throwResponseError, uninstallMarketplacePlugin, unpublishContent, unscheduleContent, updateAllowedDomain, updateByline, updateBylineField, 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 };
|
|
40972
|
+
export { API_BASE, API_TOKEN_SCOPES, AdminApp, AdminApp as App, AuthProviderProvider, CAPABILITY_LABELS, ContentEditor, ContentList, DEFAULT_LOCALE, Dashboard, EditorHeader, Header, Link, LoginPage, MEDIA_SEARCH_MAX_LENGTH, 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, createBylineField, createBylineTranslation, createCollection, createContent, createField, createMenu, createMenuItem, createMenuTranslation, createRedirect, createSection, createTaxonomy, createTerm, createTermTranslation, createWidget, createWidgetArea, deleteAllowedDomain, deleteByline, deleteBylineField, 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, fetchBylineTranslations, fetchBylines, fetchCollection, fetchCollections, fetchComment, fetchCommentCounts, fetchComments, fetchContent, fetchContentAuthors, fetchContentList, fetchDashboardStats, fetchEmailSettings, fetchFields, fetchManifest, fetchMarketplacePlugin, fetchMediaItem, 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, getBylineFieldUsage, getDraftStatus, getPreviewUrl, hasAllowedDomains, importWxrMedia, installMarketplacePlugin, inviteUser, listBylineFields, parseApiResponse, permanentDeleteContent, prepareWxrImport, probeImportUrl, publishContent, registerOrphanedTable, renamePasskey, reorderBylineFields, reorderFields, reorderMenuItems, reorderWidgets, requestSignup, resolveLocale, restoreContent, restoreRevision, revokeApiToken, rewriteContentUrls, scheduleContent, searchMarketplace, searchThemes, sendRecoveryLink, sendTestEmail, setSearchEnabled, throwResponseError, uninstallMarketplacePlugin, unpublishContent, unscheduleContent, updateAllowedDomain, updateByline, updateBylineField, 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 };
|
|
40612
40973
|
//# sourceMappingURL=index.js.map
|