@ampless/admin 0.2.0-alpha.22 → 0.2.0-alpha.23

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 (32) hide show
  1. package/dist/api/index.d.ts +1 -1
  2. package/dist/{chunk-W6BXESPW.js → chunk-2U3POKAZ.js} +1 -1
  3. package/dist/{chunk-5Q6KVRZ2.js → chunk-6NPYUTV6.js} +2 -2
  4. package/dist/{chunk-CQY55RDG.js → chunk-6SB7YICQ.js} +1 -1
  5. package/dist/{chunk-JOASK4AM.js → chunk-CFQPS5NT.js} +1 -1
  6. package/dist/{chunk-S66L5CDS.js → chunk-CTGFMK2J.js} +1 -1
  7. package/dist/{chunk-A3SWBQA6.js → chunk-F7VFVKY5.js} +1 -1
  8. package/dist/{chunk-BC4B6DLO.js → chunk-G4IY757H.js} +2 -2
  9. package/dist/{chunk-QXJIIBUQ.js → chunk-KQOE5CT6.js} +2 -2
  10. package/dist/{chunk-CVJCMTYB.js → chunk-LITTIDB3.js} +397 -152
  11. package/dist/{chunk-XY4JWSMS.js → chunk-Q66BLMNJ.js} +1 -1
  12. package/dist/{chunk-SRNH2IVA.js → chunk-TZ5F24BG.js} +1 -1
  13. package/dist/{chunk-ILSBPHVE.js → chunk-V5FWGILB.js} +2 -2
  14. package/dist/{chunk-OSUTPPAU.js → chunk-WL4IBW2D.js} +24 -0
  15. package/dist/{chunk-5JKOPRCO.js → chunk-WOMPYZNV.js} +2 -2
  16. package/dist/components/admin-dashboard.js +3 -3
  17. package/dist/components/edit-post-view.js +5 -5
  18. package/dist/components/index.d.ts +1 -1
  19. package/dist/components/index.js +6 -6
  20. package/dist/components/login-view.js +3 -3
  21. package/dist/components/mcp-tokens-view.js +3 -3
  22. package/dist/components/media-view.js +5 -5
  23. package/dist/components/new-post-view.js +5 -5
  24. package/dist/components/posts-list-view.js +3 -3
  25. package/dist/components/users-list-view.js +3 -3
  26. package/dist/{i18n-MWvAMHzn.d.ts → i18n-BhMBRfio.d.ts} +36 -0
  27. package/dist/index.d.ts +2 -2
  28. package/dist/index.js +1 -1
  29. package/dist/metafile-esm.json +1 -1
  30. package/dist/pages/index.d.ts +1 -1
  31. package/dist/pages/index.js +14 -14
  32. package/package.json +17 -8
@@ -5,13 +5,13 @@ import {
5
5
  import {
6
6
  ImageUploadDialog,
7
7
  getMediaProcessingDefaults
8
- } from "./chunk-S66L5CDS.js";
8
+ } from "./chunk-CTGFMK2J.js";
9
9
  import {
10
10
  publicMediaUrl
11
11
  } from "./chunk-2ITWLRYF.js";
12
12
  import {
13
13
  useT
14
- } from "./chunk-XY4JWSMS.js";
14
+ } from "./chunk-Q66BLMNJ.js";
15
15
 
16
16
  // src/lib/upload.ts
17
17
  import { uploadData } from "aws-amplify/storage";
@@ -177,7 +177,7 @@ function MediaPicker({ trigger, onSelect }) {
177
177
  }
178
178
 
179
179
  // src/components/post-form.tsx
180
- import { useRef as useRef2, useState as useState3 } from "react";
180
+ import { useRef as useRef3, useState as useState4 } from "react";
181
181
  import { useRouter } from "next/navigation";
182
182
  import { Image as ImageIcon3 } from "lucide-react";
183
183
  import {
@@ -193,39 +193,197 @@ import {
193
193
  markdownToHtml,
194
194
  htmlToMarkdown
195
195
  } from "@ampless/runtime";
196
- import { Button as Button5, Input, Label, Textarea } from "@ampless/runtime/ui";
196
+ import { Button as Button6, Input, Label, Textarea } from "@ampless/runtime/ui";
197
197
 
198
198
  // src/editor/tiptap-editor.tsx
199
199
  import { useEditor, EditorContent } from "@tiptap/react";
200
200
  import StarterKit from "@tiptap/starter-kit";
201
201
  import Link from "@tiptap/extension-link";
202
202
  import Image from "@tiptap/extension-image";
203
+ import { Table } from "@tiptap/extension-table";
204
+ import { TableRow } from "@tiptap/extension-table-row";
205
+ import { TableHeader } from "@tiptap/extension-table-header";
206
+ import { TableCell } from "@tiptap/extension-table-cell";
207
+ import { TaskList } from "@tiptap/extension-task-list";
208
+ import { TaskItem } from "@tiptap/extension-task-item";
209
+ import { Underline as Underline2 } from "@tiptap/extension-underline";
210
+ import { Highlight } from "@tiptap/extension-highlight";
211
+ import { TextAlign } from "@tiptap/extension-text-align";
203
212
 
204
213
  // src/editor/toolbar.tsx
205
214
  import {
206
215
  Bold,
207
216
  Italic,
217
+ Underline,
218
+ Strikethrough,
219
+ Highlighter,
208
220
  Heading1,
209
221
  Heading2,
210
222
  List,
211
223
  ListOrdered,
224
+ ListChecks,
212
225
  Code,
226
+ Quote,
227
+ Minus,
228
+ TextAlignStart,
229
+ TextAlignCenter,
230
+ TextAlignEnd,
231
+ TextAlignJustify,
213
232
  Link as LinkIcon,
214
233
  Image as ImageIcon
215
234
  } from "lucide-react";
235
+ import { Button as Button3, cn as cn2 } from "@ampless/runtime/ui";
236
+
237
+ // src/editor/table-controls.tsx
238
+ import { useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
239
+ import { Table as TableIcon } from "lucide-react";
216
240
  import { Button as Button2, cn } from "@ampless/runtime/ui";
217
241
  import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
242
+ function TableControls({ editor }) {
243
+ const t = useT();
244
+ const [open, setOpen] = useState2(false);
245
+ const rootRef = useRef2(null);
246
+ useEffect2(() => {
247
+ if (!open) return;
248
+ function onPointerDown(e) {
249
+ if (!rootRef.current) return;
250
+ if (e.target instanceof Node && rootRef.current.contains(e.target)) return;
251
+ setOpen(false);
252
+ }
253
+ function onKey(e) {
254
+ if (e.key === "Escape") setOpen(false);
255
+ }
256
+ document.addEventListener("mousedown", onPointerDown);
257
+ document.addEventListener("keydown", onKey);
258
+ return () => {
259
+ document.removeEventListener("mousedown", onPointerDown);
260
+ document.removeEventListener("keydown", onKey);
261
+ };
262
+ }, [open]);
263
+ const inTable = editor.isActive("table");
264
+ const items = [
265
+ {
266
+ key: "insert",
267
+ label: t("editor.table.insert"),
268
+ run: () => editor.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run(),
269
+ enabled: !inTable
270
+ },
271
+ {
272
+ key: "addRowBefore",
273
+ label: t("editor.table.addRowBefore"),
274
+ run: () => editor.chain().focus().addRowBefore().run(),
275
+ enabled: inTable && editor.can().addRowBefore()
276
+ },
277
+ {
278
+ key: "addRowAfter",
279
+ label: t("editor.table.addRowAfter"),
280
+ run: () => editor.chain().focus().addRowAfter().run(),
281
+ enabled: inTable && editor.can().addRowAfter()
282
+ },
283
+ {
284
+ key: "addColumnBefore",
285
+ label: t("editor.table.addColumnBefore"),
286
+ run: () => editor.chain().focus().addColumnBefore().run(),
287
+ enabled: inTable && editor.can().addColumnBefore()
288
+ },
289
+ {
290
+ key: "addColumnAfter",
291
+ label: t("editor.table.addColumnAfter"),
292
+ run: () => editor.chain().focus().addColumnAfter().run(),
293
+ enabled: inTable && editor.can().addColumnAfter()
294
+ },
295
+ {
296
+ key: "deleteRow",
297
+ label: t("editor.table.deleteRow"),
298
+ run: () => editor.chain().focus().deleteRow().run(),
299
+ enabled: inTable && editor.can().deleteRow()
300
+ },
301
+ {
302
+ key: "deleteColumn",
303
+ label: t("editor.table.deleteColumn"),
304
+ run: () => editor.chain().focus().deleteColumn().run(),
305
+ enabled: inTable && editor.can().deleteColumn()
306
+ },
307
+ {
308
+ key: "toggleHeaderRow",
309
+ label: t("editor.table.toggleHeaderRow"),
310
+ run: () => editor.chain().focus().toggleHeaderRow().run(),
311
+ enabled: inTable && editor.can().toggleHeaderRow()
312
+ },
313
+ {
314
+ key: "deleteTable",
315
+ label: t("editor.table.deleteTable"),
316
+ run: () => editor.chain().focus().deleteTable().run(),
317
+ enabled: inTable && editor.can().deleteTable()
318
+ }
319
+ ];
320
+ return /* @__PURE__ */ jsxs2("div", { ref: rootRef, className: "relative", children: [
321
+ /* @__PURE__ */ jsx2(
322
+ Button2,
323
+ {
324
+ type: "button",
325
+ variant: "ghost",
326
+ size: "icon",
327
+ onClick: () => setOpen((v) => !v),
328
+ className: cn(inTable && "bg-accent text-accent-foreground"),
329
+ title: t("editor.table.title"),
330
+ "aria-expanded": open,
331
+ "aria-haspopup": "menu",
332
+ children: /* @__PURE__ */ jsx2(TableIcon, { className: "h-4 w-4" })
333
+ }
334
+ ),
335
+ open && /* @__PURE__ */ jsx2(
336
+ "div",
337
+ {
338
+ role: "menu",
339
+ className: "absolute left-0 top-full z-50 mt-1 min-w-[12rem] rounded-md border bg-popover p-1 shadow",
340
+ children: items.map((item) => /* @__PURE__ */ jsx2(
341
+ "button",
342
+ {
343
+ type: "button",
344
+ role: "menuitem",
345
+ disabled: !item.enabled,
346
+ onClick: () => {
347
+ if (!item.enabled) return;
348
+ item.run();
349
+ setOpen(false);
350
+ },
351
+ className: cn(
352
+ "block w-full rounded-sm px-2 py-1 text-left text-sm",
353
+ item.enabled ? "hover:bg-accent hover:text-accent-foreground" : "cursor-not-allowed text-muted-foreground opacity-50"
354
+ ),
355
+ children: item.label
356
+ },
357
+ item.key
358
+ ))
359
+ }
360
+ )
361
+ ] });
362
+ }
363
+
364
+ // src/editor/toolbar.tsx
365
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
218
366
  function Toolbar({ editor }) {
219
367
  const t = useT();
220
368
  if (!editor) return null;
221
369
  const tools = [
222
370
  { name: "bold", icon: Bold, action: () => editor.chain().focus().toggleBold().run(), isActive: () => editor.isActive("bold") },
223
371
  { name: "italic", icon: Italic, action: () => editor.chain().focus().toggleItalic().run(), isActive: () => editor.isActive("italic") },
372
+ { name: "underline", icon: Underline, action: () => editor.chain().focus().toggleUnderline().run(), isActive: () => editor.isActive("underline") },
373
+ { name: "strike", icon: Strikethrough, action: () => editor.chain().focus().toggleStrike().run(), isActive: () => editor.isActive("strike") },
374
+ { name: "highlight", icon: Highlighter, action: () => editor.chain().focus().toggleHighlight().run(), isActive: () => editor.isActive("highlight") },
224
375
  { name: "h1", icon: Heading1, action: () => editor.chain().focus().toggleHeading({ level: 1 }).run(), isActive: () => editor.isActive("heading", { level: 1 }) },
225
376
  { name: "h2", icon: Heading2, action: () => editor.chain().focus().toggleHeading({ level: 2 }).run(), isActive: () => editor.isActive("heading", { level: 2 }) },
226
377
  { name: "bulletList", icon: List, action: () => editor.chain().focus().toggleBulletList().run(), isActive: () => editor.isActive("bulletList") },
227
378
  { name: "orderedList", icon: ListOrdered, action: () => editor.chain().focus().toggleOrderedList().run(), isActive: () => editor.isActive("orderedList") },
228
- { name: "code", icon: Code, action: () => editor.chain().focus().toggleCodeBlock().run(), isActive: () => editor.isActive("codeBlock") }
379
+ { name: "taskList", icon: ListChecks, action: () => editor.chain().focus().toggleTaskList().run(), isActive: () => editor.isActive("taskList") },
380
+ { name: "code", icon: Code, action: () => editor.chain().focus().toggleCodeBlock().run(), isActive: () => editor.isActive("codeBlock") },
381
+ { name: "blockquote", icon: Quote, action: () => editor.chain().focus().toggleBlockquote().run(), isActive: () => editor.isActive("blockquote") },
382
+ { name: "hr", icon: Minus, action: () => editor.chain().focus().setHorizontalRule().run(), isActive: () => false },
383
+ { name: "alignLeft", icon: TextAlignStart, action: () => editor.chain().focus().setTextAlign("left").run(), isActive: () => editor.isActive({ textAlign: "left" }) },
384
+ { name: "alignCenter", icon: TextAlignCenter, action: () => editor.chain().focus().setTextAlign("center").run(), isActive: () => editor.isActive({ textAlign: "center" }) },
385
+ { name: "alignRight", icon: TextAlignEnd, action: () => editor.chain().focus().setTextAlign("right").run(), isActive: () => editor.isActive({ textAlign: "right" }) },
386
+ { name: "alignJustify", icon: TextAlignJustify, action: () => editor.chain().focus().setTextAlign("justify").run(), isActive: () => editor.isActive({ textAlign: "justify" }) }
229
387
  ];
230
388
  const setLink = () => {
231
389
  const previousUrl = editor.getAttributes("link").href ?? "";
@@ -240,48 +398,49 @@ function Toolbar({ editor }) {
240
398
  const insertImage = (url) => {
241
399
  editor.chain().focus().setImage({ src: url }).run();
242
400
  };
243
- return /* @__PURE__ */ jsxs2("div", { className: "flex flex-wrap gap-1 border-b p-2", children: [
401
+ return /* @__PURE__ */ jsxs3("div", { className: "flex flex-wrap gap-1 border-b p-2", children: [
244
402
  tools.map((tool) => {
245
403
  const Icon = tool.icon;
246
- return /* @__PURE__ */ jsx2(
247
- Button2,
404
+ return /* @__PURE__ */ jsx3(
405
+ Button3,
248
406
  {
249
407
  type: "button",
250
408
  variant: "ghost",
251
409
  size: "icon",
252
410
  onClick: tool.action,
253
- className: cn(tool.isActive() && "bg-accent text-accent-foreground"),
254
- children: /* @__PURE__ */ jsx2(Icon, { className: "h-4 w-4" })
411
+ className: cn2(tool.isActive() && "bg-accent text-accent-foreground"),
412
+ children: /* @__PURE__ */ jsx3(Icon, { className: "h-4 w-4" })
255
413
  },
256
414
  tool.name
257
415
  );
258
416
  }),
259
- /* @__PURE__ */ jsx2(
260
- Button2,
417
+ /* @__PURE__ */ jsx3(
418
+ Button3,
261
419
  {
262
420
  type: "button",
263
421
  variant: "ghost",
264
422
  size: "icon",
265
423
  onClick: setLink,
266
- className: cn(editor.isActive("link") && "bg-accent text-accent-foreground"),
267
- children: /* @__PURE__ */ jsx2(LinkIcon, { className: "h-4 w-4" })
424
+ className: cn2(editor.isActive("link") && "bg-accent text-accent-foreground"),
425
+ children: /* @__PURE__ */ jsx3(LinkIcon, { className: "h-4 w-4" })
268
426
  }
269
427
  ),
270
- /* @__PURE__ */ jsx2(
428
+ /* @__PURE__ */ jsx3(
271
429
  MediaPicker,
272
430
  {
273
431
  onSelect: insertImage,
274
- trigger: /* @__PURE__ */ jsx2(Button2, { type: "button", variant: "ghost", size: "icon", children: /* @__PURE__ */ jsx2(ImageIcon, { className: "h-4 w-4" }) })
432
+ trigger: /* @__PURE__ */ jsx3(Button3, { type: "button", variant: "ghost", size: "icon", children: /* @__PURE__ */ jsx3(ImageIcon, { className: "h-4 w-4" }) })
275
433
  }
276
- )
434
+ ),
435
+ /* @__PURE__ */ jsx3(TableControls, { editor })
277
436
  ] });
278
437
  }
279
438
 
280
439
  // src/editor/image-bubble-menu.tsx
281
440
  import { BubbleMenu } from "@tiptap/react/menus";
282
441
  import { Trash2, Pencil, ImageIcon as ImageIcon2, Maximize2 } from "lucide-react";
283
- import { Button as Button3, cn as cn2 } from "@ampless/runtime/ui";
284
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
442
+ import { Button as Button4, cn as cn3 } from "@ampless/runtime/ui";
443
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
285
444
  function ImageBubbleMenu({ editor }) {
286
445
  const t = useT();
287
446
  const editAlt = () => {
@@ -299,50 +458,50 @@ function ImageBubbleMenu({ editor }) {
299
458
  editor.chain().focus().updateAttributes("image", { display: next }).run();
300
459
  };
301
460
  const currentDisplay = editor.getAttributes("image").display ?? null;
302
- return /* @__PURE__ */ jsx3(
461
+ return /* @__PURE__ */ jsx4(
303
462
  BubbleMenu,
304
463
  {
305
464
  editor,
306
465
  shouldShow: ({ editor: editor2 }) => editor2.isActive("image"),
307
466
  options: { placement: "top" },
308
- children: /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-1 rounded-md border bg-popover p-1 shadow", children: [
309
- /* @__PURE__ */ jsxs3(
310
- Button3,
467
+ children: /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-1 rounded-md border bg-popover p-1 shadow", children: [
468
+ /* @__PURE__ */ jsxs4(
469
+ Button4,
311
470
  {
312
471
  type: "button",
313
472
  variant: "ghost",
314
473
  size: "sm",
315
474
  onClick: () => setDisplay("inline"),
316
- className: cn2(currentDisplay === "inline" && "bg-accent text-accent-foreground"),
475
+ className: cn3(currentDisplay === "inline" && "bg-accent text-accent-foreground"),
317
476
  title: t("editor.image.inlineTitle"),
318
477
  children: [
319
- /* @__PURE__ */ jsx3(ImageIcon2, { className: "mr-1 h-3 w-3" }),
478
+ /* @__PURE__ */ jsx4(ImageIcon2, { className: "mr-1 h-3 w-3" }),
320
479
  t("editor.image.inline")
321
480
  ]
322
481
  }
323
482
  ),
324
- /* @__PURE__ */ jsxs3(
325
- Button3,
483
+ /* @__PURE__ */ jsxs4(
484
+ Button4,
326
485
  {
327
486
  type: "button",
328
487
  variant: "ghost",
329
488
  size: "sm",
330
489
  onClick: () => setDisplay("lightbox"),
331
- className: cn2(currentDisplay === "lightbox" && "bg-accent text-accent-foreground"),
490
+ className: cn3(currentDisplay === "lightbox" && "bg-accent text-accent-foreground"),
332
491
  title: t("editor.image.lightboxTitle"),
333
492
  children: [
334
- /* @__PURE__ */ jsx3(Maximize2, { className: "mr-1 h-3 w-3" }),
493
+ /* @__PURE__ */ jsx4(Maximize2, { className: "mr-1 h-3 w-3" }),
335
494
  t("editor.image.lightbox")
336
495
  ]
337
496
  }
338
497
  ),
339
- /* @__PURE__ */ jsx3("span", { className: "mx-1 h-4 w-px bg-border" }),
340
- /* @__PURE__ */ jsxs3(Button3, { type: "button", variant: "ghost", size: "sm", onClick: editAlt, children: [
341
- /* @__PURE__ */ jsx3(Pencil, { className: "mr-1 h-3 w-3" }),
498
+ /* @__PURE__ */ jsx4("span", { className: "mx-1 h-4 w-px bg-border" }),
499
+ /* @__PURE__ */ jsxs4(Button4, { type: "button", variant: "ghost", size: "sm", onClick: editAlt, children: [
500
+ /* @__PURE__ */ jsx4(Pencil, { className: "mr-1 h-3 w-3" }),
342
501
  t("editor.image.alt")
343
502
  ] }),
344
- /* @__PURE__ */ jsxs3(Button3, { type: "button", variant: "ghost", size: "sm", onClick: remove2, children: [
345
- /* @__PURE__ */ jsx3(Trash2, { className: "mr-1 h-3 w-3" }),
503
+ /* @__PURE__ */ jsxs4(Button4, { type: "button", variant: "ghost", size: "sm", onClick: remove2, children: [
504
+ /* @__PURE__ */ jsx4(Trash2, { className: "mr-1 h-3 w-3" }),
346
505
  t("editor.image.delete")
347
506
  ] })
348
507
  ] })
@@ -351,7 +510,7 @@ function ImageBubbleMenu({ editor }) {
351
510
  }
352
511
 
353
512
  // src/editor/tiptap-editor.tsx
354
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
513
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
355
514
  var AmplessImage = Image.extend({
356
515
  addAttributes() {
357
516
  return {
@@ -367,12 +526,97 @@ var AmplessImage = Image.extend({
367
526
  };
368
527
  }
369
528
  });
529
+ var EDITOR_STYLES = `
530
+ .ProseMirror .tiptap-table,
531
+ .ProseMirror table {
532
+ border-collapse: collapse;
533
+ table-layout: fixed;
534
+ width: 100%;
535
+ margin: 0.75em 0;
536
+ overflow: hidden;
537
+ }
538
+ .ProseMirror .tiptap-table td,
539
+ .ProseMirror .tiptap-table th,
540
+ .ProseMirror table td,
541
+ .ProseMirror table th {
542
+ border: 1px solid var(--border);
543
+ padding: 0.4em 0.6em;
544
+ min-width: 1em;
545
+ vertical-align: top;
546
+ position: relative;
547
+ }
548
+ .ProseMirror .tiptap-table th,
549
+ .ProseMirror table th {
550
+ background: var(--muted);
551
+ font-weight: 600;
552
+ text-align: left;
553
+ }
554
+ .ProseMirror .tiptap-table .selectedCell,
555
+ .ProseMirror table .selectedCell {
556
+ background: var(--accent);
557
+ }
558
+ .ProseMirror .tableWrapper {
559
+ overflow-x: auto;
560
+ margin: 0.75em 0;
561
+ }
562
+ .ProseMirror .column-resize-handle {
563
+ position: absolute;
564
+ right: -2px;
565
+ top: 0;
566
+ bottom: 0;
567
+ width: 4px;
568
+ background: var(--ring);
569
+ pointer-events: none;
570
+ }
571
+ .ProseMirror.resize-cursor {
572
+ cursor: col-resize;
573
+ }
574
+
575
+ .ProseMirror ul[data-type='taskList'] {
576
+ list-style: none;
577
+ padding-left: 0;
578
+ }
579
+ .ProseMirror ul[data-type='taskList'] li {
580
+ display: flex;
581
+ align-items: flex-start;
582
+ gap: 0.5em;
583
+ }
584
+ .ProseMirror ul[data-type='taskList'] li > label {
585
+ flex: 0 0 auto;
586
+ margin-top: 0.25em;
587
+ user-select: none;
588
+ }
589
+ .ProseMirror ul[data-type='taskList'] li > div {
590
+ flex: 1 1 auto;
591
+ min-width: 0;
592
+ }
593
+ .ProseMirror ul[data-type='taskList'] li[data-checked='true'] > div {
594
+ text-decoration: line-through;
595
+ color: var(--muted-foreground);
596
+ }
597
+
598
+ .ProseMirror mark {
599
+ background: #fef08a;
600
+ color: inherit;
601
+ padding: 0 0.1em;
602
+ border-radius: 2px;
603
+ }
604
+ `;
370
605
  function TiptapEditor({ initialContent, onChange }) {
371
606
  const editor = useEditor({
372
607
  extensions: [
373
608
  StarterKit,
374
609
  Link.configure({ openOnClick: false }),
375
- AmplessImage.configure({ inline: false, allowBase64: false })
610
+ AmplessImage.configure({ inline: false, allowBase64: false }),
611
+ Table.configure({ resizable: true, HTMLAttributes: { class: "tiptap-table" } }),
612
+ TableRow,
613
+ TableHeader,
614
+ TableCell,
615
+ TaskList,
616
+ TaskItem.configure({ nested: true }),
617
+ Underline2,
618
+ Highlight.configure({ multicolor: false }),
619
+ TextAlign.configure({ types: ["heading", "paragraph"] })
376
620
  ],
377
621
  content: initialContent ?? { type: "doc", content: [{ type: "paragraph" }] },
378
622
  immediatelyRender: false,
@@ -388,17 +632,18 @@ function TiptapEditor({ initialContent, onChange }) {
388
632
  onChange?.(editor2.getJSON());
389
633
  }
390
634
  });
391
- return /* @__PURE__ */ jsxs4("div", { className: "rounded-md border", children: [
392
- /* @__PURE__ */ jsx4(Toolbar, { editor }),
393
- editor && /* @__PURE__ */ jsx4(ImageBubbleMenu, { editor }),
394
- /* @__PURE__ */ jsx4(EditorContent, { editor })
635
+ return /* @__PURE__ */ jsxs5("div", { className: "rounded-md border", children: [
636
+ /* @__PURE__ */ jsx5("style", { children: EDITOR_STYLES }),
637
+ /* @__PURE__ */ jsx5(Toolbar, { editor }),
638
+ editor && /* @__PURE__ */ jsx5(ImageBubbleMenu, { editor }),
639
+ /* @__PURE__ */ jsx5(EditorContent, { editor })
395
640
  ] });
396
641
  }
397
642
 
398
643
  // src/components/static-uploader.tsx
399
- import { useState as useState2 } from "react";
644
+ import { useState as useState3 } from "react";
400
645
  import { FileText, AlertTriangle, FileArchive, X } from "lucide-react";
401
- import { Button as Button4 } from "@ampless/runtime/ui";
646
+ import { Button as Button5 } from "@ampless/runtime/ui";
402
647
 
403
648
  // src/lib/static-bundle.ts
404
649
  import JSZip from "jszip";
@@ -590,13 +835,13 @@ function pickDefaultEntrypoint(files) {
590
835
  }
591
836
 
592
837
  // src/components/static-uploader.tsx
593
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
838
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
594
839
  function StaticUploader({ initial, onFilesReady, onClear }) {
595
840
  const t = useT();
596
- const [pending, setPending] = useState2(null);
597
- const [issues, setIssues] = useState2([]);
598
- const [busy, setBusy] = useState2(false);
599
- const [error, setError] = useState2(null);
841
+ const [pending, setPending] = useState3(null);
842
+ const [issues, setIssues] = useState3([]);
843
+ const [busy, setBusy] = useState3(false);
844
+ const [error, setError] = useState3(null);
600
845
  async function handleZip(file) {
601
846
  setBusy(true);
602
847
  setError(null);
@@ -670,11 +915,11 @@ function StaticUploader({ initial, onFilesReady, onClear }) {
670
915
  onClear();
671
916
  }
672
917
  const showCurrent = !pending && initial && initial.files.length > 0;
673
- return /* @__PURE__ */ jsxs5("div", { className: "space-y-4", children: [
674
- /* @__PURE__ */ jsxs5("div", { className: "rounded-md border border-dashed p-4", children: [
675
- /* @__PURE__ */ jsxs5("label", { className: "flex flex-col items-start gap-2 text-sm", children: [
676
- /* @__PURE__ */ jsx5("span", { className: "font-medium", children: t("posts.form.static.pick") }),
677
- /* @__PURE__ */ jsx5(
918
+ return /* @__PURE__ */ jsxs6("div", { className: "space-y-4", children: [
919
+ /* @__PURE__ */ jsxs6("div", { className: "rounded-md border border-dashed p-4", children: [
920
+ /* @__PURE__ */ jsxs6("label", { className: "flex flex-col items-start gap-2 text-sm", children: [
921
+ /* @__PURE__ */ jsx6("span", { className: "font-medium", children: t("posts.form.static.pick") }),
922
+ /* @__PURE__ */ jsx6(
678
923
  "input",
679
924
  {
680
925
  type: "file",
@@ -684,13 +929,13 @@ function StaticUploader({ initial, onFilesReady, onClear }) {
684
929
  disabled: busy
685
930
  }
686
931
  ),
687
- /* @__PURE__ */ jsx5("span", { className: "text-xs text-muted-foreground", children: t("posts.form.static.pickHint") })
932
+ /* @__PURE__ */ jsx6("span", { className: "text-xs text-muted-foreground", children: t("posts.form.static.pickHint") })
688
933
  ] }),
689
- busy && /* @__PURE__ */ jsx5("p", { className: "mt-2 text-sm text-muted-foreground", children: t("common.loading") }),
690
- error && /* @__PURE__ */ jsx5("p", { className: "mt-2 text-sm text-destructive", children: error })
934
+ busy && /* @__PURE__ */ jsx6("p", { className: "mt-2 text-sm text-muted-foreground", children: t("common.loading") }),
935
+ error && /* @__PURE__ */ jsx6("p", { className: "mt-2 text-sm text-destructive", children: error })
691
936
  ] }),
692
- showCurrent && /* @__PURE__ */ jsx5(CurrentBundle, { body: initial }),
693
- pending && /* @__PURE__ */ jsx5(
937
+ showCurrent && /* @__PURE__ */ jsx6(CurrentBundle, { body: initial }),
938
+ pending && /* @__PURE__ */ jsx6(
694
939
  PendingBundle,
695
940
  {
696
941
  files: pending,
@@ -702,15 +947,15 @@ function StaticUploader({ initial, onFilesReady, onClear }) {
702
947
  }
703
948
  function CurrentBundle({ body }) {
704
949
  const t = useT();
705
- return /* @__PURE__ */ jsxs5("div", { className: "rounded-md border bg-muted/30 p-3", children: [
706
- /* @__PURE__ */ jsxs5("div", { className: "mb-2 flex items-center gap-2 text-sm font-medium", children: [
707
- /* @__PURE__ */ jsx5(FileArchive, { className: "h-4 w-4" }),
950
+ return /* @__PURE__ */ jsxs6("div", { className: "rounded-md border bg-muted/30 p-3", children: [
951
+ /* @__PURE__ */ jsxs6("div", { className: "mb-2 flex items-center gap-2 text-sm font-medium", children: [
952
+ /* @__PURE__ */ jsx6(FileArchive, { className: "h-4 w-4" }),
708
953
  t("posts.form.static.currentBundle", {
709
954
  count: body.files.length,
710
955
  entrypoint: body.entrypoint
711
956
  })
712
957
  ] }),
713
- /* @__PURE__ */ jsx5(FileList, { files: body.files })
958
+ /* @__PURE__ */ jsx6(FileList, { files: body.files })
714
959
  ] });
715
960
  }
716
961
  function PendingBundle({
@@ -720,49 +965,49 @@ function PendingBundle({
720
965
  }) {
721
966
  const t = useT();
722
967
  const totalBytes = files.reduce((sum, f) => sum + f.data.byteLength, 0);
723
- return /* @__PURE__ */ jsxs5("div", { className: "rounded-md border p-3", children: [
724
- /* @__PURE__ */ jsxs5("div", { className: "mb-2 flex items-center justify-between gap-2 text-sm font-medium", children: [
725
- /* @__PURE__ */ jsxs5("span", { className: "flex items-center gap-2", children: [
726
- /* @__PURE__ */ jsx5(FileArchive, { className: "h-4 w-4" }),
968
+ return /* @__PURE__ */ jsxs6("div", { className: "rounded-md border p-3", children: [
969
+ /* @__PURE__ */ jsxs6("div", { className: "mb-2 flex items-center justify-between gap-2 text-sm font-medium", children: [
970
+ /* @__PURE__ */ jsxs6("span", { className: "flex items-center gap-2", children: [
971
+ /* @__PURE__ */ jsx6(FileArchive, { className: "h-4 w-4" }),
727
972
  t("posts.form.static.pendingBundle", {
728
973
  count: files.length,
729
974
  size: formatBytes(totalBytes)
730
975
  })
731
976
  ] }),
732
- /* @__PURE__ */ jsxs5(Button4, { type: "button", variant: "ghost", size: "sm", onClick: onClear, children: [
733
- /* @__PURE__ */ jsx5(X, { className: "mr-1 h-3 w-3" }),
977
+ /* @__PURE__ */ jsxs6(Button5, { type: "button", variant: "ghost", size: "sm", onClick: onClear, children: [
978
+ /* @__PURE__ */ jsx6(X, { className: "mr-1 h-3 w-3" }),
734
979
  t("common.cancel")
735
980
  ] })
736
981
  ] }),
737
- issues.length > 0 && /* @__PURE__ */ jsxs5("div", { className: "mb-3 rounded-md border border-destructive/40 bg-destructive/5 p-2 text-sm", children: [
738
- /* @__PURE__ */ jsxs5("div", { className: "mb-1 flex items-center gap-2 font-medium text-destructive", children: [
739
- /* @__PURE__ */ jsx5(AlertTriangle, { className: "h-4 w-4" }),
982
+ issues.length > 0 && /* @__PURE__ */ jsxs6("div", { className: "mb-3 rounded-md border border-destructive/40 bg-destructive/5 p-2 text-sm", children: [
983
+ /* @__PURE__ */ jsxs6("div", { className: "mb-1 flex items-center gap-2 font-medium text-destructive", children: [
984
+ /* @__PURE__ */ jsx6(AlertTriangle, { className: "h-4 w-4" }),
740
985
  t("posts.form.static.issuesTitle", { count: issues.length })
741
986
  ] }),
742
- /* @__PURE__ */ jsxs5("ul", { className: "space-y-0.5 text-xs", children: [
743
- issues.slice(0, 20).map((issue, idx) => /* @__PURE__ */ jsxs5("li", { className: "font-mono", children: [
987
+ /* @__PURE__ */ jsxs6("ul", { className: "space-y-0.5 text-xs", children: [
988
+ issues.slice(0, 20).map((issue, idx) => /* @__PURE__ */ jsxs6("li", { className: "font-mono", children: [
744
989
  issue.path,
745
990
  ": ",
746
991
  issue.reason
747
992
  ] }, `${issue.path}-${idx}`)),
748
- issues.length > 20 && /* @__PURE__ */ jsxs5("li", { className: "font-mono text-muted-foreground", children: [
993
+ issues.length > 20 && /* @__PURE__ */ jsxs6("li", { className: "font-mono text-muted-foreground", children: [
749
994
  "\u2026 ",
750
995
  issues.length - 20,
751
996
  " more"
752
997
  ] })
753
998
  ] }),
754
- /* @__PURE__ */ jsx5("p", { className: "mt-2 text-xs text-muted-foreground", children: t("posts.form.static.issuesHint") })
999
+ /* @__PURE__ */ jsx6("p", { className: "mt-2 text-xs text-muted-foreground", children: t("posts.form.static.issuesHint") })
755
1000
  ] }),
756
- /* @__PURE__ */ jsx5(FileList, { files: files.map((f) => f.path) })
1001
+ /* @__PURE__ */ jsx6(FileList, { files: files.map((f) => f.path) })
757
1002
  ] });
758
1003
  }
759
1004
  function FileList({ files }) {
760
- return /* @__PURE__ */ jsxs5("ul", { className: "space-y-0.5 text-xs", children: [
761
- files.slice(0, 40).map((path) => /* @__PURE__ */ jsxs5("li", { className: "flex items-center gap-1.5 font-mono text-muted-foreground", children: [
762
- /* @__PURE__ */ jsx5(FileText, { className: "h-3 w-3 shrink-0" }),
1005
+ return /* @__PURE__ */ jsxs6("ul", { className: "space-y-0.5 text-xs", children: [
1006
+ files.slice(0, 40).map((path) => /* @__PURE__ */ jsxs6("li", { className: "flex items-center gap-1.5 font-mono text-muted-foreground", children: [
1007
+ /* @__PURE__ */ jsx6(FileText, { className: "h-3 w-3 shrink-0" }),
763
1008
  path
764
1009
  ] }, path)),
765
- files.length > 40 && /* @__PURE__ */ jsxs5("li", { className: "font-mono text-xs text-muted-foreground", children: [
1010
+ files.length > 40 && /* @__PURE__ */ jsxs6("li", { className: "font-mono text-xs text-muted-foreground", children: [
766
1011
  "\u2026 ",
767
1012
  files.length - 40,
768
1013
  " more"
@@ -785,7 +1030,7 @@ function guessEntrypoint(files) {
785
1030
  }
786
1031
 
787
1032
  // src/components/post-form.tsx
788
- import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1033
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
789
1034
  var EMPTY_TIPTAP_DOC = { type: "doc", content: [{ type: "paragraph" }] };
790
1035
  var IMAGE_URL_RE = /\.(jpe?g|png|gif|webp|avif|svg|bmp|tiff?)(\?|$)/i;
791
1036
  var STYLESHEET_URL_RE = /\.css(\?|$)/i;
@@ -815,19 +1060,19 @@ function PostForm({ post }) {
815
1060
  const router = useRouter();
816
1061
  const t = useT();
817
1062
  const isEdit = !!post;
818
- const bodyTextareaRef = useRef2(null);
819
- const [title, setTitle] = useState3(post?.title ?? "");
820
- const [slug, setSlug] = useState3(post?.slug ?? "");
821
- const [excerpt, setExcerpt] = useState3(post?.excerpt ?? "");
822
- const [format, setFormat] = useState3(post?.format ?? "tiptap");
823
- const [body, setBody] = useState3(post?.body ?? EMPTY_TIPTAP_DOC);
824
- const [status, setStatus] = useState3(post?.status ?? "draft");
825
- const [tagsInput, setTagsInput] = useState3((post?.tags ?? []).join(", "));
826
- const [noLayout, setNoLayout] = useState3(post?.metadata?.no_layout === true);
827
- const [saving, setSaving] = useState3(false);
828
- const [error, setError] = useState3(null);
829
- const [view, setView] = useState3("edit");
830
- const [pendingBundle, setPendingBundle] = useState3(null);
1063
+ const bodyTextareaRef = useRef3(null);
1064
+ const [title, setTitle] = useState4(post?.title ?? "");
1065
+ const [slug, setSlug] = useState4(post?.slug ?? "");
1066
+ const [excerpt, setExcerpt] = useState4(post?.excerpt ?? "");
1067
+ const [format, setFormat] = useState4(post?.format ?? "tiptap");
1068
+ const [body, setBody] = useState4(post?.body ?? EMPTY_TIPTAP_DOC);
1069
+ const [status, setStatus] = useState4(post?.status ?? "draft");
1070
+ const [tagsInput, setTagsInput] = useState4((post?.tags ?? []).join(", "));
1071
+ const [noLayout, setNoLayout] = useState4(post?.metadata?.no_layout === true);
1072
+ const [saving, setSaving] = useState4(false);
1073
+ const [error, setError] = useState4(null);
1074
+ const [view, setView] = useState4("edit");
1075
+ const [pendingBundle, setPendingBundle] = useState4(null);
831
1076
  const initialStaticBody = isStaticBody(post?.body) ? post.body : null;
832
1077
  function buildMetadata() {
833
1078
  const next = { ...post?.metadata ?? {} };
@@ -988,9 +1233,9 @@ function PostForm({ post }) {
988
1233
  publishedAt: status === "published" ? post?.publishedAt ?? (/* @__PURE__ */ new Date()).toISOString() : void 0,
989
1234
  tags: parseTags(tagsInput)
990
1235
  };
991
- return /* @__PURE__ */ jsxs6("form", { onSubmit: save, className: "space-y-6", children: [
992
- /* @__PURE__ */ jsxs6("div", { className: "flex gap-1 border-b", children: [
993
- /* @__PURE__ */ jsx6(
1236
+ return /* @__PURE__ */ jsxs7("form", { onSubmit: save, className: "space-y-6", children: [
1237
+ /* @__PURE__ */ jsxs7("div", { className: "flex gap-1 border-b", children: [
1238
+ /* @__PURE__ */ jsx7(
994
1239
  "button",
995
1240
  {
996
1241
  type: "button",
@@ -1000,7 +1245,7 @@ function PostForm({ post }) {
1000
1245
  children: t("posts.form.tabEdit")
1001
1246
  }
1002
1247
  ),
1003
- /* @__PURE__ */ jsx6(
1248
+ /* @__PURE__ */ jsx7(
1004
1249
  "button",
1005
1250
  {
1006
1251
  type: "button",
@@ -1011,24 +1256,24 @@ function PostForm({ post }) {
1011
1256
  }
1012
1257
  )
1013
1258
  ] }),
1014
- view === "preview" && /* @__PURE__ */ jsxs6("article", { className: "space-y-4", children: [
1015
- /* @__PURE__ */ jsxs6("header", { className: "border-b pb-4", children: [
1016
- /* @__PURE__ */ jsx6("h1", { className: "text-3xl font-bold tracking-tight", children: title || /* @__PURE__ */ jsx6("span", { className: "text-muted-foreground italic", children: t("posts.form.previewNoTitle") }) }),
1017
- /* @__PURE__ */ jsxs6("p", { className: "mt-2 text-sm text-muted-foreground", children: [
1018
- previewPost.publishedAt ? /* @__PURE__ */ jsx6("time", { dateTime: previewPost.publishedAt, children: formatDate(previewPost.publishedAt) }) : /* @__PURE__ */ jsx6("span", { children: t("common.draft") }),
1019
- /* @__PURE__ */ jsx6("span", { className: "mx-2", children: "\xB7" }),
1020
- /* @__PURE__ */ jsx6("span", { className: "font-mono text-xs uppercase", children: format })
1259
+ view === "preview" && /* @__PURE__ */ jsxs7("article", { className: "space-y-4", children: [
1260
+ /* @__PURE__ */ jsxs7("header", { className: "border-b pb-4", children: [
1261
+ /* @__PURE__ */ jsx7("h1", { className: "text-3xl font-bold tracking-tight", children: title || /* @__PURE__ */ jsx7("span", { className: "text-muted-foreground italic", children: t("posts.form.previewNoTitle") }) }),
1262
+ /* @__PURE__ */ jsxs7("p", { className: "mt-2 text-sm text-muted-foreground", children: [
1263
+ previewPost.publishedAt ? /* @__PURE__ */ jsx7("time", { dateTime: previewPost.publishedAt, children: formatDate(previewPost.publishedAt) }) : /* @__PURE__ */ jsx7("span", { children: t("common.draft") }),
1264
+ /* @__PURE__ */ jsx7("span", { className: "mx-2", children: "\xB7" }),
1265
+ /* @__PURE__ */ jsx7("span", { className: "font-mono text-xs uppercase", children: format })
1021
1266
  ] }),
1022
- excerpt && /* @__PURE__ */ jsx6("p", { className: "mt-3 text-base text-muted-foreground", children: excerpt })
1267
+ excerpt && /* @__PURE__ */ jsx7("p", { className: "mt-3 text-base text-muted-foreground", children: excerpt })
1023
1268
  ] }),
1024
- format === "static" ? /* @__PURE__ */ jsx6("p", { className: "text-sm text-muted-foreground", children: t("posts.form.static.previewHint") }) : /* @__PURE__ */ jsx6(
1269
+ format === "static" ? /* @__PURE__ */ jsx7("p", { className: "text-sm text-muted-foreground", children: t("posts.form.static.previewHint") }) : /* @__PURE__ */ jsx7(
1025
1270
  "div",
1026
1271
  {
1027
1272
  className: "prose prose-neutral dark:prose-invert max-w-none",
1028
1273
  dangerouslySetInnerHTML: { __html: renderBody(previewPost) }
1029
1274
  }
1030
1275
  ),
1031
- previewPost.tags && previewPost.tags.length > 0 && /* @__PURE__ */ jsx6("div", { className: "flex flex-wrap gap-2 border-t pt-4 text-sm", children: previewPost.tags.map((tag) => /* @__PURE__ */ jsxs6(
1276
+ previewPost.tags && previewPost.tags.length > 0 && /* @__PURE__ */ jsx7("div", { className: "flex flex-wrap gap-2 border-t pt-4 text-sm", children: previewPost.tags.map((tag) => /* @__PURE__ */ jsxs7(
1032
1277
  "span",
1033
1278
  {
1034
1279
  className: "rounded-full border px-2 py-0.5 text-xs text-muted-foreground",
@@ -1039,12 +1284,12 @@ function PostForm({ post }) {
1039
1284
  },
1040
1285
  tag
1041
1286
  )) }),
1042
- /* @__PURE__ */ jsx6("p", { className: "text-xs text-muted-foreground", children: t("posts.form.previewHint") })
1287
+ /* @__PURE__ */ jsx7("p", { className: "text-xs text-muted-foreground", children: t("posts.form.previewHint") })
1043
1288
  ] }),
1044
- /* @__PURE__ */ jsxs6("div", { className: view === "edit" ? "space-y-6" : "hidden", children: [
1045
- /* @__PURE__ */ jsxs6("div", { className: "space-y-2", children: [
1046
- /* @__PURE__ */ jsx6(Label, { htmlFor: "title", children: t("posts.form.title") }),
1047
- /* @__PURE__ */ jsx6(
1289
+ /* @__PURE__ */ jsxs7("div", { className: view === "edit" ? "space-y-6" : "hidden", children: [
1290
+ /* @__PURE__ */ jsxs7("div", { className: "space-y-2", children: [
1291
+ /* @__PURE__ */ jsx7(Label, { htmlFor: "title", children: t("posts.form.title") }),
1292
+ /* @__PURE__ */ jsx7(
1048
1293
  Input,
1049
1294
  {
1050
1295
  id: "title",
@@ -1057,9 +1302,9 @@ function PostForm({ post }) {
1057
1302
  }
1058
1303
  )
1059
1304
  ] }),
1060
- /* @__PURE__ */ jsxs6("div", { className: "space-y-2", children: [
1061
- /* @__PURE__ */ jsx6(Label, { htmlFor: "slug", children: t("posts.form.slug") }),
1062
- /* @__PURE__ */ jsx6(
1305
+ /* @__PURE__ */ jsxs7("div", { className: "space-y-2", children: [
1306
+ /* @__PURE__ */ jsx7(Label, { htmlFor: "slug", children: t("posts.form.slug") }),
1307
+ /* @__PURE__ */ jsx7(
1063
1308
  Input,
1064
1309
  {
1065
1310
  id: "slug",
@@ -1069,9 +1314,9 @@ function PostForm({ post }) {
1069
1314
  }
1070
1315
  )
1071
1316
  ] }),
1072
- /* @__PURE__ */ jsxs6("div", { className: "space-y-2", children: [
1073
- /* @__PURE__ */ jsx6(Label, { htmlFor: "excerpt", children: t("posts.form.excerpt") }),
1074
- /* @__PURE__ */ jsx6(
1317
+ /* @__PURE__ */ jsxs7("div", { className: "space-y-2", children: [
1318
+ /* @__PURE__ */ jsx7(Label, { htmlFor: "excerpt", children: t("posts.form.excerpt") }),
1319
+ /* @__PURE__ */ jsx7(
1075
1320
  Textarea,
1076
1321
  {
1077
1322
  id: "excerpt",
@@ -1081,9 +1326,9 @@ function PostForm({ post }) {
1081
1326
  }
1082
1327
  )
1083
1328
  ] }),
1084
- /* @__PURE__ */ jsxs6("div", { className: "space-y-2", children: [
1085
- /* @__PURE__ */ jsx6(Label, { htmlFor: "format", children: t("posts.form.format") }),
1086
- /* @__PURE__ */ jsxs6(
1329
+ /* @__PURE__ */ jsxs7("div", { className: "space-y-2", children: [
1330
+ /* @__PURE__ */ jsx7(Label, { htmlFor: "format", children: t("posts.form.format") }),
1331
+ /* @__PURE__ */ jsxs7(
1087
1332
  "select",
1088
1333
  {
1089
1334
  id: "format",
@@ -1091,41 +1336,41 @@ function PostForm({ post }) {
1091
1336
  onChange: (e) => changeFormat(e.target.value),
1092
1337
  className: "flex h-9 w-full max-w-xs rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm",
1093
1338
  children: [
1094
- /* @__PURE__ */ jsx6("option", { value: "tiptap", children: "Tiptap (rich editor)" }),
1095
- /* @__PURE__ */ jsx6("option", { value: "markdown", children: "Markdown" }),
1096
- /* @__PURE__ */ jsx6("option", { value: "html", children: "HTML" }),
1097
- /* @__PURE__ */ jsx6("option", { value: "static", children: t("posts.form.formatStaticLabel") })
1339
+ /* @__PURE__ */ jsx7("option", { value: "tiptap", children: "Tiptap (rich editor)" }),
1340
+ /* @__PURE__ */ jsx7("option", { value: "markdown", children: "Markdown" }),
1341
+ /* @__PURE__ */ jsx7("option", { value: "html", children: "HTML" }),
1342
+ /* @__PURE__ */ jsx7("option", { value: "static", children: t("posts.form.formatStaticLabel") })
1098
1343
  ]
1099
1344
  }
1100
1345
  ),
1101
- /* @__PURE__ */ jsx6("p", { className: "text-xs text-muted-foreground", children: t("posts.form.formatHint") })
1346
+ /* @__PURE__ */ jsx7("p", { className: "text-xs text-muted-foreground", children: t("posts.form.formatHint") })
1102
1347
  ] }),
1103
- /* @__PURE__ */ jsxs6("div", { className: "space-y-2", children: [
1104
- /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between", children: [
1105
- /* @__PURE__ */ jsx6(Label, { children: t("posts.form.body") }),
1348
+ /* @__PURE__ */ jsxs7("div", { className: "space-y-2", children: [
1349
+ /* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between", children: [
1350
+ /* @__PURE__ */ jsx7(Label, { children: t("posts.form.body") }),
1106
1351
  format !== "tiptap" && format !== "static" && // For textarea-based formats (markdown / html) there's no
1107
1352
  // embedded toolbar, so we surface the MediaPicker as a
1108
1353
  // standalone button. Selecting an asset inserts a
1109
1354
  // format-aware snippet at the cursor.
1110
- /* @__PURE__ */ jsx6(
1355
+ /* @__PURE__ */ jsx7(
1111
1356
  MediaPicker,
1112
1357
  {
1113
1358
  onSelect: insertMediaSnippet,
1114
- trigger: /* @__PURE__ */ jsxs6(Button5, { type: "button", variant: "outline", size: "sm", children: [
1115
- /* @__PURE__ */ jsx6(ImageIcon3, { className: "mr-2 h-3 w-3" }),
1359
+ trigger: /* @__PURE__ */ jsxs7(Button6, { type: "button", variant: "outline", size: "sm", children: [
1360
+ /* @__PURE__ */ jsx7(ImageIcon3, { className: "mr-2 h-3 w-3" }),
1116
1361
  t("posts.form.insertMedia")
1117
1362
  ] })
1118
1363
  }
1119
1364
  )
1120
1365
  ] }),
1121
- format === "tiptap" ? /* @__PURE__ */ jsx6(TiptapEditor, { initialContent: body, onChange: setBody }) : format === "static" ? /* @__PURE__ */ jsx6(
1366
+ format === "tiptap" ? /* @__PURE__ */ jsx7(TiptapEditor, { initialContent: body, onChange: setBody }) : format === "static" ? /* @__PURE__ */ jsx7(
1122
1367
  StaticUploader,
1123
1368
  {
1124
1369
  initial: initialStaticBody,
1125
1370
  onFilesReady: (files, entrypoint) => setPendingBundle({ files, entrypoint }),
1126
1371
  onClear: () => setPendingBundle(null)
1127
1372
  }
1128
- ) : /* @__PURE__ */ jsx6(
1373
+ ) : /* @__PURE__ */ jsx7(
1129
1374
  Textarea,
1130
1375
  {
1131
1376
  ref: bodyTextareaRef,
@@ -1136,9 +1381,9 @@ function PostForm({ post }) {
1136
1381
  }
1137
1382
  )
1138
1383
  ] }),
1139
- /* @__PURE__ */ jsxs6("div", { className: "space-y-2", children: [
1140
- /* @__PURE__ */ jsx6(Label, { htmlFor: "tags", children: t("posts.form.tags") }),
1141
- /* @__PURE__ */ jsx6(
1384
+ /* @__PURE__ */ jsxs7("div", { className: "space-y-2", children: [
1385
+ /* @__PURE__ */ jsx7(Label, { htmlFor: "tags", children: t("posts.form.tags") }),
1386
+ /* @__PURE__ */ jsx7(
1142
1387
  Input,
1143
1388
  {
1144
1389
  id: "tags",
@@ -1147,11 +1392,11 @@ function PostForm({ post }) {
1147
1392
  placeholder: t("posts.form.tagsPlaceholder")
1148
1393
  }
1149
1394
  ),
1150
- /* @__PURE__ */ jsx6("p", { className: "text-xs text-muted-foreground", children: t("posts.form.tagsHint") })
1395
+ /* @__PURE__ */ jsx7("p", { className: "text-xs text-muted-foreground", children: t("posts.form.tagsHint") })
1151
1396
  ] }),
1152
- /* @__PURE__ */ jsxs6("div", { className: "space-y-2", children: [
1153
- /* @__PURE__ */ jsx6(Label, { htmlFor: "status", children: t("posts.form.status") }),
1154
- /* @__PURE__ */ jsxs6(
1397
+ /* @__PURE__ */ jsxs7("div", { className: "space-y-2", children: [
1398
+ /* @__PURE__ */ jsx7(Label, { htmlFor: "status", children: t("posts.form.status") }),
1399
+ /* @__PURE__ */ jsxs7(
1155
1400
  "select",
1156
1401
  {
1157
1402
  id: "status",
@@ -1159,14 +1404,14 @@ function PostForm({ post }) {
1159
1404
  onChange: (e) => setStatus(e.target.value),
1160
1405
  className: "flex h-9 w-full max-w-xs rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm",
1161
1406
  children: [
1162
- /* @__PURE__ */ jsx6("option", { value: "draft", children: t("common.draft") }),
1163
- /* @__PURE__ */ jsx6("option", { value: "published", children: t("common.published") })
1407
+ /* @__PURE__ */ jsx7("option", { value: "draft", children: t("common.draft") }),
1408
+ /* @__PURE__ */ jsx7("option", { value: "published", children: t("common.published") })
1164
1409
  ]
1165
1410
  }
1166
1411
  )
1167
1412
  ] }),
1168
- format === "html" && /* @__PURE__ */ jsx6("div", { className: "space-y-2", children: /* @__PURE__ */ jsxs6("label", { className: "flex items-start gap-2 text-sm", children: [
1169
- /* @__PURE__ */ jsx6(
1413
+ format === "html" && /* @__PURE__ */ jsx7("div", { className: "space-y-2", children: /* @__PURE__ */ jsxs7("label", { className: "flex items-start gap-2 text-sm", children: [
1414
+ /* @__PURE__ */ jsx7(
1170
1415
  "input",
1171
1416
  {
1172
1417
  type: "checkbox",
@@ -1175,15 +1420,15 @@ function PostForm({ post }) {
1175
1420
  className: "mt-1"
1176
1421
  }
1177
1422
  ),
1178
- /* @__PURE__ */ jsxs6("span", { children: [
1179
- /* @__PURE__ */ jsx6("span", { className: "font-medium", children: t("posts.form.noLayout") }),
1180
- /* @__PURE__ */ jsx6("span", { className: "block text-xs text-muted-foreground", children: t("posts.form.noLayoutHint") })
1423
+ /* @__PURE__ */ jsxs7("span", { children: [
1424
+ /* @__PURE__ */ jsx7("span", { className: "font-medium", children: t("posts.form.noLayout") }),
1425
+ /* @__PURE__ */ jsx7("span", { className: "block text-xs text-muted-foreground", children: t("posts.form.noLayoutHint") })
1181
1426
  ] })
1182
1427
  ] }) }),
1183
- error && /* @__PURE__ */ jsx6("p", { className: "text-sm text-destructive", children: error }),
1184
- /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
1185
- /* @__PURE__ */ jsx6(Button5, { type: "submit", disabled: saving, children: saving ? t("common.saving") : isEdit ? t("posts.form.saveChanges") : t("posts.form.createPost") }),
1186
- isEdit && /* @__PURE__ */ jsx6(Button5, { type: "button", variant: "destructive", onClick: handleDelete, disabled: saving, children: t("posts.form.delete") })
1428
+ error && /* @__PURE__ */ jsx7("p", { className: "text-sm text-destructive", children: error }),
1429
+ /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", children: [
1430
+ /* @__PURE__ */ jsx7(Button6, { type: "submit", disabled: saving, children: saving ? t("common.saving") : isEdit ? t("posts.form.saveChanges") : t("posts.form.createPost") }),
1431
+ isEdit && /* @__PURE__ */ jsx7(Button6, { type: "button", variant: "destructive", onClick: handleDelete, disabled: saving, children: t("posts.form.delete") })
1187
1432
  ] })
1188
1433
  ] })
1189
1434
  ] });