@ampless/admin 1.0.0-beta.92 → 1.0.0-beta.93
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/api/index.d.ts +1 -1
- package/dist/{chunk-FVHQJCH4.js → chunk-26ZRUSES.js} +2 -2
- package/dist/{chunk-IBFNFTJ6.js → chunk-2GFTMGIZ.js} +1 -1
- package/dist/{chunk-M5QQJHM7.js → chunk-4UIDGQ2L.js} +8 -0
- package/dist/{chunk-TMOFUAU7.js → chunk-5KUAGEQW.js} +1 -1
- package/dist/{chunk-6275N7HG.js → chunk-5L2ICOCA.js} +1 -1
- package/dist/{chunk-2Y5SRSCZ.js → chunk-6EGOUZXY.js} +1 -1
- package/dist/{chunk-OPHSYQQV.js → chunk-ASEYWSR6.js} +2 -2
- package/dist/{chunk-OAG4NI7Q.js → chunk-BU7YQ5MS.js} +1 -1
- package/dist/{chunk-FVGWVH6Q.js → chunk-ISE2LXLA.js} +3 -3
- package/dist/{chunk-VJ5SDYVW.js → chunk-JTPEKM5J.js} +1 -1
- package/dist/{chunk-HRCUFIGW.js → chunk-LHHWZQDN.js} +2 -2
- package/dist/{chunk-HKMHNEFV.js → chunk-P7NMQTSQ.js} +1 -1
- package/dist/{chunk-QO73C7VC.js → chunk-PQU342OC.js} +1 -1
- package/dist/{chunk-TEMSFG34.js → chunk-QTU63B4K.js} +2 -2
- package/dist/{chunk-UUZAKCZZ.js → chunk-TDXYTNZB.js} +283 -213
- package/dist/{chunk-3AQGYUVP.js → chunk-UYT6WMWV.js} +1 -1
- package/dist/components/account-view.js +3 -3
- package/dist/components/admin-dashboard.js +3 -3
- package/dist/components/edit-post-view.js +5 -5
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.js +6 -6
- package/dist/components/login-view.js +3 -3
- package/dist/components/mcp-tokens-view.js +3 -3
- package/dist/components/media-view.js +5 -5
- package/dist/components/new-post-view.js +5 -5
- package/dist/components/plugin-settings-form.js +3 -3
- package/dist/components/posts-list-view.js +3 -3
- package/dist/components/users-list-view.js +3 -3
- package/dist/{i18n-CecqYBeP.d.ts → i18n-BOuZ2Yhb.d.ts} +12 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/metafile-esm.json +1 -1
- package/dist/pages/index.d.ts +1 -1
- package/dist/pages/index.js +16 -16
- package/package.json +3 -3
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
getAdminCmsConfig,
|
|
5
5
|
getMediaProcessingDefaults,
|
|
6
6
|
uploadProcessedImage
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-5L2ICOCA.js";
|
|
8
8
|
import {
|
|
9
9
|
getAdminEditorExtensions,
|
|
10
10
|
getAdminTiptapNodeHtml,
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
} from "./chunk-2ITWLRYF.js";
|
|
16
16
|
import {
|
|
17
17
|
useT
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-2GFTMGIZ.js";
|
|
19
19
|
|
|
20
20
|
// src/components/media-picker.tsx
|
|
21
21
|
import { useEffect, useRef, useState } from "react";
|
|
@@ -160,7 +160,7 @@ function MediaPicker({ trigger, onSelect }) {
|
|
|
160
160
|
}
|
|
161
161
|
|
|
162
162
|
// src/components/post-form.tsx
|
|
163
|
-
import { useEffect as
|
|
163
|
+
import { useEffect as useEffect5, useRef as useRef4, useState as useState6 } from "react";
|
|
164
164
|
import { useRouter } from "next/navigation";
|
|
165
165
|
import { Image as ImageIcon3 } from "lucide-react";
|
|
166
166
|
import {
|
|
@@ -169,7 +169,7 @@ import {
|
|
|
169
169
|
deletePost,
|
|
170
170
|
formatDate
|
|
171
171
|
} from "ampless";
|
|
172
|
-
import { Button as Button7, Input, Label, Textarea } from "@ampless/runtime/ui";
|
|
172
|
+
import { Button as Button7, Input as Input2, Label, Textarea } from "@ampless/runtime/ui";
|
|
173
173
|
|
|
174
174
|
// src/editor/tiptap-editor.tsx
|
|
175
175
|
import { useEditor, EditorContent } from "@tiptap/react";
|
|
@@ -325,8 +325,77 @@ function TableControls({ editor }) {
|
|
|
325
325
|
] });
|
|
326
326
|
}
|
|
327
327
|
|
|
328
|
-
// src/editor/
|
|
328
|
+
// src/editor/code-block-language-control.tsx
|
|
329
|
+
import { useEffect as useEffect3, useRef as useRef3, useState as useState3 } from "react";
|
|
330
|
+
import { Braces } from "lucide-react";
|
|
331
|
+
import { Input } from "@ampless/runtime/ui";
|
|
332
|
+
|
|
333
|
+
// src/editor/code-language.ts
|
|
334
|
+
var TOKEN = /^[a-z0-9][a-z0-9_-]{0,63}$/;
|
|
335
|
+
function normalizeCodeLanguage(value) {
|
|
336
|
+
const cleaned = value.toLowerCase().replace(/[^a-z0-9_-]/g, "");
|
|
337
|
+
return TOKEN.test(cleaned) ? cleaned : null;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// src/editor/code-block-language-control.tsx
|
|
329
341
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
342
|
+
function CodeBlockLanguageControl({ editor }) {
|
|
343
|
+
const t = useT();
|
|
344
|
+
const [state, setState] = useState3({ active: false, language: "" });
|
|
345
|
+
const [localValue, setLocalValue] = useState3("");
|
|
346
|
+
const focusedRef = useRef3(false);
|
|
347
|
+
const lastSeededLanguageRef = useRef3("");
|
|
348
|
+
useEffect3(() => {
|
|
349
|
+
const sync = () => {
|
|
350
|
+
const active = editor.isActive("codeBlock");
|
|
351
|
+
const language = editor.getAttributes("codeBlock").language ?? "";
|
|
352
|
+
setState({ active, language });
|
|
353
|
+
if (!focusedRef.current || language !== lastSeededLanguageRef.current) {
|
|
354
|
+
setLocalValue(language);
|
|
355
|
+
lastSeededLanguageRef.current = language;
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
sync();
|
|
359
|
+
editor.on("selectionUpdate", sync);
|
|
360
|
+
editor.on("transaction", sync);
|
|
361
|
+
return () => {
|
|
362
|
+
editor.off("selectionUpdate", sync);
|
|
363
|
+
editor.off("transaction", sync);
|
|
364
|
+
};
|
|
365
|
+
}, [editor]);
|
|
366
|
+
if (!state.active) return null;
|
|
367
|
+
return /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-1", children: [
|
|
368
|
+
/* @__PURE__ */ jsx3(Braces, { className: "h-4 w-4 shrink-0 text-muted-foreground", "aria-hidden": "true" }),
|
|
369
|
+
/* @__PURE__ */ jsx3(
|
|
370
|
+
Input,
|
|
371
|
+
{
|
|
372
|
+
type: "text",
|
|
373
|
+
className: "h-8 w-32 text-xs",
|
|
374
|
+
value: localValue,
|
|
375
|
+
title: t("editor.codeBlock.languageLabel"),
|
|
376
|
+
placeholder: t("editor.codeBlock.languagePlaceholder"),
|
|
377
|
+
"aria-label": t("editor.codeBlock.languageLabel"),
|
|
378
|
+
onFocus: () => {
|
|
379
|
+
focusedRef.current = true;
|
|
380
|
+
},
|
|
381
|
+
onBlur: () => {
|
|
382
|
+
focusedRef.current = false;
|
|
383
|
+
const committed = editor.getAttributes("codeBlock").language ?? "";
|
|
384
|
+
setLocalValue(committed);
|
|
385
|
+
lastSeededLanguageRef.current = committed;
|
|
386
|
+
},
|
|
387
|
+
onChange: (e) => {
|
|
388
|
+
const raw = e.target.value;
|
|
389
|
+
setLocalValue(raw);
|
|
390
|
+
editor.chain().updateAttributes("codeBlock", { language: normalizeCodeLanguage(raw) }).run();
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
)
|
|
394
|
+
] });
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// src/editor/toolbar.tsx
|
|
398
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
330
399
|
function Toolbar({ editor }) {
|
|
331
400
|
const t = useT();
|
|
332
401
|
if (!editor) return null;
|
|
@@ -362,10 +431,10 @@ function Toolbar({ editor }) {
|
|
|
362
431
|
const insertImage = (url) => {
|
|
363
432
|
editor.chain().focus().setImage({ src: url }).run();
|
|
364
433
|
};
|
|
365
|
-
return /* @__PURE__ */
|
|
434
|
+
return /* @__PURE__ */ jsxs4("div", { className: "flex flex-wrap gap-1 border-b p-2", children: [
|
|
366
435
|
tools.map((tool) => {
|
|
367
436
|
const Icon = tool.icon;
|
|
368
|
-
return /* @__PURE__ */
|
|
437
|
+
return /* @__PURE__ */ jsx4(
|
|
369
438
|
Button3,
|
|
370
439
|
{
|
|
371
440
|
type: "button",
|
|
@@ -373,12 +442,12 @@ function Toolbar({ editor }) {
|
|
|
373
442
|
size: "icon",
|
|
374
443
|
onClick: tool.action,
|
|
375
444
|
className: cn2(tool.isActive() && "bg-accent text-accent-foreground"),
|
|
376
|
-
children: /* @__PURE__ */
|
|
445
|
+
children: /* @__PURE__ */ jsx4(Icon, { className: "h-4 w-4" })
|
|
377
446
|
},
|
|
378
447
|
tool.name
|
|
379
448
|
);
|
|
380
449
|
}),
|
|
381
|
-
/* @__PURE__ */
|
|
450
|
+
/* @__PURE__ */ jsx4(
|
|
382
451
|
Button3,
|
|
383
452
|
{
|
|
384
453
|
type: "button",
|
|
@@ -386,17 +455,18 @@ function Toolbar({ editor }) {
|
|
|
386
455
|
size: "icon",
|
|
387
456
|
onClick: setLink,
|
|
388
457
|
className: cn2(editor.isActive("link") && "bg-accent text-accent-foreground"),
|
|
389
|
-
children: /* @__PURE__ */
|
|
458
|
+
children: /* @__PURE__ */ jsx4(LinkIcon, { className: "h-4 w-4" })
|
|
390
459
|
}
|
|
391
460
|
),
|
|
392
|
-
/* @__PURE__ */
|
|
461
|
+
/* @__PURE__ */ jsx4(
|
|
393
462
|
MediaPicker,
|
|
394
463
|
{
|
|
395
464
|
onSelect: insertImage,
|
|
396
|
-
trigger: /* @__PURE__ */
|
|
465
|
+
trigger: /* @__PURE__ */ jsx4(Button3, { type: "button", variant: "ghost", size: "icon", children: /* @__PURE__ */ jsx4(ImageIcon, { className: "h-4 w-4" }) })
|
|
397
466
|
}
|
|
398
467
|
),
|
|
399
|
-
/* @__PURE__ */
|
|
468
|
+
/* @__PURE__ */ jsx4(TableControls, { editor }),
|
|
469
|
+
/* @__PURE__ */ jsx4(CodeBlockLanguageControl, { editor })
|
|
400
470
|
] });
|
|
401
471
|
}
|
|
402
472
|
|
|
@@ -404,7 +474,7 @@ function Toolbar({ editor }) {
|
|
|
404
474
|
import { BubbleMenu } from "@tiptap/react/menus";
|
|
405
475
|
import { Trash2, Pencil, ImageIcon as ImageIcon2, Maximize2 } from "lucide-react";
|
|
406
476
|
import { Button as Button4, cn as cn3 } from "@ampless/runtime/ui";
|
|
407
|
-
import { jsx as
|
|
477
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
408
478
|
function ImageBubbleMenu({ editor }) {
|
|
409
479
|
const t = useT();
|
|
410
480
|
const editAlt = () => {
|
|
@@ -422,14 +492,14 @@ function ImageBubbleMenu({ editor }) {
|
|
|
422
492
|
editor.chain().focus().updateAttributes("image", { display: next }).run();
|
|
423
493
|
};
|
|
424
494
|
const currentDisplay = editor.getAttributes("image").display ?? null;
|
|
425
|
-
return /* @__PURE__ */
|
|
495
|
+
return /* @__PURE__ */ jsx5(
|
|
426
496
|
BubbleMenu,
|
|
427
497
|
{
|
|
428
498
|
editor,
|
|
429
499
|
shouldShow: ({ editor: editor2 }) => editor2.isActive("image"),
|
|
430
500
|
options: { placement: "top" },
|
|
431
|
-
children: /* @__PURE__ */
|
|
432
|
-
/* @__PURE__ */
|
|
501
|
+
children: /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-1 rounded-md border bg-popover p-1 shadow", children: [
|
|
502
|
+
/* @__PURE__ */ jsxs5(
|
|
433
503
|
Button4,
|
|
434
504
|
{
|
|
435
505
|
type: "button",
|
|
@@ -439,12 +509,12 @@ function ImageBubbleMenu({ editor }) {
|
|
|
439
509
|
className: cn3(currentDisplay === "inline" && "bg-accent text-accent-foreground"),
|
|
440
510
|
title: t("editor.image.inlineTitle"),
|
|
441
511
|
children: [
|
|
442
|
-
/* @__PURE__ */
|
|
512
|
+
/* @__PURE__ */ jsx5(ImageIcon2, { className: "mr-1 h-3 w-3" }),
|
|
443
513
|
t("editor.image.inline")
|
|
444
514
|
]
|
|
445
515
|
}
|
|
446
516
|
),
|
|
447
|
-
/* @__PURE__ */
|
|
517
|
+
/* @__PURE__ */ jsxs5(
|
|
448
518
|
Button4,
|
|
449
519
|
{
|
|
450
520
|
type: "button",
|
|
@@ -454,18 +524,18 @@ function ImageBubbleMenu({ editor }) {
|
|
|
454
524
|
className: cn3(currentDisplay === "lightbox" && "bg-accent text-accent-foreground"),
|
|
455
525
|
title: t("editor.image.lightboxTitle"),
|
|
456
526
|
children: [
|
|
457
|
-
/* @__PURE__ */
|
|
527
|
+
/* @__PURE__ */ jsx5(Maximize2, { className: "mr-1 h-3 w-3" }),
|
|
458
528
|
t("editor.image.lightbox")
|
|
459
529
|
]
|
|
460
530
|
}
|
|
461
531
|
),
|
|
462
|
-
/* @__PURE__ */
|
|
463
|
-
/* @__PURE__ */
|
|
464
|
-
/* @__PURE__ */
|
|
532
|
+
/* @__PURE__ */ jsx5("span", { className: "mx-1 h-4 w-px bg-border" }),
|
|
533
|
+
/* @__PURE__ */ jsxs5(Button4, { type: "button", variant: "ghost", size: "sm", onClick: editAlt, children: [
|
|
534
|
+
/* @__PURE__ */ jsx5(Pencil, { className: "mr-1 h-3 w-3" }),
|
|
465
535
|
t("editor.image.alt")
|
|
466
536
|
] }),
|
|
467
|
-
/* @__PURE__ */
|
|
468
|
-
/* @__PURE__ */
|
|
537
|
+
/* @__PURE__ */ jsxs5(Button4, { type: "button", variant: "ghost", size: "sm", onClick: remove2, children: [
|
|
538
|
+
/* @__PURE__ */ jsx5(Trash2, { className: "mr-1 h-3 w-3" }),
|
|
469
539
|
t("editor.image.delete")
|
|
470
540
|
] })
|
|
471
541
|
] })
|
|
@@ -517,7 +587,7 @@ var BASE_TIPTAP_EXTENSIONS = [
|
|
|
517
587
|
];
|
|
518
588
|
|
|
519
589
|
// src/editor/tiptap-editor.tsx
|
|
520
|
-
import { jsx as
|
|
590
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
521
591
|
var EDITOR_STYLES = `
|
|
522
592
|
.ProseMirror .tiptap-table,
|
|
523
593
|
.ProseMirror table {
|
|
@@ -617,16 +687,16 @@ function TiptapEditor({ initialContent, onChange, onUserEdit }) {
|
|
|
617
687
|
onUserEdit?.();
|
|
618
688
|
}
|
|
619
689
|
});
|
|
620
|
-
return /* @__PURE__ */
|
|
621
|
-
/* @__PURE__ */
|
|
622
|
-
/* @__PURE__ */
|
|
623
|
-
editor && /* @__PURE__ */
|
|
624
|
-
/* @__PURE__ */
|
|
690
|
+
return /* @__PURE__ */ jsxs6("div", { className: "rounded-md border", children: [
|
|
691
|
+
/* @__PURE__ */ jsx6("style", { children: EDITOR_STYLES }),
|
|
692
|
+
/* @__PURE__ */ jsx6(Toolbar, { editor }),
|
|
693
|
+
editor && /* @__PURE__ */ jsx6(ImageBubbleMenu, { editor }),
|
|
694
|
+
/* @__PURE__ */ jsx6(EditorContent, { editor })
|
|
625
695
|
] });
|
|
626
696
|
}
|
|
627
697
|
|
|
628
698
|
// src/components/post-history-panel.tsx
|
|
629
|
-
import { useCallback, useEffect as
|
|
699
|
+
import { useCallback, useEffect as useEffect4, useState as useState4 } from "react";
|
|
630
700
|
import { listPostHistory } from "ampless";
|
|
631
701
|
import { Button as Button5 } from "@ampless/runtime/ui";
|
|
632
702
|
|
|
@@ -687,7 +757,7 @@ function buildPreviewSrcDoc(html) {
|
|
|
687
757
|
}
|
|
688
758
|
|
|
689
759
|
// src/components/post-history-panel.tsx
|
|
690
|
-
import { Fragment as Fragment2, jsx as
|
|
760
|
+
import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
691
761
|
var PAGE_SIZE = 20;
|
|
692
762
|
function formatRevisedAt(iso, timezone, locale) {
|
|
693
763
|
const d = new Date(iso);
|
|
@@ -728,17 +798,17 @@ function PostHistoryPanel({
|
|
|
728
798
|
const config = getAdminCmsConfig();
|
|
729
799
|
const timezone = config?.timezone ?? "UTC";
|
|
730
800
|
const locale = config?.locale ?? "en";
|
|
731
|
-
const [open, setOpen] =
|
|
732
|
-
const [loaded, setLoaded] =
|
|
733
|
-
const [loading, setLoading] =
|
|
734
|
-
const [error, setError] =
|
|
735
|
-
const [revisions, setRevisions] =
|
|
736
|
-
const [nextToken, setNextToken] =
|
|
737
|
-
const [selected, setSelected] =
|
|
738
|
-
const [previewHtml, setPreviewHtml] =
|
|
801
|
+
const [open, setOpen] = useState4(false);
|
|
802
|
+
const [loaded, setLoaded] = useState4(false);
|
|
803
|
+
const [loading, setLoading] = useState4(false);
|
|
804
|
+
const [error, setError] = useState4(null);
|
|
805
|
+
const [revisions, setRevisions] = useState4([]);
|
|
806
|
+
const [nextToken, setNextToken] = useState4(void 0);
|
|
807
|
+
const [selected, setSelected] = useState4(null);
|
|
808
|
+
const [previewHtml, setPreviewHtml] = useState4("");
|
|
739
809
|
const selectedHistoryId = selected?.postHistoryId;
|
|
740
810
|
const selectedFormat = selected?.format;
|
|
741
|
-
|
|
811
|
+
useEffect4(() => {
|
|
742
812
|
if (!selected) return;
|
|
743
813
|
if (selected.format === "static") return;
|
|
744
814
|
const ctrl = new AbortController();
|
|
@@ -774,14 +844,14 @@ function PostHistoryPanel({
|
|
|
774
844
|
},
|
|
775
845
|
[postId]
|
|
776
846
|
);
|
|
777
|
-
|
|
847
|
+
useEffect4(() => {
|
|
778
848
|
if (open && !loaded) {
|
|
779
849
|
setLoaded(true);
|
|
780
850
|
void loadPage();
|
|
781
851
|
}
|
|
782
852
|
}, [open, loaded, loadPage]);
|
|
783
|
-
return /* @__PURE__ */
|
|
784
|
-
/* @__PURE__ */
|
|
853
|
+
return /* @__PURE__ */ jsxs7("section", { className: "rounded-md border", children: [
|
|
854
|
+
/* @__PURE__ */ jsxs7(
|
|
785
855
|
"button",
|
|
786
856
|
{
|
|
787
857
|
type: "button",
|
|
@@ -789,30 +859,30 @@ function PostHistoryPanel({
|
|
|
789
859
|
"aria-expanded": open,
|
|
790
860
|
className: "flex w-full items-center justify-between px-4 py-3 text-left text-sm font-medium",
|
|
791
861
|
children: [
|
|
792
|
-
/* @__PURE__ */
|
|
793
|
-
/* @__PURE__ */
|
|
862
|
+
/* @__PURE__ */ jsx7("span", { children: t("posts.history.title") }),
|
|
863
|
+
/* @__PURE__ */ jsx7("span", { className: "text-muted-foreground", "aria-hidden": "true", children: open ? "\u2212" : "+" })
|
|
794
864
|
]
|
|
795
865
|
}
|
|
796
866
|
),
|
|
797
|
-
open && /* @__PURE__ */
|
|
798
|
-
error && /* @__PURE__ */
|
|
799
|
-
loading && revisions.length === 0 ? /* @__PURE__ */
|
|
800
|
-
/* @__PURE__ */
|
|
801
|
-
/* @__PURE__ */
|
|
802
|
-
/* @__PURE__ */
|
|
803
|
-
/* @__PURE__ */
|
|
804
|
-
/* @__PURE__ */
|
|
867
|
+
open && /* @__PURE__ */ jsxs7("div", { className: "space-y-4 border-t px-4 py-4", children: [
|
|
868
|
+
error && /* @__PURE__ */ jsx7("p", { className: "text-sm text-destructive", children: error }),
|
|
869
|
+
loading && revisions.length === 0 ? /* @__PURE__ */ jsx7("p", { className: "text-sm text-muted-foreground", children: t("common.loading") }) : revisions.length === 0 ? /* @__PURE__ */ jsx7("p", { className: "text-sm text-muted-foreground", children: t("posts.history.empty") }) : /* @__PURE__ */ jsx7("div", { className: "overflow-x-auto rounded-md border", children: /* @__PURE__ */ jsxs7("table", { className: "w-full text-sm", children: [
|
|
870
|
+
/* @__PURE__ */ jsx7("thead", { children: /* @__PURE__ */ jsxs7("tr", { className: "border-b text-left text-xs text-muted-foreground", children: [
|
|
871
|
+
/* @__PURE__ */ jsx7("th", { className: "px-3 py-2 font-medium", children: t("posts.history.columnRevisedAt") }),
|
|
872
|
+
/* @__PURE__ */ jsx7("th", { className: "px-3 py-2 font-medium", children: t("posts.history.columnStatus") }),
|
|
873
|
+
/* @__PURE__ */ jsx7("th", { className: "px-3 py-2 font-medium", children: t("posts.history.columnTitle") }),
|
|
874
|
+
/* @__PURE__ */ jsx7("th", { className: "px-3 py-2 font-medium text-right", children: t("common.actions") })
|
|
805
875
|
] }) }),
|
|
806
|
-
/* @__PURE__ */
|
|
876
|
+
/* @__PURE__ */ jsx7("tbody", { children: revisions.map((rev) => /* @__PURE__ */ jsxs7(
|
|
807
877
|
"tr",
|
|
808
878
|
{
|
|
809
879
|
className: selected?.postHistoryId === rev.postHistoryId ? "border-b bg-muted/50" : "border-b",
|
|
810
880
|
children: [
|
|
811
|
-
/* @__PURE__ */
|
|
812
|
-
/* @__PURE__ */
|
|
813
|
-
/* @__PURE__ */
|
|
814
|
-
/* @__PURE__ */
|
|
815
|
-
/* @__PURE__ */
|
|
881
|
+
/* @__PURE__ */ jsx7("td", { className: "whitespace-nowrap px-3 py-2 font-mono text-xs", children: formatRevisedAt(rev.revisedAt, timezone, locale) }),
|
|
882
|
+
/* @__PURE__ */ jsx7("td", { className: "px-3 py-2", children: /* @__PURE__ */ jsx7("span", { className: "text-xs text-muted-foreground", children: rev.status ? t(`common.${rev.status}`) : "\u2014" }) }),
|
|
883
|
+
/* @__PURE__ */ jsx7("td", { className: "px-3 py-2", children: rev.title || "\u2014" }),
|
|
884
|
+
/* @__PURE__ */ jsx7("td", { className: "px-3 py-2 text-right", children: /* @__PURE__ */ jsxs7("div", { className: "flex justify-end gap-2", children: [
|
|
885
|
+
/* @__PURE__ */ jsx7(
|
|
816
886
|
Button5,
|
|
817
887
|
{
|
|
818
888
|
type: "button",
|
|
@@ -822,7 +892,7 @@ function PostHistoryPanel({
|
|
|
822
892
|
children: t("posts.history.view")
|
|
823
893
|
}
|
|
824
894
|
),
|
|
825
|
-
/* @__PURE__ */
|
|
895
|
+
/* @__PURE__ */ jsx7(
|
|
826
896
|
Button5,
|
|
827
897
|
{
|
|
828
898
|
type: "button",
|
|
@@ -840,7 +910,7 @@ function PostHistoryPanel({
|
|
|
840
910
|
rev.postHistoryId
|
|
841
911
|
)) })
|
|
842
912
|
] }) }),
|
|
843
|
-
nextToken && /* @__PURE__ */
|
|
913
|
+
nextToken && /* @__PURE__ */ jsx7("div", { children: /* @__PURE__ */ jsx7(
|
|
844
914
|
Button5,
|
|
845
915
|
{
|
|
846
916
|
type: "button",
|
|
@@ -851,12 +921,12 @@ function PostHistoryPanel({
|
|
|
851
921
|
children: loading ? t("common.loading") : t("posts.history.loadMore")
|
|
852
922
|
}
|
|
853
923
|
) }),
|
|
854
|
-
selected && /* @__PURE__ */
|
|
855
|
-
/* @__PURE__ */
|
|
856
|
-
/* @__PURE__ */
|
|
924
|
+
selected && /* @__PURE__ */ jsxs7("div", { className: "space-y-3 rounded-md border p-4", children: [
|
|
925
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between", children: [
|
|
926
|
+
/* @__PURE__ */ jsx7("h4", { className: "text-sm font-semibold", children: t("posts.history.viewing", {
|
|
857
927
|
date: formatRevisedAt(selected.revisedAt, timezone, locale)
|
|
858
928
|
}) }),
|
|
859
|
-
/* @__PURE__ */
|
|
929
|
+
/* @__PURE__ */ jsx7(
|
|
860
930
|
Button5,
|
|
861
931
|
{
|
|
862
932
|
type: "button",
|
|
@@ -867,14 +937,14 @@ function PostHistoryPanel({
|
|
|
867
937
|
}
|
|
868
938
|
)
|
|
869
939
|
] }),
|
|
870
|
-
/* @__PURE__ */
|
|
871
|
-
/* @__PURE__ */
|
|
872
|
-
selected.slug && /* @__PURE__ */
|
|
873
|
-
/* @__PURE__ */
|
|
874
|
-
/* @__PURE__ */
|
|
940
|
+
/* @__PURE__ */ jsxs7("p", { className: "text-xs text-muted-foreground", children: [
|
|
941
|
+
/* @__PURE__ */ jsx7("span", { className: "font-mono uppercase", children: selected.format ?? "\u2014" }),
|
|
942
|
+
selected.slug && /* @__PURE__ */ jsxs7(Fragment2, { children: [
|
|
943
|
+
/* @__PURE__ */ jsx7("span", { className: "mx-2", children: "\xB7" }),
|
|
944
|
+
/* @__PURE__ */ jsx7("span", { className: "font-mono", children: selected.slug })
|
|
875
945
|
] })
|
|
876
946
|
] }),
|
|
877
|
-
selected.format === "static" ? /* @__PURE__ */
|
|
947
|
+
selected.format === "static" ? /* @__PURE__ */ jsx7("p", { className: "rounded-md bg-amber-50 p-2 text-xs text-amber-700 dark:bg-amber-950 dark:text-amber-400", children: t("posts.history.staticCaveat") }) : (
|
|
878
948
|
// Sandbox is `allow-scripts allow-same-origin`. With
|
|
879
949
|
// srcDoc, this gives the iframe the admin's origin so
|
|
880
950
|
// 3rd-party embed widgets (YouTube SDK, x.com widgets.js)
|
|
@@ -901,7 +971,7 @@ function PostHistoryPanel({
|
|
|
901
971
|
// don't style its srcDoc contents. Typography comes from
|
|
902
972
|
// the full document the preview route now returns
|
|
903
973
|
// (PREVIEW_BASE_CSS + theme vars in createPreviewRouteHandler).
|
|
904
|
-
/* @__PURE__ */
|
|
974
|
+
/* @__PURE__ */ jsx7(
|
|
905
975
|
"iframe",
|
|
906
976
|
{
|
|
907
977
|
title: "revision-preview",
|
|
@@ -917,7 +987,7 @@ function PostHistoryPanel({
|
|
|
917
987
|
}
|
|
918
988
|
|
|
919
989
|
// src/components/static-uploader.tsx
|
|
920
|
-
import { useState as
|
|
990
|
+
import { useState as useState5 } from "react";
|
|
921
991
|
import { FileText, AlertTriangle, FileArchive, X } from "lucide-react";
|
|
922
992
|
import { Button as Button6 } from "@ampless/runtime/ui";
|
|
923
993
|
|
|
@@ -1005,13 +1075,13 @@ async function deleteBundle(slug) {
|
|
|
1005
1075
|
}
|
|
1006
1076
|
|
|
1007
1077
|
// src/components/static-uploader.tsx
|
|
1008
|
-
import { jsx as
|
|
1078
|
+
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1009
1079
|
function StaticUploader({ initial, onFilesReady, onClear }) {
|
|
1010
1080
|
const t = useT();
|
|
1011
|
-
const [pending, setPending] =
|
|
1012
|
-
const [issues, setIssues] =
|
|
1013
|
-
const [busy, setBusy] =
|
|
1014
|
-
const [error, setError] =
|
|
1081
|
+
const [pending, setPending] = useState5(null);
|
|
1082
|
+
const [issues, setIssues] = useState5([]);
|
|
1083
|
+
const [busy, setBusy] = useState5(false);
|
|
1084
|
+
const [error, setError] = useState5(null);
|
|
1015
1085
|
async function handleZip(file) {
|
|
1016
1086
|
setBusy(true);
|
|
1017
1087
|
setError(null);
|
|
@@ -1085,11 +1155,11 @@ function StaticUploader({ initial, onFilesReady, onClear }) {
|
|
|
1085
1155
|
onClear();
|
|
1086
1156
|
}
|
|
1087
1157
|
const showCurrent = !pending && initial && initial.files.length > 0;
|
|
1088
|
-
return /* @__PURE__ */
|
|
1089
|
-
/* @__PURE__ */
|
|
1090
|
-
/* @__PURE__ */
|
|
1091
|
-
/* @__PURE__ */
|
|
1092
|
-
/* @__PURE__ */
|
|
1158
|
+
return /* @__PURE__ */ jsxs8("div", { className: "space-y-4", children: [
|
|
1159
|
+
/* @__PURE__ */ jsxs8("div", { className: "rounded-md border border-dashed p-4", children: [
|
|
1160
|
+
/* @__PURE__ */ jsxs8("label", { className: "flex flex-col items-start gap-2 text-sm", children: [
|
|
1161
|
+
/* @__PURE__ */ jsx8("span", { className: "font-medium", children: t("posts.form.static.pick") }),
|
|
1162
|
+
/* @__PURE__ */ jsx8(
|
|
1093
1163
|
"input",
|
|
1094
1164
|
{
|
|
1095
1165
|
type: "file",
|
|
@@ -1099,13 +1169,13 @@ function StaticUploader({ initial, onFilesReady, onClear }) {
|
|
|
1099
1169
|
disabled: busy
|
|
1100
1170
|
}
|
|
1101
1171
|
),
|
|
1102
|
-
/* @__PURE__ */
|
|
1172
|
+
/* @__PURE__ */ jsx8("span", { className: "text-xs text-muted-foreground", children: t("posts.form.static.pickHint") })
|
|
1103
1173
|
] }),
|
|
1104
|
-
busy && /* @__PURE__ */
|
|
1105
|
-
error && /* @__PURE__ */
|
|
1174
|
+
busy && /* @__PURE__ */ jsx8("p", { className: "mt-2 text-sm text-muted-foreground", children: t("common.loading") }),
|
|
1175
|
+
error && /* @__PURE__ */ jsx8("p", { className: "mt-2 text-sm text-destructive", children: error })
|
|
1106
1176
|
] }),
|
|
1107
|
-
showCurrent && /* @__PURE__ */
|
|
1108
|
-
pending && /* @__PURE__ */
|
|
1177
|
+
showCurrent && /* @__PURE__ */ jsx8(CurrentBundle, { body: initial }),
|
|
1178
|
+
pending && /* @__PURE__ */ jsx8(
|
|
1109
1179
|
PendingBundle,
|
|
1110
1180
|
{
|
|
1111
1181
|
files: pending,
|
|
@@ -1117,15 +1187,15 @@ function StaticUploader({ initial, onFilesReady, onClear }) {
|
|
|
1117
1187
|
}
|
|
1118
1188
|
function CurrentBundle({ body }) {
|
|
1119
1189
|
const t = useT();
|
|
1120
|
-
return /* @__PURE__ */
|
|
1121
|
-
/* @__PURE__ */
|
|
1122
|
-
/* @__PURE__ */
|
|
1190
|
+
return /* @__PURE__ */ jsxs8("div", { className: "rounded-md border bg-muted/30 p-3", children: [
|
|
1191
|
+
/* @__PURE__ */ jsxs8("div", { className: "mb-2 flex items-center gap-2 text-sm font-medium", children: [
|
|
1192
|
+
/* @__PURE__ */ jsx8(FileArchive, { className: "h-4 w-4" }),
|
|
1123
1193
|
t("posts.form.static.currentBundle", {
|
|
1124
1194
|
count: body.files.length,
|
|
1125
1195
|
entrypoint: body.entrypoint
|
|
1126
1196
|
})
|
|
1127
1197
|
] }),
|
|
1128
|
-
/* @__PURE__ */
|
|
1198
|
+
/* @__PURE__ */ jsx8(FileList, { files: body.files })
|
|
1129
1199
|
] });
|
|
1130
1200
|
}
|
|
1131
1201
|
function PendingBundle({
|
|
@@ -1135,49 +1205,49 @@ function PendingBundle({
|
|
|
1135
1205
|
}) {
|
|
1136
1206
|
const t = useT();
|
|
1137
1207
|
const totalBytes = files.reduce((sum, f) => sum + f.data.byteLength, 0);
|
|
1138
|
-
return /* @__PURE__ */
|
|
1139
|
-
/* @__PURE__ */
|
|
1140
|
-
/* @__PURE__ */
|
|
1141
|
-
/* @__PURE__ */
|
|
1208
|
+
return /* @__PURE__ */ jsxs8("div", { className: "rounded-md border p-3", children: [
|
|
1209
|
+
/* @__PURE__ */ jsxs8("div", { className: "mb-2 flex items-center justify-between gap-2 text-sm font-medium", children: [
|
|
1210
|
+
/* @__PURE__ */ jsxs8("span", { className: "flex items-center gap-2", children: [
|
|
1211
|
+
/* @__PURE__ */ jsx8(FileArchive, { className: "h-4 w-4" }),
|
|
1142
1212
|
t("posts.form.static.pendingBundle", {
|
|
1143
1213
|
count: files.length,
|
|
1144
1214
|
size: formatBytes(totalBytes)
|
|
1145
1215
|
})
|
|
1146
1216
|
] }),
|
|
1147
|
-
/* @__PURE__ */
|
|
1148
|
-
/* @__PURE__ */
|
|
1217
|
+
/* @__PURE__ */ jsxs8(Button6, { type: "button", variant: "ghost", size: "sm", onClick: onClear, children: [
|
|
1218
|
+
/* @__PURE__ */ jsx8(X, { className: "mr-1 h-3 w-3" }),
|
|
1149
1219
|
t("common.cancel")
|
|
1150
1220
|
] })
|
|
1151
1221
|
] }),
|
|
1152
|
-
issues.length > 0 && /* @__PURE__ */
|
|
1153
|
-
/* @__PURE__ */
|
|
1154
|
-
/* @__PURE__ */
|
|
1222
|
+
issues.length > 0 && /* @__PURE__ */ jsxs8("div", { className: "mb-3 rounded-md border border-destructive/40 bg-destructive/5 p-2 text-sm", children: [
|
|
1223
|
+
/* @__PURE__ */ jsxs8("div", { className: "mb-1 flex items-center gap-2 font-medium text-destructive", children: [
|
|
1224
|
+
/* @__PURE__ */ jsx8(AlertTriangle, { className: "h-4 w-4" }),
|
|
1155
1225
|
t("posts.form.static.issuesTitle", { count: issues.length })
|
|
1156
1226
|
] }),
|
|
1157
|
-
/* @__PURE__ */
|
|
1158
|
-
issues.slice(0, 20).map((issue, idx) => /* @__PURE__ */
|
|
1227
|
+
/* @__PURE__ */ jsxs8("ul", { className: "space-y-0.5 text-xs", children: [
|
|
1228
|
+
issues.slice(0, 20).map((issue, idx) => /* @__PURE__ */ jsxs8("li", { className: "font-mono", children: [
|
|
1159
1229
|
issue.path,
|
|
1160
1230
|
": ",
|
|
1161
1231
|
issue.reason
|
|
1162
1232
|
] }, `${issue.path}-${idx}`)),
|
|
1163
|
-
issues.length > 20 && /* @__PURE__ */
|
|
1233
|
+
issues.length > 20 && /* @__PURE__ */ jsxs8("li", { className: "font-mono text-muted-foreground", children: [
|
|
1164
1234
|
"\u2026 ",
|
|
1165
1235
|
issues.length - 20,
|
|
1166
1236
|
" more"
|
|
1167
1237
|
] })
|
|
1168
1238
|
] }),
|
|
1169
|
-
/* @__PURE__ */
|
|
1239
|
+
/* @__PURE__ */ jsx8("p", { className: "mt-2 text-xs text-muted-foreground", children: t("posts.form.static.issuesHint") })
|
|
1170
1240
|
] }),
|
|
1171
|
-
/* @__PURE__ */
|
|
1241
|
+
/* @__PURE__ */ jsx8(FileList, { files: files.map((f) => f.path) })
|
|
1172
1242
|
] });
|
|
1173
1243
|
}
|
|
1174
1244
|
function FileList({ files }) {
|
|
1175
|
-
return /* @__PURE__ */
|
|
1176
|
-
files.slice(0, 40).map((path) => /* @__PURE__ */
|
|
1177
|
-
/* @__PURE__ */
|
|
1245
|
+
return /* @__PURE__ */ jsxs8("ul", { className: "space-y-0.5 text-xs", children: [
|
|
1246
|
+
files.slice(0, 40).map((path) => /* @__PURE__ */ jsxs8("li", { className: "flex items-center gap-1.5 font-mono text-muted-foreground", children: [
|
|
1247
|
+
/* @__PURE__ */ jsx8(FileText, { className: "h-3 w-3 shrink-0" }),
|
|
1178
1248
|
path
|
|
1179
1249
|
] }, path)),
|
|
1180
|
-
files.length > 40 && /* @__PURE__ */
|
|
1250
|
+
files.length > 40 && /* @__PURE__ */ jsxs8("li", { className: "font-mono text-xs text-muted-foreground", children: [
|
|
1181
1251
|
"\u2026 ",
|
|
1182
1252
|
files.length - 40,
|
|
1183
1253
|
" more"
|
|
@@ -1371,7 +1441,7 @@ function convertBodyFormat(body, from, to, registries) {
|
|
|
1371
1441
|
}
|
|
1372
1442
|
|
|
1373
1443
|
// src/components/post-form.tsx
|
|
1374
|
-
import { jsx as
|
|
1444
|
+
import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1375
1445
|
var EMPTY_TIPTAP_DOC = { type: "doc", content: [{ type: "paragraph" }] };
|
|
1376
1446
|
var IMAGE_URL_RE = /\.(jpe?g|png|gif|webp|avif|svg|bmp|tiff?)(\?|$)/i;
|
|
1377
1447
|
var STYLESHEET_URL_RE = /\.css(\?|$)/i;
|
|
@@ -1417,27 +1487,27 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
1417
1487
|
const router = useRouter();
|
|
1418
1488
|
const t = useT();
|
|
1419
1489
|
const isEdit = !!post;
|
|
1420
|
-
const bodyTextareaRef =
|
|
1421
|
-
const [title, setTitle] =
|
|
1422
|
-
const [slug, setSlug] =
|
|
1423
|
-
const [excerpt, setExcerpt] =
|
|
1424
|
-
const [format, setFormat] =
|
|
1425
|
-
const [body, setBody] =
|
|
1426
|
-
const [status, setStatus] =
|
|
1427
|
-
const [tagsInput, setTagsInput] =
|
|
1428
|
-
const [noLayout, setNoLayout] =
|
|
1429
|
-
const [publishedAtInput, setPublishedAtInput] =
|
|
1430
|
-
const [saving, setSaving] =
|
|
1431
|
-
const [error, setError] =
|
|
1432
|
-
const [view, setView] =
|
|
1433
|
-
const [previewHtml, setPreviewHtml] =
|
|
1434
|
-
const [editorEpoch, setEditorEpoch] =
|
|
1435
|
-
const dirtyRef =
|
|
1490
|
+
const bodyTextareaRef = useRef4(null);
|
|
1491
|
+
const [title, setTitle] = useState6(post?.title ?? "");
|
|
1492
|
+
const [slug, setSlug] = useState6(post?.slug ?? "");
|
|
1493
|
+
const [excerpt, setExcerpt] = useState6(post?.excerpt ?? "");
|
|
1494
|
+
const [format, setFormat] = useState6(post?.format ?? "tiptap");
|
|
1495
|
+
const [body, setBody] = useState6(post?.body ?? EMPTY_TIPTAP_DOC);
|
|
1496
|
+
const [status, setStatus] = useState6(post?.status ?? "draft");
|
|
1497
|
+
const [tagsInput, setTagsInput] = useState6((post?.tags ?? []).join(", "));
|
|
1498
|
+
const [noLayout, setNoLayout] = useState6(post?.metadata?.no_layout === true);
|
|
1499
|
+
const [publishedAtInput, setPublishedAtInput] = useState6(isoToLocalInput(post?.publishedAt));
|
|
1500
|
+
const [saving, setSaving] = useState6(false);
|
|
1501
|
+
const [error, setError] = useState6(null);
|
|
1502
|
+
const [view, setView] = useState6("edit");
|
|
1503
|
+
const [previewHtml, setPreviewHtml] = useState6("");
|
|
1504
|
+
const [editorEpoch, setEditorEpoch] = useState6(0);
|
|
1505
|
+
const dirtyRef = useRef4(false);
|
|
1436
1506
|
function markDirty() {
|
|
1437
1507
|
dirtyRef.current = true;
|
|
1438
1508
|
}
|
|
1439
|
-
const [recovery, setRecovery] =
|
|
1440
|
-
const [restoredHint, setRestoredHint] =
|
|
1509
|
+
const [recovery, setRecovery] = useState6(null);
|
|
1510
|
+
const [restoredHint, setRestoredHint] = useState6(false);
|
|
1441
1511
|
const draftId = post?.postId ?? NEW_POST_DRAFT_ID;
|
|
1442
1512
|
const isStaticFormat = format === "static";
|
|
1443
1513
|
const cmsConfig = getAdminCmsConfig();
|
|
@@ -1450,7 +1520,7 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
1450
1520
|
initialInput: initialPublishedAtInput,
|
|
1451
1521
|
existing: post?.publishedAt
|
|
1452
1522
|
});
|
|
1453
|
-
const [pendingBundle, setPendingBundle] =
|
|
1523
|
+
const [pendingBundle, setPendingBundle] = useState6(null);
|
|
1454
1524
|
const initialStaticBody = isStaticBody(post?.body) ? post.body : null;
|
|
1455
1525
|
function buildMetadata() {
|
|
1456
1526
|
const next = { ...post?.metadata ?? {} };
|
|
@@ -1518,7 +1588,7 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
1518
1588
|
dirtyRef.current = false;
|
|
1519
1589
|
setRecovery(null);
|
|
1520
1590
|
}
|
|
1521
|
-
|
|
1591
|
+
useEffect5(() => {
|
|
1522
1592
|
if (loadedState.format === "static") return;
|
|
1523
1593
|
const draft = readDraft(draftId);
|
|
1524
1594
|
if (!draft) return;
|
|
@@ -1533,7 +1603,7 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
1533
1603
|
}
|
|
1534
1604
|
setRecovery({ draft, decision });
|
|
1535
1605
|
}, []);
|
|
1536
|
-
|
|
1606
|
+
useEffect5(() => {
|
|
1537
1607
|
if (isStaticFormat) return;
|
|
1538
1608
|
if (!dirtyRef.current) return;
|
|
1539
1609
|
const handle = setTimeout(() => {
|
|
@@ -1700,7 +1770,7 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
1700
1770
|
publishedAt: resolvedPublishedAt,
|
|
1701
1771
|
tags: parseTags(tagsInput)
|
|
1702
1772
|
};
|
|
1703
|
-
|
|
1773
|
+
useEffect5(() => {
|
|
1704
1774
|
if (view !== "preview") return;
|
|
1705
1775
|
if (format === "static") return;
|
|
1706
1776
|
const ctrl = new AbortController();
|
|
@@ -1736,9 +1806,9 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
1736
1806
|
resolvedPublishedAt,
|
|
1737
1807
|
tagsInput
|
|
1738
1808
|
]);
|
|
1739
|
-
return /* @__PURE__ */
|
|
1740
|
-
/* @__PURE__ */
|
|
1741
|
-
/* @__PURE__ */
|
|
1809
|
+
return /* @__PURE__ */ jsxs9("form", { onSubmit: save, className: "space-y-6", children: [
|
|
1810
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex gap-1 border-b", children: [
|
|
1811
|
+
/* @__PURE__ */ jsx9(
|
|
1742
1812
|
"button",
|
|
1743
1813
|
{
|
|
1744
1814
|
type: "button",
|
|
@@ -1748,7 +1818,7 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
1748
1818
|
children: t("posts.form.tabEdit")
|
|
1749
1819
|
}
|
|
1750
1820
|
),
|
|
1751
|
-
/* @__PURE__ */
|
|
1821
|
+
/* @__PURE__ */ jsx9(
|
|
1752
1822
|
"button",
|
|
1753
1823
|
{
|
|
1754
1824
|
type: "button",
|
|
@@ -1759,17 +1829,17 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
1759
1829
|
}
|
|
1760
1830
|
)
|
|
1761
1831
|
] }),
|
|
1762
|
-
view === "preview" && /* @__PURE__ */
|
|
1763
|
-
/* @__PURE__ */
|
|
1764
|
-
/* @__PURE__ */
|
|
1765
|
-
/* @__PURE__ */
|
|
1766
|
-
previewPost.publishedAt ? /* @__PURE__ */
|
|
1767
|
-
/* @__PURE__ */
|
|
1768
|
-
/* @__PURE__ */
|
|
1832
|
+
view === "preview" && /* @__PURE__ */ jsxs9("article", { className: "space-y-4", children: [
|
|
1833
|
+
/* @__PURE__ */ jsxs9("header", { className: "border-b pb-4", children: [
|
|
1834
|
+
/* @__PURE__ */ jsx9("h1", { className: "text-3xl font-bold tracking-tight", children: title || /* @__PURE__ */ jsx9("span", { className: "text-muted-foreground italic", children: t("posts.form.previewNoTitle") }) }),
|
|
1835
|
+
/* @__PURE__ */ jsxs9("p", { className: "mt-2 text-sm text-muted-foreground", children: [
|
|
1836
|
+
previewPost.publishedAt ? /* @__PURE__ */ jsx9("time", { dateTime: previewPost.publishedAt, children: formatDate(previewPost.publishedAt) }) : /* @__PURE__ */ jsx9("span", { children: t("common.draft") }),
|
|
1837
|
+
/* @__PURE__ */ jsx9("span", { className: "mx-2", children: "\xB7" }),
|
|
1838
|
+
/* @__PURE__ */ jsx9("span", { className: "font-mono text-xs uppercase", children: format })
|
|
1769
1839
|
] }),
|
|
1770
|
-
excerpt && /* @__PURE__ */
|
|
1840
|
+
excerpt && /* @__PURE__ */ jsx9("p", { className: "mt-3 text-base text-muted-foreground", children: excerpt })
|
|
1771
1841
|
] }),
|
|
1772
|
-
format === "static" ? /* @__PURE__ */
|
|
1842
|
+
format === "static" ? /* @__PURE__ */ jsx9("p", { className: "text-sm text-muted-foreground", children: t("posts.form.static.previewHint") }) : (
|
|
1773
1843
|
// Phase 7: preview HTML is fetched from the template's
|
|
1774
1844
|
// `/admin/preview` Route Handler so `ampless.renderBody`
|
|
1775
1845
|
// (async ReactNode) + `ampless.publicPostScriptsForPage(
|
|
@@ -1807,7 +1877,7 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
1807
1877
|
// document — an iframe srcDoc does not inherit the parent page's
|
|
1808
1878
|
// CSS. Typography is now applied inside the document returned by
|
|
1809
1879
|
// createPreviewRouteHandler (PREVIEW_BASE_CSS + theme cssVars).
|
|
1810
|
-
/* @__PURE__ */
|
|
1880
|
+
/* @__PURE__ */ jsx9(
|
|
1811
1881
|
"iframe",
|
|
1812
1882
|
{
|
|
1813
1883
|
title: "post-preview",
|
|
@@ -1817,7 +1887,7 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
1817
1887
|
}
|
|
1818
1888
|
)
|
|
1819
1889
|
),
|
|
1820
|
-
previewPost.tags && previewPost.tags.length > 0 && /* @__PURE__ */
|
|
1890
|
+
previewPost.tags && previewPost.tags.length > 0 && /* @__PURE__ */ jsx9("div", { className: "flex flex-wrap gap-2 border-t pt-4 text-sm", children: previewPost.tags.map((tag) => /* @__PURE__ */ jsxs9(
|
|
1821
1891
|
"span",
|
|
1822
1892
|
{
|
|
1823
1893
|
className: "rounded-full border px-2 py-0.5 text-xs text-muted-foreground",
|
|
@@ -1828,34 +1898,34 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
1828
1898
|
},
|
|
1829
1899
|
tag
|
|
1830
1900
|
)) }),
|
|
1831
|
-
/* @__PURE__ */
|
|
1901
|
+
/* @__PURE__ */ jsx9("p", { className: "text-xs text-muted-foreground", children: t("posts.form.previewHint") })
|
|
1832
1902
|
] }),
|
|
1833
|
-
/* @__PURE__ */
|
|
1834
|
-
recovery && /* @__PURE__ */
|
|
1903
|
+
/* @__PURE__ */ jsxs9("div", { className: view === "edit" ? "space-y-6" : "hidden", children: [
|
|
1904
|
+
recovery && /* @__PURE__ */ jsxs9(
|
|
1835
1905
|
"div",
|
|
1836
1906
|
{
|
|
1837
1907
|
role: "alert",
|
|
1838
1908
|
className: recovery.decision === "stale" ? "space-y-2 rounded-md border border-amber-300 bg-amber-50 p-4 text-sm dark:border-amber-800 dark:bg-amber-950" : "space-y-2 rounded-md border border-[var(--primary)]/40 bg-[var(--primary)]/5 p-4 text-sm",
|
|
1839
1909
|
children: [
|
|
1840
|
-
/* @__PURE__ */
|
|
1841
|
-
/* @__PURE__ */
|
|
1910
|
+
/* @__PURE__ */ jsx9("p", { className: "font-medium", children: recovery.decision === "stale" ? t("posts.draft.staleTitle") : t("posts.draft.recoverTitle") }),
|
|
1911
|
+
/* @__PURE__ */ jsx9("p", { className: "text-muted-foreground", children: recovery.decision === "stale" ? t("posts.draft.staleBody", {
|
|
1842
1912
|
when: formatDraftTime(recovery.draft.savedAt, draftTimezone, draftLocale)
|
|
1843
1913
|
}) : t("posts.draft.recoverBody", {
|
|
1844
1914
|
when: formatDraftTime(recovery.draft.savedAt, draftTimezone, draftLocale)
|
|
1845
1915
|
}) }),
|
|
1846
|
-
/* @__PURE__ */
|
|
1847
|
-
/* @__PURE__ */
|
|
1848
|
-
/* @__PURE__ */
|
|
1916
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex gap-2", children: [
|
|
1917
|
+
/* @__PURE__ */ jsx9(Button7, { type: "button", size: "sm", onClick: acceptRecovery, children: recovery.decision === "stale" ? t("posts.draft.restoreAnyway") : t("posts.draft.restore") }),
|
|
1918
|
+
/* @__PURE__ */ jsx9(Button7, { type: "button", size: "sm", variant: "outline", onClick: discardRecovery, children: t("posts.draft.discard") })
|
|
1849
1919
|
] })
|
|
1850
1920
|
]
|
|
1851
1921
|
}
|
|
1852
1922
|
),
|
|
1853
|
-
restoredHint && !recovery && /* @__PURE__ */
|
|
1854
|
-
isStaticFormat && /* @__PURE__ */
|
|
1855
|
-
/* @__PURE__ */
|
|
1856
|
-
/* @__PURE__ */
|
|
1857
|
-
/* @__PURE__ */
|
|
1858
|
-
|
|
1923
|
+
restoredHint && !recovery && /* @__PURE__ */ jsx9("p", { className: "rounded-md border border-[var(--primary)]/40 bg-[var(--primary)]/5 px-3 py-2 text-xs text-muted-foreground", children: t("posts.draft.restored") }),
|
|
1924
|
+
isStaticFormat && /* @__PURE__ */ jsx9("p", { className: "rounded-md border bg-muted/40 px-3 py-2 text-xs text-muted-foreground", children: t("posts.draft.staticUnsupported") }),
|
|
1925
|
+
/* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
|
|
1926
|
+
/* @__PURE__ */ jsx9(Label, { htmlFor: "title", children: t("posts.form.title") }),
|
|
1927
|
+
/* @__PURE__ */ jsx9(
|
|
1928
|
+
Input2,
|
|
1859
1929
|
{
|
|
1860
1930
|
id: "title",
|
|
1861
1931
|
required: true,
|
|
@@ -1868,10 +1938,10 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
1868
1938
|
}
|
|
1869
1939
|
)
|
|
1870
1940
|
] }),
|
|
1871
|
-
/* @__PURE__ */
|
|
1872
|
-
/* @__PURE__ */
|
|
1873
|
-
/* @__PURE__ */
|
|
1874
|
-
|
|
1941
|
+
/* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
|
|
1942
|
+
/* @__PURE__ */ jsx9(Label, { htmlFor: "slug", children: t("posts.form.slug") }),
|
|
1943
|
+
/* @__PURE__ */ jsx9(
|
|
1944
|
+
Input2,
|
|
1875
1945
|
{
|
|
1876
1946
|
id: "slug",
|
|
1877
1947
|
value: slug,
|
|
@@ -1883,9 +1953,9 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
1883
1953
|
}
|
|
1884
1954
|
)
|
|
1885
1955
|
] }),
|
|
1886
|
-
/* @__PURE__ */
|
|
1887
|
-
/* @__PURE__ */
|
|
1888
|
-
/* @__PURE__ */
|
|
1956
|
+
/* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
|
|
1957
|
+
/* @__PURE__ */ jsx9(Label, { htmlFor: "excerpt", children: t("posts.form.excerpt") }),
|
|
1958
|
+
/* @__PURE__ */ jsx9(
|
|
1889
1959
|
Textarea,
|
|
1890
1960
|
{
|
|
1891
1961
|
id: "excerpt",
|
|
@@ -1898,9 +1968,9 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
1898
1968
|
}
|
|
1899
1969
|
)
|
|
1900
1970
|
] }),
|
|
1901
|
-
/* @__PURE__ */
|
|
1902
|
-
/* @__PURE__ */
|
|
1903
|
-
/* @__PURE__ */
|
|
1971
|
+
/* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
|
|
1972
|
+
/* @__PURE__ */ jsx9(Label, { htmlFor: "format", children: t("posts.form.format") }),
|
|
1973
|
+
/* @__PURE__ */ jsxs9(
|
|
1904
1974
|
"select",
|
|
1905
1975
|
{
|
|
1906
1976
|
id: "format",
|
|
@@ -1908,34 +1978,34 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
1908
1978
|
onChange: (e) => changeFormat(e.target.value),
|
|
1909
1979
|
className: "flex h-9 w-full max-w-xs rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm",
|
|
1910
1980
|
children: [
|
|
1911
|
-
/* @__PURE__ */
|
|
1912
|
-
/* @__PURE__ */
|
|
1913
|
-
/* @__PURE__ */
|
|
1914
|
-
/* @__PURE__ */
|
|
1981
|
+
/* @__PURE__ */ jsx9("option", { value: "tiptap", children: "Tiptap (rich editor)" }),
|
|
1982
|
+
/* @__PURE__ */ jsx9("option", { value: "markdown", children: "Markdown" }),
|
|
1983
|
+
/* @__PURE__ */ jsx9("option", { value: "html", children: "HTML" }),
|
|
1984
|
+
/* @__PURE__ */ jsx9("option", { value: "static", children: t("posts.form.formatStaticLabel") })
|
|
1915
1985
|
]
|
|
1916
1986
|
}
|
|
1917
1987
|
),
|
|
1918
|
-
/* @__PURE__ */
|
|
1988
|
+
/* @__PURE__ */ jsx9("p", { className: "text-xs text-muted-foreground", children: t("posts.form.formatHint") })
|
|
1919
1989
|
] }),
|
|
1920
|
-
/* @__PURE__ */
|
|
1921
|
-
/* @__PURE__ */
|
|
1922
|
-
/* @__PURE__ */
|
|
1990
|
+
/* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
|
|
1991
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between", children: [
|
|
1992
|
+
/* @__PURE__ */ jsx9(Label, { children: t("posts.form.body") }),
|
|
1923
1993
|
format !== "tiptap" && format !== "static" && // For textarea-based formats (markdown / html) there's no
|
|
1924
1994
|
// embedded toolbar, so we surface the MediaPicker as a
|
|
1925
1995
|
// standalone button. Selecting an asset inserts a
|
|
1926
1996
|
// format-aware snippet at the cursor.
|
|
1927
|
-
/* @__PURE__ */
|
|
1997
|
+
/* @__PURE__ */ jsx9(
|
|
1928
1998
|
MediaPicker,
|
|
1929
1999
|
{
|
|
1930
2000
|
onSelect: insertMediaSnippet,
|
|
1931
|
-
trigger: /* @__PURE__ */
|
|
1932
|
-
/* @__PURE__ */
|
|
2001
|
+
trigger: /* @__PURE__ */ jsxs9(Button7, { type: "button", variant: "outline", size: "sm", children: [
|
|
2002
|
+
/* @__PURE__ */ jsx9(ImageIcon3, { className: "mr-2 h-3 w-3" }),
|
|
1933
2003
|
t("posts.form.insertMedia")
|
|
1934
2004
|
] })
|
|
1935
2005
|
}
|
|
1936
2006
|
)
|
|
1937
2007
|
] }),
|
|
1938
|
-
format === "tiptap" ? /* @__PURE__ */
|
|
2008
|
+
format === "tiptap" ? /* @__PURE__ */ jsx9(
|
|
1939
2009
|
TiptapEditor,
|
|
1940
2010
|
{
|
|
1941
2011
|
initialContent: body,
|
|
@@ -1943,14 +2013,14 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
1943
2013
|
onUserEdit: markDirty
|
|
1944
2014
|
},
|
|
1945
2015
|
editorEpoch
|
|
1946
|
-
) : format === "static" ? /* @__PURE__ */
|
|
2016
|
+
) : format === "static" ? /* @__PURE__ */ jsx9(
|
|
1947
2017
|
StaticUploader,
|
|
1948
2018
|
{
|
|
1949
2019
|
initial: initialStaticBody,
|
|
1950
2020
|
onFilesReady: (files, entrypoint) => setPendingBundle({ files, entrypoint }),
|
|
1951
2021
|
onClear: () => setPendingBundle(null)
|
|
1952
2022
|
}
|
|
1953
|
-
) : /* @__PURE__ */
|
|
2023
|
+
) : /* @__PURE__ */ jsx9(
|
|
1954
2024
|
Textarea,
|
|
1955
2025
|
{
|
|
1956
2026
|
ref: bodyTextareaRef,
|
|
@@ -1964,10 +2034,10 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
1964
2034
|
}
|
|
1965
2035
|
)
|
|
1966
2036
|
] }),
|
|
1967
|
-
/* @__PURE__ */
|
|
1968
|
-
/* @__PURE__ */
|
|
1969
|
-
/* @__PURE__ */
|
|
1970
|
-
|
|
2037
|
+
/* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
|
|
2038
|
+
/* @__PURE__ */ jsx9(Label, { htmlFor: "tags", children: t("posts.form.tags") }),
|
|
2039
|
+
/* @__PURE__ */ jsx9(
|
|
2040
|
+
Input2,
|
|
1971
2041
|
{
|
|
1972
2042
|
id: "tags",
|
|
1973
2043
|
value: tagsInput,
|
|
@@ -1978,11 +2048,11 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
1978
2048
|
placeholder: t("posts.form.tagsPlaceholder")
|
|
1979
2049
|
}
|
|
1980
2050
|
),
|
|
1981
|
-
/* @__PURE__ */
|
|
2051
|
+
/* @__PURE__ */ jsx9("p", { className: "text-xs text-muted-foreground", children: t("posts.form.tagsHint") })
|
|
1982
2052
|
] }),
|
|
1983
|
-
/* @__PURE__ */
|
|
1984
|
-
/* @__PURE__ */
|
|
1985
|
-
/* @__PURE__ */
|
|
2053
|
+
/* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
|
|
2054
|
+
/* @__PURE__ */ jsx9(Label, { htmlFor: "status", children: t("posts.form.status") }),
|
|
2055
|
+
/* @__PURE__ */ jsxs9(
|
|
1986
2056
|
"select",
|
|
1987
2057
|
{
|
|
1988
2058
|
id: "status",
|
|
@@ -1993,15 +2063,15 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
1993
2063
|
},
|
|
1994
2064
|
className: "flex h-9 w-full max-w-xs rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm",
|
|
1995
2065
|
children: [
|
|
1996
|
-
/* @__PURE__ */
|
|
1997
|
-
/* @__PURE__ */
|
|
2066
|
+
/* @__PURE__ */ jsx9("option", { value: "draft", children: t("common.draft") }),
|
|
2067
|
+
/* @__PURE__ */ jsx9("option", { value: "published", children: t("common.published") })
|
|
1998
2068
|
]
|
|
1999
2069
|
}
|
|
2000
2070
|
)
|
|
2001
2071
|
] }),
|
|
2002
|
-
/* @__PURE__ */
|
|
2003
|
-
/* @__PURE__ */
|
|
2004
|
-
/* @__PURE__ */
|
|
2072
|
+
/* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
|
|
2073
|
+
/* @__PURE__ */ jsx9(Label, { htmlFor: "publishedAt", children: t("posts.form.publishedAt") }),
|
|
2074
|
+
/* @__PURE__ */ jsx9(
|
|
2005
2075
|
"input",
|
|
2006
2076
|
{
|
|
2007
2077
|
id: "publishedAt",
|
|
@@ -2014,11 +2084,11 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
2014
2084
|
className: "flex h-9 w-full max-w-xs rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm"
|
|
2015
2085
|
}
|
|
2016
2086
|
),
|
|
2017
|
-
/* @__PURE__ */
|
|
2018
|
-
status === "published" && isFuture(resolvedPublishedAt) && /* @__PURE__ */
|
|
2087
|
+
/* @__PURE__ */ jsx9("p", { className: "text-xs text-muted-foreground", children: t("posts.form.publishedAtHint") }),
|
|
2088
|
+
status === "published" && isFuture(resolvedPublishedAt) && /* @__PURE__ */ jsx9("p", { className: "text-xs text-amber-600 dark:text-amber-400", children: t("posts.form.scheduledNotice", { date: publishedAtInput }) })
|
|
2019
2089
|
] }),
|
|
2020
|
-
format === "html" && /* @__PURE__ */
|
|
2021
|
-
/* @__PURE__ */
|
|
2090
|
+
format === "html" && /* @__PURE__ */ jsx9("div", { className: "space-y-2", children: /* @__PURE__ */ jsxs9("label", { className: "flex items-start gap-2 text-sm", children: [
|
|
2091
|
+
/* @__PURE__ */ jsx9(
|
|
2022
2092
|
"input",
|
|
2023
2093
|
{
|
|
2024
2094
|
type: "checkbox",
|
|
@@ -2030,17 +2100,17 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
2030
2100
|
className: "mt-1"
|
|
2031
2101
|
}
|
|
2032
2102
|
),
|
|
2033
|
-
/* @__PURE__ */
|
|
2034
|
-
/* @__PURE__ */
|
|
2035
|
-
/* @__PURE__ */
|
|
2103
|
+
/* @__PURE__ */ jsxs9("span", { children: [
|
|
2104
|
+
/* @__PURE__ */ jsx9("span", { className: "font-medium", children: t("posts.form.noLayout") }),
|
|
2105
|
+
/* @__PURE__ */ jsx9("span", { className: "block text-xs text-muted-foreground", children: t("posts.form.noLayoutHint") })
|
|
2036
2106
|
] })
|
|
2037
2107
|
] }) }),
|
|
2038
|
-
error && /* @__PURE__ */
|
|
2039
|
-
/* @__PURE__ */
|
|
2040
|
-
/* @__PURE__ */
|
|
2041
|
-
isEdit && /* @__PURE__ */
|
|
2108
|
+
error && /* @__PURE__ */ jsx9("p", { className: "text-sm text-destructive", children: error }),
|
|
2109
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2", children: [
|
|
2110
|
+
/* @__PURE__ */ jsx9(Button7, { type: "submit", disabled: saving, children: saving ? t("common.saving") : isEdit ? t("posts.form.saveChanges") : t("posts.form.createPost") }),
|
|
2111
|
+
isEdit && /* @__PURE__ */ jsx9(Button7, { type: "button", variant: "destructive", onClick: handleDelete, disabled: saving, children: t("posts.form.delete") })
|
|
2042
2112
|
] }),
|
|
2043
|
-
isEdit && post && /* @__PURE__ */
|
|
2113
|
+
isEdit && post && /* @__PURE__ */ jsx9(
|
|
2044
2114
|
PostHistoryPanel,
|
|
2045
2115
|
{
|
|
2046
2116
|
postId: post.postId,
|