astro-md-editor 0.0.7 → 0.0.8

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 (52) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/index-CstiJsWh.js +378 -0
  3. package/.output/public/assets/{main-BrRIwdKE.js → main-Cc9C-tdG.js} +1 -1
  4. package/.output/public/assets/styles-DCSwPMSs.css +1 -0
  5. package/.output/server/{__root-CL_tq3ov.mjs → __root-Bv3dTvZ5.mjs} +1 -1
  6. package/.output/server/_libs/@radix-ui/react-dismissable-layer+[...].mjs +210 -0
  7. package/.output/server/_libs/@radix-ui/react-use-callback-ref+[...].mjs +11 -0
  8. package/.output/server/_libs/@radix-ui/react-use-controllable-state+[...].mjs +69 -0
  9. package/.output/server/_libs/@radix-ui/react-use-effect-event+[...].mjs +1 -0
  10. package/.output/server/_libs/@radix-ui/react-use-escape-keydown+[...].mjs +17 -0
  11. package/.output/server/_libs/@radix-ui/react-use-layout-effect+[...].mjs +6 -0
  12. package/.output/server/_libs/aria-hidden.mjs +122 -0
  13. package/.output/server/_libs/base-ui__react.mjs +2548 -2548
  14. package/.output/server/_libs/base-ui__utils.mjs +2 -2
  15. package/.output/server/_libs/cmdk.mjs +315 -0
  16. package/.output/server/_libs/detect-node-es.mjs +1 -0
  17. package/.output/server/_libs/get-nonce.mjs +9 -0
  18. package/.output/server/_libs/lucide-react.mjs +25 -17
  19. package/.output/server/_libs/radix-ui__primitive.mjs +11 -0
  20. package/.output/server/_libs/radix-ui__react-compose-refs.mjs +39 -0
  21. package/.output/server/_libs/radix-ui__react-context.mjs +78 -0
  22. package/.output/server/_libs/radix-ui__react-dialog.mjs +319 -0
  23. package/.output/server/_libs/radix-ui__react-focus-guards.mjs +29 -0
  24. package/.output/server/_libs/radix-ui__react-focus-scope.mjs +206 -0
  25. package/.output/server/_libs/radix-ui__react-id.mjs +14 -0
  26. package/.output/server/_libs/radix-ui__react-portal.mjs +16 -0
  27. package/.output/server/_libs/radix-ui__react-presence.mjs +128 -0
  28. package/.output/server/_libs/radix-ui__react-primitive.mjs +75 -0
  29. package/.output/server/_libs/radix-ui__react-slot.mjs +184 -0
  30. package/.output/server/_libs/react-remove-scroll-bar.mjs +82 -0
  31. package/.output/server/_libs/react-remove-scroll.mjs +328 -0
  32. package/.output/server/_libs/react-style-singleton.mjs +69 -0
  33. package/.output/server/_libs/react.mjs +2 -0
  34. package/.output/server/_libs/tslib.mjs +576 -0
  35. package/.output/server/_libs/use-callback-ref.mjs +66 -0
  36. package/.output/server/_libs/use-sidecar.mjs +106 -0
  37. package/.output/server/_ssr/{ImageAssetBrowser-DNDdTqtf.mjs → ImageAssetBrowser-DuPVChYO.mjs} +2 -2
  38. package/.output/server/_ssr/{collections.server-s12asITg.mjs → collections.server-DjgohZR7.mjs} +2 -1
  39. package/.output/server/_ssr/{file-history.api-oydnxFVV.mjs → file-history.api-JMkTXrYq.mjs} +1 -1
  40. package/.output/server/_ssr/{image-assets.server-Ci2E1_Tm.mjs → image-assets.server-2-0DgxSb.mjs} +1 -1
  41. package/.output/server/_ssr/{image-preview.api-pcN5PQhH.mjs → image-preview.api-V_Q-MBx9.mjs} +2 -2
  42. package/.output/server/_ssr/{index-BjQuGIib.mjs → index-ByW88Uz2.mjs} +3 -2
  43. package/.output/server/_ssr/{index-qpTkRHX1.mjs → index-C6Fb3DjG.mjs} +796 -409
  44. package/.output/server/_ssr/index.mjs +15 -15
  45. package/.output/server/_ssr/{router-DU3Hv7p_.mjs → router-DbnWNAi_.mjs} +2 -2
  46. package/.output/server/{_tanstack-start-manifest_v-BdKE8Xjm.mjs → _tanstack-start-manifest_v-BDWWBEf1.mjs} +1 -1
  47. package/.output/server/index.mjs +49 -49
  48. package/LICENSE.md +1 -1
  49. package/package.json +2 -1
  50. package/scripts/bootstrap-collections.mjs +2 -0
  51. package/.output/public/assets/index-CBGDT9fi.js +0 -334
  52. package/.output/public/assets/styles-CezfLgHY.css +0 -1
@@ -1,10 +1,11 @@
1
1
  import { r as reactExports, j as jsxRuntimeExports } from "../_libs/react.mjs";
2
- import { u as useCollectionsData, R as Route, c as createSsrRpc } from "./router-DU3Hv7p_.mjs";
2
+ import { u as useCollectionsData, R as Route, c as createSsrRpc } from "./router-DbnWNAi_.mjs";
3
3
  import { t as toast } from "../_libs/sonner.mjs";
4
4
  import { c as cva } from "../_libs/class-variance-authority.mjs";
5
5
  import { c as clsx } from "../_libs/clsx.mjs";
6
6
  import { t as twMerge } from "../_libs/tailwind-merge.mjs";
7
7
  import { U as Ut, q as qt, Z as Zt } from "../_libs/react-resizable-panels.mjs";
8
+ import { _ as _e } from "../_libs/cmdk.mjs";
8
9
  import { u as useEditor, E as EditorContent } from "../_libs/tiptap__react.mjs";
9
10
  import { i as index_default$1 } from "../_libs/tiptap__starter-kit.mjs";
10
11
  import { i as index_default$2 } from "../_libs/tiptap__extension-link.mjs";
@@ -18,9 +19,9 @@ import { T as TurndownService } from "../_libs/turndown.mjs";
18
19
  import { g as gfm } from "../_libs/turndown-plugin-gfm.mjs";
19
20
  import { A as Ajv2020 } from "../_libs/ajv.mjs";
20
21
  import { a as addFormats } from "../_libs/ajv-formats.mjs";
21
- import { P as PanelLeftClose, a as PanelLeftOpen, L as LoaderCircle, S as Save, b as PanelRightClose, c as PanelRightOpen, d as Trash2, e as LaptopMinimal, M as Moon, f as Sun, g as ChevronDown, h as Check, H as Heading1, i as Heading2, j as List, k as ListOrdered, l as ListChecks, Q as Quote, m as CodeXml, n as Minus, o as Link, p as Image, X, q as CalendarDays, r as Clock3, s as ChevronUp, t as Search, u as ChevronLeft, v as ChevronRight } from "../_libs/lucide-react.mjs";
22
+ import { P as PanelLeftClose, a as PanelLeftOpen, L as LoaderCircle, S as Save, b as PanelRightClose, c as PanelRightOpen, d as Search, A as ArrowUpDown, e as Trash2, f as LaptopMinimal, M as Moon, g as Sun, h as ChevronDown, i as Check, H as Heading1, j as Heading2, k as List, l as ListOrdered, m as ListChecks, Q as Quote, n as CodeXml, o as Minus, p as Link, q as Image, X, r as CalendarDays, s as Clock3, t as ChevronUp, u as ChevronLeft, v as ChevronRight } from "../_libs/lucide-react.mjs";
22
23
  import { c as create } from "../_libs/zustand.mjs";
23
- import { S as SelectRoot, B as Button$1, a as TabsRoot, b as TabsList$1, c as TabsTab, d as SelectTrigger$1, e as SelectIcon, f as SelectValue$1, g as SelectPortal, h as SelectPositioner, i as SelectPopup, j as SelectList, k as SelectGroup$1, l as SelectItem$1, m as SelectItemText, n as SelectItemIndicator, u as useRender, o as mergeProps, A as AlertDialogRoot, D as DialogPopup, p as DialogTitle, q as DialogDescription, r as DialogClose, s as TabsPanel, I as Input$1, t as SelectScrollUpArrow, v as SelectScrollDownArrow, w as DialogPortal, x as DialogBackdrop, P as PopoverRoot, y as PopoverTrigger$1, z as PopoverPortal, C as PopoverPositioner, E as PopoverPopup, F as SwitchRoot, G as SwitchThumb } from "../_libs/base-ui__react.mjs";
24
+ import { S as SelectRoot, B as Button$1, a as TabsRoot, b as TabsList$1, c as TabsTab, d as SelectTrigger$1, e as SelectIcon, f as SelectValue$1, g as SelectPortal, h as SelectPositioner, i as SelectPopup, j as SelectList, k as SelectGroup$1, l as SelectItem$1, m as SelectItemText, n as SelectItemIndicator, I as Input$1, P as PopoverRoot, o as PopoverTrigger$1, p as PopoverPortal, q as PopoverPositioner, r as PopoverPopup, u as useRender, s as mergeProps, A as AlertDialogRoot, D as DialogPopup, t as DialogTitle, v as DialogDescription, w as DialogClose, x as TabsPanel, y as SelectScrollUpArrow, z as SelectScrollDownArrow, C as DialogPortal, E as DialogBackdrop, F as SwitchRoot, G as SwitchThumb } from "../_libs/base-ui__react.mjs";
24
25
  import { g as getDefaultClassNames, D as DayPicker } from "../_libs/react-day-picker.mjs";
25
26
  import { a as array, o as object, l as literal, r as record, s as string, u as unknown } from "../_libs/zod.mjs";
26
27
  import "../_libs/tanstack__react-router.mjs";
@@ -54,6 +55,30 @@ import "../_libs/floating-ui__react-dom.mjs";
54
55
  import "../_libs/floating-ui__dom.mjs";
55
56
  import "../_libs/floating-ui__core.mjs";
56
57
  import "../_libs/tabbable.mjs";
58
+ import "../_libs/radix-ui__react-dialog.mjs";
59
+ import "../_libs/radix-ui__primitive.mjs";
60
+ import "../_libs/radix-ui__react-compose-refs.mjs";
61
+ import "../_libs/radix-ui__react-context.mjs";
62
+ import "../_libs/radix-ui__react-id.mjs";
63
+ import "../_libs/@radix-ui/react-use-layout-effect+[...].mjs";
64
+ import "../_libs/@radix-ui/react-use-controllable-state+[...].mjs";
65
+ import "../_libs/@radix-ui/react-dismissable-layer+[...].mjs";
66
+ import "../_libs/radix-ui__react-primitive.mjs";
67
+ import "../_libs/radix-ui__react-slot.mjs";
68
+ import "../_libs/@radix-ui/react-use-callback-ref+[...].mjs";
69
+ import "../_libs/@radix-ui/react-use-escape-keydown+[...].mjs";
70
+ import "../_libs/radix-ui__react-focus-scope.mjs";
71
+ import "../_libs/radix-ui__react-portal.mjs";
72
+ import "../_libs/radix-ui__react-presence.mjs";
73
+ import "../_libs/radix-ui__react-focus-guards.mjs";
74
+ import "../_libs/react-remove-scroll.mjs";
75
+ import "../_libs/tslib.mjs";
76
+ import "../_libs/react-remove-scroll-bar.mjs";
77
+ import "../_libs/react-style-singleton.mjs";
78
+ import "../_libs/get-nonce.mjs";
79
+ import "../_libs/use-sidecar.mjs";
80
+ import "../_libs/use-callback-ref.mjs";
81
+ import "../_libs/aria-hidden.mjs";
57
82
  import "../_libs/tiptap__core.mjs";
58
83
  import "../_libs/prosemirror-transform.mjs";
59
84
  import "../_libs/prosemirror-model.mjs";
@@ -95,7 +120,7 @@ function cn(...inputs) {
95
120
  return twMerge(clsx(inputs));
96
121
  }
97
122
  const buttonVariants = cva(
98
- "group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
123
+ "group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
99
124
  {
100
125
  variants: {
101
126
  variant: {
@@ -423,6 +448,219 @@ function Badge({
423
448
  }
424
449
  });
425
450
  }
451
+ function Input({ className, type, ...props }) {
452
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
453
+ Input$1,
454
+ {
455
+ type,
456
+ "data-slot": "input",
457
+ className: cn(
458
+ "border-input file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 disabled:bg-input/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 h-8 w-full min-w-0 rounded-lg border bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:ring-3 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:ring-3 md:text-sm",
459
+ className
460
+ ),
461
+ ...props
462
+ }
463
+ );
464
+ }
465
+ function Textarea({ className, ...props }) {
466
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
467
+ "textarea",
468
+ {
469
+ "data-slot": "textarea",
470
+ className: cn(
471
+ "border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 disabled:bg-input/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 flex field-sizing-content min-h-16 w-full rounded-lg border bg-transparent px-2.5 py-2 text-base transition-colors outline-none focus-visible:ring-3 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:ring-3 md:text-sm",
472
+ className
473
+ ),
474
+ ...props
475
+ }
476
+ );
477
+ }
478
+ function InputGroup({ className, ...props }) {
479
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
480
+ "div",
481
+ {
482
+ "data-slot": "input-group",
483
+ role: "group",
484
+ className: cn(
485
+ "group/input-group border-input has-disabled:bg-input/50 has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot][aria-invalid=true]]:border-destructive has-[[data-slot][aria-invalid=true]]:ring-destructive/20 dark:bg-input/30 dark:has-disabled:bg-input/80 dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 relative flex h-8 w-full min-w-0 items-center rounded-lg border transition-colors outline-none in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-disabled:opacity-50 has-[[data-slot=input-group-control]:focus-visible]:ring-3 has-[[data-slot][aria-invalid=true]]:ring-3 has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>textarea]:h-auto has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pr-1.5 has-[>[data-align=inline-start]]:[&>input]:pl-1.5",
486
+ className
487
+ ),
488
+ ...props
489
+ }
490
+ );
491
+ }
492
+ const inputGroupAddonVariants = cva(
493
+ "flex h-auto cursor-text items-center justify-center gap-2 py-1.5 text-sm font-medium text-muted-foreground select-none group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-4",
494
+ {
495
+ variants: {
496
+ align: {
497
+ "inline-start": "order-first pl-2 has-[>button]:ml-[-0.3rem] has-[>kbd]:ml-[-0.15rem]",
498
+ "inline-end": "order-last pr-2 has-[>button]:mr-[-0.3rem] has-[>kbd]:mr-[-0.15rem]",
499
+ "block-start": "order-first w-full justify-start px-2.5 pt-2 group-has-[>input]/input-group:pt-2 [.border-b]:pb-2",
500
+ "block-end": "order-last w-full justify-start px-2.5 pb-2 group-has-[>input]/input-group:pb-2 [.border-t]:pt-2"
501
+ }
502
+ },
503
+ defaultVariants: {
504
+ align: "inline-start"
505
+ }
506
+ }
507
+ );
508
+ function InputGroupAddon({
509
+ className,
510
+ align = "inline-start",
511
+ ...props
512
+ }) {
513
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
514
+ "div",
515
+ {
516
+ role: "group",
517
+ "data-slot": "input-group-addon",
518
+ "data-align": align,
519
+ className: cn(inputGroupAddonVariants({ align }), className),
520
+ onClick: (e) => {
521
+ if (e.target.closest("button")) {
522
+ return;
523
+ }
524
+ e.currentTarget.parentElement?.querySelector("input")?.focus();
525
+ },
526
+ ...props
527
+ }
528
+ );
529
+ }
530
+ function Command({
531
+ className,
532
+ ...props
533
+ }) {
534
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
535
+ _e,
536
+ {
537
+ "data-slot": "command",
538
+ className: cn(
539
+ "bg-popover text-popover-foreground flex size-full flex-col overflow-hidden rounded-xl! p-1",
540
+ className
541
+ ),
542
+ ...props
543
+ }
544
+ );
545
+ }
546
+ function CommandInput({
547
+ className,
548
+ ...props
549
+ }) {
550
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { "data-slot": "command-input-wrapper", className: "p-1 pb-0", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(InputGroup, { className: "border-input/30 bg-input/30 h-8! rounded-lg! shadow-none! *:data-[slot=input-group-addon]:pl-2!", children: [
551
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
552
+ _e.Input,
553
+ {
554
+ "data-slot": "command-input",
555
+ className: cn(
556
+ "w-full text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50",
557
+ className
558
+ ),
559
+ ...props
560
+ }
561
+ ),
562
+ /* @__PURE__ */ jsxRuntimeExports.jsx(InputGroupAddon, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(Search, { className: "size-4 shrink-0 opacity-50" }) })
563
+ ] }) });
564
+ }
565
+ function CommandEmpty({
566
+ className,
567
+ ...props
568
+ }) {
569
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
570
+ _e.Empty,
571
+ {
572
+ "data-slot": "command-empty",
573
+ className: cn("py-6 text-center text-sm", className),
574
+ ...props
575
+ }
576
+ );
577
+ }
578
+ function CommandGroup({
579
+ className,
580
+ ...props
581
+ }) {
582
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
583
+ _e.Group,
584
+ {
585
+ "data-slot": "command-group",
586
+ className: cn(
587
+ "text-foreground **:[[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 **:[[cmdk-group-heading]]:px-2 **:[[cmdk-group-heading]]:py-1.5 **:[[cmdk-group-heading]]:text-xs **:[[cmdk-group-heading]]:font-medium",
588
+ className
589
+ ),
590
+ ...props
591
+ }
592
+ );
593
+ }
594
+ function CommandSeparator({
595
+ className,
596
+ ...props
597
+ }) {
598
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
599
+ _e.Separator,
600
+ {
601
+ "data-slot": "command-separator",
602
+ className: cn("bg-border -mx-1 h-px", className),
603
+ ...props
604
+ }
605
+ );
606
+ }
607
+ function CommandItem({
608
+ className,
609
+ children,
610
+ ...props
611
+ }) {
612
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
613
+ _e.Item,
614
+ {
615
+ "data-slot": "command-item",
616
+ className: cn(
617
+ "group/command-item data-selected:bg-muted data-selected:text-foreground data-selected:*:[svg]:text-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none in-data-[slot=dialog-content]:rounded-lg! data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
618
+ className
619
+ ),
620
+ ...props,
621
+ children: [
622
+ children,
623
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "ml-auto opacity-0 group-has-data-[slot=command-shortcut]/command-item:hidden group-data-[checked=true]/command-item:opacity-100" })
624
+ ]
625
+ }
626
+ );
627
+ }
628
+ function Popover({ ...props }) {
629
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(PopoverRoot, { "data-slot": "popover", ...props });
630
+ }
631
+ function PopoverTrigger({ ...props }) {
632
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(PopoverTrigger$1, { "data-slot": "popover-trigger", ...props });
633
+ }
634
+ function PopoverContent({
635
+ className,
636
+ align = "center",
637
+ alignOffset = 0,
638
+ side = "bottom",
639
+ sideOffset = 4,
640
+ ...props
641
+ }) {
642
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(PopoverPortal, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(
643
+ PopoverPositioner,
644
+ {
645
+ align,
646
+ alignOffset,
647
+ side,
648
+ sideOffset,
649
+ className: "isolate z-50",
650
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(
651
+ PopoverPopup,
652
+ {
653
+ "data-slot": "popover-content",
654
+ className: cn(
655
+ "bg-popover text-popover-foreground ring-foreground/10 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 z-50 flex w-72 origin-(--transform-origin) flex-col gap-2.5 rounded-lg p-2.5 text-sm shadow-md ring-1 outline-hidden duration-100",
656
+ className
657
+ ),
658
+ ...props
659
+ }
660
+ )
661
+ }
662
+ ) });
663
+ }
426
664
  const Select = SelectRoot;
427
665
  function SelectGroup({ className, ...props }) {
428
666
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -572,6 +810,13 @@ function SelectScrollDownButton({
572
810
  }
573
811
  );
574
812
  }
813
+ const DEFAULT_SORT = { kind: "newest" };
814
+ const PRESET_SORT_OPTIONS = [
815
+ { label: "Newest first", option: { kind: "newest" } },
816
+ { label: "Oldest first", option: { kind: "oldest" } },
817
+ { label: "Title A-Z", option: { kind: "titleAsc" } },
818
+ { label: "Title Z-A", option: { kind: "titleDesc" } }
819
+ ];
575
820
  function getFileName(pathLike) {
576
821
  const normalized = pathLike.replaceAll("\\", "/");
577
822
  const parts = normalized.split("/");
@@ -588,22 +833,105 @@ function getFileDisplayLabel(file) {
588
833
  const fileName = getFileName(file.filePath || file.id);
589
834
  return stripExtension(fileName);
590
835
  }
591
- function getSortedCollectionFiles(collection) {
836
+ function compareDates(a, b) {
837
+ if (!a && !b) return 0;
838
+ if (!a) return 1;
839
+ if (!b) return -1;
840
+ return new Date(a).getTime() - new Date(b).getTime();
841
+ }
842
+ function compareLabels(a, b) {
843
+ const labelCompare = getFileDisplayLabel(a).localeCompare(
844
+ getFileDisplayLabel(b),
845
+ void 0,
846
+ { sensitivity: "base" }
847
+ );
848
+ if (labelCompare !== 0) {
849
+ return labelCompare;
850
+ }
851
+ return a.id.localeCompare(b.id, void 0, { sensitivity: "base" });
852
+ }
853
+ function compareFrontmatterField(a, b, fieldKey, direction) {
854
+ const aVal = a.data[fieldKey];
855
+ const bVal = b.data[fieldKey];
856
+ if (aVal == null && bVal == null) return 0;
857
+ if (aVal == null) return 1;
858
+ if (bVal == null) return -1;
859
+ let result = 0;
860
+ if (typeof aVal === "string" && typeof bVal === "string") {
861
+ const aDate = Date.parse(aVal);
862
+ const bDate = Date.parse(bVal);
863
+ if (!Number.isNaN(aDate) && !Number.isNaN(bDate)) {
864
+ result = aDate - bDate;
865
+ } else {
866
+ result = aVal.localeCompare(bVal, void 0, { sensitivity: "base" });
867
+ }
868
+ } else if (typeof aVal === "number" && typeof bVal === "number") {
869
+ result = aVal - bVal;
870
+ } else {
871
+ result = String(aVal).localeCompare(String(bVal), void 0, {
872
+ sensitivity: "base"
873
+ });
874
+ }
875
+ return direction === "desc" ? -result : result;
876
+ }
877
+ function getSortedCollectionFiles(collection, sort = DEFAULT_SORT) {
592
878
  if (!collection) {
593
879
  return [];
594
880
  }
595
881
  return [...collection.files].sort((a, b) => {
596
- const labelCompare = getFileDisplayLabel(a).localeCompare(
597
- getFileDisplayLabel(b),
598
- void 0,
599
- { sensitivity: "base" }
600
- );
601
- if (labelCompare !== 0) {
602
- return labelCompare;
882
+ switch (sort.kind) {
883
+ case "newest":
884
+ return compareDates(b.createdAt, a.createdAt);
885
+ case "oldest":
886
+ return compareDates(a.createdAt, b.createdAt);
887
+ case "titleAsc":
888
+ return compareLabels(a, b);
889
+ case "titleDesc":
890
+ return compareLabels(b, a);
891
+ case "frontmatter":
892
+ return compareFrontmatterField(a, b, sort.fieldKey, sort.direction);
603
893
  }
604
- return a.id.localeCompare(b.id, void 0, { sensitivity: "base" });
605
894
  });
606
895
  }
896
+ function getSortableFields(resolvedFields) {
897
+ return resolvedFields.filter(
898
+ (f) => f.kind === "string" || f.kind === "number" || f.kind === "dateAnyOf" || f.kind === "enum"
899
+ ).map((f) => ({ key: f.key, label: f.key }));
900
+ }
901
+ function sortOptionToValue(option) {
902
+ switch (option.kind) {
903
+ case "newest":
904
+ case "oldest":
905
+ case "titleAsc":
906
+ case "titleDesc":
907
+ return option.kind;
908
+ case "frontmatter":
909
+ return `field:${option.fieldKey}:${option.direction}`;
910
+ }
911
+ }
912
+ function valueToSortOption(value) {
913
+ switch (value) {
914
+ case "newest":
915
+ return { kind: "newest" };
916
+ case "oldest":
917
+ return { kind: "oldest" };
918
+ case "titleAsc":
919
+ return { kind: "titleAsc" };
920
+ case "titleDesc":
921
+ return { kind: "titleDesc" };
922
+ default: {
923
+ const match = value.match(/^field:(.+):(asc|desc)$/);
924
+ if (match) {
925
+ return {
926
+ kind: "frontmatter",
927
+ fieldKey: match[1],
928
+ direction: match[2]
929
+ };
930
+ }
931
+ return DEFAULT_SORT;
932
+ }
933
+ }
934
+ }
607
935
  function areEditorSearchEqual(a, b) {
608
936
  return a.collection === b.collection && a.file === b.file;
609
937
  }
@@ -632,81 +960,403 @@ function resolveEditorSelection(collections, search) {
632
960
  }
633
961
  };
634
962
  }
635
- function LeftSidebar({
636
- collections,
637
- selectedCollectionName,
638
- selectedFileId,
639
- onSelectCollection,
640
- onSelectFile,
641
- onCreateFile,
642
- onDeleteFile,
643
- isCreatingFile,
644
- deletingFileId
645
- }) {
646
- const [deleteCandidate, setDeleteCandidate] = reactExports.useState(null);
647
- const selectedCollection = collections.find(
648
- (collection) => collection.name === selectedCollectionName
649
- );
650
- const files = getSortedCollectionFiles(selectedCollection);
651
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex h-full flex-col gap-3", children: [
652
- /* @__PURE__ */ jsxRuntimeExports.jsxs(
653
- Select,
654
- {
655
- value: selectedCollectionName,
656
- onValueChange: (nextCollectionName) => {
657
- if (!nextCollectionName) {
658
- return;
659
- }
660
- onSelectCollection(nextCollectionName);
661
- },
662
- children: [
663
- /* @__PURE__ */ jsxRuntimeExports.jsx(SelectTrigger, { className: "bg-muted/50 focus-visible:ring-ring/35 w-full border-transparent shadow-none focus-visible:border-transparent focus-visible:ring-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SelectValue, { placeholder: "Select a collection" }) }),
664
- /* @__PURE__ */ jsxRuntimeExports.jsx(SelectContent, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(SelectGroup, { children: collections.map((collection) => /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: collection.name, children: collection.name }, collection.name)) }) })
665
- ]
666
- }
667
- ),
668
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "bg-background/35 min-h-0 flex-1 overflow-auto rounded-md p-1", children: files.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-muted-foreground px-2 py-2 text-sm", children: "No files in this collection." }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-0.5", children: files.map((file) => {
669
- const isActive = file.id === selectedFileId;
670
- const title = getFileDisplayLabel(file);
671
- const slug = file.id;
672
- const isMdxFile = /\.mdx$/i.test(file.filePath);
673
- const isDraft = file.data.draft === true;
674
- const isDeleting = deletingFileId === file.id;
675
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "group/item relative", children: [
676
- /* @__PURE__ */ jsxRuntimeExports.jsx(
677
- Button,
678
- {
679
- type: "button",
680
- variant: "ghost",
681
- className: cn(
682
- "h-auto w-full justify-start border-0 px-2.5 py-3 pr-9 text-left shadow-none",
683
- "hover:bg-background/70",
684
- isActive && "bg-muted text-foreground hover:bg-muted/55"
685
- ),
686
- onClick: () => onSelectFile(file.id),
687
- title: file.filePath,
688
- children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex w-full min-w-0 flex-col items-start gap-0.5", children: [
689
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-full truncate text-sm font-normal", children: title }),
690
- /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex w-full min-w-0 items-center gap-1.5", children: [
691
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground min-w-0 flex-1 truncate text-xs", children: slug }),
692
- isMdxFile ? /* @__PURE__ */ jsxRuntimeExports.jsx(
693
- Badge,
694
- {
695
- variant: "secondary",
696
- className: "bg-muted h-4 border-transparent px-1.5 text-[10px] leading-none",
697
- children: "MDX"
698
- }
699
- ) : null,
700
- isDraft ? /* @__PURE__ */ jsxRuntimeExports.jsx(
701
- Badge,
702
- {
703
- variant: "outline",
704
- className: "h-4 border-transparent bg-amber-100 px-1.5 text-[10px] leading-none text-amber-900 dark:bg-amber-900/40 dark:text-amber-200",
705
- children: "Draft"
706
- }
707
- ) : null
708
- ] })
709
- ] })
963
+ const recordSchema = record(string(), unknown());
964
+ const jsonObjectSchema = object({
965
+ type: literal("object"),
966
+ properties: recordSchema,
967
+ required: array(string()).optional()
968
+ }).passthrough();
969
+ const propertySchema = object({
970
+ type: string().optional(),
971
+ format: string().optional(),
972
+ enum: array(string()).optional(),
973
+ anyOf: array(recordSchema).optional(),
974
+ items: recordSchema.optional()
975
+ }).passthrough();
976
+ const ASTRO_DEF_PREFIX = "#/definitions/";
977
+ function asRecord(value) {
978
+ const parsed = recordSchema.safeParse(value);
979
+ return parsed.success ? parsed.data : void 0;
980
+ }
981
+ function parsePropertySchema(value) {
982
+ const parsed = propertySchema.safeParse(value);
983
+ return parsed.success ? parsed.data : void 0;
984
+ }
985
+ function asObjectSchema(value) {
986
+ const parsed = jsonObjectSchema.safeParse(value);
987
+ return parsed.success ? parsed.data : void 0;
988
+ }
989
+ function isStringArraySchema(schema) {
990
+ if (schema.type !== "array") {
991
+ return false;
992
+ }
993
+ const itemSchema = parsePropertySchema(schema.items);
994
+ return itemSchema?.type === "string";
995
+ }
996
+ function isDateAnyOfSchema(schema) {
997
+ if (!schema.anyOf || schema.anyOf.length === 0) {
998
+ return false;
999
+ }
1000
+ let hasDateOption = false;
1001
+ for (const option of schema.anyOf) {
1002
+ const candidate = parsePropertySchema(option);
1003
+ if (!candidate) {
1004
+ return false;
1005
+ }
1006
+ if (candidate.type === "string" && (candidate.format === "date" || candidate.format === "date-time")) {
1007
+ hasDateOption = true;
1008
+ continue;
1009
+ }
1010
+ if ((candidate.type === "integer" || candidate.type === "number") && candidate.format === "unix-time") {
1011
+ hasDateOption = true;
1012
+ continue;
1013
+ }
1014
+ if (candidate.type === "null") {
1015
+ continue;
1016
+ }
1017
+ return false;
1018
+ }
1019
+ return hasDateOption;
1020
+ }
1021
+ function resolveRequiredFields(required) {
1022
+ const parsed = array(string()).safeParse(required);
1023
+ return new Set(parsed.success ? parsed.data : []);
1024
+ }
1025
+ function resolveCustomFieldKind(params) {
1026
+ const customKind = params.fieldUi?.[params.key];
1027
+ if (!customKind) {
1028
+ return void 0;
1029
+ }
1030
+ if (customKind.kind === "image" && params.property.type === "string") {
1031
+ return {
1032
+ kind: "image",
1033
+ key: params.key,
1034
+ required: params.required,
1035
+ sourceMode: customKind.mode
1036
+ };
1037
+ }
1038
+ if (customKind.kind === "imageArray" && isStringArraySchema(params.property)) {
1039
+ return {
1040
+ kind: "imageArray",
1041
+ key: params.key,
1042
+ required: params.required,
1043
+ sourceMode: customKind.mode
1044
+ };
1045
+ }
1046
+ if (customKind.kind === "color" && params.property.type === "string") {
1047
+ return {
1048
+ kind: "color",
1049
+ key: params.key,
1050
+ required: params.required
1051
+ };
1052
+ }
1053
+ if (customKind.kind === "icon" && params.property.type === "string") {
1054
+ return {
1055
+ kind: "icon",
1056
+ key: params.key,
1057
+ required: params.required,
1058
+ iconLibraries: customKind.iconLibraries
1059
+ };
1060
+ }
1061
+ return void 0;
1062
+ }
1063
+ function resolveAstroObjectSchema(schema) {
1064
+ if (!schema) {
1065
+ return void 0;
1066
+ }
1067
+ const direct = asObjectSchema(schema);
1068
+ if (direct) {
1069
+ return direct;
1070
+ }
1071
+ const ref = typeof schema.$ref === "string" ? schema.$ref : void 0;
1072
+ if (!ref?.startsWith(ASTRO_DEF_PREFIX)) {
1073
+ return void 0;
1074
+ }
1075
+ const definitionKey = ref.slice(ASTRO_DEF_PREFIX.length);
1076
+ const definitions = asRecord(schema.definitions);
1077
+ const definitionSchema = definitions ? definitions[definitionKey] : void 0;
1078
+ return asObjectSchema(definitionSchema);
1079
+ }
1080
+ function resolveSchemaFields(schema, fieldUi) {
1081
+ const requiredFields = resolveRequiredFields(schema.required);
1082
+ const fields = [];
1083
+ for (const [key, rawPropertySchema] of Object.entries(schema.properties)) {
1084
+ if (key === "$schema") {
1085
+ continue;
1086
+ }
1087
+ const parsedProperty = parsePropertySchema(rawPropertySchema);
1088
+ const isRequired = requiredFields.has(key);
1089
+ if (!parsedProperty) {
1090
+ fields.push({
1091
+ kind: "unsupported",
1092
+ key,
1093
+ required: isRequired,
1094
+ reason: "invalid schema node"
1095
+ });
1096
+ continue;
1097
+ }
1098
+ const customField = resolveCustomFieldKind({
1099
+ key,
1100
+ property: parsedProperty,
1101
+ required: isRequired,
1102
+ fieldUi
1103
+ });
1104
+ if (customField) {
1105
+ fields.push(customField);
1106
+ continue;
1107
+ }
1108
+ if (isDateAnyOfSchema(parsedProperty)) {
1109
+ fields.push({ kind: "dateAnyOf", key, required: isRequired });
1110
+ continue;
1111
+ }
1112
+ if (parsedProperty.type === "string" && (parsedProperty.format === "date" || parsedProperty.format === "date-time")) {
1113
+ fields.push({ kind: "dateAnyOf", key, required: isRequired });
1114
+ continue;
1115
+ }
1116
+ if ((parsedProperty.type === "number" || parsedProperty.type === "integer") && parsedProperty.format === "unix-time") {
1117
+ fields.push({ kind: "dateAnyOf", key, required: isRequired });
1118
+ continue;
1119
+ }
1120
+ const enumValues = parsedProperty.enum;
1121
+ if (enumValues && enumValues.length > 0) {
1122
+ fields.push({
1123
+ kind: "enum",
1124
+ key,
1125
+ required: isRequired,
1126
+ options: enumValues
1127
+ });
1128
+ continue;
1129
+ }
1130
+ if (parsedProperty.type === "string") {
1131
+ fields.push({ kind: "string", key, required: isRequired });
1132
+ continue;
1133
+ }
1134
+ if (parsedProperty.type === "boolean") {
1135
+ fields.push({ kind: "boolean", key, required: isRequired });
1136
+ continue;
1137
+ }
1138
+ if (parsedProperty.type === "number" || parsedProperty.type === "integer") {
1139
+ fields.push({ kind: "number", key, required: isRequired });
1140
+ continue;
1141
+ }
1142
+ if (isStringArraySchema(parsedProperty)) {
1143
+ fields.push({ kind: "stringArray", key, required: isRequired });
1144
+ continue;
1145
+ }
1146
+ if (parsedProperty.type === "array") {
1147
+ fields.push({
1148
+ kind: "unsupported",
1149
+ key,
1150
+ required: isRequired,
1151
+ reason: "array items are not string"
1152
+ });
1153
+ continue;
1154
+ }
1155
+ fields.push({
1156
+ kind: "unsupported",
1157
+ key,
1158
+ required: isRequired,
1159
+ reason: "schema type not supported"
1160
+ });
1161
+ }
1162
+ return fields;
1163
+ }
1164
+ const SORT_STORAGE_KEY = "astro-md-editor:sort";
1165
+ function loadSortOption() {
1166
+ try {
1167
+ const stored = window.localStorage.getItem(SORT_STORAGE_KEY);
1168
+ if (stored) {
1169
+ return valueToSortOption(stored);
1170
+ }
1171
+ } catch {
1172
+ }
1173
+ return DEFAULT_SORT;
1174
+ }
1175
+ function saveSortOption(option) {
1176
+ try {
1177
+ window.localStorage.setItem(SORT_STORAGE_KEY, sortOptionToValue(option));
1178
+ } catch {
1179
+ }
1180
+ }
1181
+ function LeftSidebar({
1182
+ collections,
1183
+ selectedCollectionName,
1184
+ selectedFileId,
1185
+ onSelectCollection,
1186
+ onSelectFile,
1187
+ onCreateFile,
1188
+ onDeleteFile,
1189
+ isCreatingFile,
1190
+ deletingFileId,
1191
+ schema,
1192
+ fieldUi
1193
+ }) {
1194
+ const [deleteCandidate, setDeleteCandidate] = reactExports.useState(null);
1195
+ const [searchQuery, setSearchQuery] = reactExports.useState("");
1196
+ const [sortOption, setSortOption] = reactExports.useState(DEFAULT_SORT);
1197
+ reactExports.useEffect(() => {
1198
+ setSortOption(loadSortOption());
1199
+ }, []);
1200
+ reactExports.useEffect(() => {
1201
+ setSearchQuery("");
1202
+ }, [selectedCollectionName]);
1203
+ const selectedCollection = collections.find(
1204
+ (collection) => collection.name === selectedCollectionName
1205
+ );
1206
+ const allFiles = getSortedCollectionFiles(selectedCollection, sortOption);
1207
+ const files = searchQuery.trim() ? allFiles.filter((file) => {
1208
+ const q = searchQuery.toLowerCase();
1209
+ return getFileDisplayLabel(file).toLowerCase().includes(q) || file.id.toLowerCase().includes(q);
1210
+ }) : allFiles;
1211
+ const sortableFields = reactExports.useMemo(() => {
1212
+ if (!schema) return [];
1213
+ const objectSchema = resolveAstroObjectSchema(
1214
+ schema
1215
+ );
1216
+ if (!objectSchema) return [];
1217
+ const resolved = resolveSchemaFields(objectSchema, fieldUi);
1218
+ return getSortableFields(resolved);
1219
+ }, [schema, fieldUi]);
1220
+ const [sortOpen, setSortOpen] = reactExports.useState(false);
1221
+ const handleSortSelect = reactExports.useCallback((value) => {
1222
+ const next = valueToSortOption(value);
1223
+ setSortOption(next);
1224
+ saveSortOption(next);
1225
+ setSortOpen(false);
1226
+ }, []);
1227
+ const sortValue = sortOptionToValue(sortOption);
1228
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex h-full flex-col gap-3", children: [
1229
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
1230
+ Select,
1231
+ {
1232
+ value: selectedCollectionName,
1233
+ onValueChange: (nextCollectionName) => {
1234
+ if (!nextCollectionName) {
1235
+ return;
1236
+ }
1237
+ onSelectCollection(nextCollectionName);
1238
+ },
1239
+ children: [
1240
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SelectTrigger, { className: "bg-muted/50 focus-visible:ring-ring/35 w-full border-transparent shadow-none focus-visible:border-transparent focus-visible:ring-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SelectValue, { placeholder: "Select a collection" }) }),
1241
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SelectContent, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(SelectGroup, { children: collections.map((collection) => /* @__PURE__ */ jsxRuntimeExports.jsx(SelectItem, { value: collection.name, children: collection.name }, collection.name)) }) })
1242
+ ]
1243
+ }
1244
+ ),
1245
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative", children: [
1246
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Search, { className: "text-muted-foreground pointer-events-none absolute top-1/2 left-2 size-3.5 -translate-y-1/2" }),
1247
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1248
+ Input,
1249
+ {
1250
+ id: "file-search-input",
1251
+ placeholder: "Search files...",
1252
+ value: searchQuery,
1253
+ onChange: (e) => setSearchQuery(e.target.value),
1254
+ className: "h-7 pr-7 pl-7 text-xs"
1255
+ }
1256
+ ),
1257
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Popover, { open: sortOpen, onOpenChange: setSortOpen, children: [
1258
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1259
+ PopoverTrigger,
1260
+ {
1261
+ className: "text-muted-foreground hover:text-foreground absolute top-1/2 right-0.5 flex size-6 -translate-y-1/2 cursor-pointer items-center justify-center rounded-md",
1262
+ "aria-label": "Sort files",
1263
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(ArrowUpDown, { className: "size-3.5" })
1264
+ }
1265
+ ),
1266
+ /* @__PURE__ */ jsxRuntimeExports.jsx(PopoverContent, { align: "end", className: "w-52 p-0", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Command, { children: [
1267
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CommandInput, { placeholder: "Search sort..." }),
1268
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CommandEmpty, { children: "No sort option found." }),
1269
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CommandGroup, { heading: "Sort", children: PRESET_SORT_OPTIONS.map((preset) => {
1270
+ const val = sortOptionToValue(preset.option);
1271
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
1272
+ CommandItem,
1273
+ {
1274
+ value: val,
1275
+ "data-checked": sortValue === val,
1276
+ onSelect: handleSortSelect,
1277
+ children: preset.label
1278
+ },
1279
+ val
1280
+ );
1281
+ }) }),
1282
+ sortableFields.length > 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
1283
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CommandSeparator, {}),
1284
+ /* @__PURE__ */ jsxRuntimeExports.jsx(CommandGroup, { heading: "Frontmatter fields", children: sortableFields.map((field) => {
1285
+ const ascVal = `field:${field.key}:asc`;
1286
+ const descVal = `field:${field.key}:desc`;
1287
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(reactExports.Fragment, { children: [
1288
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
1289
+ CommandItem,
1290
+ {
1291
+ value: ascVal,
1292
+ "data-checked": sortValue === ascVal,
1293
+ onSelect: handleSortSelect,
1294
+ children: [
1295
+ field.label,
1296
+ " (asc)"
1297
+ ]
1298
+ }
1299
+ ),
1300
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
1301
+ CommandItem,
1302
+ {
1303
+ value: descVal,
1304
+ "data-checked": sortValue === descVal,
1305
+ onSelect: handleSortSelect,
1306
+ children: [
1307
+ field.label,
1308
+ " (desc)"
1309
+ ]
1310
+ }
1311
+ )
1312
+ ] }, field.key);
1313
+ }) })
1314
+ ] }) : null
1315
+ ] }) })
1316
+ ] })
1317
+ ] }),
1318
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "bg-background/35 min-h-0 flex-1 overflow-auto rounded-md p-1", children: files.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-muted-foreground px-2 py-2 text-sm", children: searchQuery.trim() ? "No matching files." : "No files in this collection." }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-0.5", children: files.map((file) => {
1319
+ const isActive = file.id === selectedFileId;
1320
+ const title = getFileDisplayLabel(file);
1321
+ const slug = file.id;
1322
+ const isMdxFile = /\.mdx$/i.test(file.filePath);
1323
+ const isDraft = file.data.draft === true;
1324
+ const isDeleting = deletingFileId === file.id;
1325
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "group/item relative", children: [
1326
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1327
+ Button,
1328
+ {
1329
+ type: "button",
1330
+ variant: "ghost",
1331
+ className: cn(
1332
+ "h-auto w-full justify-start border-0 px-2.5 py-3 pr-9 text-left shadow-none",
1333
+ "hover:bg-background/70",
1334
+ isActive && "bg-muted text-foreground hover:bg-muted/55"
1335
+ ),
1336
+ onClick: () => onSelectFile(file.id),
1337
+ title: file.filePath,
1338
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex w-full min-w-0 flex-col items-start gap-0.5", children: [
1339
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-full truncate text-sm font-normal", children: title }),
1340
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex w-full min-w-0 items-center gap-1.5", children: [
1341
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-muted-foreground min-w-0 flex-1 truncate text-xs", children: slug }),
1342
+ isMdxFile ? /* @__PURE__ */ jsxRuntimeExports.jsx(
1343
+ Badge,
1344
+ {
1345
+ variant: "secondary",
1346
+ className: "bg-muted h-4 border-transparent px-1.5 text-[10px] leading-none",
1347
+ children: "MDX"
1348
+ }
1349
+ ) : null,
1350
+ isDraft ? /* @__PURE__ */ jsxRuntimeExports.jsx(
1351
+ Badge,
1352
+ {
1353
+ variant: "outline",
1354
+ className: "h-4 border-transparent bg-amber-100 px-1.5 text-[10px] leading-none text-amber-900 dark:bg-amber-900/40 dark:text-amber-200",
1355
+ children: "Draft"
1356
+ }
1357
+ ) : null
1358
+ ] })
1359
+ ] })
710
1360
  }
711
1361
  ),
712
1362
  /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -740,124 +1390,61 @@ function LeftSidebar({
740
1390
  {
741
1391
  type: "button",
742
1392
  variant: "outline",
743
- className: "w-full",
744
- disabled: !selectedCollection || isCreatingFile,
745
- onClick: async () => {
746
- const rawSlug = window.prompt("Enter slug (e.g. my-new-post)");
747
- if (!rawSlug) {
748
- return;
749
- }
750
- await onCreateFile(rawSlug);
751
- },
752
- children: [
753
- isCreatingFile ? /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-4 animate-spin" }) : null,
754
- "New file"
755
- ]
756
- }
757
- ),
758
- /* @__PURE__ */ jsxRuntimeExports.jsx(
759
- AlertDialog,
760
- {
761
- open: deleteCandidate !== null,
762
- onOpenChange: (open) => {
763
- if (!open) {
764
- setDeleteCandidate(null);
765
- }
766
- },
767
- children: /* @__PURE__ */ jsxRuntimeExports.jsxs(AlertDialogContent, { children: [
768
- /* @__PURE__ */ jsxRuntimeExports.jsxs(AlertDialogHeader, { children: [
769
- /* @__PURE__ */ jsxRuntimeExports.jsx(AlertDialogTitle, { children: "Delete file?" }),
770
- /* @__PURE__ */ jsxRuntimeExports.jsxs(AlertDialogDescription, { children: [
771
- 'This will permanently delete "',
772
- deleteCandidate?.label,
773
- '" from disk.'
774
- ] })
775
- ] }),
776
- /* @__PURE__ */ jsxRuntimeExports.jsxs(AlertDialogFooter, { children: [
777
- /* @__PURE__ */ jsxRuntimeExports.jsx(AlertDialogCancel, { disabled: !!deletingFileId, children: "Cancel" }),
778
- /* @__PURE__ */ jsxRuntimeExports.jsx(
779
- AlertDialogAction,
780
- {
781
- variant: "destructive",
782
- disabled: !deleteCandidate || !!deletingFileId,
783
- onClick: async () => {
784
- if (!deleteCandidate) {
785
- return;
786
- }
787
- await onDeleteFile(deleteCandidate.id);
788
- setDeleteCandidate(null);
789
- },
790
- children: "Delete"
791
- }
792
- )
793
- ] })
794
- ] })
795
- }
796
- )
797
- ] });
798
- }
799
- function Textarea({ className, ...props }) {
800
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
801
- "textarea",
802
- {
803
- "data-slot": "textarea",
804
- className: cn(
805
- "border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 disabled:bg-input/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 flex field-sizing-content min-h-16 w-full rounded-lg border bg-transparent px-2.5 py-2 text-base transition-colors outline-none focus-visible:ring-3 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:ring-3 md:text-sm",
806
- className
807
- ),
808
- ...props
809
- }
810
- );
811
- }
812
- function Input({ className, type, ...props }) {
813
- return /* @__PURE__ */ jsxRuntimeExports.jsx(
814
- Input$1,
815
- {
816
- type,
817
- "data-slot": "input",
818
- className: cn(
819
- "border-input file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 disabled:bg-input/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 h-8 w-full min-w-0 rounded-lg border bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:ring-3 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:ring-3 md:text-sm",
820
- className
821
- ),
822
- ...props
823
- }
824
- );
825
- }
826
- function Popover({ ...props }) {
827
- return /* @__PURE__ */ jsxRuntimeExports.jsx(PopoverRoot, { "data-slot": "popover", ...props });
828
- }
829
- function PopoverTrigger({ ...props }) {
830
- return /* @__PURE__ */ jsxRuntimeExports.jsx(PopoverTrigger$1, { "data-slot": "popover-trigger", ...props });
831
- }
832
- function PopoverContent({
833
- className,
834
- align = "center",
835
- alignOffset = 0,
836
- side = "bottom",
837
- sideOffset = 4,
838
- ...props
839
- }) {
840
- return /* @__PURE__ */ jsxRuntimeExports.jsx(PopoverPortal, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(
841
- PopoverPositioner,
842
- {
843
- align,
844
- alignOffset,
845
- side,
846
- sideOffset,
847
- className: "isolate z-50",
848
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(
849
- PopoverPopup,
850
- {
851
- "data-slot": "popover-content",
852
- className: cn(
853
- "bg-popover text-popover-foreground ring-foreground/10 data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 z-50 flex w-72 origin-(--transform-origin) flex-col gap-2.5 rounded-lg p-2.5 text-sm shadow-md ring-1 outline-hidden duration-100",
854
- className
855
- ),
856
- ...props
857
- }
858
- )
859
- }
860
- ) });
1393
+ className: "w-full",
1394
+ disabled: !selectedCollection || isCreatingFile,
1395
+ onClick: async () => {
1396
+ const rawSlug = window.prompt("Enter slug (e.g. my-new-post)");
1397
+ if (!rawSlug) {
1398
+ return;
1399
+ }
1400
+ await onCreateFile(rawSlug);
1401
+ },
1402
+ children: [
1403
+ isCreatingFile ? /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-4 animate-spin" }) : null,
1404
+ "New file"
1405
+ ]
1406
+ }
1407
+ ),
1408
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1409
+ AlertDialog,
1410
+ {
1411
+ open: deleteCandidate !== null,
1412
+ onOpenChange: (open) => {
1413
+ if (!open) {
1414
+ setDeleteCandidate(null);
1415
+ }
1416
+ },
1417
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs(AlertDialogContent, { children: [
1418
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(AlertDialogHeader, { children: [
1419
+ /* @__PURE__ */ jsxRuntimeExports.jsx(AlertDialogTitle, { children: "Delete file?" }),
1420
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(AlertDialogDescription, { children: [
1421
+ 'This will permanently delete "',
1422
+ deleteCandidate?.label,
1423
+ '" from disk.'
1424
+ ] })
1425
+ ] }),
1426
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(AlertDialogFooter, { children: [
1427
+ /* @__PURE__ */ jsxRuntimeExports.jsx(AlertDialogCancel, { disabled: !!deletingFileId, children: "Cancel" }),
1428
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1429
+ AlertDialogAction,
1430
+ {
1431
+ variant: "destructive",
1432
+ disabled: !deleteCandidate || !!deletingFileId,
1433
+ onClick: async () => {
1434
+ if (!deleteCandidate) {
1435
+ return;
1436
+ }
1437
+ await onDeleteFile(deleteCandidate.id);
1438
+ setDeleteCandidate(null);
1439
+ },
1440
+ children: "Delete"
1441
+ }
1442
+ )
1443
+ ] })
1444
+ ] })
1445
+ }
1446
+ )
1447
+ ] });
861
1448
  }
862
1449
  const MAX_ASSET_RESULTS = 120;
863
1450
  function isObjectRecord$4(value) {
@@ -2796,207 +3383,6 @@ const readFileRevisionServerFn = createServerFn({
2796
3383
  commitSha
2797
3384
  };
2798
3385
  }).handler(createSsrRpc("02ba027930daf730cf535415a08fab7365d58edddcc678dbcb19c72f990c25b5"));
2799
- const recordSchema = record(string(), unknown());
2800
- const jsonObjectSchema = object({
2801
- type: literal("object"),
2802
- properties: recordSchema,
2803
- required: array(string()).optional()
2804
- }).passthrough();
2805
- const propertySchema = object({
2806
- type: string().optional(),
2807
- format: string().optional(),
2808
- enum: array(string()).optional(),
2809
- anyOf: array(recordSchema).optional(),
2810
- items: recordSchema.optional()
2811
- }).passthrough();
2812
- const ASTRO_DEF_PREFIX = "#/definitions/";
2813
- function asRecord(value) {
2814
- const parsed = recordSchema.safeParse(value);
2815
- return parsed.success ? parsed.data : void 0;
2816
- }
2817
- function parsePropertySchema(value) {
2818
- const parsed = propertySchema.safeParse(value);
2819
- return parsed.success ? parsed.data : void 0;
2820
- }
2821
- function asObjectSchema(value) {
2822
- const parsed = jsonObjectSchema.safeParse(value);
2823
- return parsed.success ? parsed.data : void 0;
2824
- }
2825
- function isStringArraySchema(schema) {
2826
- if (schema.type !== "array") {
2827
- return false;
2828
- }
2829
- const itemSchema = parsePropertySchema(schema.items);
2830
- return itemSchema?.type === "string";
2831
- }
2832
- function isDateAnyOfSchema(schema) {
2833
- if (!schema.anyOf || schema.anyOf.length === 0) {
2834
- return false;
2835
- }
2836
- let hasDateOption = false;
2837
- for (const option of schema.anyOf) {
2838
- const candidate = parsePropertySchema(option);
2839
- if (!candidate) {
2840
- return false;
2841
- }
2842
- if (candidate.type === "string" && (candidate.format === "date" || candidate.format === "date-time")) {
2843
- hasDateOption = true;
2844
- continue;
2845
- }
2846
- if ((candidate.type === "integer" || candidate.type === "number") && candidate.format === "unix-time") {
2847
- hasDateOption = true;
2848
- continue;
2849
- }
2850
- if (candidate.type === "null") {
2851
- continue;
2852
- }
2853
- return false;
2854
- }
2855
- return hasDateOption;
2856
- }
2857
- function resolveRequiredFields(required) {
2858
- const parsed = array(string()).safeParse(required);
2859
- return new Set(parsed.success ? parsed.data : []);
2860
- }
2861
- function resolveCustomFieldKind(params) {
2862
- const customKind = params.fieldUi?.[params.key];
2863
- if (!customKind) {
2864
- return void 0;
2865
- }
2866
- if (customKind.kind === "image" && params.property.type === "string") {
2867
- return {
2868
- kind: "image",
2869
- key: params.key,
2870
- required: params.required,
2871
- sourceMode: customKind.mode
2872
- };
2873
- }
2874
- if (customKind.kind === "imageArray" && isStringArraySchema(params.property)) {
2875
- return {
2876
- kind: "imageArray",
2877
- key: params.key,
2878
- required: params.required,
2879
- sourceMode: customKind.mode
2880
- };
2881
- }
2882
- if (customKind.kind === "color" && params.property.type === "string") {
2883
- return {
2884
- kind: "color",
2885
- key: params.key,
2886
- required: params.required
2887
- };
2888
- }
2889
- if (customKind.kind === "icon" && params.property.type === "string") {
2890
- return {
2891
- kind: "icon",
2892
- key: params.key,
2893
- required: params.required,
2894
- iconLibraries: customKind.iconLibraries
2895
- };
2896
- }
2897
- return void 0;
2898
- }
2899
- function resolveAstroObjectSchema(schema) {
2900
- if (!schema) {
2901
- return void 0;
2902
- }
2903
- const direct = asObjectSchema(schema);
2904
- if (direct) {
2905
- return direct;
2906
- }
2907
- const ref = typeof schema.$ref === "string" ? schema.$ref : void 0;
2908
- if (!ref?.startsWith(ASTRO_DEF_PREFIX)) {
2909
- return void 0;
2910
- }
2911
- const definitionKey = ref.slice(ASTRO_DEF_PREFIX.length);
2912
- const definitions = asRecord(schema.definitions);
2913
- const definitionSchema = definitions ? definitions[definitionKey] : void 0;
2914
- return asObjectSchema(definitionSchema);
2915
- }
2916
- function resolveSchemaFields(schema, fieldUi) {
2917
- const requiredFields = resolveRequiredFields(schema.required);
2918
- const fields = [];
2919
- for (const [key, rawPropertySchema] of Object.entries(schema.properties)) {
2920
- if (key === "$schema") {
2921
- continue;
2922
- }
2923
- const parsedProperty = parsePropertySchema(rawPropertySchema);
2924
- const isRequired = requiredFields.has(key);
2925
- if (!parsedProperty) {
2926
- fields.push({
2927
- kind: "unsupported",
2928
- key,
2929
- required: isRequired,
2930
- reason: "invalid schema node"
2931
- });
2932
- continue;
2933
- }
2934
- const customField = resolveCustomFieldKind({
2935
- key,
2936
- property: parsedProperty,
2937
- required: isRequired,
2938
- fieldUi
2939
- });
2940
- if (customField) {
2941
- fields.push(customField);
2942
- continue;
2943
- }
2944
- if (isDateAnyOfSchema(parsedProperty)) {
2945
- fields.push({ kind: "dateAnyOf", key, required: isRequired });
2946
- continue;
2947
- }
2948
- if (parsedProperty.type === "string" && (parsedProperty.format === "date" || parsedProperty.format === "date-time")) {
2949
- fields.push({ kind: "dateAnyOf", key, required: isRequired });
2950
- continue;
2951
- }
2952
- if ((parsedProperty.type === "number" || parsedProperty.type === "integer") && parsedProperty.format === "unix-time") {
2953
- fields.push({ kind: "dateAnyOf", key, required: isRequired });
2954
- continue;
2955
- }
2956
- const enumValues = parsedProperty.enum;
2957
- if (enumValues && enumValues.length > 0) {
2958
- fields.push({
2959
- kind: "enum",
2960
- key,
2961
- required: isRequired,
2962
- options: enumValues
2963
- });
2964
- continue;
2965
- }
2966
- if (parsedProperty.type === "string") {
2967
- fields.push({ kind: "string", key, required: isRequired });
2968
- continue;
2969
- }
2970
- if (parsedProperty.type === "boolean") {
2971
- fields.push({ kind: "boolean", key, required: isRequired });
2972
- continue;
2973
- }
2974
- if (parsedProperty.type === "number" || parsedProperty.type === "integer") {
2975
- fields.push({ kind: "number", key, required: isRequired });
2976
- continue;
2977
- }
2978
- if (isStringArraySchema(parsedProperty)) {
2979
- fields.push({ kind: "stringArray", key, required: isRequired });
2980
- continue;
2981
- }
2982
- if (parsedProperty.type === "array") {
2983
- fields.push({
2984
- kind: "unsupported",
2985
- key,
2986
- required: isRequired,
2987
- reason: "array items are not string"
2988
- });
2989
- continue;
2990
- }
2991
- fields.push({
2992
- kind: "unsupported",
2993
- key,
2994
- required: isRequired,
2995
- reason: "schema type not supported"
2996
- });
2997
- }
2998
- return fields;
2999
- }
3000
3386
  function cloneRecord(value) {
3001
3387
  return JSON.parse(JSON.stringify(value));
3002
3388
  }
@@ -4772,7 +5158,8 @@ function App() {
4772
5158
  id: result.fileId,
4773
5159
  filePath: result.filePath,
4774
5160
  data: {},
4775
- content: ""
5161
+ content: "",
5162
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
4776
5163
  }]
4777
5164
  };
4778
5165
  }));
@@ -4799,7 +5186,7 @@ function App() {
4799
5186
  "editor-main-panel": 64,
4800
5187
  "editor-right-sidebar": 18
4801
5188
  }, children: [
4802
- /* @__PURE__ */ jsxRuntimeExports.jsx(ResizablePanel, { id: "editor-left-sidebar", panelRef: leftPanelRef, collapsible: true, collapsedSize: 0, defaultSize: "18%", minSize: "14%", maxSize: "40%", className: "min-w-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx("aside", { className: "bg-background/55 flex h-full flex-col overflow-hidden rounded-xl px-2.5 py-3 backdrop-blur-sm", children: /* @__PURE__ */ jsxRuntimeExports.jsx(LeftSidebar, { collections, selectedCollectionName: selectedCollection?.name, selectedFileId: selectedFile?.id, onSelectCollection: selectCollection, onSelectFile: selectFile, onCreateFile: handleCreateFile, onDeleteFile: handleDeleteFile, isCreatingFile, deletingFileId }) }) }),
5189
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ResizablePanel, { id: "editor-left-sidebar", panelRef: leftPanelRef, collapsible: true, collapsedSize: 0, defaultSize: "18%", minSize: "14%", maxSize: "40%", className: "min-w-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx("aside", { className: "bg-background/55 flex h-full flex-col overflow-hidden rounded-xl px-2.5 py-3 backdrop-blur-sm", children: /* @__PURE__ */ jsxRuntimeExports.jsx(LeftSidebar, { collections, selectedCollectionName: selectedCollection?.name, selectedFileId: selectedFile?.id, onSelectCollection: selectCollection, onSelectFile: selectFile, onCreateFile: handleCreateFile, onDeleteFile: handleDeleteFile, isCreatingFile, deletingFileId, schema: selectedCollection?.schema, fieldUi: selectedCollection?.fieldUi }) }) }),
4803
5190
  /* @__PURE__ */ jsxRuntimeExports.jsx(ResizableHandle, { withHandle: true, className: cn(leftOpen ? "mx-1 w-2 bg-transparent" : "mx-0 w-0", !leftOpen && "pointer-events-none opacity-0") }),
4804
5191
  /* @__PURE__ */ jsxRuntimeExports.jsx(ResizablePanel, { id: "editor-main-panel", minSize: "30%", className: "min-w-0", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("main", { className: "bg-background/75 flex h-full w-full min-w-0 flex-1 flex-col overflow-hidden rounded-xl px-3 py-2 backdrop-blur-sm", children: [
4805
5192
  /* @__PURE__ */ jsxRuntimeExports.jsxs("header", { className: "border-border/45 flex items-center justify-between gap-3 border-b pb-2", children: [