@ampless/admin 1.0.0-beta.113 → 1.0.0-beta.114
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-XQAPTM5X.js → chunk-2DB3EDD7.js} +1 -1
- package/dist/{chunk-IMWUSMAA.js → chunk-7UEIAZPY.js} +16 -2
- package/dist/{chunk-L6CFURU6.js → chunk-GNZZ33OH.js} +1 -1
- package/dist/{chunk-DR2HES7B.js → chunk-HEBAGP4Q.js} +288 -146
- package/dist/{chunk-CRHOOLCJ.js → chunk-HNI5IJWI.js} +1 -1
- package/dist/{chunk-TQUMC5HE.js → chunk-JSJ6OFNB.js} +1 -1
- package/dist/{chunk-IYBKPYWB.js → chunk-L3LY5KUM.js} +1 -1
- package/dist/{chunk-MQT2ULYX.js → chunk-LSEBYLVJ.js} +2 -2
- package/dist/{chunk-4X3HTOYV.js → chunk-OT4JJTAW.js} +1 -1
- package/dist/{chunk-N4JBA225.js → chunk-OZ2MSV43.js} +3 -3
- package/dist/{chunk-XQNR5GZE.js → chunk-RAAQWTZ2.js} +6 -5
- package/dist/{chunk-Q2EB5CFY.js → chunk-RP5YCLR4.js} +1 -1
- package/dist/{chunk-TLON56UA.js → chunk-XAEQWVMZ.js} +2 -2
- package/dist/{chunk-LE4INBQU.js → chunk-XDV7HADD.js} +6 -5
- package/dist/{chunk-CRZNBNEF.js → chunk-XGI3Y5KL.js} +1 -1
- package/dist/{chunk-OR6TTYYM.js → chunk-YB2GFJU7.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.d.ts +7 -1
- 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.d.ts +7 -1
- 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-CiexA8rJ.d.ts → i18n-Cx6FCYEy.d.ts} +22 -1
- 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 +10 -11
- package/dist/pages/index.js +45 -24
- package/dist/table-classes-context-CQvkORm3.d.ts +12 -0
- package/package.json +4 -4
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
getAdminCmsConfig,
|
|
5
5
|
getMediaProcessingDefaults,
|
|
6
6
|
uploadProcessedImage
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-XGI3Y5KL.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-JSJ6OFNB.js";
|
|
19
19
|
|
|
20
20
|
// src/components/media-picker.tsx
|
|
21
21
|
import { useEffect, useRef, useState } from "react";
|
|
@@ -159,6 +159,20 @@ function MediaPicker({ trigger, onSelect }) {
|
|
|
159
159
|
] });
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
+
// src/editor/table-classes-context.tsx
|
|
163
|
+
import { createContext, useContext } from "react";
|
|
164
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
165
|
+
var TableClassesContext = createContext([]);
|
|
166
|
+
function TableClassesProvider({
|
|
167
|
+
classes,
|
|
168
|
+
children
|
|
169
|
+
}) {
|
|
170
|
+
return /* @__PURE__ */ jsx2(TableClassesContext.Provider, { value: classes ?? [], children });
|
|
171
|
+
}
|
|
172
|
+
function useTableClasses() {
|
|
173
|
+
return useContext(TableClassesContext);
|
|
174
|
+
}
|
|
175
|
+
|
|
162
176
|
// src/components/post-form.tsx
|
|
163
177
|
import { useEffect as useEffect5, useRef as useRef4, useState as useState6 } from "react";
|
|
164
178
|
import { useRouter } from "next/navigation";
|
|
@@ -200,13 +214,31 @@ import { Button as Button3, cn as cn2 } from "@ampless/runtime/ui";
|
|
|
200
214
|
|
|
201
215
|
// src/editor/table-controls.tsx
|
|
202
216
|
import { useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
|
|
203
|
-
import { Table as TableIcon } from "lucide-react";
|
|
217
|
+
import { Table as TableIcon, Check } from "lucide-react";
|
|
218
|
+
import { isValidCustomClassId } from "ampless";
|
|
204
219
|
import { Button as Button2, cn } from "@ampless/runtime/ui";
|
|
205
|
-
import { jsx as
|
|
220
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
221
|
+
function currentTableClass(editor) {
|
|
222
|
+
if (!editor.isActive("table")) return null;
|
|
223
|
+
const v = editor.getAttributes("table").customClass;
|
|
224
|
+
return isValidCustomClassId(v) ? v : null;
|
|
225
|
+
}
|
|
206
226
|
function TableControls({ editor }) {
|
|
207
227
|
const t = useT();
|
|
208
228
|
const [open, setOpen] = useState2(false);
|
|
209
229
|
const rootRef = useRef2(null);
|
|
230
|
+
const themeClasses = useTableClasses();
|
|
231
|
+
const [activeClass, setActiveClass] = useState2(() => currentTableClass(editor));
|
|
232
|
+
useEffect2(() => {
|
|
233
|
+
const sync = () => setActiveClass(currentTableClass(editor));
|
|
234
|
+
sync();
|
|
235
|
+
editor.on("selectionUpdate", sync);
|
|
236
|
+
editor.on("transaction", sync);
|
|
237
|
+
return () => {
|
|
238
|
+
editor.off("selectionUpdate", sync);
|
|
239
|
+
editor.off("transaction", sync);
|
|
240
|
+
};
|
|
241
|
+
}, [editor]);
|
|
210
242
|
useEffect2(() => {
|
|
211
243
|
if (!open) return;
|
|
212
244
|
function onPointerDown(e) {
|
|
@@ -281,8 +313,15 @@ function TableControls({ editor }) {
|
|
|
281
313
|
enabled: inTable && editor.can().deleteTable()
|
|
282
314
|
}
|
|
283
315
|
];
|
|
316
|
+
const declared = themeClasses.find((c) => c.id === activeClass);
|
|
317
|
+
const unknownActive = activeClass !== null && !declared;
|
|
318
|
+
const styleLabel = declared?.label ?? activeClass;
|
|
319
|
+
const setStyle = (id) => {
|
|
320
|
+
editor.chain().focus().updateAttributes("table", { customClass: id }).run();
|
|
321
|
+
setOpen(false);
|
|
322
|
+
};
|
|
284
323
|
return /* @__PURE__ */ jsxs2("div", { ref: rootRef, className: "relative", children: [
|
|
285
|
-
/* @__PURE__ */
|
|
324
|
+
/* @__PURE__ */ jsx3(
|
|
286
325
|
Button2,
|
|
287
326
|
{
|
|
288
327
|
type: "button",
|
|
@@ -290,36 +329,69 @@ function TableControls({ editor }) {
|
|
|
290
329
|
size: "icon",
|
|
291
330
|
onClick: () => setOpen((v) => !v),
|
|
292
331
|
className: cn(inTable && "bg-accent text-accent-foreground"),
|
|
293
|
-
title: t("editor.table.title"),
|
|
332
|
+
title: styleLabel ? t("editor.table.titleWithStyle", { style: styleLabel }) : t("editor.table.title"),
|
|
294
333
|
"aria-expanded": open,
|
|
295
334
|
"aria-haspopup": "menu",
|
|
296
|
-
|
|
335
|
+
"data-table-style": activeClass ?? void 0,
|
|
336
|
+
children: /* @__PURE__ */ jsx3(TableIcon, { className: "h-4 w-4" })
|
|
297
337
|
}
|
|
298
338
|
),
|
|
299
|
-
open && /* @__PURE__ */
|
|
339
|
+
open && /* @__PURE__ */ jsxs2(
|
|
300
340
|
"div",
|
|
301
341
|
{
|
|
302
342
|
role: "menu",
|
|
303
343
|
className: "absolute left-0 top-full z-50 mt-1 min-w-[12rem] rounded-md border bg-popover p-1 shadow",
|
|
304
|
-
children:
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
344
|
+
children: [
|
|
345
|
+
items.map((item) => /* @__PURE__ */ jsx3(
|
|
346
|
+
"button",
|
|
347
|
+
{
|
|
348
|
+
type: "button",
|
|
349
|
+
role: "menuitem",
|
|
350
|
+
disabled: !item.enabled,
|
|
351
|
+
onClick: () => {
|
|
352
|
+
if (!item.enabled) return;
|
|
353
|
+
item.run();
|
|
354
|
+
setOpen(false);
|
|
355
|
+
},
|
|
356
|
+
className: cn(
|
|
357
|
+
"block w-full rounded-sm px-2 py-1 text-left text-sm",
|
|
358
|
+
item.enabled ? "hover:bg-accent hover:text-accent-foreground" : "cursor-not-allowed text-muted-foreground opacity-50"
|
|
359
|
+
),
|
|
360
|
+
children: item.label
|
|
314
361
|
},
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
),
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
362
|
+
item.key
|
|
363
|
+
)),
|
|
364
|
+
inTable && /* @__PURE__ */ jsxs2("div", { role: "group", "aria-label": t("editor.table.style"), className: "mt-1 border-t pt-1", children: [
|
|
365
|
+
/* @__PURE__ */ jsx3("div", { className: "px-2 py-1 text-xs font-medium text-muted-foreground", children: t("editor.table.style") }),
|
|
366
|
+
[
|
|
367
|
+
{ id: null, label: t("editor.table.styleDefault"), description: void 0, unknown: false },
|
|
368
|
+
...themeClasses.map((c) => ({ id: c.id, label: c.label, description: c.description, unknown: false })),
|
|
369
|
+
...unknownActive ? [{ id: activeClass, label: t("editor.table.styleUnknown", { id: activeClass ?? "" }), description: t("editor.table.styleUnknownHint"), unknown: true }] : []
|
|
370
|
+
].map((opt) => {
|
|
371
|
+
const selected = opt.id === activeClass;
|
|
372
|
+
return /* @__PURE__ */ jsxs2(
|
|
373
|
+
"button",
|
|
374
|
+
{
|
|
375
|
+
type: "button",
|
|
376
|
+
role: "menuitemradio",
|
|
377
|
+
"aria-checked": selected,
|
|
378
|
+
title: opt.description,
|
|
379
|
+
onClick: () => setStyle(opt.id),
|
|
380
|
+
className: cn(
|
|
381
|
+
"flex w-full items-center gap-2 rounded-sm px-2 py-1 text-left text-sm hover:bg-accent hover:text-accent-foreground",
|
|
382
|
+
opt.unknown && "text-amber-700 dark:text-amber-400"
|
|
383
|
+
),
|
|
384
|
+
children: [
|
|
385
|
+
/* @__PURE__ */ jsx3(Check, { className: cn("h-3.5 w-3.5 shrink-0", selected ? "opacity-100" : "opacity-0") }),
|
|
386
|
+
/* @__PURE__ */ jsx3("span", { children: opt.label })
|
|
387
|
+
]
|
|
388
|
+
},
|
|
389
|
+
opt.id ?? "__default"
|
|
390
|
+
);
|
|
391
|
+
}),
|
|
392
|
+
themeClasses.length === 0 && /* @__PURE__ */ jsx3("div", { className: "px-2 py-1 text-xs text-muted-foreground", children: t("editor.table.styleNoneDeclared") })
|
|
393
|
+
] })
|
|
394
|
+
]
|
|
323
395
|
}
|
|
324
396
|
)
|
|
325
397
|
] });
|
|
@@ -338,7 +410,7 @@ function normalizeCodeLanguage(value) {
|
|
|
338
410
|
}
|
|
339
411
|
|
|
340
412
|
// src/editor/code-block-language-control.tsx
|
|
341
|
-
import { jsx as
|
|
413
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
342
414
|
function CodeBlockLanguageControl({ editor }) {
|
|
343
415
|
const t = useT();
|
|
344
416
|
const [state, setState] = useState3({ active: false, language: "" });
|
|
@@ -365,8 +437,8 @@ function CodeBlockLanguageControl({ editor }) {
|
|
|
365
437
|
}, [editor]);
|
|
366
438
|
if (!state.active) return null;
|
|
367
439
|
return /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-1", children: [
|
|
368
|
-
/* @__PURE__ */
|
|
369
|
-
/* @__PURE__ */
|
|
440
|
+
/* @__PURE__ */ jsx4(Braces, { className: "h-4 w-4 shrink-0 text-muted-foreground", "aria-hidden": "true" }),
|
|
441
|
+
/* @__PURE__ */ jsx4(
|
|
370
442
|
Input,
|
|
371
443
|
{
|
|
372
444
|
type: "text",
|
|
@@ -395,7 +467,7 @@ function CodeBlockLanguageControl({ editor }) {
|
|
|
395
467
|
}
|
|
396
468
|
|
|
397
469
|
// src/editor/toolbar.tsx
|
|
398
|
-
import { jsx as
|
|
470
|
+
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
399
471
|
function Toolbar({ editor }) {
|
|
400
472
|
const t = useT();
|
|
401
473
|
if (!editor) return null;
|
|
@@ -434,7 +506,7 @@ function Toolbar({ editor }) {
|
|
|
434
506
|
return /* @__PURE__ */ jsxs4("div", { className: "flex flex-wrap gap-1 border-b p-2", children: [
|
|
435
507
|
tools.map((tool) => {
|
|
436
508
|
const Icon = tool.icon;
|
|
437
|
-
return /* @__PURE__ */
|
|
509
|
+
return /* @__PURE__ */ jsx5(
|
|
438
510
|
Button3,
|
|
439
511
|
{
|
|
440
512
|
type: "button",
|
|
@@ -442,12 +514,12 @@ function Toolbar({ editor }) {
|
|
|
442
514
|
size: "icon",
|
|
443
515
|
onClick: tool.action,
|
|
444
516
|
className: cn2(tool.isActive() && "bg-accent text-accent-foreground"),
|
|
445
|
-
children: /* @__PURE__ */
|
|
517
|
+
children: /* @__PURE__ */ jsx5(Icon, { className: "h-4 w-4" })
|
|
446
518
|
},
|
|
447
519
|
tool.name
|
|
448
520
|
);
|
|
449
521
|
}),
|
|
450
|
-
/* @__PURE__ */
|
|
522
|
+
/* @__PURE__ */ jsx5(
|
|
451
523
|
Button3,
|
|
452
524
|
{
|
|
453
525
|
type: "button",
|
|
@@ -455,18 +527,18 @@ function Toolbar({ editor }) {
|
|
|
455
527
|
size: "icon",
|
|
456
528
|
onClick: setLink,
|
|
457
529
|
className: cn2(editor.isActive("link") && "bg-accent text-accent-foreground"),
|
|
458
|
-
children: /* @__PURE__ */
|
|
530
|
+
children: /* @__PURE__ */ jsx5(LinkIcon, { className: "h-4 w-4" })
|
|
459
531
|
}
|
|
460
532
|
),
|
|
461
|
-
/* @__PURE__ */
|
|
533
|
+
/* @__PURE__ */ jsx5(
|
|
462
534
|
MediaPicker,
|
|
463
535
|
{
|
|
464
536
|
onSelect: insertImage,
|
|
465
|
-
trigger: /* @__PURE__ */
|
|
537
|
+
trigger: /* @__PURE__ */ jsx5(Button3, { type: "button", variant: "ghost", size: "icon", children: /* @__PURE__ */ jsx5(ImageIcon, { className: "h-4 w-4" }) })
|
|
466
538
|
}
|
|
467
539
|
),
|
|
468
|
-
/* @__PURE__ */
|
|
469
|
-
/* @__PURE__ */
|
|
540
|
+
/* @__PURE__ */ jsx5(TableControls, { editor }),
|
|
541
|
+
/* @__PURE__ */ jsx5(CodeBlockLanguageControl, { editor })
|
|
470
542
|
] });
|
|
471
543
|
}
|
|
472
544
|
|
|
@@ -474,7 +546,7 @@ function Toolbar({ editor }) {
|
|
|
474
546
|
import { BubbleMenu } from "@tiptap/react/menus";
|
|
475
547
|
import { Trash2, Pencil, ImageIcon as ImageIcon2, Maximize2 } from "lucide-react";
|
|
476
548
|
import { Button as Button4, cn as cn3 } from "@ampless/runtime/ui";
|
|
477
|
-
import { jsx as
|
|
549
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
478
550
|
function ImageBubbleMenu({ editor }) {
|
|
479
551
|
const t = useT();
|
|
480
552
|
const editAlt = () => {
|
|
@@ -492,7 +564,7 @@ function ImageBubbleMenu({ editor }) {
|
|
|
492
564
|
editor.chain().focus().updateAttributes("image", { display: next }).run();
|
|
493
565
|
};
|
|
494
566
|
const currentDisplay = editor.getAttributes("image").display ?? null;
|
|
495
|
-
return /* @__PURE__ */
|
|
567
|
+
return /* @__PURE__ */ jsx6(
|
|
496
568
|
BubbleMenu,
|
|
497
569
|
{
|
|
498
570
|
editor,
|
|
@@ -509,7 +581,7 @@ function ImageBubbleMenu({ editor }) {
|
|
|
509
581
|
className: cn3(currentDisplay === "inline" && "bg-accent text-accent-foreground"),
|
|
510
582
|
title: t("editor.image.inlineTitle"),
|
|
511
583
|
children: [
|
|
512
|
-
/* @__PURE__ */
|
|
584
|
+
/* @__PURE__ */ jsx6(ImageIcon2, { className: "mr-1 h-3 w-3" }),
|
|
513
585
|
t("editor.image.inline")
|
|
514
586
|
]
|
|
515
587
|
}
|
|
@@ -524,18 +596,18 @@ function ImageBubbleMenu({ editor }) {
|
|
|
524
596
|
className: cn3(currentDisplay === "lightbox" && "bg-accent text-accent-foreground"),
|
|
525
597
|
title: t("editor.image.lightboxTitle"),
|
|
526
598
|
children: [
|
|
527
|
-
/* @__PURE__ */
|
|
599
|
+
/* @__PURE__ */ jsx6(Maximize2, { className: "mr-1 h-3 w-3" }),
|
|
528
600
|
t("editor.image.lightbox")
|
|
529
601
|
]
|
|
530
602
|
}
|
|
531
603
|
),
|
|
532
|
-
/* @__PURE__ */
|
|
604
|
+
/* @__PURE__ */ jsx6("span", { className: "mx-1 h-4 w-px bg-border" }),
|
|
533
605
|
/* @__PURE__ */ jsxs5(Button4, { type: "button", variant: "ghost", size: "sm", onClick: editAlt, children: [
|
|
534
|
-
/* @__PURE__ */
|
|
606
|
+
/* @__PURE__ */ jsx6(Pencil, { className: "mr-1 h-3 w-3" }),
|
|
535
607
|
t("editor.image.alt")
|
|
536
608
|
] }),
|
|
537
609
|
/* @__PURE__ */ jsxs5(Button4, { type: "button", variant: "ghost", size: "sm", onClick: remove2, children: [
|
|
538
|
-
/* @__PURE__ */
|
|
610
|
+
/* @__PURE__ */ jsx6(Trash2, { className: "mr-1 h-3 w-3" }),
|
|
539
611
|
t("editor.image.delete")
|
|
540
612
|
] })
|
|
541
613
|
] })
|
|
@@ -556,6 +628,31 @@ import { TaskItem } from "@tiptap/extension-task-item";
|
|
|
556
628
|
import { Underline as Underline2 } from "@tiptap/extension-underline";
|
|
557
629
|
import { Highlight } from "@tiptap/extension-highlight";
|
|
558
630
|
import { TextAlign } from "@tiptap/extension-text-align";
|
|
631
|
+
import { isValidCustomClassId as isValidCustomClassId2, tableCustomClassName } from "ampless";
|
|
632
|
+
var TABLE_CLASS_PREFIX = tableCustomClassName("");
|
|
633
|
+
function parseTableCustomClass(className) {
|
|
634
|
+
for (const cls of (className ?? "").split(/\s+/)) {
|
|
635
|
+
if (!cls.startsWith(TABLE_CLASS_PREFIX)) continue;
|
|
636
|
+
const id = cls.slice(TABLE_CLASS_PREFIX.length);
|
|
637
|
+
if (isValidCustomClassId2(id)) return id;
|
|
638
|
+
}
|
|
639
|
+
return null;
|
|
640
|
+
}
|
|
641
|
+
var AmplessTable = Table.extend({
|
|
642
|
+
addAttributes() {
|
|
643
|
+
return {
|
|
644
|
+
...this.parent?.(),
|
|
645
|
+
customClass: {
|
|
646
|
+
default: null,
|
|
647
|
+
parseHTML: (el) => parseTableCustomClass(el.getAttribute("class")),
|
|
648
|
+
renderHTML: (attrs) => {
|
|
649
|
+
const v = attrs.customClass;
|
|
650
|
+
return isValidCustomClassId2(v) ? { class: tableCustomClassName(v) } : {};
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
};
|
|
654
|
+
}
|
|
655
|
+
});
|
|
559
656
|
var AmplessImage = Image.extend({
|
|
560
657
|
addAttributes() {
|
|
561
658
|
return {
|
|
@@ -575,7 +672,7 @@ var BASE_TIPTAP_EXTENSIONS = [
|
|
|
575
672
|
StarterKit,
|
|
576
673
|
Link.configure({ openOnClick: false }),
|
|
577
674
|
AmplessImage.configure({ inline: false, allowBase64: false }),
|
|
578
|
-
|
|
675
|
+
AmplessTable.configure({ resizable: true, HTMLAttributes: { class: "tiptap-table" } }),
|
|
579
676
|
TableRow,
|
|
580
677
|
TableHeader,
|
|
581
678
|
TableCell,
|
|
@@ -587,7 +684,7 @@ var BASE_TIPTAP_EXTENSIONS = [
|
|
|
587
684
|
];
|
|
588
685
|
|
|
589
686
|
// src/editor/tiptap-editor.tsx
|
|
590
|
-
import { jsx as
|
|
687
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
591
688
|
var EDITOR_STYLES = `
|
|
592
689
|
.ProseMirror .tiptap-table,
|
|
593
690
|
.ProseMirror table {
|
|
@@ -688,10 +785,10 @@ function TiptapEditor({ initialContent, onChange, onUserEdit }) {
|
|
|
688
785
|
}
|
|
689
786
|
});
|
|
690
787
|
return /* @__PURE__ */ jsxs6("div", { className: "rounded-md border", children: [
|
|
691
|
-
/* @__PURE__ */
|
|
692
|
-
/* @__PURE__ */
|
|
693
|
-
editor && /* @__PURE__ */
|
|
694
|
-
/* @__PURE__ */
|
|
788
|
+
/* @__PURE__ */ jsx7("style", { children: EDITOR_STYLES }),
|
|
789
|
+
/* @__PURE__ */ jsx7(Toolbar, { editor }),
|
|
790
|
+
editor && /* @__PURE__ */ jsx7(ImageBubbleMenu, { editor }),
|
|
791
|
+
/* @__PURE__ */ jsx7(EditorContent, { editor })
|
|
695
792
|
] });
|
|
696
793
|
}
|
|
697
794
|
|
|
@@ -757,7 +854,7 @@ function buildPreviewSrcDoc(html) {
|
|
|
757
854
|
}
|
|
758
855
|
|
|
759
856
|
// src/components/post-history-panel.tsx
|
|
760
|
-
import { Fragment as Fragment2, jsx as
|
|
857
|
+
import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
761
858
|
var PAGE_SIZE = 20;
|
|
762
859
|
function formatRevisedAt(iso, timezone, locale) {
|
|
763
860
|
const d = new Date(iso);
|
|
@@ -859,30 +956,30 @@ function PostHistoryPanel({
|
|
|
859
956
|
"aria-expanded": open,
|
|
860
957
|
className: "flex w-full items-center justify-between px-4 py-3 text-left text-sm font-medium",
|
|
861
958
|
children: [
|
|
862
|
-
/* @__PURE__ */
|
|
863
|
-
/* @__PURE__ */
|
|
959
|
+
/* @__PURE__ */ jsx8("span", { children: t("posts.history.title") }),
|
|
960
|
+
/* @__PURE__ */ jsx8("span", { className: "text-muted-foreground", "aria-hidden": "true", children: open ? "\u2212" : "+" })
|
|
864
961
|
]
|
|
865
962
|
}
|
|
866
963
|
),
|
|
867
964
|
open && /* @__PURE__ */ jsxs7("div", { className: "space-y-4 border-t px-4 py-4", children: [
|
|
868
|
-
error && /* @__PURE__ */
|
|
869
|
-
loading && revisions.length === 0 ? /* @__PURE__ */
|
|
870
|
-
/* @__PURE__ */
|
|
871
|
-
/* @__PURE__ */
|
|
872
|
-
/* @__PURE__ */
|
|
873
|
-
/* @__PURE__ */
|
|
874
|
-
/* @__PURE__ */
|
|
965
|
+
error && /* @__PURE__ */ jsx8("p", { className: "text-sm text-destructive", children: error }),
|
|
966
|
+
loading && revisions.length === 0 ? /* @__PURE__ */ jsx8("p", { className: "text-sm text-muted-foreground", children: t("common.loading") }) : revisions.length === 0 ? /* @__PURE__ */ jsx8("p", { className: "text-sm text-muted-foreground", children: t("posts.history.empty") }) : /* @__PURE__ */ jsx8("div", { className: "overflow-x-auto rounded-md border", children: /* @__PURE__ */ jsxs7("table", { className: "w-full text-sm", children: [
|
|
967
|
+
/* @__PURE__ */ jsx8("thead", { children: /* @__PURE__ */ jsxs7("tr", { className: "border-b text-left text-xs text-muted-foreground", children: [
|
|
968
|
+
/* @__PURE__ */ jsx8("th", { className: "px-3 py-2 font-medium", children: t("posts.history.columnRevisedAt") }),
|
|
969
|
+
/* @__PURE__ */ jsx8("th", { className: "px-3 py-2 font-medium", children: t("posts.history.columnStatus") }),
|
|
970
|
+
/* @__PURE__ */ jsx8("th", { className: "px-3 py-2 font-medium", children: t("posts.history.columnTitle") }),
|
|
971
|
+
/* @__PURE__ */ jsx8("th", { className: "px-3 py-2 font-medium text-right", children: t("common.actions") })
|
|
875
972
|
] }) }),
|
|
876
|
-
/* @__PURE__ */
|
|
973
|
+
/* @__PURE__ */ jsx8("tbody", { children: revisions.map((rev) => /* @__PURE__ */ jsxs7(
|
|
877
974
|
"tr",
|
|
878
975
|
{
|
|
879
976
|
className: selected?.postHistoryId === rev.postHistoryId ? "border-b bg-muted/50" : "border-b",
|
|
880
977
|
children: [
|
|
881
|
-
/* @__PURE__ */
|
|
882
|
-
/* @__PURE__ */
|
|
883
|
-
/* @__PURE__ */
|
|
884
|
-
/* @__PURE__ */
|
|
885
|
-
/* @__PURE__ */
|
|
978
|
+
/* @__PURE__ */ jsx8("td", { className: "whitespace-nowrap px-3 py-2 font-mono text-xs", children: formatRevisedAt(rev.revisedAt, timezone, locale) }),
|
|
979
|
+
/* @__PURE__ */ jsx8("td", { className: "px-3 py-2", children: /* @__PURE__ */ jsx8("span", { className: "text-xs text-muted-foreground", children: rev.status ? t(`common.${rev.status}`) : "\u2014" }) }),
|
|
980
|
+
/* @__PURE__ */ jsx8("td", { className: "px-3 py-2", children: rev.title || "\u2014" }),
|
|
981
|
+
/* @__PURE__ */ jsx8("td", { className: "px-3 py-2 text-right", children: /* @__PURE__ */ jsxs7("div", { className: "flex justify-end gap-2", children: [
|
|
982
|
+
/* @__PURE__ */ jsx8(
|
|
886
983
|
Button5,
|
|
887
984
|
{
|
|
888
985
|
type: "button",
|
|
@@ -892,7 +989,7 @@ function PostHistoryPanel({
|
|
|
892
989
|
children: t("posts.history.view")
|
|
893
990
|
}
|
|
894
991
|
),
|
|
895
|
-
/* @__PURE__ */
|
|
992
|
+
/* @__PURE__ */ jsx8(
|
|
896
993
|
Button5,
|
|
897
994
|
{
|
|
898
995
|
type: "button",
|
|
@@ -910,7 +1007,7 @@ function PostHistoryPanel({
|
|
|
910
1007
|
rev.postHistoryId
|
|
911
1008
|
)) })
|
|
912
1009
|
] }) }),
|
|
913
|
-
nextToken && /* @__PURE__ */
|
|
1010
|
+
nextToken && /* @__PURE__ */ jsx8("div", { children: /* @__PURE__ */ jsx8(
|
|
914
1011
|
Button5,
|
|
915
1012
|
{
|
|
916
1013
|
type: "button",
|
|
@@ -923,10 +1020,10 @@ function PostHistoryPanel({
|
|
|
923
1020
|
) }),
|
|
924
1021
|
selected && /* @__PURE__ */ jsxs7("div", { className: "space-y-3 rounded-md border p-4", children: [
|
|
925
1022
|
/* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between", children: [
|
|
926
|
-
/* @__PURE__ */
|
|
1023
|
+
/* @__PURE__ */ jsx8("h4", { className: "text-sm font-semibold", children: t("posts.history.viewing", {
|
|
927
1024
|
date: formatRevisedAt(selected.revisedAt, timezone, locale)
|
|
928
1025
|
}) }),
|
|
929
|
-
/* @__PURE__ */
|
|
1026
|
+
/* @__PURE__ */ jsx8(
|
|
930
1027
|
Button5,
|
|
931
1028
|
{
|
|
932
1029
|
type: "button",
|
|
@@ -938,13 +1035,13 @@ function PostHistoryPanel({
|
|
|
938
1035
|
)
|
|
939
1036
|
] }),
|
|
940
1037
|
/* @__PURE__ */ jsxs7("p", { className: "text-xs text-muted-foreground", children: [
|
|
941
|
-
/* @__PURE__ */
|
|
1038
|
+
/* @__PURE__ */ jsx8("span", { className: "font-mono uppercase", children: selected.format ?? "\u2014" }),
|
|
942
1039
|
selected.slug && /* @__PURE__ */ jsxs7(Fragment2, { children: [
|
|
943
|
-
/* @__PURE__ */
|
|
944
|
-
/* @__PURE__ */
|
|
1040
|
+
/* @__PURE__ */ jsx8("span", { className: "mx-2", children: "\xB7" }),
|
|
1041
|
+
/* @__PURE__ */ jsx8("span", { className: "font-mono", children: selected.slug })
|
|
945
1042
|
] })
|
|
946
1043
|
] }),
|
|
947
|
-
selected.format === "static" ? /* @__PURE__ */
|
|
1044
|
+
selected.format === "static" ? /* @__PURE__ */ jsx8("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") }) : (
|
|
948
1045
|
// Sandbox is `allow-scripts allow-same-origin`. With
|
|
949
1046
|
// srcDoc, this gives the iframe the admin's origin so
|
|
950
1047
|
// 3rd-party embed widgets (YouTube SDK, x.com widgets.js)
|
|
@@ -971,7 +1068,7 @@ function PostHistoryPanel({
|
|
|
971
1068
|
// don't style its srcDoc contents. Typography comes from
|
|
972
1069
|
// the full document the preview route now returns
|
|
973
1070
|
// (PREVIEW_BASE_CSS + theme vars in createPreviewRouteHandler).
|
|
974
|
-
/* @__PURE__ */
|
|
1071
|
+
/* @__PURE__ */ jsx8(
|
|
975
1072
|
"iframe",
|
|
976
1073
|
{
|
|
977
1074
|
title: "revision-preview",
|
|
@@ -1083,7 +1180,7 @@ async function deleteBundle(slug) {
|
|
|
1083
1180
|
}
|
|
1084
1181
|
|
|
1085
1182
|
// src/components/static-uploader.tsx
|
|
1086
|
-
import { jsx as
|
|
1183
|
+
import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1087
1184
|
function StaticUploader({ initial, onFilesReady, onClear }) {
|
|
1088
1185
|
const t = useT();
|
|
1089
1186
|
const [pending, setPending] = useState5(null);
|
|
@@ -1167,8 +1264,8 @@ function StaticUploader({ initial, onFilesReady, onClear }) {
|
|
|
1167
1264
|
return /* @__PURE__ */ jsxs8("div", { className: "space-y-4", children: [
|
|
1168
1265
|
/* @__PURE__ */ jsxs8("div", { className: "rounded-md border border-dashed p-4", children: [
|
|
1169
1266
|
/* @__PURE__ */ jsxs8("label", { className: "flex flex-col items-start gap-2 text-sm", children: [
|
|
1170
|
-
/* @__PURE__ */
|
|
1171
|
-
/* @__PURE__ */
|
|
1267
|
+
/* @__PURE__ */ jsx9("span", { className: "font-medium", children: t("posts.form.static.pick") }),
|
|
1268
|
+
/* @__PURE__ */ jsx9(
|
|
1172
1269
|
"input",
|
|
1173
1270
|
{
|
|
1174
1271
|
type: "file",
|
|
@@ -1178,13 +1275,13 @@ function StaticUploader({ initial, onFilesReady, onClear }) {
|
|
|
1178
1275
|
disabled: busy
|
|
1179
1276
|
}
|
|
1180
1277
|
),
|
|
1181
|
-
/* @__PURE__ */
|
|
1278
|
+
/* @__PURE__ */ jsx9("span", { className: "text-xs text-muted-foreground", children: t("posts.form.static.pickHint") })
|
|
1182
1279
|
] }),
|
|
1183
|
-
busy && /* @__PURE__ */
|
|
1184
|
-
error && /* @__PURE__ */
|
|
1280
|
+
busy && /* @__PURE__ */ jsx9("p", { className: "mt-2 text-sm text-muted-foreground", children: t("common.loading") }),
|
|
1281
|
+
error && /* @__PURE__ */ jsx9("p", { className: "mt-2 text-sm text-destructive", children: error })
|
|
1185
1282
|
] }),
|
|
1186
|
-
showCurrent && /* @__PURE__ */
|
|
1187
|
-
pending && /* @__PURE__ */
|
|
1283
|
+
showCurrent && /* @__PURE__ */ jsx9(CurrentBundle, { body: initial }),
|
|
1284
|
+
pending && /* @__PURE__ */ jsx9(
|
|
1188
1285
|
PendingBundle,
|
|
1189
1286
|
{
|
|
1190
1287
|
files: pending,
|
|
@@ -1198,13 +1295,13 @@ function CurrentBundle({ body }) {
|
|
|
1198
1295
|
const t = useT();
|
|
1199
1296
|
return /* @__PURE__ */ jsxs8("div", { className: "rounded-md border bg-muted/30 p-3", children: [
|
|
1200
1297
|
/* @__PURE__ */ jsxs8("div", { className: "mb-2 flex items-center gap-2 text-sm font-medium", children: [
|
|
1201
|
-
/* @__PURE__ */
|
|
1298
|
+
/* @__PURE__ */ jsx9(FileArchive, { className: "h-4 w-4" }),
|
|
1202
1299
|
t("posts.form.static.currentBundle", {
|
|
1203
1300
|
count: body.files.length,
|
|
1204
1301
|
entrypoint: body.entrypoint
|
|
1205
1302
|
})
|
|
1206
1303
|
] }),
|
|
1207
|
-
/* @__PURE__ */
|
|
1304
|
+
/* @__PURE__ */ jsx9(FileList, { files: body.files })
|
|
1208
1305
|
] });
|
|
1209
1306
|
}
|
|
1210
1307
|
function PendingBundle({
|
|
@@ -1217,20 +1314,20 @@ function PendingBundle({
|
|
|
1217
1314
|
return /* @__PURE__ */ jsxs8("div", { className: "rounded-md border p-3", children: [
|
|
1218
1315
|
/* @__PURE__ */ jsxs8("div", { className: "mb-2 flex items-center justify-between gap-2 text-sm font-medium", children: [
|
|
1219
1316
|
/* @__PURE__ */ jsxs8("span", { className: "flex items-center gap-2", children: [
|
|
1220
|
-
/* @__PURE__ */
|
|
1317
|
+
/* @__PURE__ */ jsx9(FileArchive, { className: "h-4 w-4" }),
|
|
1221
1318
|
t("posts.form.static.pendingBundle", {
|
|
1222
1319
|
count: files.length,
|
|
1223
1320
|
size: formatBytes(totalBytes)
|
|
1224
1321
|
})
|
|
1225
1322
|
] }),
|
|
1226
1323
|
/* @__PURE__ */ jsxs8(Button6, { type: "button", variant: "ghost", size: "sm", onClick: onClear, children: [
|
|
1227
|
-
/* @__PURE__ */
|
|
1324
|
+
/* @__PURE__ */ jsx9(X, { className: "mr-1 h-3 w-3" }),
|
|
1228
1325
|
t("common.cancel")
|
|
1229
1326
|
] })
|
|
1230
1327
|
] }),
|
|
1231
1328
|
issues.length > 0 && /* @__PURE__ */ jsxs8("div", { className: "mb-3 rounded-md border border-destructive/40 bg-destructive/5 p-2 text-sm", children: [
|
|
1232
1329
|
/* @__PURE__ */ jsxs8("div", { className: "mb-1 flex items-center gap-2 font-medium text-destructive", children: [
|
|
1233
|
-
/* @__PURE__ */
|
|
1330
|
+
/* @__PURE__ */ jsx9(AlertTriangle, { className: "h-4 w-4" }),
|
|
1234
1331
|
t("posts.form.static.issuesTitle", { count: issues.length })
|
|
1235
1332
|
] }),
|
|
1236
1333
|
/* @__PURE__ */ jsxs8("ul", { className: "space-y-0.5 text-xs", children: [
|
|
@@ -1245,15 +1342,15 @@ function PendingBundle({
|
|
|
1245
1342
|
" more"
|
|
1246
1343
|
] })
|
|
1247
1344
|
] }),
|
|
1248
|
-
/* @__PURE__ */
|
|
1345
|
+
/* @__PURE__ */ jsx9("p", { className: "mt-2 text-xs text-muted-foreground", children: t("posts.form.static.issuesHint") })
|
|
1249
1346
|
] }),
|
|
1250
|
-
/* @__PURE__ */
|
|
1347
|
+
/* @__PURE__ */ jsx9(FileList, { files: files.map((f) => f.path) })
|
|
1251
1348
|
] });
|
|
1252
1349
|
}
|
|
1253
1350
|
function FileList({ files }) {
|
|
1254
1351
|
return /* @__PURE__ */ jsxs8("ul", { className: "space-y-0.5 text-xs", children: [
|
|
1255
1352
|
files.slice(0, 40).map((path) => /* @__PURE__ */ jsxs8("li", { className: "flex items-center gap-1.5 font-mono text-muted-foreground", children: [
|
|
1256
|
-
/* @__PURE__ */
|
|
1353
|
+
/* @__PURE__ */ jsx9(FileText, { className: "h-3 w-3 shrink-0" }),
|
|
1257
1354
|
path
|
|
1258
1355
|
] }, path)),
|
|
1259
1356
|
files.length > 40 && /* @__PURE__ */ jsxs8("li", { className: "font-mono text-xs text-muted-foreground", children: [
|
|
@@ -1420,6 +1517,7 @@ function deepEqual(a, b) {
|
|
|
1420
1517
|
}
|
|
1421
1518
|
|
|
1422
1519
|
// src/editor/format-switch.ts
|
|
1520
|
+
import { isValidCustomClassId as isValidCustomClassId3, tableCustomClassName as tableCustomClassName2 } from "ampless";
|
|
1423
1521
|
import {
|
|
1424
1522
|
tiptapToHtml,
|
|
1425
1523
|
tiptapToMarkdown,
|
|
@@ -1427,6 +1525,40 @@ import {
|
|
|
1427
1525
|
htmlToMarkdown
|
|
1428
1526
|
} from "@ampless/runtime";
|
|
1429
1527
|
import { generateJSON } from "@tiptap/core";
|
|
1528
|
+
var TABLE_CLASS_PREFIX2 = tableCustomClassName2("");
|
|
1529
|
+
function collectTiptapTableClasses(node, out) {
|
|
1530
|
+
if (!node || typeof node !== "object") return;
|
|
1531
|
+
const n = node;
|
|
1532
|
+
if (n.type === "table" && isValidCustomClassId3(n.attrs?.customClass)) out.add(n.attrs.customClass);
|
|
1533
|
+
if (Array.isArray(n.content)) for (const c of n.content) collectTiptapTableClasses(c, out);
|
|
1534
|
+
}
|
|
1535
|
+
function addTableClass(cls, out) {
|
|
1536
|
+
if (!cls.startsWith(TABLE_CLASS_PREFIX2)) return;
|
|
1537
|
+
const id = cls.slice(TABLE_CLASS_PREFIX2.length);
|
|
1538
|
+
if (isValidCustomClassId3(id)) out.add(id);
|
|
1539
|
+
}
|
|
1540
|
+
function collectHtmlTableClasses(html, out) {
|
|
1541
|
+
if (typeof DOMParser !== "undefined") {
|
|
1542
|
+
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
1543
|
+
for (const table of Array.from(doc.querySelectorAll("table"))) {
|
|
1544
|
+
for (const cls of Array.from(table.classList)) addTableClass(cls, out);
|
|
1545
|
+
}
|
|
1546
|
+
return;
|
|
1547
|
+
}
|
|
1548
|
+
for (const m of html.matchAll(/tiptap-table--[a-z0-9-]+/g)) addTableClass(m[0], out);
|
|
1549
|
+
}
|
|
1550
|
+
function tableClassesLostOnConversion(body, from, to) {
|
|
1551
|
+
if (to !== "markdown" || from === "markdown" || from === "static") return [];
|
|
1552
|
+
const found = /* @__PURE__ */ new Set();
|
|
1553
|
+
if (typeof body === "string") collectHtmlTableClasses(body, found);
|
|
1554
|
+
else if (from === "tiptap") collectTiptapTableClasses(body, found);
|
|
1555
|
+
return [...found];
|
|
1556
|
+
}
|
|
1557
|
+
function confirmLossyFormatChange(body, from, to, confirm2, message) {
|
|
1558
|
+
const lost = tableClassesLostOnConversion(body, from, to);
|
|
1559
|
+
if (lost.length === 0) return true;
|
|
1560
|
+
return confirm2(message(lost));
|
|
1561
|
+
}
|
|
1430
1562
|
function convertBodyFormat(body, from, to, registries) {
|
|
1431
1563
|
if (from === to) return body;
|
|
1432
1564
|
const k = `${from}\u2192${to}`;
|
|
@@ -1450,7 +1582,7 @@ function convertBodyFormat(body, from, to, registries) {
|
|
|
1450
1582
|
}
|
|
1451
1583
|
|
|
1452
1584
|
// src/components/post-form.tsx
|
|
1453
|
-
import { jsx as
|
|
1585
|
+
import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1454
1586
|
var EMPTY_TIPTAP_DOC = { type: "doc", content: [{ type: "paragraph" }] };
|
|
1455
1587
|
var IMAGE_URL_RE = /\.(jpe?g|png|gif|webp|avif|svg|bmp|tiff?)(\?|$)/i;
|
|
1456
1588
|
var STYLESHEET_URL_RE = /\.css(\?|$)/i;
|
|
@@ -1645,6 +1777,15 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
1645
1777
|
}
|
|
1646
1778
|
function changeFormat(next) {
|
|
1647
1779
|
if (next === format) return;
|
|
1780
|
+
if (!confirmLossyFormatChange(
|
|
1781
|
+
body,
|
|
1782
|
+
format,
|
|
1783
|
+
next,
|
|
1784
|
+
(message) => window.confirm(message),
|
|
1785
|
+
(classes) => t("posts.form.formatLossTableClasses", { classes: classes.join(", ") })
|
|
1786
|
+
)) {
|
|
1787
|
+
return;
|
|
1788
|
+
}
|
|
1648
1789
|
let nextBody = body;
|
|
1649
1790
|
if (next === "static" || format === "static") {
|
|
1650
1791
|
nextBody = defaultBodyForFormat(next);
|
|
@@ -1817,7 +1958,7 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
1817
1958
|
]);
|
|
1818
1959
|
return /* @__PURE__ */ jsxs9("form", { onSubmit: save, className: "space-y-6", children: [
|
|
1819
1960
|
/* @__PURE__ */ jsxs9("div", { className: "flex gap-1 border-b", children: [
|
|
1820
|
-
/* @__PURE__ */
|
|
1961
|
+
/* @__PURE__ */ jsx10(
|
|
1821
1962
|
"button",
|
|
1822
1963
|
{
|
|
1823
1964
|
type: "button",
|
|
@@ -1827,7 +1968,7 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
1827
1968
|
children: t("posts.form.tabEdit")
|
|
1828
1969
|
}
|
|
1829
1970
|
),
|
|
1830
|
-
/* @__PURE__ */
|
|
1971
|
+
/* @__PURE__ */ jsx10(
|
|
1831
1972
|
"button",
|
|
1832
1973
|
{
|
|
1833
1974
|
type: "button",
|
|
@@ -1840,15 +1981,15 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
1840
1981
|
] }),
|
|
1841
1982
|
view === "preview" && /* @__PURE__ */ jsxs9("article", { className: "space-y-4", children: [
|
|
1842
1983
|
/* @__PURE__ */ jsxs9("header", { className: "border-b pb-4", children: [
|
|
1843
|
-
/* @__PURE__ */
|
|
1984
|
+
/* @__PURE__ */ jsx10("h1", { className: "text-3xl font-bold tracking-tight", children: title || /* @__PURE__ */ jsx10("span", { className: "text-muted-foreground italic", children: t("posts.form.previewNoTitle") }) }),
|
|
1844
1985
|
/* @__PURE__ */ jsxs9("p", { className: "mt-2 text-sm text-muted-foreground", children: [
|
|
1845
|
-
previewPost.publishedAt ? /* @__PURE__ */
|
|
1846
|
-
/* @__PURE__ */
|
|
1847
|
-
/* @__PURE__ */
|
|
1986
|
+
previewPost.publishedAt ? /* @__PURE__ */ jsx10("time", { dateTime: previewPost.publishedAt, children: formatDate(previewPost.publishedAt) }) : /* @__PURE__ */ jsx10("span", { children: t("common.draft") }),
|
|
1987
|
+
/* @__PURE__ */ jsx10("span", { className: "mx-2", children: "\xB7" }),
|
|
1988
|
+
/* @__PURE__ */ jsx10("span", { className: "font-mono text-xs uppercase", children: format })
|
|
1848
1989
|
] }),
|
|
1849
|
-
excerpt && /* @__PURE__ */
|
|
1990
|
+
excerpt && /* @__PURE__ */ jsx10("p", { className: "mt-3 text-base text-muted-foreground", children: excerpt })
|
|
1850
1991
|
] }),
|
|
1851
|
-
format === "static" ? /* @__PURE__ */
|
|
1992
|
+
format === "static" ? /* @__PURE__ */ jsx10("p", { className: "text-sm text-muted-foreground", children: t("posts.form.static.previewHint") }) : (
|
|
1852
1993
|
// Phase 7: preview HTML is fetched from the template's
|
|
1853
1994
|
// `/admin/preview` Route Handler so `ampless.renderBody`
|
|
1854
1995
|
// (async ReactNode) + `ampless.publicPostScriptsForPage(
|
|
@@ -1886,7 +2027,7 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
1886
2027
|
// document — an iframe srcDoc does not inherit the parent page's
|
|
1887
2028
|
// CSS. Typography is now applied inside the document returned by
|
|
1888
2029
|
// createPreviewRouteHandler (PREVIEW_BASE_CSS + theme cssVars).
|
|
1889
|
-
/* @__PURE__ */
|
|
2030
|
+
/* @__PURE__ */ jsx10(
|
|
1890
2031
|
"iframe",
|
|
1891
2032
|
{
|
|
1892
2033
|
title: "post-preview",
|
|
@@ -1896,7 +2037,7 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
1896
2037
|
}
|
|
1897
2038
|
)
|
|
1898
2039
|
),
|
|
1899
|
-
previewPost.tags && previewPost.tags.length > 0 && /* @__PURE__ */
|
|
2040
|
+
previewPost.tags && previewPost.tags.length > 0 && /* @__PURE__ */ jsx10("div", { className: "flex flex-wrap gap-2 border-t pt-4 text-sm", children: previewPost.tags.map((tag) => /* @__PURE__ */ jsxs9(
|
|
1900
2041
|
"span",
|
|
1901
2042
|
{
|
|
1902
2043
|
className: "rounded-full border px-2 py-0.5 text-xs text-muted-foreground",
|
|
@@ -1907,7 +2048,7 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
1907
2048
|
},
|
|
1908
2049
|
tag
|
|
1909
2050
|
)) }),
|
|
1910
|
-
/* @__PURE__ */
|
|
2051
|
+
/* @__PURE__ */ jsx10("p", { className: "text-xs text-muted-foreground", children: t("posts.form.previewHint") })
|
|
1911
2052
|
] }),
|
|
1912
2053
|
/* @__PURE__ */ jsxs9("div", { className: view === "edit" ? "space-y-6" : "hidden", children: [
|
|
1913
2054
|
recovery && /* @__PURE__ */ jsxs9(
|
|
@@ -1916,24 +2057,24 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
1916
2057
|
role: "alert",
|
|
1917
2058
|
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",
|
|
1918
2059
|
children: [
|
|
1919
|
-
/* @__PURE__ */
|
|
1920
|
-
/* @__PURE__ */
|
|
2060
|
+
/* @__PURE__ */ jsx10("p", { className: "font-medium", children: recovery.decision === "stale" ? t("posts.draft.staleTitle") : t("posts.draft.recoverTitle") }),
|
|
2061
|
+
/* @__PURE__ */ jsx10("p", { className: "text-muted-foreground", children: recovery.decision === "stale" ? t("posts.draft.staleBody", {
|
|
1921
2062
|
when: formatDraftTime(recovery.draft.savedAt, draftTimezone, draftLocale)
|
|
1922
2063
|
}) : t("posts.draft.recoverBody", {
|
|
1923
2064
|
when: formatDraftTime(recovery.draft.savedAt, draftTimezone, draftLocale)
|
|
1924
2065
|
}) }),
|
|
1925
2066
|
/* @__PURE__ */ jsxs9("div", { className: "flex gap-2", children: [
|
|
1926
|
-
/* @__PURE__ */
|
|
1927
|
-
/* @__PURE__ */
|
|
2067
|
+
/* @__PURE__ */ jsx10(Button7, { type: "button", size: "sm", onClick: acceptRecovery, children: recovery.decision === "stale" ? t("posts.draft.restoreAnyway") : t("posts.draft.restore") }),
|
|
2068
|
+
/* @__PURE__ */ jsx10(Button7, { type: "button", size: "sm", variant: "outline", onClick: discardRecovery, children: t("posts.draft.discard") })
|
|
1928
2069
|
] })
|
|
1929
2070
|
]
|
|
1930
2071
|
}
|
|
1931
2072
|
),
|
|
1932
|
-
restoredHint && !recovery && /* @__PURE__ */
|
|
1933
|
-
isStaticFormat && /* @__PURE__ */
|
|
2073
|
+
restoredHint && !recovery && /* @__PURE__ */ jsx10("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") }),
|
|
2074
|
+
isStaticFormat && /* @__PURE__ */ jsx10("p", { className: "rounded-md border bg-muted/40 px-3 py-2 text-xs text-muted-foreground", children: t("posts.draft.staticUnsupported") }),
|
|
1934
2075
|
/* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
|
|
1935
|
-
/* @__PURE__ */
|
|
1936
|
-
/* @__PURE__ */
|
|
2076
|
+
/* @__PURE__ */ jsx10(Label, { htmlFor: "title", children: t("posts.form.title") }),
|
|
2077
|
+
/* @__PURE__ */ jsx10(
|
|
1937
2078
|
Input2,
|
|
1938
2079
|
{
|
|
1939
2080
|
id: "title",
|
|
@@ -1948,8 +2089,8 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
1948
2089
|
)
|
|
1949
2090
|
] }),
|
|
1950
2091
|
/* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
|
|
1951
|
-
/* @__PURE__ */
|
|
1952
|
-
/* @__PURE__ */
|
|
2092
|
+
/* @__PURE__ */ jsx10(Label, { htmlFor: "slug", children: t("posts.form.slug") }),
|
|
2093
|
+
/* @__PURE__ */ jsx10(
|
|
1953
2094
|
Input2,
|
|
1954
2095
|
{
|
|
1955
2096
|
id: "slug",
|
|
@@ -1963,8 +2104,8 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
1963
2104
|
)
|
|
1964
2105
|
] }),
|
|
1965
2106
|
/* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
|
|
1966
|
-
/* @__PURE__ */
|
|
1967
|
-
/* @__PURE__ */
|
|
2107
|
+
/* @__PURE__ */ jsx10(Label, { htmlFor: "excerpt", children: t("posts.form.excerpt") }),
|
|
2108
|
+
/* @__PURE__ */ jsx10(
|
|
1968
2109
|
Textarea,
|
|
1969
2110
|
{
|
|
1970
2111
|
id: "excerpt",
|
|
@@ -1978,7 +2119,7 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
1978
2119
|
)
|
|
1979
2120
|
] }),
|
|
1980
2121
|
/* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
|
|
1981
|
-
/* @__PURE__ */
|
|
2122
|
+
/* @__PURE__ */ jsx10(Label, { htmlFor: "format", children: t("posts.form.format") }),
|
|
1982
2123
|
/* @__PURE__ */ jsxs9(
|
|
1983
2124
|
"select",
|
|
1984
2125
|
{
|
|
@@ -1987,34 +2128,34 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
1987
2128
|
onChange: (e) => changeFormat(e.target.value),
|
|
1988
2129
|
className: "flex h-9 w-full max-w-xs rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm",
|
|
1989
2130
|
children: [
|
|
1990
|
-
/* @__PURE__ */
|
|
1991
|
-
/* @__PURE__ */
|
|
1992
|
-
/* @__PURE__ */
|
|
1993
|
-
/* @__PURE__ */
|
|
2131
|
+
/* @__PURE__ */ jsx10("option", { value: "tiptap", children: "Tiptap (rich editor)" }),
|
|
2132
|
+
/* @__PURE__ */ jsx10("option", { value: "markdown", children: "Markdown" }),
|
|
2133
|
+
/* @__PURE__ */ jsx10("option", { value: "html", children: "HTML" }),
|
|
2134
|
+
/* @__PURE__ */ jsx10("option", { value: "static", children: t("posts.form.formatStaticLabel") })
|
|
1994
2135
|
]
|
|
1995
2136
|
}
|
|
1996
2137
|
),
|
|
1997
|
-
/* @__PURE__ */
|
|
2138
|
+
/* @__PURE__ */ jsx10("p", { className: "text-xs text-muted-foreground", children: t("posts.form.formatHint") })
|
|
1998
2139
|
] }),
|
|
1999
2140
|
/* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
|
|
2000
2141
|
/* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between", children: [
|
|
2001
|
-
/* @__PURE__ */
|
|
2142
|
+
/* @__PURE__ */ jsx10(Label, { children: t("posts.form.body") }),
|
|
2002
2143
|
format !== "tiptap" && format !== "static" && // For textarea-based formats (markdown / html) there's no
|
|
2003
2144
|
// embedded toolbar, so we surface the MediaPicker as a
|
|
2004
2145
|
// standalone button. Selecting an asset inserts a
|
|
2005
2146
|
// format-aware snippet at the cursor.
|
|
2006
|
-
/* @__PURE__ */
|
|
2147
|
+
/* @__PURE__ */ jsx10(
|
|
2007
2148
|
MediaPicker,
|
|
2008
2149
|
{
|
|
2009
2150
|
onSelect: insertMediaSnippet,
|
|
2010
2151
|
trigger: /* @__PURE__ */ jsxs9(Button7, { type: "button", variant: "outline", size: "sm", children: [
|
|
2011
|
-
/* @__PURE__ */
|
|
2152
|
+
/* @__PURE__ */ jsx10(ImageIcon3, { className: "mr-2 h-3 w-3" }),
|
|
2012
2153
|
t("posts.form.insertMedia")
|
|
2013
2154
|
] })
|
|
2014
2155
|
}
|
|
2015
2156
|
)
|
|
2016
2157
|
] }),
|
|
2017
|
-
format === "tiptap" ? /* @__PURE__ */
|
|
2158
|
+
format === "tiptap" ? /* @__PURE__ */ jsx10(
|
|
2018
2159
|
TiptapEditor,
|
|
2019
2160
|
{
|
|
2020
2161
|
initialContent: body,
|
|
@@ -2022,14 +2163,14 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
2022
2163
|
onUserEdit: markDirty
|
|
2023
2164
|
},
|
|
2024
2165
|
editorEpoch
|
|
2025
|
-
) : format === "static" ? /* @__PURE__ */
|
|
2166
|
+
) : format === "static" ? /* @__PURE__ */ jsx10(
|
|
2026
2167
|
StaticUploader,
|
|
2027
2168
|
{
|
|
2028
2169
|
initial: initialStaticBody,
|
|
2029
2170
|
onFilesReady: (files, entrypoint) => setPendingBundle({ files, entrypoint }),
|
|
2030
2171
|
onClear: () => setPendingBundle(null)
|
|
2031
2172
|
}
|
|
2032
|
-
) : /* @__PURE__ */
|
|
2173
|
+
) : /* @__PURE__ */ jsx10(
|
|
2033
2174
|
Textarea,
|
|
2034
2175
|
{
|
|
2035
2176
|
ref: bodyTextareaRef,
|
|
@@ -2044,8 +2185,8 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
2044
2185
|
)
|
|
2045
2186
|
] }),
|
|
2046
2187
|
/* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
|
|
2047
|
-
/* @__PURE__ */
|
|
2048
|
-
/* @__PURE__ */
|
|
2188
|
+
/* @__PURE__ */ jsx10(Label, { htmlFor: "tags", children: t("posts.form.tags") }),
|
|
2189
|
+
/* @__PURE__ */ jsx10(
|
|
2049
2190
|
Input2,
|
|
2050
2191
|
{
|
|
2051
2192
|
id: "tags",
|
|
@@ -2057,10 +2198,10 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
2057
2198
|
placeholder: t("posts.form.tagsPlaceholder")
|
|
2058
2199
|
}
|
|
2059
2200
|
),
|
|
2060
|
-
/* @__PURE__ */
|
|
2201
|
+
/* @__PURE__ */ jsx10("p", { className: "text-xs text-muted-foreground", children: t("posts.form.tagsHint") })
|
|
2061
2202
|
] }),
|
|
2062
2203
|
/* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
|
|
2063
|
-
/* @__PURE__ */
|
|
2204
|
+
/* @__PURE__ */ jsx10(Label, { htmlFor: "status", children: t("posts.form.status") }),
|
|
2064
2205
|
/* @__PURE__ */ jsxs9(
|
|
2065
2206
|
"select",
|
|
2066
2207
|
{
|
|
@@ -2072,15 +2213,15 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
2072
2213
|
},
|
|
2073
2214
|
className: "flex h-9 w-full max-w-xs rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm",
|
|
2074
2215
|
children: [
|
|
2075
|
-
/* @__PURE__ */
|
|
2076
|
-
/* @__PURE__ */
|
|
2216
|
+
/* @__PURE__ */ jsx10("option", { value: "draft", children: t("common.draft") }),
|
|
2217
|
+
/* @__PURE__ */ jsx10("option", { value: "published", children: t("common.published") })
|
|
2077
2218
|
]
|
|
2078
2219
|
}
|
|
2079
2220
|
)
|
|
2080
2221
|
] }),
|
|
2081
2222
|
/* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
|
|
2082
|
-
/* @__PURE__ */
|
|
2083
|
-
/* @__PURE__ */
|
|
2223
|
+
/* @__PURE__ */ jsx10(Label, { htmlFor: "publishedAt", children: t("posts.form.publishedAt") }),
|
|
2224
|
+
/* @__PURE__ */ jsx10(
|
|
2084
2225
|
"input",
|
|
2085
2226
|
{
|
|
2086
2227
|
id: "publishedAt",
|
|
@@ -2093,11 +2234,11 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
2093
2234
|
className: "flex h-9 w-full max-w-xs rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm"
|
|
2094
2235
|
}
|
|
2095
2236
|
),
|
|
2096
|
-
/* @__PURE__ */
|
|
2097
|
-
status === "published" && isFuture(resolvedPublishedAt) && /* @__PURE__ */
|
|
2237
|
+
/* @__PURE__ */ jsx10("p", { className: "text-xs text-muted-foreground", children: t("posts.form.publishedAtHint") }),
|
|
2238
|
+
status === "published" && isFuture(resolvedPublishedAt) && /* @__PURE__ */ jsx10("p", { className: "text-xs text-amber-600 dark:text-amber-400", children: t("posts.form.scheduledNotice", { date: publishedAtInput }) })
|
|
2098
2239
|
] }),
|
|
2099
|
-
format === "html" && /* @__PURE__ */
|
|
2100
|
-
/* @__PURE__ */
|
|
2240
|
+
format === "html" && /* @__PURE__ */ jsx10("div", { className: "space-y-2", children: /* @__PURE__ */ jsxs9("label", { className: "flex items-start gap-2 text-sm", children: [
|
|
2241
|
+
/* @__PURE__ */ jsx10(
|
|
2101
2242
|
"input",
|
|
2102
2243
|
{
|
|
2103
2244
|
type: "checkbox",
|
|
@@ -2110,16 +2251,16 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
2110
2251
|
}
|
|
2111
2252
|
),
|
|
2112
2253
|
/* @__PURE__ */ jsxs9("span", { children: [
|
|
2113
|
-
/* @__PURE__ */
|
|
2114
|
-
/* @__PURE__ */
|
|
2254
|
+
/* @__PURE__ */ jsx10("span", { className: "font-medium", children: t("posts.form.noLayout") }),
|
|
2255
|
+
/* @__PURE__ */ jsx10("span", { className: "block text-xs text-muted-foreground", children: t("posts.form.noLayoutHint") })
|
|
2115
2256
|
] })
|
|
2116
2257
|
] }) }),
|
|
2117
|
-
error && /* @__PURE__ */
|
|
2258
|
+
error && /* @__PURE__ */ jsx10("p", { className: "text-sm text-destructive", children: error }),
|
|
2118
2259
|
/* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2", children: [
|
|
2119
|
-
/* @__PURE__ */
|
|
2120
|
-
isEdit && /* @__PURE__ */
|
|
2260
|
+
/* @__PURE__ */ jsx10(Button7, { type: "submit", disabled: saving, children: saving ? t("common.saving") : isEdit ? t("posts.form.saveChanges") : t("posts.form.createPost") }),
|
|
2261
|
+
isEdit && /* @__PURE__ */ jsx10(Button7, { type: "button", variant: "destructive", onClick: handleDelete, disabled: saving, children: t("posts.form.delete") })
|
|
2121
2262
|
] }),
|
|
2122
|
-
isEdit && post && /* @__PURE__ */
|
|
2263
|
+
isEdit && post && /* @__PURE__ */ jsx10(
|
|
2123
2264
|
PostHistoryPanel,
|
|
2124
2265
|
{
|
|
2125
2266
|
postId: post.postId,
|
|
@@ -2133,6 +2274,7 @@ function PostForm({ post, previewEndpoint = "/admin/preview" }) {
|
|
|
2133
2274
|
|
|
2134
2275
|
export {
|
|
2135
2276
|
MediaPicker,
|
|
2277
|
+
TableClassesProvider,
|
|
2136
2278
|
clearAllDrafts,
|
|
2137
2279
|
PostForm
|
|
2138
2280
|
};
|