@emdash-cms/admin 0.1.1 → 0.2.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/config-BHC21FmY.d.ts +34 -0
- package/dist/config-BHC21FmY.d.ts.map +1 -0
- package/dist/index.d.ts +33 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +430 -190
- package/dist/index.js.map +1 -1
- package/dist/locales/de/messages.mjs +1 -0
- package/dist/locales/en/messages.mjs +1 -0
- package/dist/locales/index.d.ts +2 -0
- package/dist/locales/index.js +3 -0
- package/dist/plugins-XhZqfegd.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/useLocale-CXsoFCFt.js +80 -0
- package/dist/useLocale-CXsoFCFt.js.map +1 -0
- package/package.json +19 -5
package/dist/index.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { c as fetchManifest, i as fetchPlugins, l as parseApiResponse, n as enablePlugin, o as API_BASE, r as fetchPlugin, s as apiFetch, t as disablePlugin, u as throwResponseError } from "./plugins-XhZqfegd.js";
|
|
2
|
+
import { i as SUPPORTED_LOCALE_CODES, n as DEFAULT_LOCALE, o as resolveLocale, r as SUPPORTED_LOCALES, t as useLocale } from "./useLocale-CXsoFCFt.js";
|
|
3
|
+
import "./locales/index.js";
|
|
2
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
|
+
import { i18n } from "@lingui/core";
|
|
6
|
+
import { I18nProvider, Trans, useLingui } from "@lingui/react";
|
|
3
7
|
import { QueryClient, QueryClientProvider, useInfiniteQuery, useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
4
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";
|
|
5
9
|
import * as React from "react";
|
|
@@ -3284,7 +3288,7 @@ function MediaPickerModal({ open, onOpenChange, onSelect, mimeTypeFilter = "imag
|
|
|
3284
3288
|
open,
|
|
3285
3289
|
onOpenChange: handleClose,
|
|
3286
3290
|
children: /* @__PURE__ */ jsxs(Dialog, {
|
|
3287
|
-
className: "p-6 max-w-4xl max-h-[80vh] flex flex-col",
|
|
3291
|
+
className: "p-6 max-w-4xl max-h-[80vh] flex flex-col overflow-hidden",
|
|
3288
3292
|
size: "xl",
|
|
3289
3293
|
children: [
|
|
3290
3294
|
/* @__PURE__ */ jsxs("div", {
|
|
@@ -3412,7 +3416,7 @@ function MediaPickerModal({ open, onOpenChange, onSelect, mimeTypeFilter = "imag
|
|
|
3412
3416
|
className: "mb-3"
|
|
3413
3417
|
}),
|
|
3414
3418
|
/* @__PURE__ */ jsx("div", {
|
|
3415
|
-
className: "flex-1 overflow-y-auto min-h-
|
|
3419
|
+
className: "flex-1 overflow-y-auto min-h-0",
|
|
3416
3420
|
children: isLoading ? /* @__PURE__ */ jsx("div", {
|
|
3417
3421
|
className: "flex items-center justify-center h-full",
|
|
3418
3422
|
children: /* @__PURE__ */ jsx(Loader, {})
|
|
@@ -8112,43 +8116,40 @@ function ContentEditor({ collection, collectionLabel, item, fields, isNew, isSav
|
|
|
8112
8116
|
isSaving: isSaving || false
|
|
8113
8117
|
}),
|
|
8114
8118
|
!isNew && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8115
|
-
supportsDrafts && hasPendingChanges && onDiscardDraft && /* @__PURE__ */ jsxs(Dialog.Root, {
|
|
8116
|
-
|
|
8117
|
-
|
|
8118
|
-
|
|
8119
|
-
|
|
8120
|
-
|
|
8121
|
-
|
|
8122
|
-
|
|
8123
|
-
|
|
8124
|
-
|
|
8125
|
-
|
|
8126
|
-
|
|
8127
|
-
|
|
8128
|
-
|
|
8129
|
-
|
|
8130
|
-
|
|
8131
|
-
|
|
8132
|
-
|
|
8133
|
-
|
|
8134
|
-
|
|
8135
|
-
|
|
8136
|
-
/* @__PURE__ */
|
|
8137
|
-
|
|
8138
|
-
|
|
8139
|
-
|
|
8140
|
-
|
|
8141
|
-
|
|
8142
|
-
|
|
8143
|
-
|
|
8144
|
-
|
|
8145
|
-
|
|
8146
|
-
|
|
8147
|
-
|
|
8148
|
-
|
|
8149
|
-
]
|
|
8150
|
-
})]
|
|
8151
|
-
}),
|
|
8119
|
+
supportsDrafts && hasPendingChanges && onDiscardDraft && /* @__PURE__ */ jsxs(Dialog.Root, { children: [/* @__PURE__ */ jsx(Dialog.Trigger, { render: (p) => /* @__PURE__ */ jsx(Button, {
|
|
8120
|
+
...p,
|
|
8121
|
+
type: "button",
|
|
8122
|
+
variant: "outline",
|
|
8123
|
+
size: "sm",
|
|
8124
|
+
icon: /* @__PURE__ */ jsx(X, {}),
|
|
8125
|
+
children: "Discard changes"
|
|
8126
|
+
}) }), /* @__PURE__ */ jsxs(Dialog, {
|
|
8127
|
+
className: "p-6",
|
|
8128
|
+
size: "sm",
|
|
8129
|
+
children: [
|
|
8130
|
+
/* @__PURE__ */ jsx(Dialog.Title, {
|
|
8131
|
+
className: "text-lg font-semibold",
|
|
8132
|
+
children: "Discard draft changes?"
|
|
8133
|
+
}),
|
|
8134
|
+
/* @__PURE__ */ jsx(Dialog.Description, {
|
|
8135
|
+
className: "text-kumo-subtle",
|
|
8136
|
+
children: "This will revert to the published version. Your draft changes will be lost."
|
|
8137
|
+
}),
|
|
8138
|
+
/* @__PURE__ */ jsxs("div", {
|
|
8139
|
+
className: "mt-6 flex justify-end gap-2",
|
|
8140
|
+
children: [/* @__PURE__ */ jsx(Dialog.Close, { render: (p) => /* @__PURE__ */ jsx(Button, {
|
|
8141
|
+
...p,
|
|
8142
|
+
variant: "secondary",
|
|
8143
|
+
children: "Cancel"
|
|
8144
|
+
}) }), /* @__PURE__ */ jsx(Dialog.Close, { render: (p) => /* @__PURE__ */ jsx(Button, {
|
|
8145
|
+
...p,
|
|
8146
|
+
variant: "destructive",
|
|
8147
|
+
onClick: onDiscardDraft,
|
|
8148
|
+
children: "Discard changes"
|
|
8149
|
+
}) })]
|
|
8150
|
+
})
|
|
8151
|
+
]
|
|
8152
|
+
})] }),
|
|
8152
8153
|
isLive ? /* @__PURE__ */ jsx(Fragment, { children: hasPendingChanges ? /* @__PURE__ */ jsx(Button, {
|
|
8153
8154
|
type: "button",
|
|
8154
8155
|
variant: "primary",
|
|
@@ -8246,6 +8247,7 @@ function ContentEditor({ collection, collectionLabel, item, fields, isNew, isSav
|
|
|
8246
8247
|
children: supportsDrafts ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8247
8248
|
isLive && /* @__PURE__ */ jsx(Badge, {
|
|
8248
8249
|
variant: "primary",
|
|
8250
|
+
className: "text-white",
|
|
8249
8251
|
children: "Published"
|
|
8250
8252
|
}),
|
|
8251
8253
|
hasPendingChanges && /* @__PURE__ */ jsx(Badge, {
|
|
@@ -8538,27 +8540,31 @@ function FieldRenderer({ name, field, value, onChange, onEditorReady, minimal, p
|
|
|
8538
8540
|
required: field.required
|
|
8539
8541
|
});
|
|
8540
8542
|
case "boolean": return /* @__PURE__ */ jsx(Switch, {
|
|
8543
|
+
id,
|
|
8541
8544
|
label,
|
|
8542
8545
|
checked: typeof value === "boolean" ? value : false,
|
|
8543
8546
|
onCheckedChange: handleChange
|
|
8544
8547
|
});
|
|
8545
8548
|
case "portableText": {
|
|
8546
8549
|
const labelId = `${id}-label`;
|
|
8547
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
8548
|
-
id
|
|
8549
|
-
|
|
8550
|
-
|
|
8551
|
-
|
|
8552
|
-
|
|
8553
|
-
|
|
8554
|
-
|
|
8555
|
-
|
|
8556
|
-
|
|
8557
|
-
|
|
8558
|
-
|
|
8559
|
-
|
|
8560
|
-
|
|
8561
|
-
|
|
8550
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
8551
|
+
id,
|
|
8552
|
+
children: [!minimal && /* @__PURE__ */ jsx("span", {
|
|
8553
|
+
id: labelId,
|
|
8554
|
+
className: cn("text-sm font-medium leading-none text-kumo-default", labelClass),
|
|
8555
|
+
children: label
|
|
8556
|
+
}), /* @__PURE__ */ jsx(PortableTextEditor, {
|
|
8557
|
+
value: Array.isArray(value) ? value : [],
|
|
8558
|
+
onChange: handleChange,
|
|
8559
|
+
placeholder: `Enter ${label.toLowerCase()}...`,
|
|
8560
|
+
"aria-labelledby": labelId,
|
|
8561
|
+
pluginBlocks,
|
|
8562
|
+
onEditorReady,
|
|
8563
|
+
minimal,
|
|
8564
|
+
onBlockSidebarOpen,
|
|
8565
|
+
onBlockSidebarClose
|
|
8566
|
+
})]
|
|
8567
|
+
});
|
|
8562
8568
|
}
|
|
8563
8569
|
case "richText": return /* @__PURE__ */ jsx(InputArea, {
|
|
8564
8570
|
label,
|
|
@@ -8572,6 +8578,7 @@ function FieldRenderer({ name, field, value, onChange, onEditorReady, minimal, p
|
|
|
8572
8578
|
const selectItems = {};
|
|
8573
8579
|
for (const opt of field.options ?? []) selectItems[opt.value] = opt.label;
|
|
8574
8580
|
return /* @__PURE__ */ jsx(Select, {
|
|
8581
|
+
id,
|
|
8575
8582
|
label,
|
|
8576
8583
|
value: typeof value === "string" ? value : "",
|
|
8577
8584
|
onValueChange: (v) => handleChange(v ?? ""),
|
|
@@ -8610,6 +8617,7 @@ function FieldRenderer({ name, field, value, onChange, onEditorReady, minimal, p
|
|
|
8610
8617
|
required: field.required
|
|
8611
8618
|
});
|
|
8612
8619
|
case "image": return /* @__PURE__ */ jsx(ImageFieldRenderer, {
|
|
8620
|
+
id,
|
|
8613
8621
|
label,
|
|
8614
8622
|
description: name === "featured_image" ? "Used as the main visual for this post on listing pages and at the top of the post" : void 0,
|
|
8615
8623
|
value: value != null && typeof value === "object" ? value : void 0,
|
|
@@ -8639,7 +8647,7 @@ function FieldRenderer({ name, field, value, onChange, onEditorReady, minimal, p
|
|
|
8639
8647
|
});
|
|
8640
8648
|
}
|
|
8641
8649
|
}
|
|
8642
|
-
function ImageFieldRenderer({ label, description, value, onChange, required }) {
|
|
8650
|
+
function ImageFieldRenderer({ id, label, description, value, onChange, required }) {
|
|
8643
8651
|
const [pickerOpen, setPickerOpen] = React.useState(false);
|
|
8644
8652
|
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);
|
|
8645
8653
|
const handleSelect = (item) => {
|
|
@@ -8660,58 +8668,61 @@ function ImageFieldRenderer({ label, description, value, onChange, required }) {
|
|
|
8660
8668
|
const handleRemove = () => {
|
|
8661
8669
|
onChange(void 0);
|
|
8662
8670
|
};
|
|
8663
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
8664
|
-
|
|
8665
|
-
|
|
8666
|
-
|
|
8667
|
-
|
|
8668
|
-
|
|
8669
|
-
|
|
8670
|
-
|
|
8671
|
-
|
|
8672
|
-
|
|
8673
|
-
|
|
8674
|
-
|
|
8675
|
-
|
|
8676
|
-
|
|
8677
|
-
|
|
8678
|
-
|
|
8679
|
-
|
|
8680
|
-
|
|
8681
|
-
|
|
8682
|
-
|
|
8683
|
-
|
|
8684
|
-
|
|
8685
|
-
|
|
8686
|
-
|
|
8671
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
8672
|
+
id,
|
|
8673
|
+
children: [
|
|
8674
|
+
/* @__PURE__ */ jsx(Label, { children: label }),
|
|
8675
|
+
displayUrl ? /* @__PURE__ */ jsxs("div", {
|
|
8676
|
+
className: "mt-2 relative group",
|
|
8677
|
+
children: [/* @__PURE__ */ jsx("img", {
|
|
8678
|
+
src: displayUrl,
|
|
8679
|
+
alt: "",
|
|
8680
|
+
className: "max-h-48 rounded-lg border object-cover"
|
|
8681
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
8682
|
+
className: "absolute top-2 right-2 opacity-0 group-hover:opacity-100 transition-opacity flex gap-1",
|
|
8683
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
8684
|
+
type: "button",
|
|
8685
|
+
size: "sm",
|
|
8686
|
+
variant: "secondary",
|
|
8687
|
+
onClick: () => setPickerOpen(true),
|
|
8688
|
+
children: "Change"
|
|
8689
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
8690
|
+
type: "button",
|
|
8691
|
+
shape: "square",
|
|
8692
|
+
variant: "destructive",
|
|
8693
|
+
className: "h-8 w-8",
|
|
8694
|
+
onClick: handleRemove,
|
|
8695
|
+
"aria-label": "Remove image",
|
|
8696
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" })
|
|
8697
|
+
})]
|
|
8687
8698
|
})]
|
|
8688
|
-
})
|
|
8689
|
-
|
|
8690
|
-
|
|
8691
|
-
|
|
8692
|
-
|
|
8693
|
-
|
|
8694
|
-
|
|
8695
|
-
|
|
8696
|
-
|
|
8699
|
+
}) : /* @__PURE__ */ jsx(Button, {
|
|
8700
|
+
type: "button",
|
|
8701
|
+
variant: "outline",
|
|
8702
|
+
className: "mt-2 w-full h-32 border-dashed",
|
|
8703
|
+
onClick: () => setPickerOpen(true),
|
|
8704
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
8705
|
+
className: "flex flex-col items-center gap-2 text-kumo-subtle",
|
|
8706
|
+
children: [/* @__PURE__ */ jsx(Image$1, { className: "h-8 w-8" }), /* @__PURE__ */ jsx("span", { children: "Select image" })]
|
|
8707
|
+
})
|
|
8708
|
+
}),
|
|
8709
|
+
/* @__PURE__ */ jsx(MediaPickerModal, {
|
|
8710
|
+
open: pickerOpen,
|
|
8711
|
+
onOpenChange: setPickerOpen,
|
|
8712
|
+
onSelect: handleSelect,
|
|
8713
|
+
mimeTypeFilter: "image/",
|
|
8714
|
+
title: `Select ${label}`
|
|
8715
|
+
}),
|
|
8716
|
+
description && /* @__PURE__ */ jsx("p", {
|
|
8717
|
+
className: "text-xs text-kumo-subtle mt-1",
|
|
8718
|
+
children: description
|
|
8719
|
+
}),
|
|
8720
|
+
required && !displayUrl && /* @__PURE__ */ jsx("p", {
|
|
8721
|
+
className: "text-sm text-kumo-danger mt-1",
|
|
8722
|
+
children: "This field is required"
|
|
8697
8723
|
})
|
|
8698
|
-
|
|
8699
|
-
|
|
8700
|
-
open: pickerOpen,
|
|
8701
|
-
onOpenChange: setPickerOpen,
|
|
8702
|
-
onSelect: handleSelect,
|
|
8703
|
-
mimeTypeFilter: "image/",
|
|
8704
|
-
title: `Select ${label}`
|
|
8705
|
-
}),
|
|
8706
|
-
description && /* @__PURE__ */ jsx("p", {
|
|
8707
|
-
className: "text-xs text-kumo-subtle mt-1",
|
|
8708
|
-
children: description
|
|
8709
|
-
}),
|
|
8710
|
-
required && !displayUrl && /* @__PURE__ */ jsx("p", {
|
|
8711
|
-
className: "text-sm text-kumo-danger mt-1",
|
|
8712
|
-
children: "This field is required"
|
|
8713
|
-
})
|
|
8714
|
-
] });
|
|
8724
|
+
]
|
|
8725
|
+
});
|
|
8715
8726
|
}
|
|
8716
8727
|
function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuickEdit }) {
|
|
8717
8728
|
const [selectedBylineId, setSelectedBylineId] = React.useState("");
|
|
@@ -8891,7 +8902,10 @@ function BylineCreditsEditor({ credits, bylines, onChange, onQuickCreate, onQuic
|
|
|
8891
8902
|
children: [/* @__PURE__ */ jsx(Dialog.Close, { render: (p) => /* @__PURE__ */ jsx(Button, {
|
|
8892
8903
|
...p,
|
|
8893
8904
|
variant: "secondary",
|
|
8894
|
-
onClick:
|
|
8905
|
+
onClick: (e) => {
|
|
8906
|
+
resetQuickCreate();
|
|
8907
|
+
p.onClick?.(e);
|
|
8908
|
+
},
|
|
8895
8909
|
children: "Cancel"
|
|
8896
8910
|
}) }), /* @__PURE__ */ jsx(Button, {
|
|
8897
8911
|
type: "button",
|
|
@@ -9035,6 +9049,7 @@ function AuthorSelector({ authorId, users, onChange }) {
|
|
|
9035
9049
|
* Only renders when i18n is configured (manifest.i18n is present).
|
|
9036
9050
|
*/
|
|
9037
9051
|
function LocaleSwitcher({ locales, defaultLocale, value, onChange, showAll = false, className, size = "md" }) {
|
|
9052
|
+
const { _: _t } = useLingui();
|
|
9038
9053
|
return /* @__PURE__ */ jsxs("div", {
|
|
9039
9054
|
className: cn("flex items-center gap-1.5", className),
|
|
9040
9055
|
children: [/* @__PURE__ */ jsx(GlobeSimple, {
|
|
@@ -9043,14 +9058,23 @@ function LocaleSwitcher({ locales, defaultLocale, value, onChange, showAll = fal
|
|
|
9043
9058
|
}), /* @__PURE__ */ jsxs("select", {
|
|
9044
9059
|
value,
|
|
9045
9060
|
onChange: (e) => onChange(e.target.value),
|
|
9046
|
-
"aria-label":
|
|
9061
|
+
"aria-label": _t({
|
|
9062
|
+
id: "8NbHF7",
|
|
9063
|
+
message: "Locale"
|
|
9064
|
+
}),
|
|
9047
9065
|
className: cn("rounded-md border bg-transparent font-medium transition-colors", "focus:ring-kumo-ring focus:outline-none focus:ring-2 focus:ring-offset-1", "hover:bg-kumo-tint/50 cursor-pointer", size === "sm" ? "px-1.5 py-0.5 text-xs" : "px-2 py-1 text-sm"),
|
|
9048
9066
|
children: [showAll && /* @__PURE__ */ jsx("option", {
|
|
9049
9067
|
value: "",
|
|
9050
|
-
children:
|
|
9068
|
+
children: _t({
|
|
9069
|
+
id: "JjOi48",
|
|
9070
|
+
message: "All locales"
|
|
9071
|
+
})
|
|
9051
9072
|
}), locales.map((locale) => /* @__PURE__ */ jsxs("option", {
|
|
9052
9073
|
value: locale,
|
|
9053
|
-
children: [locale.toUpperCase(), locale === defaultLocale ?
|
|
9074
|
+
children: [locale.toUpperCase(), locale === defaultLocale ? _t({
|
|
9075
|
+
id: "FozKV6",
|
|
9076
|
+
message: " (default)"
|
|
9077
|
+
}) : ""]
|
|
9054
9078
|
}, locale))]
|
|
9055
9079
|
})]
|
|
9056
9080
|
});
|
|
@@ -9082,6 +9106,15 @@ function ContentList({ collection, collectionLabel, items, trashedItems = [], is
|
|
|
9082
9106
|
}, [items, searchQuery]);
|
|
9083
9107
|
const totalPages = Math.max(1, Math.ceil(filteredItems.length / PAGE_SIZE));
|
|
9084
9108
|
const paginatedItems = filteredItems.slice(page * PAGE_SIZE, (page + 1) * PAGE_SIZE);
|
|
9109
|
+
React.useEffect(() => {
|
|
9110
|
+
if (page >= totalPages - 1 && hasMore && onLoadMore && !searchQuery) onLoadMore();
|
|
9111
|
+
}, [
|
|
9112
|
+
page,
|
|
9113
|
+
totalPages,
|
|
9114
|
+
hasMore,
|
|
9115
|
+
onLoadMore,
|
|
9116
|
+
searchQuery
|
|
9117
|
+
]);
|
|
9085
9118
|
return /* @__PURE__ */ jsxs("div", {
|
|
9086
9119
|
className: "space-y-4",
|
|
9087
9120
|
children: [
|
|
@@ -9102,6 +9135,7 @@ function ContentList({ collection, collectionLabel, items, trashedItems = [], is
|
|
|
9102
9135
|
}), /* @__PURE__ */ jsxs(Link$1, {
|
|
9103
9136
|
to: "/content/$collection/new",
|
|
9104
9137
|
params: { collection },
|
|
9138
|
+
search: { locale: activeLocale },
|
|
9105
9139
|
className: buttonVariants(),
|
|
9106
9140
|
children: [/* @__PURE__ */ jsx(Plus, {
|
|
9107
9141
|
className: "mr-2 h-4 w-4",
|
|
@@ -9192,6 +9226,7 @@ function ContentList({ collection, collectionLabel, items, trashedItems = [], is
|
|
|
9192
9226
|
/* @__PURE__ */ jsx(Link$1, {
|
|
9193
9227
|
to: "/content/$collection/new",
|
|
9194
9228
|
params: { collection },
|
|
9229
|
+
search: { locale: activeLocale },
|
|
9195
9230
|
className: "text-kumo-brand underline",
|
|
9196
9231
|
children: "Create your first one"
|
|
9197
9232
|
})
|
|
@@ -9220,6 +9255,7 @@ function ContentList({ collection, collectionLabel, items, trashedItems = [], is
|
|
|
9220
9255
|
className: "text-sm text-kumo-subtle",
|
|
9221
9256
|
children: [
|
|
9222
9257
|
filteredItems.length,
|
|
9258
|
+
hasMore && !searchQuery ? "+" : "",
|
|
9223
9259
|
" ",
|
|
9224
9260
|
filteredItems.length === 1 ? "item" : "items",
|
|
9225
9261
|
searchQuery && ` matching "${searchQuery}"`
|
|
@@ -12076,6 +12112,7 @@ const OAUTH_PROVIDERS = [{
|
|
|
12076
12112
|
icon: /* @__PURE__ */ jsx(GoogleIcon, { className: "h-5 w-5" })
|
|
12077
12113
|
}];
|
|
12078
12114
|
function MagicLinkForm({ onBack }) {
|
|
12115
|
+
const { _: _t } = useLingui();
|
|
12079
12116
|
const [email, setEmail] = React.useState("");
|
|
12080
12117
|
const [isLoading, setIsLoading] = React.useState(false);
|
|
12081
12118
|
const [error, setError] = React.useState(null);
|
|
@@ -12092,11 +12129,17 @@ function MagicLinkForm({ onBack }) {
|
|
|
12092
12129
|
});
|
|
12093
12130
|
if (!response.ok) {
|
|
12094
12131
|
const body = await response.json().catch(() => ({}));
|
|
12095
|
-
throw new Error(body?.error?.message ||
|
|
12132
|
+
throw new Error(body?.error?.message || _t({
|
|
12133
|
+
id: "dsPiA2",
|
|
12134
|
+
message: "Failed to send magic link"
|
|
12135
|
+
}));
|
|
12096
12136
|
}
|
|
12097
12137
|
setSent(true);
|
|
12098
12138
|
} catch (err) {
|
|
12099
|
-
setError(err instanceof Error ? err.message :
|
|
12139
|
+
setError(err instanceof Error ? err.message : _t({
|
|
12140
|
+
id: "dsPiA2",
|
|
12141
|
+
message: "Failed to send magic link"
|
|
12142
|
+
}));
|
|
12100
12143
|
} finally {
|
|
12101
12144
|
setIsLoading(false);
|
|
12102
12145
|
}
|
|
@@ -12121,30 +12164,40 @@ function MagicLinkForm({ onBack }) {
|
|
|
12121
12164
|
}),
|
|
12122
12165
|
/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h2", {
|
|
12123
12166
|
className: "text-xl font-semibold",
|
|
12124
|
-
children:
|
|
12125
|
-
|
|
12167
|
+
children: _t({
|
|
12168
|
+
id: "v4fiSg",
|
|
12169
|
+
message: "Check your email"
|
|
12170
|
+
})
|
|
12171
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
12126
12172
|
className: "text-kumo-subtle mt-2",
|
|
12127
|
-
children:
|
|
12128
|
-
|
|
12129
|
-
|
|
12130
|
-
|
|
12131
|
-
|
|
12132
|
-
|
|
12133
|
-
", we've sent a sign-in link."
|
|
12134
|
-
]
|
|
12173
|
+
children: /* @__PURE__ */ jsx(Trans, {
|
|
12174
|
+
id: "HvU4EW",
|
|
12175
|
+
message: "If an account exists for <0>{email}</0>, we've sent a sign-in link.",
|
|
12176
|
+
values: { email },
|
|
12177
|
+
components: { 0: /* @__PURE__ */ jsx("span", { className: "font-medium text-kumo-default" }) }
|
|
12178
|
+
})
|
|
12135
12179
|
})] }),
|
|
12136
12180
|
/* @__PURE__ */ jsxs("div", {
|
|
12137
12181
|
className: "text-sm text-kumo-subtle",
|
|
12138
|
-
children: [/* @__PURE__ */ jsx("p", { children:
|
|
12182
|
+
children: [/* @__PURE__ */ jsx("p", { children: _t({
|
|
12183
|
+
id: "tfQcxX",
|
|
12184
|
+
message: "Click the link in the email to sign in."
|
|
12185
|
+
}) }), /* @__PURE__ */ jsx("p", {
|
|
12139
12186
|
className: "mt-2",
|
|
12140
|
-
children:
|
|
12187
|
+
children: _t({
|
|
12188
|
+
id: "Cw9Xfg",
|
|
12189
|
+
message: "The link will expire in 15 minutes."
|
|
12190
|
+
})
|
|
12141
12191
|
})]
|
|
12142
12192
|
}),
|
|
12143
12193
|
/* @__PURE__ */ jsx(Button, {
|
|
12144
12194
|
variant: "outline",
|
|
12145
12195
|
onClick: onBack,
|
|
12146
12196
|
className: "mt-4 w-full justify-center",
|
|
12147
|
-
children:
|
|
12197
|
+
children: _t({
|
|
12198
|
+
id: "VCoEm+",
|
|
12199
|
+
message: "Back to login"
|
|
12200
|
+
})
|
|
12148
12201
|
})
|
|
12149
12202
|
]
|
|
12150
12203
|
});
|
|
@@ -12153,7 +12206,10 @@ function MagicLinkForm({ onBack }) {
|
|
|
12153
12206
|
className: "space-y-4",
|
|
12154
12207
|
children: [
|
|
12155
12208
|
/* @__PURE__ */ jsx(Input, {
|
|
12156
|
-
label:
|
|
12209
|
+
label: _t({
|
|
12210
|
+
id: "ATGYL1",
|
|
12211
|
+
message: "Email address"
|
|
12212
|
+
}),
|
|
12157
12213
|
type: "email",
|
|
12158
12214
|
value: email,
|
|
12159
12215
|
onChange: (e) => setEmail(e.target.value),
|
|
@@ -12174,14 +12230,23 @@ function MagicLinkForm({ onBack }) {
|
|
|
12174
12230
|
variant: "primary",
|
|
12175
12231
|
loading: isLoading,
|
|
12176
12232
|
disabled: !email,
|
|
12177
|
-
children: isLoading ?
|
|
12233
|
+
children: isLoading ? _t({
|
|
12234
|
+
id: "IoAuJG",
|
|
12235
|
+
message: "Sending..."
|
|
12236
|
+
}) : _t({
|
|
12237
|
+
id: "+Ni3Gv",
|
|
12238
|
+
message: "Send magic link"
|
|
12239
|
+
})
|
|
12178
12240
|
}),
|
|
12179
12241
|
/* @__PURE__ */ jsx(Button, {
|
|
12180
12242
|
type: "button",
|
|
12181
12243
|
variant: "ghost",
|
|
12182
12244
|
className: "w-full justify-center",
|
|
12183
12245
|
onClick: onBack,
|
|
12184
|
-
children:
|
|
12246
|
+
children: _t({
|
|
12247
|
+
id: "VCoEm+",
|
|
12248
|
+
message: "Back to login"
|
|
12249
|
+
})
|
|
12185
12250
|
})
|
|
12186
12251
|
]
|
|
12187
12252
|
});
|
|
@@ -12191,6 +12256,8 @@ function handleOAuthClick(providerId) {
|
|
|
12191
12256
|
}
|
|
12192
12257
|
function LoginPage({ redirectUrl = "/_emdash/admin" }) {
|
|
12193
12258
|
const safeRedirectUrl = sanitizeRedirectUrl(redirectUrl);
|
|
12259
|
+
const { _: _t2 } = useLingui();
|
|
12260
|
+
const { locale, setLocale } = useLocale();
|
|
12194
12261
|
const [method, setMethod] = React.useState("passkey");
|
|
12195
12262
|
const [urlError, setUrlError] = React.useState(null);
|
|
12196
12263
|
const { data: manifest, isLoading: manifestLoading } = useQuery({
|
|
@@ -12205,7 +12272,11 @@ function LoginPage({ redirectUrl = "/_emdash/admin" }) {
|
|
|
12205
12272
|
const error = params.get("error");
|
|
12206
12273
|
const message = params.get("message");
|
|
12207
12274
|
if (error) {
|
|
12208
|
-
setUrlError(message ||
|
|
12275
|
+
setUrlError(message || _t2({
|
|
12276
|
+
id: "Xeb2Gt",
|
|
12277
|
+
message: "Authentication error: {error}",
|
|
12278
|
+
values: { error }
|
|
12279
|
+
}));
|
|
12209
12280
|
window.history.replaceState({}, "", window.location.pathname);
|
|
12210
12281
|
}
|
|
12211
12282
|
}, []);
|
|
@@ -12228,7 +12299,13 @@ function LoginPage({ redirectUrl = "/_emdash/admin" }) {
|
|
|
12228
12299
|
className: "text-center mb-8",
|
|
12229
12300
|
children: [/* @__PURE__ */ jsx(LogoLockup, { className: "h-10 mx-auto mb-2" }), /* @__PURE__ */ jsxs("h1", {
|
|
12230
12301
|
className: "text-2xl font-semibold text-kumo-default",
|
|
12231
|
-
children: [method === "passkey" &&
|
|
12302
|
+
children: [method === "passkey" && _t2({
|
|
12303
|
+
id: "lE0wHD",
|
|
12304
|
+
message: "Sign in to your site"
|
|
12305
|
+
}), method === "magic-link" && _t2({
|
|
12306
|
+
id: "me9L29",
|
|
12307
|
+
message: "Sign in with email"
|
|
12308
|
+
})]
|
|
12232
12309
|
})]
|
|
12233
12310
|
}),
|
|
12234
12311
|
urlError && /* @__PURE__ */ jsx("div", {
|
|
@@ -12244,7 +12321,10 @@ function LoginPage({ redirectUrl = "/_emdash/admin" }) {
|
|
|
12244
12321
|
optionsEndpoint: "/_emdash/api/auth/passkey/options",
|
|
12245
12322
|
verifyEndpoint: "/_emdash/api/auth/passkey/verify",
|
|
12246
12323
|
onSuccess: handleSuccess,
|
|
12247
|
-
buttonText:
|
|
12324
|
+
buttonText: _t2({
|
|
12325
|
+
id: "QjsOMP",
|
|
12326
|
+
message: "Sign in with Passkey"
|
|
12327
|
+
})
|
|
12248
12328
|
}),
|
|
12249
12329
|
/* @__PURE__ */ jsxs("div", {
|
|
12250
12330
|
className: "relative",
|
|
@@ -12255,7 +12335,10 @@ function LoginPage({ redirectUrl = "/_emdash/admin" }) {
|
|
|
12255
12335
|
className: "relative flex justify-center text-xs uppercase",
|
|
12256
12336
|
children: /* @__PURE__ */ jsx("span", {
|
|
12257
12337
|
className: "bg-kumo-base px-2 text-kumo-subtle",
|
|
12258
|
-
children:
|
|
12338
|
+
children: _t2({
|
|
12339
|
+
id: "zW+FpA",
|
|
12340
|
+
message: "Or continue with"
|
|
12341
|
+
})
|
|
12259
12342
|
})
|
|
12260
12343
|
})]
|
|
12261
12344
|
}),
|
|
@@ -12277,26 +12360,42 @@ function LoginPage({ redirectUrl = "/_emdash/admin" }) {
|
|
|
12277
12360
|
className: "w-full justify-center",
|
|
12278
12361
|
type: "button",
|
|
12279
12362
|
onClick: () => setMethod("magic-link"),
|
|
12280
|
-
children:
|
|
12363
|
+
children: _t2({
|
|
12364
|
+
id: "RxerEl",
|
|
12365
|
+
message: "Sign in with email link"
|
|
12366
|
+
})
|
|
12281
12367
|
})
|
|
12282
12368
|
]
|
|
12283
12369
|
}), method === "magic-link" && /* @__PURE__ */ jsx(MagicLinkForm, { onBack: () => setMethod("passkey") })]
|
|
12284
12370
|
}),
|
|
12285
12371
|
/* @__PURE__ */ jsx("p", {
|
|
12286
12372
|
className: "text-center mt-6 text-sm text-kumo-subtle",
|
|
12287
|
-
children: method === "passkey" ?
|
|
12373
|
+
children: method === "passkey" ? _t2({
|
|
12374
|
+
id: "+ET/av",
|
|
12375
|
+
message: "Use your registered passkey to sign in securely."
|
|
12376
|
+
}) : _t2({
|
|
12377
|
+
id: "pv+wH3",
|
|
12378
|
+
message: "We'll send you a link to sign in without a password."
|
|
12379
|
+
})
|
|
12288
12380
|
}),
|
|
12289
|
-
manifest?.signupEnabled && /* @__PURE__ */
|
|
12381
|
+
manifest?.signupEnabled && /* @__PURE__ */ jsx("p", {
|
|
12290
12382
|
className: "text-center mt-4 text-sm text-kumo-subtle",
|
|
12291
|
-
children:
|
|
12292
|
-
|
|
12293
|
-
" ",
|
|
12294
|
-
/* @__PURE__ */ jsx(Link$1, {
|
|
12383
|
+
children: /* @__PURE__ */ jsx(Trans, {
|
|
12384
|
+
id: "352VU2",
|
|
12385
|
+
message: "Don't have an account? <0>Sign up</0>",
|
|
12386
|
+
components: { 0: /* @__PURE__ */ jsx(Link$1, {
|
|
12295
12387
|
to: "/signup",
|
|
12296
|
-
className: "text-kumo-brand hover:underline font-medium"
|
|
12297
|
-
|
|
12298
|
-
|
|
12299
|
-
|
|
12388
|
+
className: "text-kumo-brand hover:underline font-medium"
|
|
12389
|
+
}) }
|
|
12390
|
+
})
|
|
12391
|
+
}),
|
|
12392
|
+
SUPPORTED_LOCALES.length > 1 && /* @__PURE__ */ jsx("div", {
|
|
12393
|
+
className: "mt-6 flex justify-center gap-2 text-xs text-kumo-subtle",
|
|
12394
|
+
children: SUPPORTED_LOCALES.map((l, i) => /* @__PURE__ */ jsxs(React.Fragment, { children: [i > 0 && /* @__PURE__ */ jsx("span", { children: "·" }), /* @__PURE__ */ jsx("button", {
|
|
12395
|
+
onClick: () => setLocale(l.code),
|
|
12396
|
+
className: l.code === locale ? "font-medium text-kumo-default" : "hover:text-kumo-default transition-colors",
|
|
12397
|
+
children: l.label
|
|
12398
|
+
})] }, l.code))
|
|
12300
12399
|
})
|
|
12301
12400
|
]
|
|
12302
12401
|
})
|
|
@@ -14471,7 +14570,7 @@ function ContentPickerModal({ open, onOpenChange, onSelect }) {
|
|
|
14471
14570
|
open,
|
|
14472
14571
|
onOpenChange,
|
|
14473
14572
|
children: /* @__PURE__ */ jsxs(Dialog, {
|
|
14474
|
-
className: "p-6 w-2xl h-[80vh] flex flex-col",
|
|
14573
|
+
className: "p-6 max-w-2xl h-[80vh] flex flex-col",
|
|
14475
14574
|
size: "lg",
|
|
14476
14575
|
children: [
|
|
14477
14576
|
/* @__PURE__ */ jsxs("div", {
|
|
@@ -14821,9 +14920,11 @@ function MenuEditor() {
|
|
|
14821
14920
|
/* @__PURE__ */ jsx(Input, {
|
|
14822
14921
|
label: "URL",
|
|
14823
14922
|
name: "url",
|
|
14824
|
-
type: "
|
|
14923
|
+
type: "text",
|
|
14825
14924
|
required: true,
|
|
14826
|
-
|
|
14925
|
+
pattern: "(https?://.+|/.*)",
|
|
14926
|
+
title: "Enter a URL (https://…) or a relative path (/…)",
|
|
14927
|
+
placeholder: "https://example.com or /about"
|
|
14827
14928
|
}),
|
|
14828
14929
|
/* @__PURE__ */ jsxs(Select, {
|
|
14829
14930
|
label: "Target",
|
|
@@ -14987,8 +15088,10 @@ function MenuEditor() {
|
|
|
14987
15088
|
editingItem.type === "custom" && /* @__PURE__ */ jsx(Input, {
|
|
14988
15089
|
label: "URL",
|
|
14989
15090
|
name: "url",
|
|
14990
|
-
type: "
|
|
15091
|
+
type: "text",
|
|
14991
15092
|
required: true,
|
|
15093
|
+
pattern: "(https?://.+|/.*)",
|
|
15094
|
+
title: "Enter a URL (https://…) or a relative path (/…)",
|
|
14992
15095
|
defaultValue: editingItem.custom_url || ""
|
|
14993
15096
|
}),
|
|
14994
15097
|
/* @__PURE__ */ jsxs(Select, {
|
|
@@ -16463,13 +16566,18 @@ function Settings() {
|
|
|
16463
16566
|
queryKey: ["manifest"],
|
|
16464
16567
|
queryFn: fetchManifest
|
|
16465
16568
|
});
|
|
16569
|
+
const { _: _t } = useLingui();
|
|
16570
|
+
const { locale, setLocale } = useLocale();
|
|
16466
16571
|
const showSecuritySettings = manifest?.authMode === "passkey";
|
|
16467
16572
|
return /* @__PURE__ */ jsxs("div", {
|
|
16468
16573
|
className: "space-y-6",
|
|
16469
16574
|
children: [
|
|
16470
16575
|
/* @__PURE__ */ jsx("h1", {
|
|
16471
16576
|
className: "text-2xl font-bold",
|
|
16472
|
-
children:
|
|
16577
|
+
children: _t({
|
|
16578
|
+
id: "Tz0i8g",
|
|
16579
|
+
message: "Settings"
|
|
16580
|
+
})
|
|
16473
16581
|
}),
|
|
16474
16582
|
/* @__PURE__ */ jsxs("div", {
|
|
16475
16583
|
className: "space-y-2",
|
|
@@ -16477,20 +16585,38 @@ function Settings() {
|
|
|
16477
16585
|
/* @__PURE__ */ jsx(SettingsLink, {
|
|
16478
16586
|
to: "/settings/general",
|
|
16479
16587
|
icon: /* @__PURE__ */ jsx(Gear, { className: "h-5 w-5" }),
|
|
16480
|
-
title:
|
|
16481
|
-
|
|
16588
|
+
title: _t({
|
|
16589
|
+
id: "Weq9zb",
|
|
16590
|
+
message: "General"
|
|
16591
|
+
}),
|
|
16592
|
+
description: _t({
|
|
16593
|
+
id: "RR0ADZ",
|
|
16594
|
+
message: "Site identity, logo, favicon, and reading preferences"
|
|
16595
|
+
})
|
|
16482
16596
|
}),
|
|
16483
16597
|
/* @__PURE__ */ jsx(SettingsLink, {
|
|
16484
16598
|
to: "/settings/social",
|
|
16485
16599
|
icon: /* @__PURE__ */ jsx(ShareNetwork, { className: "h-5 w-5" }),
|
|
16486
|
-
title:
|
|
16487
|
-
|
|
16600
|
+
title: _t({
|
|
16601
|
+
id: "d0rUsW",
|
|
16602
|
+
message: "Social Links"
|
|
16603
|
+
}),
|
|
16604
|
+
description: _t({
|
|
16605
|
+
id: "qS3mgX",
|
|
16606
|
+
message: "Social media profile links"
|
|
16607
|
+
})
|
|
16488
16608
|
}),
|
|
16489
16609
|
/* @__PURE__ */ jsx(SettingsLink, {
|
|
16490
16610
|
to: "/settings/seo",
|
|
16491
16611
|
icon: /* @__PURE__ */ jsx(MagnifyingGlass, { className: "h-5 w-5" }),
|
|
16492
|
-
title:
|
|
16493
|
-
|
|
16612
|
+
title: _t({
|
|
16613
|
+
id: "4Ml90q",
|
|
16614
|
+
message: "SEO"
|
|
16615
|
+
}),
|
|
16616
|
+
description: _t({
|
|
16617
|
+
id: "zY0S+v",
|
|
16618
|
+
message: "Search engine optimization and verification"
|
|
16619
|
+
})
|
|
16494
16620
|
})
|
|
16495
16621
|
]
|
|
16496
16622
|
}),
|
|
@@ -16499,13 +16625,25 @@ function Settings() {
|
|
|
16499
16625
|
children: [/* @__PURE__ */ jsx(SettingsLink, {
|
|
16500
16626
|
to: "/settings/security",
|
|
16501
16627
|
icon: /* @__PURE__ */ jsx(Shield, { className: "h-5 w-5" }),
|
|
16502
|
-
title:
|
|
16503
|
-
|
|
16628
|
+
title: _t({
|
|
16629
|
+
id: "a3LDKx",
|
|
16630
|
+
message: "Security"
|
|
16631
|
+
}),
|
|
16632
|
+
description: _t({
|
|
16633
|
+
id: "OfnTKV",
|
|
16634
|
+
message: "Manage your passkeys and authentication"
|
|
16635
|
+
})
|
|
16504
16636
|
}), /* @__PURE__ */ jsx(SettingsLink, {
|
|
16505
16637
|
to: "/settings/allowed-domains",
|
|
16506
16638
|
icon: /* @__PURE__ */ jsx(Globe, { className: "h-5 w-5" }),
|
|
16507
|
-
title:
|
|
16508
|
-
|
|
16639
|
+
title: _t({
|
|
16640
|
+
id: "Tllxyd",
|
|
16641
|
+
message: "Self-Signup Domains"
|
|
16642
|
+
}),
|
|
16643
|
+
description: _t({
|
|
16644
|
+
id: "DsZc8w",
|
|
16645
|
+
message: "Allow users from specific domains to sign up"
|
|
16646
|
+
})
|
|
16509
16647
|
})]
|
|
16510
16648
|
}),
|
|
16511
16649
|
/* @__PURE__ */ jsxs("div", {
|
|
@@ -16513,14 +16651,58 @@ function Settings() {
|
|
|
16513
16651
|
children: [/* @__PURE__ */ jsx(SettingsLink, {
|
|
16514
16652
|
to: "/settings/api-tokens",
|
|
16515
16653
|
icon: /* @__PURE__ */ jsx(Key, { className: "h-5 w-5" }),
|
|
16516
|
-
title:
|
|
16517
|
-
|
|
16654
|
+
title: _t({
|
|
16655
|
+
id: "ZiooJI",
|
|
16656
|
+
message: "API Tokens"
|
|
16657
|
+
}),
|
|
16658
|
+
description: _t({
|
|
16659
|
+
id: "dhH+RW",
|
|
16660
|
+
message: "Create personal access tokens for programmatic API access"
|
|
16661
|
+
})
|
|
16518
16662
|
}), /* @__PURE__ */ jsx(SettingsLink, {
|
|
16519
16663
|
to: "/settings/email",
|
|
16520
16664
|
icon: /* @__PURE__ */ jsx(Envelope, { className: "h-5 w-5" }),
|
|
16521
|
-
title:
|
|
16522
|
-
|
|
16665
|
+
title: _t({
|
|
16666
|
+
id: "O3oNi5",
|
|
16667
|
+
message: "Email"
|
|
16668
|
+
}),
|
|
16669
|
+
description: _t({
|
|
16670
|
+
id: "/JPN+P",
|
|
16671
|
+
message: "View email provider status and send test emails"
|
|
16672
|
+
})
|
|
16523
16673
|
})]
|
|
16674
|
+
}),
|
|
16675
|
+
SUPPORTED_LOCALES.length > 1 && /* @__PURE__ */ jsx("div", {
|
|
16676
|
+
className: "space-y-2",
|
|
16677
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
16678
|
+
className: "flex items-center justify-between p-4 rounded-lg border bg-kumo-base",
|
|
16679
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
16680
|
+
className: "flex items-center gap-3",
|
|
16681
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
16682
|
+
className: "text-kumo-subtle",
|
|
16683
|
+
children: /* @__PURE__ */ jsx(GlobeSimple, { className: "h-5 w-5" })
|
|
16684
|
+
}), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
|
|
16685
|
+
className: "font-medium",
|
|
16686
|
+
children: _t({
|
|
16687
|
+
id: "vXIe7J",
|
|
16688
|
+
message: "Language"
|
|
16689
|
+
})
|
|
16690
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
16691
|
+
className: "text-sm text-kumo-subtle",
|
|
16692
|
+
children: _t({
|
|
16693
|
+
id: "Y8S9QC",
|
|
16694
|
+
message: "Choose your preferred admin language"
|
|
16695
|
+
})
|
|
16696
|
+
})] })]
|
|
16697
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
16698
|
+
className: "flex gap-1",
|
|
16699
|
+
children: SUPPORTED_LOCALES.map((l) => /* @__PURE__ */ jsx("button", {
|
|
16700
|
+
onClick: () => setLocale(l.code),
|
|
16701
|
+
className: cn("rounded-md px-3 py-1.5 text-sm transition-colors", l.code === locale ? "bg-kumo-brand/10 text-kumo-brand font-medium" : "hover:bg-kumo-tint"),
|
|
16702
|
+
children: l.label
|
|
16703
|
+
}, l.code))
|
|
16704
|
+
})]
|
|
16705
|
+
})
|
|
16524
16706
|
})
|
|
16525
16707
|
]
|
|
16526
16708
|
});
|
|
@@ -17276,7 +17458,7 @@ function EmailSettings() {
|
|
|
17276
17458
|
const timer = setTimeout(setStatus, 5e3, null);
|
|
17277
17459
|
return () => clearTimeout(timer);
|
|
17278
17460
|
}, [status]);
|
|
17279
|
-
const { data: settings, isLoading } = useQuery({
|
|
17461
|
+
const { data: settings, isLoading, error: fetchError } = useQuery({
|
|
17280
17462
|
queryKey: ["email-settings"],
|
|
17281
17463
|
queryFn: fetchEmailSettings
|
|
17282
17464
|
});
|
|
@@ -17305,6 +17487,27 @@ function EmailSettings() {
|
|
|
17305
17487
|
className: "flex items-center justify-center py-12",
|
|
17306
17488
|
children: /* @__PURE__ */ jsx(Loader, { size: "lg" })
|
|
17307
17489
|
});
|
|
17490
|
+
if (fetchError) return /* @__PURE__ */ jsxs("div", {
|
|
17491
|
+
className: "space-y-6",
|
|
17492
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
17493
|
+
className: "flex items-center gap-3",
|
|
17494
|
+
children: [/* @__PURE__ */ jsx(Link$1, {
|
|
17495
|
+
to: "/settings",
|
|
17496
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
17497
|
+
variant: "ghost",
|
|
17498
|
+
shape: "square",
|
|
17499
|
+
"aria-label": "Back to settings",
|
|
17500
|
+
children: /* @__PURE__ */ jsx(ArrowLeft, { className: "h-4 w-4" })
|
|
17501
|
+
})
|
|
17502
|
+
}), /* @__PURE__ */ jsx("h1", {
|
|
17503
|
+
className: "text-2xl font-bold",
|
|
17504
|
+
children: "Email Settings"
|
|
17505
|
+
})]
|
|
17506
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
17507
|
+
className: "flex items-center gap-2 rounded-lg border border-red-200 bg-red-50 p-3 text-sm text-red-800 dark:border-red-800 dark:bg-red-950/30 dark:text-red-200",
|
|
17508
|
+
children: [/* @__PURE__ */ jsx(WarningCircle, { className: "h-4 w-4 flex-shrink-0" }), getMutationError(fetchError) || "Failed to load email settings"]
|
|
17509
|
+
})]
|
|
17510
|
+
});
|
|
17308
17511
|
return /* @__PURE__ */ jsxs("div", {
|
|
17309
17512
|
className: "space-y-6",
|
|
17310
17513
|
children: [
|
|
@@ -19489,20 +19692,13 @@ function SidebarNav({ manifest }) {
|
|
|
19489
19692
|
icon: Stack,
|
|
19490
19693
|
minRole: ROLE_EDITOR$1
|
|
19491
19694
|
},
|
|
19492
|
-
{
|
|
19493
|
-
to: "/taxonomies/$taxonomy",
|
|
19494
|
-
label: "Categories",
|
|
19495
|
-
icon: FileText,
|
|
19496
|
-
params: { taxonomy: "category" },
|
|
19497
|
-
minRole: ROLE_EDITOR$1
|
|
19498
|
-
},
|
|
19499
|
-
{
|
|
19695
|
+
...manifest.taxonomies.map((tax) => ({
|
|
19500
19696
|
to: "/taxonomies/$taxonomy",
|
|
19501
|
-
label:
|
|
19697
|
+
label: tax.label,
|
|
19502
19698
|
icon: FileText,
|
|
19503
|
-
params: { taxonomy:
|
|
19699
|
+
params: { taxonomy: tax.name },
|
|
19504
19700
|
minRole: ROLE_EDITOR$1
|
|
19505
|
-
},
|
|
19701
|
+
})),
|
|
19506
19702
|
{
|
|
19507
19703
|
to: "/bylines",
|
|
19508
19704
|
label: "Bylines",
|
|
@@ -19894,7 +20090,6 @@ function WelcomeModal({ open, onClose, userName, userRole }) {
|
|
|
19894
20090
|
onOpenChange: (isOpen) => !isOpen && handleGetStarted(),
|
|
19895
20091
|
children: /* @__PURE__ */ jsxs(Dialog, {
|
|
19896
20092
|
className: "p-6 sm:max-w-md",
|
|
19897
|
-
size: "lg",
|
|
19898
20093
|
children: [
|
|
19899
20094
|
/* @__PURE__ */ jsxs("div", {
|
|
19900
20095
|
className: "flex items-start justify-between gap-4",
|
|
@@ -25551,6 +25746,10 @@ const adminLayoutRoute = createRoute({
|
|
|
25551
25746
|
id: "_admin",
|
|
25552
25747
|
component: RootComponent
|
|
25553
25748
|
});
|
|
25749
|
+
if (typeof window !== "undefined" && typeof window.requestIdleCallback === "undefined") {
|
|
25750
|
+
window.requestIdleCallback = (cb) => setTimeout(cb, 50);
|
|
25751
|
+
window.cancelIdleCallback = (id) => clearTimeout(id);
|
|
25752
|
+
}
|
|
25554
25753
|
function RootComponent() {
|
|
25555
25754
|
const { data: manifest, isLoading, error } = useQuery({
|
|
25556
25755
|
queryKey: ["manifest"],
|
|
@@ -25683,6 +25882,9 @@ function ContentListPage() {
|
|
|
25683
25882
|
});
|
|
25684
25883
|
}
|
|
25685
25884
|
});
|
|
25885
|
+
const items = React.useMemo(() => {
|
|
25886
|
+
return data?.pages.flatMap((page) => page.items) || [];
|
|
25887
|
+
}, [data]);
|
|
25686
25888
|
if (!manifest) return /* @__PURE__ */ jsx(LoadingScreen, {});
|
|
25687
25889
|
const collectionConfig = manifest.collections[collection];
|
|
25688
25890
|
if (!collectionConfig) return /* @__PURE__ */ jsx(NotFoundPage, { message: `Collection "${collection}" not found` });
|
|
@@ -25694,9 +25896,6 @@ function ContentListPage() {
|
|
|
25694
25896
|
search: { locale: locale || void 0 }
|
|
25695
25897
|
});
|
|
25696
25898
|
};
|
|
25697
|
-
const items = React.useMemo(() => {
|
|
25698
|
-
return data?.pages.flatMap((page) => page.items) || [];
|
|
25699
|
-
}, [data]);
|
|
25700
25899
|
return /* @__PURE__ */ jsx(ContentList, {
|
|
25701
25900
|
collection,
|
|
25702
25901
|
collectionLabel: collectionConfig.label,
|
|
@@ -25705,7 +25904,7 @@ function ContentListPage() {
|
|
|
25705
25904
|
isLoading: isLoading || isFetchingNextPage,
|
|
25706
25905
|
isTrashedLoading,
|
|
25707
25906
|
hasMore: !!hasNextPage,
|
|
25708
|
-
onLoadMore: () => void fetchNextPage(),
|
|
25907
|
+
onLoadMore: React.useCallback(() => void fetchNextPage(), [fetchNextPage]),
|
|
25709
25908
|
trashedCount: trashedData?.items?.length || 0,
|
|
25710
25909
|
onDelete: (id) => deleteMutation.mutate(id),
|
|
25711
25910
|
onRestore: (id) => restoreMutation.mutate(id),
|
|
@@ -25729,10 +25928,12 @@ function getPluginBlocks(manifest) {
|
|
|
25729
25928
|
const contentNewRoute = createRoute({
|
|
25730
25929
|
getParentRoute: () => adminLayoutRoute,
|
|
25731
25930
|
path: "/content/$collection/new",
|
|
25732
|
-
component: ContentNewPage
|
|
25931
|
+
component: ContentNewPage,
|
|
25932
|
+
validateSearch: (search) => ({ locale: typeof search.locale === "string" ? search.locale : void 0 })
|
|
25733
25933
|
});
|
|
25734
25934
|
function ContentNewPage() {
|
|
25735
25935
|
const { collection } = useParams({ from: "/_admin/content/$collection/new" });
|
|
25936
|
+
const { locale } = useSearch({ from: "/_admin/content/$collection/new" });
|
|
25736
25937
|
const navigate = useNavigate();
|
|
25737
25938
|
const queryClient = useQueryClient();
|
|
25738
25939
|
const [selectedBylines, setSelectedBylines] = React.useState([]);
|
|
@@ -25741,7 +25942,10 @@ function ContentNewPage() {
|
|
|
25741
25942
|
queryFn: fetchManifest
|
|
25742
25943
|
});
|
|
25743
25944
|
const createMutation = useMutation({
|
|
25744
|
-
mutationFn: (data) => createContent(collection,
|
|
25945
|
+
mutationFn: (data) => createContent(collection, {
|
|
25946
|
+
...data,
|
|
25947
|
+
locale
|
|
25948
|
+
}),
|
|
25745
25949
|
onSuccess: (result) => {
|
|
25746
25950
|
queryClient.invalidateQueries({ queryKey: ["content", collection] });
|
|
25747
25951
|
navigate({
|
|
@@ -25808,11 +26012,13 @@ function ContentNewPage() {
|
|
|
25808
26012
|
const contentEditRoute = createRoute({
|
|
25809
26013
|
getParentRoute: () => adminLayoutRoute,
|
|
25810
26014
|
path: "/content/$collection/$id",
|
|
25811
|
-
component: ContentEditPage
|
|
26015
|
+
component: ContentEditPage,
|
|
26016
|
+
validateSearch: (search) => ({ ...typeof search.field === "string" && { field: search.field } })
|
|
25812
26017
|
});
|
|
25813
26018
|
const ROLE_EDITOR = 40;
|
|
25814
26019
|
function ContentEditPage() {
|
|
25815
26020
|
const { collection, id } = useParams({ from: "/_admin/content/$collection/$id" });
|
|
26021
|
+
const searchParams = useSearch({ from: "/_admin/content/$collection/$id" });
|
|
25816
26022
|
const queryClient = useQueryClient();
|
|
25817
26023
|
const navigate = useNavigate();
|
|
25818
26024
|
const toastManager = Toast.useToastManager();
|
|
@@ -25829,6 +26035,29 @@ function ContentEditPage() {
|
|
|
25829
26035
|
],
|
|
25830
26036
|
queryFn: () => fetchContent(collection, id)
|
|
25831
26037
|
});
|
|
26038
|
+
React.useEffect(() => {
|
|
26039
|
+
if (typeof searchParams.field !== "string" || isLoading) return;
|
|
26040
|
+
const timeoutId = requestIdleCallback(() => {
|
|
26041
|
+
const el = document.getElementById(`field-${searchParams.field}`);
|
|
26042
|
+
if (el) {
|
|
26043
|
+
el.scrollIntoView({
|
|
26044
|
+
behavior: "smooth",
|
|
26045
|
+
block: "center"
|
|
26046
|
+
});
|
|
26047
|
+
el.focus();
|
|
26048
|
+
const { field: _, ...preservedSearch } = searchParams;
|
|
26049
|
+
navigate({
|
|
26050
|
+
search: preservedSearch,
|
|
26051
|
+
replace: true
|
|
26052
|
+
});
|
|
26053
|
+
}
|
|
26054
|
+
});
|
|
26055
|
+
return () => cancelIdleCallback(timeoutId);
|
|
26056
|
+
}, [
|
|
26057
|
+
searchParams,
|
|
26058
|
+
isLoading,
|
|
26059
|
+
navigate
|
|
26060
|
+
]);
|
|
25832
26061
|
const { data: translationsData } = useQuery({
|
|
25833
26062
|
queryKey: [
|
|
25834
26063
|
"translations",
|
|
@@ -26826,19 +27055,30 @@ const router = createAdminRouter(queryClient);
|
|
|
26826
27055
|
* Main Admin Application
|
|
26827
27056
|
*/
|
|
26828
27057
|
const EMPTY_PLUGINS = {};
|
|
26829
|
-
function AdminApp({ pluginAdmins = EMPTY_PLUGINS }) {
|
|
27058
|
+
function AdminApp({ pluginAdmins = EMPTY_PLUGINS, locale = "en", messages = {} }) {
|
|
26830
27059
|
React.useEffect(() => {
|
|
26831
27060
|
document.getElementById("emdash-boot-loader")?.remove();
|
|
26832
27061
|
}, []);
|
|
26833
|
-
|
|
26834
|
-
|
|
26835
|
-
|
|
26836
|
-
|
|
26837
|
-
|
|
26838
|
-
})
|
|
26839
|
-
|
|
27062
|
+
const i18nInitialized = React.useRef(false);
|
|
27063
|
+
if (!i18nInitialized.current) {
|
|
27064
|
+
i18n.loadAndActivate({
|
|
27065
|
+
locale,
|
|
27066
|
+
messages
|
|
27067
|
+
});
|
|
27068
|
+
i18nInitialized.current = true;
|
|
27069
|
+
}
|
|
27070
|
+
return /* @__PURE__ */ jsx(ThemeProvider, { children: /* @__PURE__ */ jsx(I18nProvider, {
|
|
27071
|
+
i18n,
|
|
27072
|
+
children: /* @__PURE__ */ jsx(Toasty, { children: /* @__PURE__ */ jsx(PluginAdminProvider, {
|
|
27073
|
+
pluginAdmins,
|
|
27074
|
+
children: /* @__PURE__ */ jsx(QueryClientProvider, {
|
|
27075
|
+
client: queryClient,
|
|
27076
|
+
children: /* @__PURE__ */ jsx(RouterProvider, { router })
|
|
27077
|
+
})
|
|
27078
|
+
}) })
|
|
27079
|
+
}) });
|
|
26840
27080
|
}
|
|
26841
27081
|
|
|
26842
27082
|
//#endregion
|
|
26843
|
-
export { API_BASE, API_TOKEN_SCOPES, AdminApp, AdminApp as App, CAPABILITY_LABELS, ContentEditor, ContentList, Dashboard, Header, Link, LoginPage, MediaLibrary, MediaPickerModal, PasskeyLogin, PasskeyRegistration, PluginAdminProvider, PortableTextEditor, 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, 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, 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, useCurrentUser, useNavigate, useParams, usePluginAdmins, usePluginField, usePluginHasPages, usePluginHasWidgets, usePluginPage, usePluginWidget, verifySignupToken };
|
|
27083
|
+
export { API_BASE, API_TOKEN_SCOPES, AdminApp, AdminApp as App, CAPABILITY_LABELS, ContentEditor, ContentList, DEFAULT_LOCALE, Dashboard, 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, 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, useCurrentUser, useLocale, useNavigate, useParams, usePluginAdmins, usePluginField, usePluginHasPages, usePluginHasWidgets, usePluginPage, usePluginWidget, verifySignupToken };
|
|
26844
27084
|
//# sourceMappingURL=index.js.map
|