@ampless/admin 1.0.0-alpha.84 → 1.0.0-beta.100

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.
Files changed (43) hide show
  1. package/README.ja.md +2 -2
  2. package/README.md +2 -2
  3. package/dist/api/index.d.ts +34 -7
  4. package/dist/api/index.js +8 -3
  5. package/dist/{chunk-SQ6LFPXH.js → chunk-2TBGPB5H.js} +2 -2
  6. package/dist/{chunk-K44QF3MV.js → chunk-4OFRX6QX.js} +1 -1
  7. package/dist/{chunk-BRTC5O3E.js → chunk-4WYMEUYU.js} +361 -224
  8. package/dist/chunk-7HSWOQWV.js +172 -0
  9. package/dist/{chunk-J6R356H3.js → chunk-7OZ23MLD.js} +1 -1
  10. package/dist/{chunk-OFPNBZKP.js → chunk-7W7LAQXY.js} +76 -8
  11. package/dist/{chunk-HN3UFHP7.js → chunk-ANME5KDN.js} +1 -1
  12. package/dist/{chunk-GGHN2RKQ.js → chunk-E5VF3Y65.js} +69 -3
  13. package/dist/{chunk-V6JNTCPS.js → chunk-JLCTF5HY.js} +8 -2
  14. package/dist/{chunk-YU5MPQXB.js → chunk-LXY3BRKQ.js} +2 -2
  15. package/dist/{chunk-MKWYNK4J.js → chunk-NHMG2MRJ.js} +2 -2
  16. package/dist/{chunk-WXIYV2PO.js → chunk-OPVLQOOB.js} +44 -13
  17. package/dist/{chunk-SMI7Y77B.js → chunk-ORXOMW7M.js} +265 -190
  18. package/dist/{chunk-W4VHP2JW.js → chunk-SYAEM5DM.js} +1 -1
  19. package/dist/{chunk-7NQERXNY.js → chunk-TJZ4FTU6.js} +1 -1
  20. package/dist/{chunk-CFIOUXVE.js → chunk-V5XORHKX.js} +1 -1
  21. package/dist/chunk-ZDIDJCSU.js +40 -0
  22. package/dist/components/account-view.d.ts +8 -0
  23. package/dist/components/account-view.js +10 -0
  24. package/dist/components/admin-dashboard.js +3 -3
  25. package/dist/components/edit-post-view.js +5 -5
  26. package/dist/components/index.d.ts +4 -2
  27. package/dist/components/index.js +7 -7
  28. package/dist/components/login-view.d.ts +3 -1
  29. package/dist/components/login-view.js +4 -3
  30. package/dist/components/mcp-tokens-view.js +3 -3
  31. package/dist/components/media-view.js +5 -5
  32. package/dist/components/new-post-view.js +5 -5
  33. package/dist/components/plugin-settings-form.d.ts +2 -10
  34. package/dist/components/plugin-settings-form.js +5 -7
  35. package/dist/components/posts-list-view.js +3 -3
  36. package/dist/components/users-list-view.js +3 -3
  37. package/dist/{i18n-DA-aakRX.d.ts → i18n-Bd8q9aTl.d.ts} +108 -5
  38. package/dist/index.d.ts +2 -2
  39. package/dist/index.js +1 -1
  40. package/dist/metafile-esm.json +1 -1
  41. package/dist/pages/index.d.ts +21 -4
  42. package/dist/pages/index.js +54 -24
  43. package/package.json +5 -6
@@ -4,7 +4,7 @@ import {
4
4
  getAdminCmsConfig,
5
5
  getMediaProcessingDefaults,
6
6
  uploadProcessedImage
7
- } from "./chunk-HN3UFHP7.js";
7
+ } from "./chunk-ANME5KDN.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-K44QF3MV.js";
18
+ } from "./chunk-4OFRX6QX.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 useEffect4, useRef as useRef3, useState as useState5 } from "react";
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/toolbar.tsx
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__ */ jsxs3("div", { className: "flex flex-wrap gap-1 border-b p-2", children: [
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__ */ jsx3(
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__ */ jsx3(Icon, { className: "h-4 w-4" })
445
+ children: /* @__PURE__ */ jsx4(Icon, { className: "h-4 w-4" })
377
446
  },
378
447
  tool.name
379
448
  );
380
449
  }),
381
- /* @__PURE__ */ jsx3(
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__ */ jsx3(LinkIcon, { className: "h-4 w-4" })
458
+ children: /* @__PURE__ */ jsx4(LinkIcon, { className: "h-4 w-4" })
390
459
  }
391
460
  ),
392
- /* @__PURE__ */ jsx3(
461
+ /* @__PURE__ */ jsx4(
393
462
  MediaPicker,
394
463
  {
395
464
  onSelect: insertImage,
396
- trigger: /* @__PURE__ */ jsx3(Button3, { type: "button", variant: "ghost", size: "icon", children: /* @__PURE__ */ jsx3(ImageIcon, { className: "h-4 w-4" }) })
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__ */ jsx3(TableControls, { editor })
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 jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
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__ */ jsx4(
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__ */ jsxs4("div", { className: "flex items-center gap-1 rounded-md border bg-popover p-1 shadow", children: [
432
- /* @__PURE__ */ jsxs4(
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__ */ jsx4(ImageIcon2, { className: "mr-1 h-3 w-3" }),
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__ */ jsxs4(
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__ */ jsx4(Maximize2, { className: "mr-1 h-3 w-3" }),
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__ */ jsx4("span", { className: "mx-1 h-4 w-px bg-border" }),
463
- /* @__PURE__ */ jsxs4(Button4, { type: "button", variant: "ghost", size: "sm", onClick: editAlt, children: [
464
- /* @__PURE__ */ jsx4(Pencil, { className: "mr-1 h-3 w-3" }),
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__ */ jsxs4(Button4, { type: "button", variant: "ghost", size: "sm", onClick: remove2, children: [
468
- /* @__PURE__ */ jsx4(Trash2, { className: "mr-1 h-3 w-3" }),
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 jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
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,19 +687,77 @@ function TiptapEditor({ initialContent, onChange, onUserEdit }) {
617
687
  onUserEdit?.();
618
688
  }
619
689
  });
620
- return /* @__PURE__ */ jsxs5("div", { className: "rounded-md border", children: [
621
- /* @__PURE__ */ jsx5("style", { children: EDITOR_STYLES }),
622
- /* @__PURE__ */ jsx5(Toolbar, { editor }),
623
- editor && /* @__PURE__ */ jsx5(ImageBubbleMenu, { editor }),
624
- /* @__PURE__ */ jsx5(EditorContent, { editor })
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 useEffect3, useState as useState3 } from "react";
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
- import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
702
+
703
+ // src/lib/preview-srcdoc.ts
704
+ function buildPreviewSrcDoc(html) {
705
+ if (typeof document === "undefined") return html;
706
+ if (!html.includes("<head>")) return html;
707
+ const linkTags = [];
708
+ const styleTags = [];
709
+ const linkEls = document.querySelectorAll('link[rel="stylesheet"]');
710
+ for (const el of linkEls) {
711
+ if (el.href) {
712
+ linkTags.push(`<link rel="stylesheet" href="${el.href}">`);
713
+ }
714
+ }
715
+ const styleEls = document.querySelectorAll("style");
716
+ for (const el of styleEls) {
717
+ const content = el.textContent ?? "";
718
+ if (content.trim()) {
719
+ styleTags.push(`<style>${content}</style>`);
720
+ }
721
+ }
722
+ const collected = [...linkTags, ...styleTags];
723
+ let result = html;
724
+ if (collected.length > 0) {
725
+ result = result.replace("<head>", `<head>${collected.join("")}`);
726
+ }
727
+ const bodyDataAttrs = [];
728
+ for (const attr of document.body.attributes) {
729
+ if (attr.name.startsWith("data-")) {
730
+ const escaped = attr.value.replace(/"/g, "&quot;");
731
+ bodyDataAttrs.push(`${attr.name}="${escaped}"`);
732
+ }
733
+ }
734
+ if (bodyDataAttrs.length > 0) {
735
+ result = result.replace(
736
+ /(<body\b[^>]*)(>)/,
737
+ `$1 ${bodyDataAttrs.join(" ")}$2`
738
+ );
739
+ }
740
+ const htmlClass = document.documentElement.className;
741
+ if (htmlClass) {
742
+ const escaped = htmlClass.replace(/"/g, "&quot;");
743
+ result = result.replace(
744
+ /(<html\b)([^>]*)(>)/,
745
+ (_, open, attrs, close) => {
746
+ if (/class=/.test(attrs)) {
747
+ return `${open}${attrs.replace(/class="([^"]*)"/, `class="$1 ${escaped}`)}${close}`;
748
+ }
749
+ return `${open}${attrs} class="${escaped}"${close}`;
750
+ }
751
+ );
752
+ }
753
+ if (collected.length > 0) {
754
+ result = result.replace(/<style\s+id="ampless-preview-base">[\s\S]*?<\/style>/, "");
755
+ }
756
+ return result;
757
+ }
758
+
759
+ // src/components/post-history-panel.tsx
760
+ import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
633
761
  var PAGE_SIZE = 20;
634
762
  function formatRevisedAt(iso, timezone, locale) {
635
763
  const d = new Date(iso);
@@ -670,17 +798,17 @@ function PostHistoryPanel({
670
798
  const config = getAdminCmsConfig();
671
799
  const timezone = config?.timezone ?? "UTC";
672
800
  const locale = config?.locale ?? "en";
673
- const [open, setOpen] = useState3(false);
674
- const [loaded, setLoaded] = useState3(false);
675
- const [loading, setLoading] = useState3(false);
676
- const [error, setError] = useState3(null);
677
- const [revisions, setRevisions] = useState3([]);
678
- const [nextToken, setNextToken] = useState3(void 0);
679
- const [selected, setSelected] = useState3(null);
680
- const [previewHtml, setPreviewHtml] = useState3("");
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("");
681
809
  const selectedHistoryId = selected?.postHistoryId;
682
810
  const selectedFormat = selected?.format;
683
- useEffect3(() => {
811
+ useEffect4(() => {
684
812
  if (!selected) return;
685
813
  if (selected.format === "static") return;
686
814
  const ctrl = new AbortController();
@@ -693,7 +821,7 @@ function PostHistoryPanel({
693
821
  if (!r.ok) throw new Error(`preview ${r.status}`);
694
822
  return r.text();
695
823
  }).then((html) => {
696
- if (!ctrl.signal.aborted) setPreviewHtml(html);
824
+ if (!ctrl.signal.aborted) setPreviewHtml(buildPreviewSrcDoc(html));
697
825
  }).catch((err) => {
698
826
  if (ctrl.signal.aborted) return;
699
827
  console.error("[ampless admin] revision preview fetch failed:", err);
@@ -716,14 +844,14 @@ function PostHistoryPanel({
716
844
  },
717
845
  [postId]
718
846
  );
719
- useEffect3(() => {
847
+ useEffect4(() => {
720
848
  if (open && !loaded) {
721
849
  setLoaded(true);
722
850
  void loadPage();
723
851
  }
724
852
  }, [open, loaded, loadPage]);
725
- return /* @__PURE__ */ jsxs6("section", { className: "rounded-md border", children: [
726
- /* @__PURE__ */ jsxs6(
853
+ return /* @__PURE__ */ jsxs7("section", { className: "rounded-md border", children: [
854
+ /* @__PURE__ */ jsxs7(
727
855
  "button",
728
856
  {
729
857
  type: "button",
@@ -731,30 +859,30 @@ function PostHistoryPanel({
731
859
  "aria-expanded": open,
732
860
  className: "flex w-full items-center justify-between px-4 py-3 text-left text-sm font-medium",
733
861
  children: [
734
- /* @__PURE__ */ jsx6("span", { children: t("posts.history.title") }),
735
- /* @__PURE__ */ jsx6("span", { className: "text-muted-foreground", "aria-hidden": "true", children: open ? "\u2212" : "+" })
862
+ /* @__PURE__ */ jsx7("span", { children: t("posts.history.title") }),
863
+ /* @__PURE__ */ jsx7("span", { className: "text-muted-foreground", "aria-hidden": "true", children: open ? "\u2212" : "+" })
736
864
  ]
737
865
  }
738
866
  ),
739
- open && /* @__PURE__ */ jsxs6("div", { className: "space-y-4 border-t px-4 py-4", children: [
740
- error && /* @__PURE__ */ jsx6("p", { className: "text-sm text-destructive", children: error }),
741
- loading && revisions.length === 0 ? /* @__PURE__ */ jsx6("p", { className: "text-sm text-muted-foreground", children: t("common.loading") }) : revisions.length === 0 ? /* @__PURE__ */ jsx6("p", { className: "text-sm text-muted-foreground", children: t("posts.history.empty") }) : /* @__PURE__ */ jsx6("div", { className: "overflow-x-auto rounded-md border", children: /* @__PURE__ */ jsxs6("table", { className: "w-full text-sm", children: [
742
- /* @__PURE__ */ jsx6("thead", { children: /* @__PURE__ */ jsxs6("tr", { className: "border-b text-left text-xs text-muted-foreground", children: [
743
- /* @__PURE__ */ jsx6("th", { className: "px-3 py-2 font-medium", children: t("posts.history.columnRevisedAt") }),
744
- /* @__PURE__ */ jsx6("th", { className: "px-3 py-2 font-medium", children: t("posts.history.columnStatus") }),
745
- /* @__PURE__ */ jsx6("th", { className: "px-3 py-2 font-medium", children: t("posts.history.columnTitle") }),
746
- /* @__PURE__ */ jsx6("th", { className: "px-3 py-2 font-medium text-right", children: t("common.actions") })
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") })
747
875
  ] }) }),
748
- /* @__PURE__ */ jsx6("tbody", { children: revisions.map((rev) => /* @__PURE__ */ jsxs6(
876
+ /* @__PURE__ */ jsx7("tbody", { children: revisions.map((rev) => /* @__PURE__ */ jsxs7(
749
877
  "tr",
750
878
  {
751
879
  className: selected?.postHistoryId === rev.postHistoryId ? "border-b bg-muted/50" : "border-b",
752
880
  children: [
753
- /* @__PURE__ */ jsx6("td", { className: "whitespace-nowrap px-3 py-2 font-mono text-xs", children: formatRevisedAt(rev.revisedAt, timezone, locale) }),
754
- /* @__PURE__ */ jsx6("td", { className: "px-3 py-2", children: /* @__PURE__ */ jsx6("span", { className: "text-xs text-muted-foreground", children: rev.status ? t(`common.${rev.status}`) : "\u2014" }) }),
755
- /* @__PURE__ */ jsx6("td", { className: "px-3 py-2", children: rev.title || "\u2014" }),
756
- /* @__PURE__ */ jsx6("td", { className: "px-3 py-2 text-right", children: /* @__PURE__ */ jsxs6("div", { className: "flex justify-end gap-2", children: [
757
- /* @__PURE__ */ jsx6(
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(
758
886
  Button5,
759
887
  {
760
888
  type: "button",
@@ -764,7 +892,7 @@ function PostHistoryPanel({
764
892
  children: t("posts.history.view")
765
893
  }
766
894
  ),
767
- /* @__PURE__ */ jsx6(
895
+ /* @__PURE__ */ jsx7(
768
896
  Button5,
769
897
  {
770
898
  type: "button",
@@ -782,7 +910,7 @@ function PostHistoryPanel({
782
910
  rev.postHistoryId
783
911
  )) })
784
912
  ] }) }),
785
- nextToken && /* @__PURE__ */ jsx6("div", { children: /* @__PURE__ */ jsx6(
913
+ nextToken && /* @__PURE__ */ jsx7("div", { children: /* @__PURE__ */ jsx7(
786
914
  Button5,
787
915
  {
788
916
  type: "button",
@@ -793,12 +921,12 @@ function PostHistoryPanel({
793
921
  children: loading ? t("common.loading") : t("posts.history.loadMore")
794
922
  }
795
923
  ) }),
796
- selected && /* @__PURE__ */ jsxs6("div", { className: "space-y-3 rounded-md border p-4", children: [
797
- /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between", children: [
798
- /* @__PURE__ */ jsx6("h4", { className: "text-sm font-semibold", children: t("posts.history.viewing", {
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", {
799
927
  date: formatRevisedAt(selected.revisedAt, timezone, locale)
800
928
  }) }),
801
- /* @__PURE__ */ jsx6(
929
+ /* @__PURE__ */ jsx7(
802
930
  Button5,
803
931
  {
804
932
  type: "button",
@@ -809,14 +937,14 @@ function PostHistoryPanel({
809
937
  }
810
938
  )
811
939
  ] }),
812
- /* @__PURE__ */ jsxs6("p", { className: "text-xs text-muted-foreground", children: [
813
- /* @__PURE__ */ jsx6("span", { className: "font-mono uppercase", children: selected.format ?? "\u2014" }),
814
- selected.slug && /* @__PURE__ */ jsxs6(Fragment2, { children: [
815
- /* @__PURE__ */ jsx6("span", { className: "mx-2", children: "\xB7" }),
816
- /* @__PURE__ */ jsx6("span", { className: "font-mono", children: selected.slug })
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 })
817
945
  ] })
818
946
  ] }),
819
- selected.format === "static" ? /* @__PURE__ */ jsx6("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") }) : (
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") }) : (
820
948
  // Sandbox is `allow-scripts allow-same-origin`. With
821
949
  // srcDoc, this gives the iframe the admin's origin so
822
950
  // 3rd-party embed widgets (YouTube SDK, x.com widgets.js)
@@ -843,7 +971,7 @@ function PostHistoryPanel({
843
971
  // don't style its srcDoc contents. Typography comes from
844
972
  // the full document the preview route now returns
845
973
  // (PREVIEW_BASE_CSS + theme vars in createPreviewRouteHandler).
846
- /* @__PURE__ */ jsx6(
974
+ /* @__PURE__ */ jsx7(
847
975
  "iframe",
848
976
  {
849
977
  title: "revision-preview",
@@ -859,7 +987,7 @@ function PostHistoryPanel({
859
987
  }
860
988
 
861
989
  // src/components/static-uploader.tsx
862
- import { useState as useState4 } from "react";
990
+ import { useState as useState5 } from "react";
863
991
  import { FileText, AlertTriangle, FileArchive, X } from "lucide-react";
864
992
  import { Button as Button6 } from "@ampless/runtime/ui";
865
993
 
@@ -909,7 +1037,15 @@ async function uploadBundle(opts) {
909
1037
  if (!opts.files.some((f) => f.path === entrypoint)) {
910
1038
  throw new Error(`Entrypoint "${entrypoint}" is not present in the bundle.`);
911
1039
  }
912
- await deleteBundle(opts.slug).catch(() => void 0);
1040
+ try {
1041
+ await deleteBundle(opts.slug);
1042
+ } catch (err) {
1043
+ console.error(
1044
+ "[ampless static-bundle] failed to clear existing bundle before replace:",
1045
+ err
1046
+ );
1047
+ throw err;
1048
+ }
913
1049
  const prefix = bundlePrefix(opts.slug);
914
1050
  let uploaded = 0;
915
1051
  const filesMeta = {};
@@ -947,13 +1083,13 @@ async function deleteBundle(slug) {
947
1083
  }
948
1084
 
949
1085
  // src/components/static-uploader.tsx
950
- import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
1086
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
951
1087
  function StaticUploader({ initial, onFilesReady, onClear }) {
952
1088
  const t = useT();
953
- const [pending, setPending] = useState4(null);
954
- const [issues, setIssues] = useState4([]);
955
- const [busy, setBusy] = useState4(false);
956
- const [error, setError] = useState4(null);
1089
+ const [pending, setPending] = useState5(null);
1090
+ const [issues, setIssues] = useState5([]);
1091
+ const [busy, setBusy] = useState5(false);
1092
+ const [error, setError] = useState5(null);
957
1093
  async function handleZip(file) {
958
1094
  setBusy(true);
959
1095
  setError(null);
@@ -983,7 +1119,7 @@ function StaticUploader({ initial, onFilesReady, onClear }) {
983
1119
  const extracted = [];
984
1120
  const structural = [];
985
1121
  for (const f of Array.from(files)) {
986
- const rel = f.webkitRelativePath ?? f.name;
1122
+ const rel = f.webkitRelativePath || f.name;
987
1123
  const stripped = rel.includes("/") ? rel.slice(rel.indexOf("/") + 1) : rel;
988
1124
  const reason = validateBundlePath(stripped);
989
1125
  if (reason) {
@@ -1011,13 +1147,14 @@ function StaticUploader({ initial, onFilesReady, onClear }) {
1011
1147
  }
1012
1148
  }
1013
1149
  function onPickerChange(e) {
1014
- const fl = e.target.files;
1015
- if (!fl || fl.length === 0) return;
1150
+ const picked = e.target.files;
1151
+ if (!picked || picked.length === 0) return;
1152
+ const files = Array.from(picked);
1016
1153
  e.target.value = "";
1017
- if (fl.length === 1 && fl[0].name.toLowerCase().endsWith(".zip")) {
1018
- void handleZip(fl[0]);
1154
+ if (files.length === 1 && files[0].name.toLowerCase().endsWith(".zip")) {
1155
+ void handleZip(files[0]);
1019
1156
  } else {
1020
- void handleLooseFiles(fl);
1157
+ void handleLooseFiles(files);
1021
1158
  }
1022
1159
  }
1023
1160
  function clearPending() {
@@ -1027,11 +1164,11 @@ function StaticUploader({ initial, onFilesReady, onClear }) {
1027
1164
  onClear();
1028
1165
  }
1029
1166
  const showCurrent = !pending && initial && initial.files.length > 0;
1030
- return /* @__PURE__ */ jsxs7("div", { className: "space-y-4", children: [
1031
- /* @__PURE__ */ jsxs7("div", { className: "rounded-md border border-dashed p-4", children: [
1032
- /* @__PURE__ */ jsxs7("label", { className: "flex flex-col items-start gap-2 text-sm", children: [
1033
- /* @__PURE__ */ jsx7("span", { className: "font-medium", children: t("posts.form.static.pick") }),
1034
- /* @__PURE__ */ jsx7(
1167
+ return /* @__PURE__ */ jsxs8("div", { className: "space-y-4", children: [
1168
+ /* @__PURE__ */ jsxs8("div", { className: "rounded-md border border-dashed p-4", children: [
1169
+ /* @__PURE__ */ jsxs8("label", { className: "flex flex-col items-start gap-2 text-sm", children: [
1170
+ /* @__PURE__ */ jsx8("span", { className: "font-medium", children: t("posts.form.static.pick") }),
1171
+ /* @__PURE__ */ jsx8(
1035
1172
  "input",
1036
1173
  {
1037
1174
  type: "file",
@@ -1041,13 +1178,13 @@ function StaticUploader({ initial, onFilesReady, onClear }) {
1041
1178
  disabled: busy
1042
1179
  }
1043
1180
  ),
1044
- /* @__PURE__ */ jsx7("span", { className: "text-xs text-muted-foreground", children: t("posts.form.static.pickHint") })
1181
+ /* @__PURE__ */ jsx8("span", { className: "text-xs text-muted-foreground", children: t("posts.form.static.pickHint") })
1045
1182
  ] }),
1046
- busy && /* @__PURE__ */ jsx7("p", { className: "mt-2 text-sm text-muted-foreground", children: t("common.loading") }),
1047
- error && /* @__PURE__ */ jsx7("p", { className: "mt-2 text-sm text-destructive", children: error })
1183
+ busy && /* @__PURE__ */ jsx8("p", { className: "mt-2 text-sm text-muted-foreground", children: t("common.loading") }),
1184
+ error && /* @__PURE__ */ jsx8("p", { className: "mt-2 text-sm text-destructive", children: error })
1048
1185
  ] }),
1049
- showCurrent && /* @__PURE__ */ jsx7(CurrentBundle, { body: initial }),
1050
- pending && /* @__PURE__ */ jsx7(
1186
+ showCurrent && /* @__PURE__ */ jsx8(CurrentBundle, { body: initial }),
1187
+ pending && /* @__PURE__ */ jsx8(
1051
1188
  PendingBundle,
1052
1189
  {
1053
1190
  files: pending,
@@ -1059,15 +1196,15 @@ function StaticUploader({ initial, onFilesReady, onClear }) {
1059
1196
  }
1060
1197
  function CurrentBundle({ body }) {
1061
1198
  const t = useT();
1062
- return /* @__PURE__ */ jsxs7("div", { className: "rounded-md border bg-muted/30 p-3", children: [
1063
- /* @__PURE__ */ jsxs7("div", { className: "mb-2 flex items-center gap-2 text-sm font-medium", children: [
1064
- /* @__PURE__ */ jsx7(FileArchive, { className: "h-4 w-4" }),
1199
+ return /* @__PURE__ */ jsxs8("div", { className: "rounded-md border bg-muted/30 p-3", children: [
1200
+ /* @__PURE__ */ jsxs8("div", { className: "mb-2 flex items-center gap-2 text-sm font-medium", children: [
1201
+ /* @__PURE__ */ jsx8(FileArchive, { className: "h-4 w-4" }),
1065
1202
  t("posts.form.static.currentBundle", {
1066
1203
  count: body.files.length,
1067
1204
  entrypoint: body.entrypoint
1068
1205
  })
1069
1206
  ] }),
1070
- /* @__PURE__ */ jsx7(FileList, { files: body.files })
1207
+ /* @__PURE__ */ jsx8(FileList, { files: body.files })
1071
1208
  ] });
1072
1209
  }
1073
1210
  function PendingBundle({
@@ -1077,49 +1214,49 @@ function PendingBundle({
1077
1214
  }) {
1078
1215
  const t = useT();
1079
1216
  const totalBytes = files.reduce((sum, f) => sum + f.data.byteLength, 0);
1080
- return /* @__PURE__ */ jsxs7("div", { className: "rounded-md border p-3", children: [
1081
- /* @__PURE__ */ jsxs7("div", { className: "mb-2 flex items-center justify-between gap-2 text-sm font-medium", children: [
1082
- /* @__PURE__ */ jsxs7("span", { className: "flex items-center gap-2", children: [
1083
- /* @__PURE__ */ jsx7(FileArchive, { className: "h-4 w-4" }),
1217
+ return /* @__PURE__ */ jsxs8("div", { className: "rounded-md border p-3", children: [
1218
+ /* @__PURE__ */ jsxs8("div", { className: "mb-2 flex items-center justify-between gap-2 text-sm font-medium", children: [
1219
+ /* @__PURE__ */ jsxs8("span", { className: "flex items-center gap-2", children: [
1220
+ /* @__PURE__ */ jsx8(FileArchive, { className: "h-4 w-4" }),
1084
1221
  t("posts.form.static.pendingBundle", {
1085
1222
  count: files.length,
1086
1223
  size: formatBytes(totalBytes)
1087
1224
  })
1088
1225
  ] }),
1089
- /* @__PURE__ */ jsxs7(Button6, { type: "button", variant: "ghost", size: "sm", onClick: onClear, children: [
1090
- /* @__PURE__ */ jsx7(X, { className: "mr-1 h-3 w-3" }),
1226
+ /* @__PURE__ */ jsxs8(Button6, { type: "button", variant: "ghost", size: "sm", onClick: onClear, children: [
1227
+ /* @__PURE__ */ jsx8(X, { className: "mr-1 h-3 w-3" }),
1091
1228
  t("common.cancel")
1092
1229
  ] })
1093
1230
  ] }),
1094
- issues.length > 0 && /* @__PURE__ */ jsxs7("div", { className: "mb-3 rounded-md border border-destructive/40 bg-destructive/5 p-2 text-sm", children: [
1095
- /* @__PURE__ */ jsxs7("div", { className: "mb-1 flex items-center gap-2 font-medium text-destructive", children: [
1096
- /* @__PURE__ */ jsx7(AlertTriangle, { className: "h-4 w-4" }),
1231
+ issues.length > 0 && /* @__PURE__ */ jsxs8("div", { className: "mb-3 rounded-md border border-destructive/40 bg-destructive/5 p-2 text-sm", children: [
1232
+ /* @__PURE__ */ jsxs8("div", { className: "mb-1 flex items-center gap-2 font-medium text-destructive", children: [
1233
+ /* @__PURE__ */ jsx8(AlertTriangle, { className: "h-4 w-4" }),
1097
1234
  t("posts.form.static.issuesTitle", { count: issues.length })
1098
1235
  ] }),
1099
- /* @__PURE__ */ jsxs7("ul", { className: "space-y-0.5 text-xs", children: [
1100
- issues.slice(0, 20).map((issue, idx) => /* @__PURE__ */ jsxs7("li", { className: "font-mono", children: [
1236
+ /* @__PURE__ */ jsxs8("ul", { className: "space-y-0.5 text-xs", children: [
1237
+ issues.slice(0, 20).map((issue, idx) => /* @__PURE__ */ jsxs8("li", { className: "font-mono", children: [
1101
1238
  issue.path,
1102
1239
  ": ",
1103
1240
  issue.reason
1104
1241
  ] }, `${issue.path}-${idx}`)),
1105
- issues.length > 20 && /* @__PURE__ */ jsxs7("li", { className: "font-mono text-muted-foreground", children: [
1242
+ issues.length > 20 && /* @__PURE__ */ jsxs8("li", { className: "font-mono text-muted-foreground", children: [
1106
1243
  "\u2026 ",
1107
1244
  issues.length - 20,
1108
1245
  " more"
1109
1246
  ] })
1110
1247
  ] }),
1111
- /* @__PURE__ */ jsx7("p", { className: "mt-2 text-xs text-muted-foreground", children: t("posts.form.static.issuesHint") })
1248
+ /* @__PURE__ */ jsx8("p", { className: "mt-2 text-xs text-muted-foreground", children: t("posts.form.static.issuesHint") })
1112
1249
  ] }),
1113
- /* @__PURE__ */ jsx7(FileList, { files: files.map((f) => f.path) })
1250
+ /* @__PURE__ */ jsx8(FileList, { files: files.map((f) => f.path) })
1114
1251
  ] });
1115
1252
  }
1116
1253
  function FileList({ files }) {
1117
- return /* @__PURE__ */ jsxs7("ul", { className: "space-y-0.5 text-xs", children: [
1118
- files.slice(0, 40).map((path) => /* @__PURE__ */ jsxs7("li", { className: "flex items-center gap-1.5 font-mono text-muted-foreground", children: [
1119
- /* @__PURE__ */ jsx7(FileText, { className: "h-3 w-3 shrink-0" }),
1254
+ return /* @__PURE__ */ jsxs8("ul", { className: "space-y-0.5 text-xs", children: [
1255
+ files.slice(0, 40).map((path) => /* @__PURE__ */ jsxs8("li", { className: "flex items-center gap-1.5 font-mono text-muted-foreground", children: [
1256
+ /* @__PURE__ */ jsx8(FileText, { className: "h-3 w-3 shrink-0" }),
1120
1257
  path
1121
1258
  ] }, path)),
1122
- files.length > 40 && /* @__PURE__ */ jsxs7("li", { className: "font-mono text-xs text-muted-foreground", children: [
1259
+ files.length > 40 && /* @__PURE__ */ jsxs8("li", { className: "font-mono text-xs text-muted-foreground", children: [
1123
1260
  "\u2026 ",
1124
1261
  files.length - 40,
1125
1262
  " more"
@@ -1313,7 +1450,7 @@ function convertBodyFormat(body, from, to, registries) {
1313
1450
  }
1314
1451
 
1315
1452
  // src/components/post-form.tsx
1316
- import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
1453
+ import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
1317
1454
  var EMPTY_TIPTAP_DOC = { type: "doc", content: [{ type: "paragraph" }] };
1318
1455
  var IMAGE_URL_RE = /\.(jpe?g|png|gif|webp|avif|svg|bmp|tiff?)(\?|$)/i;
1319
1456
  var STYLESHEET_URL_RE = /\.css(\?|$)/i;
@@ -1359,27 +1496,27 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
1359
1496
  const router = useRouter();
1360
1497
  const t = useT();
1361
1498
  const isEdit = !!post;
1362
- const bodyTextareaRef = useRef3(null);
1363
- const [title, setTitle] = useState5(post?.title ?? "");
1364
- const [slug, setSlug] = useState5(post?.slug ?? "");
1365
- const [excerpt, setExcerpt] = useState5(post?.excerpt ?? "");
1366
- const [format, setFormat] = useState5(post?.format ?? "tiptap");
1367
- const [body, setBody] = useState5(post?.body ?? EMPTY_TIPTAP_DOC);
1368
- const [status, setStatus] = useState5(post?.status ?? "draft");
1369
- const [tagsInput, setTagsInput] = useState5((post?.tags ?? []).join(", "));
1370
- const [noLayout, setNoLayout] = useState5(post?.metadata?.no_layout === true);
1371
- const [publishedAtInput, setPublishedAtInput] = useState5(isoToLocalInput(post?.publishedAt));
1372
- const [saving, setSaving] = useState5(false);
1373
- const [error, setError] = useState5(null);
1374
- const [view, setView] = useState5("edit");
1375
- const [previewHtml, setPreviewHtml] = useState5("");
1376
- const [editorEpoch, setEditorEpoch] = useState5(0);
1377
- const dirtyRef = useRef3(false);
1499
+ const bodyTextareaRef = useRef4(null);
1500
+ const [title, setTitle] = useState6(post?.title ?? "");
1501
+ const [slug, setSlug] = useState6(post?.slug ?? "");
1502
+ const [excerpt, setExcerpt] = useState6(post?.excerpt ?? "");
1503
+ const [format, setFormat] = useState6(post?.format ?? "tiptap");
1504
+ const [body, setBody] = useState6(post?.body ?? EMPTY_TIPTAP_DOC);
1505
+ const [status, setStatus] = useState6(post?.status ?? "draft");
1506
+ const [tagsInput, setTagsInput] = useState6((post?.tags ?? []).join(", "));
1507
+ const [noLayout, setNoLayout] = useState6(post?.metadata?.no_layout === true);
1508
+ const [publishedAtInput, setPublishedAtInput] = useState6(isoToLocalInput(post?.publishedAt));
1509
+ const [saving, setSaving] = useState6(false);
1510
+ const [error, setError] = useState6(null);
1511
+ const [view, setView] = useState6("edit");
1512
+ const [previewHtml, setPreviewHtml] = useState6("");
1513
+ const [editorEpoch, setEditorEpoch] = useState6(0);
1514
+ const dirtyRef = useRef4(false);
1378
1515
  function markDirty() {
1379
1516
  dirtyRef.current = true;
1380
1517
  }
1381
- const [recovery, setRecovery] = useState5(null);
1382
- const [restoredHint, setRestoredHint] = useState5(false);
1518
+ const [recovery, setRecovery] = useState6(null);
1519
+ const [restoredHint, setRestoredHint] = useState6(false);
1383
1520
  const draftId = post?.postId ?? NEW_POST_DRAFT_ID;
1384
1521
  const isStaticFormat = format === "static";
1385
1522
  const cmsConfig = getAdminCmsConfig();
@@ -1392,7 +1529,7 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
1392
1529
  initialInput: initialPublishedAtInput,
1393
1530
  existing: post?.publishedAt
1394
1531
  });
1395
- const [pendingBundle, setPendingBundle] = useState5(null);
1532
+ const [pendingBundle, setPendingBundle] = useState6(null);
1396
1533
  const initialStaticBody = isStaticBody(post?.body) ? post.body : null;
1397
1534
  function buildMetadata() {
1398
1535
  const next = { ...post?.metadata ?? {} };
@@ -1460,7 +1597,7 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
1460
1597
  dirtyRef.current = false;
1461
1598
  setRecovery(null);
1462
1599
  }
1463
- useEffect4(() => {
1600
+ useEffect5(() => {
1464
1601
  if (loadedState.format === "static") return;
1465
1602
  const draft = readDraft(draftId);
1466
1603
  if (!draft) return;
@@ -1475,7 +1612,7 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
1475
1612
  }
1476
1613
  setRecovery({ draft, decision });
1477
1614
  }, []);
1478
- useEffect4(() => {
1615
+ useEffect5(() => {
1479
1616
  if (isStaticFormat) return;
1480
1617
  if (!dirtyRef.current) return;
1481
1618
  const handle = setTimeout(() => {
@@ -1583,13 +1720,13 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
1583
1720
  await updatePost(post.postId, {
1584
1721
  title,
1585
1722
  slug: finalSlug,
1586
- excerpt: excerpt || void 0,
1723
+ excerpt,
1587
1724
  format,
1588
1725
  body: nextBody,
1589
1726
  status,
1590
1727
  publishedAt,
1591
1728
  tags,
1592
- metadata
1729
+ metadata: metadata ?? {}
1593
1730
  });
1594
1731
  } else {
1595
1732
  await createPost({
@@ -1642,7 +1779,7 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
1642
1779
  publishedAt: resolvedPublishedAt,
1643
1780
  tags: parseTags(tagsInput)
1644
1781
  };
1645
- useEffect4(() => {
1782
+ useEffect5(() => {
1646
1783
  if (view !== "preview") return;
1647
1784
  if (format === "static") return;
1648
1785
  const ctrl = new AbortController();
@@ -1656,7 +1793,7 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
1656
1793
  if (!r.ok) throw new Error(`preview ${r.status}`);
1657
1794
  return r.text();
1658
1795
  }).then((html) => {
1659
- if (!ctrl.signal.aborted) setPreviewHtml(html);
1796
+ if (!ctrl.signal.aborted) setPreviewHtml(buildPreviewSrcDoc(html));
1660
1797
  }).catch((err) => {
1661
1798
  if (ctrl.signal.aborted) return;
1662
1799
  console.error("[ampless admin] preview fetch failed:", err);
@@ -1678,9 +1815,9 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
1678
1815
  resolvedPublishedAt,
1679
1816
  tagsInput
1680
1817
  ]);
1681
- return /* @__PURE__ */ jsxs8("form", { onSubmit: save, className: "space-y-6", children: [
1682
- /* @__PURE__ */ jsxs8("div", { className: "flex gap-1 border-b", children: [
1683
- /* @__PURE__ */ jsx8(
1818
+ return /* @__PURE__ */ jsxs9("form", { onSubmit: save, className: "space-y-6", children: [
1819
+ /* @__PURE__ */ jsxs9("div", { className: "flex gap-1 border-b", children: [
1820
+ /* @__PURE__ */ jsx9(
1684
1821
  "button",
1685
1822
  {
1686
1823
  type: "button",
@@ -1690,7 +1827,7 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
1690
1827
  children: t("posts.form.tabEdit")
1691
1828
  }
1692
1829
  ),
1693
- /* @__PURE__ */ jsx8(
1830
+ /* @__PURE__ */ jsx9(
1694
1831
  "button",
1695
1832
  {
1696
1833
  type: "button",
@@ -1701,17 +1838,17 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
1701
1838
  }
1702
1839
  )
1703
1840
  ] }),
1704
- view === "preview" && /* @__PURE__ */ jsxs8("article", { className: "space-y-4", children: [
1705
- /* @__PURE__ */ jsxs8("header", { className: "border-b pb-4", children: [
1706
- /* @__PURE__ */ jsx8("h1", { className: "text-3xl font-bold tracking-tight", children: title || /* @__PURE__ */ jsx8("span", { className: "text-muted-foreground italic", children: t("posts.form.previewNoTitle") }) }),
1707
- /* @__PURE__ */ jsxs8("p", { className: "mt-2 text-sm text-muted-foreground", children: [
1708
- previewPost.publishedAt ? /* @__PURE__ */ jsx8("time", { dateTime: previewPost.publishedAt, children: formatDate(previewPost.publishedAt) }) : /* @__PURE__ */ jsx8("span", { children: t("common.draft") }),
1709
- /* @__PURE__ */ jsx8("span", { className: "mx-2", children: "\xB7" }),
1710
- /* @__PURE__ */ jsx8("span", { className: "font-mono text-xs uppercase", children: format })
1841
+ view === "preview" && /* @__PURE__ */ jsxs9("article", { className: "space-y-4", children: [
1842
+ /* @__PURE__ */ jsxs9("header", { className: "border-b pb-4", children: [
1843
+ /* @__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") }) }),
1844
+ /* @__PURE__ */ jsxs9("p", { className: "mt-2 text-sm text-muted-foreground", children: [
1845
+ previewPost.publishedAt ? /* @__PURE__ */ jsx9("time", { dateTime: previewPost.publishedAt, children: formatDate(previewPost.publishedAt) }) : /* @__PURE__ */ jsx9("span", { children: t("common.draft") }),
1846
+ /* @__PURE__ */ jsx9("span", { className: "mx-2", children: "\xB7" }),
1847
+ /* @__PURE__ */ jsx9("span", { className: "font-mono text-xs uppercase", children: format })
1711
1848
  ] }),
1712
- excerpt && /* @__PURE__ */ jsx8("p", { className: "mt-3 text-base text-muted-foreground", children: excerpt })
1849
+ excerpt && /* @__PURE__ */ jsx9("p", { className: "mt-3 text-base text-muted-foreground", children: excerpt })
1713
1850
  ] }),
1714
- format === "static" ? /* @__PURE__ */ jsx8("p", { className: "text-sm text-muted-foreground", children: t("posts.form.static.previewHint") }) : (
1851
+ format === "static" ? /* @__PURE__ */ jsx9("p", { className: "text-sm text-muted-foreground", children: t("posts.form.static.previewHint") }) : (
1715
1852
  // Phase 7: preview HTML is fetched from the template's
1716
1853
  // `/admin/preview` Route Handler so `ampless.renderBody`
1717
1854
  // (async ReactNode) + `ampless.publicPostScriptsForPage(
@@ -1749,7 +1886,7 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
1749
1886
  // document — an iframe srcDoc does not inherit the parent page's
1750
1887
  // CSS. Typography is now applied inside the document returned by
1751
1888
  // createPreviewRouteHandler (PREVIEW_BASE_CSS + theme cssVars).
1752
- /* @__PURE__ */ jsx8(
1889
+ /* @__PURE__ */ jsx9(
1753
1890
  "iframe",
1754
1891
  {
1755
1892
  title: "post-preview",
@@ -1759,7 +1896,7 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
1759
1896
  }
1760
1897
  )
1761
1898
  ),
1762
- previewPost.tags && previewPost.tags.length > 0 && /* @__PURE__ */ jsx8("div", { className: "flex flex-wrap gap-2 border-t pt-4 text-sm", children: previewPost.tags.map((tag) => /* @__PURE__ */ jsxs8(
1899
+ 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(
1763
1900
  "span",
1764
1901
  {
1765
1902
  className: "rounded-full border px-2 py-0.5 text-xs text-muted-foreground",
@@ -1770,34 +1907,34 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
1770
1907
  },
1771
1908
  tag
1772
1909
  )) }),
1773
- /* @__PURE__ */ jsx8("p", { className: "text-xs text-muted-foreground", children: t("posts.form.previewHint") })
1910
+ /* @__PURE__ */ jsx9("p", { className: "text-xs text-muted-foreground", children: t("posts.form.previewHint") })
1774
1911
  ] }),
1775
- /* @__PURE__ */ jsxs8("div", { className: view === "edit" ? "space-y-6" : "hidden", children: [
1776
- recovery && /* @__PURE__ */ jsxs8(
1912
+ /* @__PURE__ */ jsxs9("div", { className: view === "edit" ? "space-y-6" : "hidden", children: [
1913
+ recovery && /* @__PURE__ */ jsxs9(
1777
1914
  "div",
1778
1915
  {
1779
1916
  role: "alert",
1780
1917
  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",
1781
1918
  children: [
1782
- /* @__PURE__ */ jsx8("p", { className: "font-medium", children: recovery.decision === "stale" ? t("posts.draft.staleTitle") : t("posts.draft.recoverTitle") }),
1783
- /* @__PURE__ */ jsx8("p", { className: "text-muted-foreground", children: recovery.decision === "stale" ? t("posts.draft.staleBody", {
1919
+ /* @__PURE__ */ jsx9("p", { className: "font-medium", children: recovery.decision === "stale" ? t("posts.draft.staleTitle") : t("posts.draft.recoverTitle") }),
1920
+ /* @__PURE__ */ jsx9("p", { className: "text-muted-foreground", children: recovery.decision === "stale" ? t("posts.draft.staleBody", {
1784
1921
  when: formatDraftTime(recovery.draft.savedAt, draftTimezone, draftLocale)
1785
1922
  }) : t("posts.draft.recoverBody", {
1786
1923
  when: formatDraftTime(recovery.draft.savedAt, draftTimezone, draftLocale)
1787
1924
  }) }),
1788
- /* @__PURE__ */ jsxs8("div", { className: "flex gap-2", children: [
1789
- /* @__PURE__ */ jsx8(Button7, { type: "button", size: "sm", onClick: acceptRecovery, children: recovery.decision === "stale" ? t("posts.draft.restoreAnyway") : t("posts.draft.restore") }),
1790
- /* @__PURE__ */ jsx8(Button7, { type: "button", size: "sm", variant: "outline", onClick: discardRecovery, children: t("posts.draft.discard") })
1925
+ /* @__PURE__ */ jsxs9("div", { className: "flex gap-2", children: [
1926
+ /* @__PURE__ */ jsx9(Button7, { type: "button", size: "sm", onClick: acceptRecovery, children: recovery.decision === "stale" ? t("posts.draft.restoreAnyway") : t("posts.draft.restore") }),
1927
+ /* @__PURE__ */ jsx9(Button7, { type: "button", size: "sm", variant: "outline", onClick: discardRecovery, children: t("posts.draft.discard") })
1791
1928
  ] })
1792
1929
  ]
1793
1930
  }
1794
1931
  ),
1795
- restoredHint && !recovery && /* @__PURE__ */ jsx8("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") }),
1796
- isStaticFormat && /* @__PURE__ */ jsx8("p", { className: "rounded-md border bg-muted/40 px-3 py-2 text-xs text-muted-foreground", children: t("posts.draft.staticUnsupported") }),
1797
- /* @__PURE__ */ jsxs8("div", { className: "space-y-2", children: [
1798
- /* @__PURE__ */ jsx8(Label, { htmlFor: "title", children: t("posts.form.title") }),
1799
- /* @__PURE__ */ jsx8(
1800
- Input,
1932
+ 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") }),
1933
+ 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") }),
1934
+ /* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
1935
+ /* @__PURE__ */ jsx9(Label, { htmlFor: "title", children: t("posts.form.title") }),
1936
+ /* @__PURE__ */ jsx9(
1937
+ Input2,
1801
1938
  {
1802
1939
  id: "title",
1803
1940
  required: true,
@@ -1810,10 +1947,10 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
1810
1947
  }
1811
1948
  )
1812
1949
  ] }),
1813
- /* @__PURE__ */ jsxs8("div", { className: "space-y-2", children: [
1814
- /* @__PURE__ */ jsx8(Label, { htmlFor: "slug", children: t("posts.form.slug") }),
1815
- /* @__PURE__ */ jsx8(
1816
- Input,
1950
+ /* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
1951
+ /* @__PURE__ */ jsx9(Label, { htmlFor: "slug", children: t("posts.form.slug") }),
1952
+ /* @__PURE__ */ jsx9(
1953
+ Input2,
1817
1954
  {
1818
1955
  id: "slug",
1819
1956
  value: slug,
@@ -1825,9 +1962,9 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
1825
1962
  }
1826
1963
  )
1827
1964
  ] }),
1828
- /* @__PURE__ */ jsxs8("div", { className: "space-y-2", children: [
1829
- /* @__PURE__ */ jsx8(Label, { htmlFor: "excerpt", children: t("posts.form.excerpt") }),
1830
- /* @__PURE__ */ jsx8(
1965
+ /* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
1966
+ /* @__PURE__ */ jsx9(Label, { htmlFor: "excerpt", children: t("posts.form.excerpt") }),
1967
+ /* @__PURE__ */ jsx9(
1831
1968
  Textarea,
1832
1969
  {
1833
1970
  id: "excerpt",
@@ -1840,9 +1977,9 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
1840
1977
  }
1841
1978
  )
1842
1979
  ] }),
1843
- /* @__PURE__ */ jsxs8("div", { className: "space-y-2", children: [
1844
- /* @__PURE__ */ jsx8(Label, { htmlFor: "format", children: t("posts.form.format") }),
1845
- /* @__PURE__ */ jsxs8(
1980
+ /* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
1981
+ /* @__PURE__ */ jsx9(Label, { htmlFor: "format", children: t("posts.form.format") }),
1982
+ /* @__PURE__ */ jsxs9(
1846
1983
  "select",
1847
1984
  {
1848
1985
  id: "format",
@@ -1850,34 +1987,34 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
1850
1987
  onChange: (e) => changeFormat(e.target.value),
1851
1988
  className: "flex h-9 w-full max-w-xs rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm",
1852
1989
  children: [
1853
- /* @__PURE__ */ jsx8("option", { value: "tiptap", children: "Tiptap (rich editor)" }),
1854
- /* @__PURE__ */ jsx8("option", { value: "markdown", children: "Markdown" }),
1855
- /* @__PURE__ */ jsx8("option", { value: "html", children: "HTML" }),
1856
- /* @__PURE__ */ jsx8("option", { value: "static", children: t("posts.form.formatStaticLabel") })
1990
+ /* @__PURE__ */ jsx9("option", { value: "tiptap", children: "Tiptap (rich editor)" }),
1991
+ /* @__PURE__ */ jsx9("option", { value: "markdown", children: "Markdown" }),
1992
+ /* @__PURE__ */ jsx9("option", { value: "html", children: "HTML" }),
1993
+ /* @__PURE__ */ jsx9("option", { value: "static", children: t("posts.form.formatStaticLabel") })
1857
1994
  ]
1858
1995
  }
1859
1996
  ),
1860
- /* @__PURE__ */ jsx8("p", { className: "text-xs text-muted-foreground", children: t("posts.form.formatHint") })
1997
+ /* @__PURE__ */ jsx9("p", { className: "text-xs text-muted-foreground", children: t("posts.form.formatHint") })
1861
1998
  ] }),
1862
- /* @__PURE__ */ jsxs8("div", { className: "space-y-2", children: [
1863
- /* @__PURE__ */ jsxs8("div", { className: "flex items-center justify-between", children: [
1864
- /* @__PURE__ */ jsx8(Label, { children: t("posts.form.body") }),
1999
+ /* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
2000
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between", children: [
2001
+ /* @__PURE__ */ jsx9(Label, { children: t("posts.form.body") }),
1865
2002
  format !== "tiptap" && format !== "static" && // For textarea-based formats (markdown / html) there's no
1866
2003
  // embedded toolbar, so we surface the MediaPicker as a
1867
2004
  // standalone button. Selecting an asset inserts a
1868
2005
  // format-aware snippet at the cursor.
1869
- /* @__PURE__ */ jsx8(
2006
+ /* @__PURE__ */ jsx9(
1870
2007
  MediaPicker,
1871
2008
  {
1872
2009
  onSelect: insertMediaSnippet,
1873
- trigger: /* @__PURE__ */ jsxs8(Button7, { type: "button", variant: "outline", size: "sm", children: [
1874
- /* @__PURE__ */ jsx8(ImageIcon3, { className: "mr-2 h-3 w-3" }),
2010
+ trigger: /* @__PURE__ */ jsxs9(Button7, { type: "button", variant: "outline", size: "sm", children: [
2011
+ /* @__PURE__ */ jsx9(ImageIcon3, { className: "mr-2 h-3 w-3" }),
1875
2012
  t("posts.form.insertMedia")
1876
2013
  ] })
1877
2014
  }
1878
2015
  )
1879
2016
  ] }),
1880
- format === "tiptap" ? /* @__PURE__ */ jsx8(
2017
+ format === "tiptap" ? /* @__PURE__ */ jsx9(
1881
2018
  TiptapEditor,
1882
2019
  {
1883
2020
  initialContent: body,
@@ -1885,14 +2022,14 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
1885
2022
  onUserEdit: markDirty
1886
2023
  },
1887
2024
  editorEpoch
1888
- ) : format === "static" ? /* @__PURE__ */ jsx8(
2025
+ ) : format === "static" ? /* @__PURE__ */ jsx9(
1889
2026
  StaticUploader,
1890
2027
  {
1891
2028
  initial: initialStaticBody,
1892
2029
  onFilesReady: (files, entrypoint) => setPendingBundle({ files, entrypoint }),
1893
2030
  onClear: () => setPendingBundle(null)
1894
2031
  }
1895
- ) : /* @__PURE__ */ jsx8(
2032
+ ) : /* @__PURE__ */ jsx9(
1896
2033
  Textarea,
1897
2034
  {
1898
2035
  ref: bodyTextareaRef,
@@ -1906,10 +2043,10 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
1906
2043
  }
1907
2044
  )
1908
2045
  ] }),
1909
- /* @__PURE__ */ jsxs8("div", { className: "space-y-2", children: [
1910
- /* @__PURE__ */ jsx8(Label, { htmlFor: "tags", children: t("posts.form.tags") }),
1911
- /* @__PURE__ */ jsx8(
1912
- Input,
2046
+ /* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
2047
+ /* @__PURE__ */ jsx9(Label, { htmlFor: "tags", children: t("posts.form.tags") }),
2048
+ /* @__PURE__ */ jsx9(
2049
+ Input2,
1913
2050
  {
1914
2051
  id: "tags",
1915
2052
  value: tagsInput,
@@ -1920,11 +2057,11 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
1920
2057
  placeholder: t("posts.form.tagsPlaceholder")
1921
2058
  }
1922
2059
  ),
1923
- /* @__PURE__ */ jsx8("p", { className: "text-xs text-muted-foreground", children: t("posts.form.tagsHint") })
2060
+ /* @__PURE__ */ jsx9("p", { className: "text-xs text-muted-foreground", children: t("posts.form.tagsHint") })
1924
2061
  ] }),
1925
- /* @__PURE__ */ jsxs8("div", { className: "space-y-2", children: [
1926
- /* @__PURE__ */ jsx8(Label, { htmlFor: "status", children: t("posts.form.status") }),
1927
- /* @__PURE__ */ jsxs8(
2062
+ /* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
2063
+ /* @__PURE__ */ jsx9(Label, { htmlFor: "status", children: t("posts.form.status") }),
2064
+ /* @__PURE__ */ jsxs9(
1928
2065
  "select",
1929
2066
  {
1930
2067
  id: "status",
@@ -1935,15 +2072,15 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
1935
2072
  },
1936
2073
  className: "flex h-9 w-full max-w-xs rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm",
1937
2074
  children: [
1938
- /* @__PURE__ */ jsx8("option", { value: "draft", children: t("common.draft") }),
1939
- /* @__PURE__ */ jsx8("option", { value: "published", children: t("common.published") })
2075
+ /* @__PURE__ */ jsx9("option", { value: "draft", children: t("common.draft") }),
2076
+ /* @__PURE__ */ jsx9("option", { value: "published", children: t("common.published") })
1940
2077
  ]
1941
2078
  }
1942
2079
  )
1943
2080
  ] }),
1944
- /* @__PURE__ */ jsxs8("div", { className: "space-y-2", children: [
1945
- /* @__PURE__ */ jsx8(Label, { htmlFor: "publishedAt", children: t("posts.form.publishedAt") }),
1946
- /* @__PURE__ */ jsx8(
2081
+ /* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
2082
+ /* @__PURE__ */ jsx9(Label, { htmlFor: "publishedAt", children: t("posts.form.publishedAt") }),
2083
+ /* @__PURE__ */ jsx9(
1947
2084
  "input",
1948
2085
  {
1949
2086
  id: "publishedAt",
@@ -1956,11 +2093,11 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
1956
2093
  className: "flex h-9 w-full max-w-xs rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm"
1957
2094
  }
1958
2095
  ),
1959
- /* @__PURE__ */ jsx8("p", { className: "text-xs text-muted-foreground", children: t("posts.form.publishedAtHint") }),
1960
- status === "published" && isFuture(resolvedPublishedAt) && /* @__PURE__ */ jsx8("p", { className: "text-xs text-amber-600 dark:text-amber-400", children: t("posts.form.scheduledNotice", { date: publishedAtInput }) })
2096
+ /* @__PURE__ */ jsx9("p", { className: "text-xs text-muted-foreground", children: t("posts.form.publishedAtHint") }),
2097
+ status === "published" && isFuture(resolvedPublishedAt) && /* @__PURE__ */ jsx9("p", { className: "text-xs text-amber-600 dark:text-amber-400", children: t("posts.form.scheduledNotice", { date: publishedAtInput }) })
1961
2098
  ] }),
1962
- format === "html" && /* @__PURE__ */ jsx8("div", { className: "space-y-2", children: /* @__PURE__ */ jsxs8("label", { className: "flex items-start gap-2 text-sm", children: [
1963
- /* @__PURE__ */ jsx8(
2099
+ format === "html" && /* @__PURE__ */ jsx9("div", { className: "space-y-2", children: /* @__PURE__ */ jsxs9("label", { className: "flex items-start gap-2 text-sm", children: [
2100
+ /* @__PURE__ */ jsx9(
1964
2101
  "input",
1965
2102
  {
1966
2103
  type: "checkbox",
@@ -1972,17 +2109,17 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
1972
2109
  className: "mt-1"
1973
2110
  }
1974
2111
  ),
1975
- /* @__PURE__ */ jsxs8("span", { children: [
1976
- /* @__PURE__ */ jsx8("span", { className: "font-medium", children: t("posts.form.noLayout") }),
1977
- /* @__PURE__ */ jsx8("span", { className: "block text-xs text-muted-foreground", children: t("posts.form.noLayoutHint") })
2112
+ /* @__PURE__ */ jsxs9("span", { children: [
2113
+ /* @__PURE__ */ jsx9("span", { className: "font-medium", children: t("posts.form.noLayout") }),
2114
+ /* @__PURE__ */ jsx9("span", { className: "block text-xs text-muted-foreground", children: t("posts.form.noLayoutHint") })
1978
2115
  ] })
1979
2116
  ] }) }),
1980
- error && /* @__PURE__ */ jsx8("p", { className: "text-sm text-destructive", children: error }),
1981
- /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
1982
- /* @__PURE__ */ jsx8(Button7, { type: "submit", disabled: saving, children: saving ? t("common.saving") : isEdit ? t("posts.form.saveChanges") : t("posts.form.createPost") }),
1983
- isEdit && /* @__PURE__ */ jsx8(Button7, { type: "button", variant: "destructive", onClick: handleDelete, disabled: saving, children: t("posts.form.delete") })
2117
+ error && /* @__PURE__ */ jsx9("p", { className: "text-sm text-destructive", children: error }),
2118
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2", children: [
2119
+ /* @__PURE__ */ jsx9(Button7, { type: "submit", disabled: saving, children: saving ? t("common.saving") : isEdit ? t("posts.form.saveChanges") : t("posts.form.createPost") }),
2120
+ isEdit && /* @__PURE__ */ jsx9(Button7, { type: "button", variant: "destructive", onClick: handleDelete, disabled: saving, children: t("posts.form.delete") })
1984
2121
  ] }),
1985
- isEdit && post && /* @__PURE__ */ jsx8(
2122
+ isEdit && post && /* @__PURE__ */ jsx9(
1986
2123
  PostHistoryPanel,
1987
2124
  {
1988
2125
  postId: post.postId,