@webdevarif/dashui 0.2.4 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -96,6 +96,11 @@ __export(index_exports, {
96
96
  Popover: () => Popover,
97
97
  PopoverContent: () => PopoverContent,
98
98
  PopoverTrigger: () => PopoverTrigger,
99
+ PostEditorShell: () => PostEditorShell,
100
+ PostFiltersBar: () => PostFiltersBar,
101
+ PostListTable: () => PostListTable,
102
+ PostSidebarSection: () => PostSidebarSection,
103
+ PostStatusBadge: () => PostStatusBadge,
99
104
  SearchBar: () => SearchBar,
100
105
  Select: () => Select,
101
106
  SelectContent: () => SelectContent,
@@ -110,6 +115,7 @@ __export(index_exports, {
110
115
  Separator: () => Separator3,
111
116
  Sidebar: () => Sidebar,
112
117
  Skeleton: () => Skeleton2,
118
+ SlugInput: () => SlugInput,
113
119
  Stats: () => Stats,
114
120
  StorageBar: () => StorageBar,
115
121
  Switch: () => Switch,
@@ -2049,14 +2055,22 @@ function MediaPickerDialog({
2049
2055
  const fileInputRef = React20.useRef(null);
2050
2056
  const dragCounterRef = React20.useRef(0);
2051
2057
  React20.useEffect(() => {
2052
- if (open) {
2053
- setLocalSelected(new Set(initialSelected));
2054
- } else {
2058
+ if (!open) {
2055
2059
  setLocalSelected(/* @__PURE__ */ new Set());
2056
2060
  setIsDragging(false);
2057
2061
  dragCounterRef.current = 0;
2058
2062
  }
2059
2063
  }, [open]);
2064
+ const prevInitialRef = React20.useRef("");
2065
+ React20.useEffect(() => {
2066
+ if (!open) return;
2067
+ const key = initialSelected.join(",");
2068
+ if (key === prevInitialRef.current) return;
2069
+ prevInitialRef.current = key;
2070
+ if (initialSelected.length > 0) {
2071
+ setLocalSelected(new Set(initialSelected));
2072
+ }
2073
+ }, [open, initialSelected]);
2060
2074
  const handleDragEnter = (e) => {
2061
2075
  e.preventDefault();
2062
2076
  e.stopPropagation();
@@ -2567,6 +2581,730 @@ function ConfirmDialog({
2567
2581
  ] }) });
2568
2582
  }
2569
2583
 
2584
+ // src/components/content/post-status-badge.tsx
2585
+ var import_jsx_runtime42 = require("react/jsx-runtime");
2586
+ var statusConfig = {
2587
+ DRAFT: {
2588
+ label: "Draft",
2589
+ container: "bg-muted text-muted-foreground",
2590
+ dot: "bg-gray-400"
2591
+ },
2592
+ PUBLISHED: {
2593
+ label: "Published",
2594
+ container: "bg-primary/10 text-primary",
2595
+ dot: "bg-primary animate-pulse"
2596
+ },
2597
+ SCHEDULED: {
2598
+ label: "Scheduled",
2599
+ container: "bg-blue-50 text-blue-600 dark:bg-blue-950 dark:text-blue-400",
2600
+ dot: "bg-blue-500 dark:bg-blue-400"
2601
+ },
2602
+ ARCHIVED: {
2603
+ label: "Archived",
2604
+ container: "bg-amber-50 text-amber-600 dark:bg-amber-950 dark:text-amber-400",
2605
+ dot: "bg-amber-500 dark:bg-amber-400"
2606
+ }
2607
+ };
2608
+ var sizeConfig = {
2609
+ sm: "text-[10px] px-1.5 py-0.5",
2610
+ md: "text-xs px-2 py-1"
2611
+ };
2612
+ function PostStatusBadge({
2613
+ status,
2614
+ size = "md",
2615
+ className
2616
+ }) {
2617
+ const config = statusConfig[status];
2618
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
2619
+ "span",
2620
+ {
2621
+ className: cn(
2622
+ "inline-flex items-center gap-1.5 rounded-full font-medium",
2623
+ config.container,
2624
+ sizeConfig[size],
2625
+ className
2626
+ ),
2627
+ children: [
2628
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
2629
+ "span",
2630
+ {
2631
+ className: cn("inline-block rounded-full", config.dot, {
2632
+ "w-1.5 h-1.5": size === "md",
2633
+ "w-1 h-1": size === "sm"
2634
+ })
2635
+ }
2636
+ ),
2637
+ config.label
2638
+ ]
2639
+ }
2640
+ );
2641
+ }
2642
+
2643
+ // src/components/content/post-list-table.tsx
2644
+ var React21 = __toESM(require("react"));
2645
+
2646
+ // src/components/Skeleton.tsx
2647
+ var import_jsx_runtime43 = require("react/jsx-runtime");
2648
+ function Skeleton2({ width = "100%", height = 16, rounded, style }) {
2649
+ return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
2650
+ "div",
2651
+ {
2652
+ style: {
2653
+ width,
2654
+ height,
2655
+ background: "var(--muted, #e5e7eb)",
2656
+ borderRadius: rounded ?? "var(--radius, 0.5rem)",
2657
+ overflow: "hidden",
2658
+ position: "relative",
2659
+ flexShrink: 0,
2660
+ ...style
2661
+ },
2662
+ children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
2663
+ "div",
2664
+ {
2665
+ style: {
2666
+ position: "absolute",
2667
+ inset: 0,
2668
+ background: "linear-gradient(90deg, transparent 0%, color-mix(in oklab, var(--background, #fff) 40%, transparent) 50%, transparent 100%)",
2669
+ animation: "dashui-shimmer 1.6s ease-in-out infinite"
2670
+ }
2671
+ }
2672
+ )
2673
+ }
2674
+ );
2675
+ }
2676
+
2677
+ // src/components/content/post-list-table.tsx
2678
+ var import_jsx_runtime44 = require("react/jsx-runtime");
2679
+ function IconEdit() {
2680
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
2681
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("path", { d: "M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" }),
2682
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("path", { d: "M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" })
2683
+ ] });
2684
+ }
2685
+ function IconTrash() {
2686
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
2687
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("polyline", { points: "3 6 5 6 21 6" }),
2688
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("path", { d: "M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6" }),
2689
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("path", { d: "M10 11v6" }),
2690
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("path", { d: "M14 11v6" }),
2691
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("path", { d: "M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2" })
2692
+ ] });
2693
+ }
2694
+ function IconCopy() {
2695
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
2696
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", ry: "2" }),
2697
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
2698
+ ] });
2699
+ }
2700
+ function IconMoreHorizontal() {
2701
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
2702
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("circle", { cx: "5", cy: "12", r: "1", fill: "currentColor" }),
2703
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("circle", { cx: "12", cy: "12", r: "1", fill: "currentColor" }),
2704
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("circle", { cx: "19", cy: "12", r: "1", fill: "currentColor" })
2705
+ ] });
2706
+ }
2707
+ function IconChevronRight() {
2708
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("polyline", { points: "9 18 15 12 9 6" }) });
2709
+ }
2710
+ function IconImage() {
2711
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
2712
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }),
2713
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("circle", { cx: "8.5", cy: "8.5", r: "1.5" }),
2714
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("polyline", { points: "21 15 16 10 5 21" })
2715
+ ] });
2716
+ }
2717
+ function IconPlus() {
2718
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
2719
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("line", { x1: "12", y1: "5", x2: "12", y2: "19" }),
2720
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
2721
+ ] });
2722
+ }
2723
+ function formatDate(date) {
2724
+ return new Date(date).toLocaleDateString("en-US", {
2725
+ year: "numeric",
2726
+ month: "short",
2727
+ day: "numeric"
2728
+ });
2729
+ }
2730
+ function getInitials(name) {
2731
+ return name.split(" ").slice(0, 2).map((w) => w[0]?.toUpperCase() ?? "").join("");
2732
+ }
2733
+ function RowActions({ post, onEdit, onDelete, onDuplicate, onStatusChange }) {
2734
+ const [open, setOpen] = React21.useState(false);
2735
+ const [statusOpen, setStatusOpen] = React21.useState(false);
2736
+ const ref = React21.useRef(null);
2737
+ React21.useEffect(() => {
2738
+ if (!open) return;
2739
+ function handleClick(e) {
2740
+ if (ref.current && !ref.current.contains(e.target)) {
2741
+ setOpen(false);
2742
+ setStatusOpen(false);
2743
+ }
2744
+ }
2745
+ document.addEventListener("mousedown", handleClick);
2746
+ return () => document.removeEventListener("mousedown", handleClick);
2747
+ }, [open]);
2748
+ const statusOptions = [
2749
+ { label: "Draft", value: "DRAFT" },
2750
+ { label: "Publish", value: "PUBLISHED" },
2751
+ { label: "Archive", value: "ARCHIVED" }
2752
+ ];
2753
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "relative flex items-center gap-1", ref, children: [
2754
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
2755
+ "button",
2756
+ {
2757
+ onClick: () => onEdit?.(post.id),
2758
+ className: "inline-flex items-center justify-center h-7 w-7 rounded-md text-muted-foreground hover:bg-accent hover:text-foreground transition-colors",
2759
+ title: "Edit",
2760
+ children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(IconEdit, {})
2761
+ }
2762
+ ),
2763
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
2764
+ "button",
2765
+ {
2766
+ onClick: () => {
2767
+ setOpen((v) => !v);
2768
+ setStatusOpen(false);
2769
+ },
2770
+ className: "inline-flex items-center justify-center h-7 w-7 rounded-md text-muted-foreground hover:bg-accent hover:text-foreground transition-colors",
2771
+ title: "More actions",
2772
+ children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(IconMoreHorizontal, {})
2773
+ }
2774
+ ),
2775
+ open && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "absolute right-0 top-8 z-50 min-w-[160px] rounded-lg border border-border bg-card shadow-md py-1", children: [
2776
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
2777
+ "button",
2778
+ {
2779
+ onClick: () => {
2780
+ onDuplicate?.(post.id);
2781
+ setOpen(false);
2782
+ },
2783
+ className: "flex w-full items-center gap-2 px-3 py-1.5 text-sm hover:bg-accent transition-colors",
2784
+ children: [
2785
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(IconCopy, {}),
2786
+ "Duplicate"
2787
+ ]
2788
+ }
2789
+ ),
2790
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "relative", children: [
2791
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
2792
+ "button",
2793
+ {
2794
+ onMouseEnter: () => setStatusOpen(true),
2795
+ onMouseLeave: () => setStatusOpen(false),
2796
+ onClick: () => setStatusOpen((v) => !v),
2797
+ className: "flex w-full items-center justify-between gap-2 px-3 py-1.5 text-sm hover:bg-accent transition-colors",
2798
+ children: [
2799
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { children: "Change status" }),
2800
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(IconChevronRight, {})
2801
+ ]
2802
+ }
2803
+ ),
2804
+ statusOpen && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
2805
+ "div",
2806
+ {
2807
+ className: "absolute left-full top-0 z-50 min-w-[130px] rounded-lg border border-border bg-card shadow-md py-1",
2808
+ onMouseEnter: () => setStatusOpen(true),
2809
+ onMouseLeave: () => setStatusOpen(false),
2810
+ children: statusOptions.map((opt) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
2811
+ "button",
2812
+ {
2813
+ onClick: () => {
2814
+ onStatusChange?.(post.id, opt.value);
2815
+ setOpen(false);
2816
+ setStatusOpen(false);
2817
+ },
2818
+ className: cn(
2819
+ "flex w-full items-center gap-2 px-3 py-1.5 text-sm hover:bg-accent transition-colors",
2820
+ post.status === opt.value && "text-primary font-medium"
2821
+ ),
2822
+ children: opt.label
2823
+ },
2824
+ opt.value
2825
+ ))
2826
+ }
2827
+ )
2828
+ ] }),
2829
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "my-1 border-t border-border" }),
2830
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
2831
+ "button",
2832
+ {
2833
+ onClick: () => {
2834
+ onDelete?.(post.id);
2835
+ setOpen(false);
2836
+ },
2837
+ className: "flex w-full items-center gap-2 px-3 py-1.5 text-sm text-destructive hover:bg-destructive/10 transition-colors",
2838
+ children: [
2839
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(IconTrash, {}),
2840
+ "Delete"
2841
+ ]
2842
+ }
2843
+ )
2844
+ ] })
2845
+ ] });
2846
+ }
2847
+ function SkeletonRow() {
2848
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("tr", { children: [
2849
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("td", { className: "px-4 py-3", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Skeleton2, { className: "w-10 h-10 rounded-lg" }) }),
2850
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("td", { className: "px-4 py-3", children: [
2851
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Skeleton2, { className: "h-4 w-40 mb-1.5" }),
2852
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Skeleton2, { className: "h-3 w-24" })
2853
+ ] }),
2854
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("td", { className: "px-4 py-3", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Skeleton2, { className: "h-5 w-20 rounded-full" }) }),
2855
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("td", { className: "px-4 py-3", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex items-center gap-2", children: [
2856
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Skeleton2, { className: "w-6 h-6 rounded-full" }),
2857
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Skeleton2, { className: "h-4 w-20" })
2858
+ ] }) }),
2859
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("td", { className: "px-4 py-3", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Skeleton2, { className: "h-4 w-24" }) }),
2860
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("td", { className: "px-4 py-3", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex gap-1", children: [
2861
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Skeleton2, { className: "w-7 h-7 rounded-md" }),
2862
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(Skeleton2, { className: "w-7 h-7 rounded-md" })
2863
+ ] }) })
2864
+ ] });
2865
+ }
2866
+ function PostListTable({
2867
+ posts,
2868
+ loading = false,
2869
+ singularLabel = "Post",
2870
+ onEdit,
2871
+ onDelete,
2872
+ onDuplicate,
2873
+ onStatusChange,
2874
+ emptyMessage,
2875
+ emptyIcon,
2876
+ onNewPost,
2877
+ newPostLabel,
2878
+ className
2879
+ }) {
2880
+ const isEmpty = !loading && posts.length === 0;
2881
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: cn("w-full overflow-x-auto rounded-lg border border-border bg-card", className), children: [
2882
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("table", { className: "w-full text-sm", children: [
2883
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("tr", { className: "border-b border-border bg-muted/40", children: [
2884
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground w-14", children: "Image" }),
2885
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Title" }),
2886
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Status" }),
2887
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Author" }),
2888
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Date" }),
2889
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("th", { className: "px-4 py-2.5 text-right text-xs font-medium text-muted-foreground", children: "Actions" })
2890
+ ] }) }),
2891
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("tbody", { children: loading ? Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(SkeletonRow, {}, i)) : isEmpty ? null : posts.map((post) => {
2892
+ const date = post.status === "PUBLISHED" && post.publishedAt ? formatDate(post.publishedAt) : formatDate(post.createdAt);
2893
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
2894
+ "tr",
2895
+ {
2896
+ className: "border-b border-border last:border-0 hover:bg-muted/30 transition-colors",
2897
+ children: [
2898
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("td", { className: "px-4 py-3", children: post.featuredImageUrl ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
2899
+ "img",
2900
+ {
2901
+ src: post.featuredImageUrl,
2902
+ alt: post.title,
2903
+ className: "w-10 h-10 rounded-lg object-cover"
2904
+ }
2905
+ ) : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "w-10 h-10 rounded-lg bg-muted flex items-center justify-center text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(IconImage, {}) }) }),
2906
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("td", { className: "px-4 py-3", children: [
2907
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "font-medium text-foreground leading-tight truncate max-w-[240px]", children: post.title }),
2908
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "text-xs text-muted-foreground mt-0.5 truncate max-w-[240px]", children: [
2909
+ "/",
2910
+ post.slug
2911
+ ] })
2912
+ ] }),
2913
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("td", { className: "px-4 py-3", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(PostStatusBadge, { status: post.status, size: "sm" }) }),
2914
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("td", { className: "px-4 py-3", children: post.author ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex items-center gap-2", children: [
2915
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "w-6 h-6 rounded-full bg-primary/20 text-primary flex items-center justify-center text-[10px] font-semibold shrink-0", children: getInitials(post.author) }),
2916
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "text-sm text-foreground truncate max-w-[100px]", children: post.author })
2917
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "text-muted-foreground text-xs", children: "\u2014" }) }),
2918
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("td", { className: "px-4 py-3 text-sm text-muted-foreground whitespace-nowrap", children: date }),
2919
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("td", { className: "px-4 py-3", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "flex justify-end", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
2920
+ RowActions,
2921
+ {
2922
+ post,
2923
+ onEdit,
2924
+ onDelete,
2925
+ onDuplicate,
2926
+ onStatusChange
2927
+ }
2928
+ ) }) })
2929
+ ]
2930
+ },
2931
+ post.id
2932
+ );
2933
+ }) })
2934
+ ] }),
2935
+ isEmpty && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex flex-col items-center justify-center py-16 px-6 text-center", children: [
2936
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "text-muted-foreground mb-3", children: emptyIcon ?? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("svg", { width: "40", height: "40", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round", className: "opacity-40", children: [
2937
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
2938
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("polyline", { points: "14 2 14 8 20 8" }),
2939
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("line", { x1: "16", y1: "13", x2: "8", y2: "13" }),
2940
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("line", { x1: "16", y1: "17", x2: "8", y2: "17" }),
2941
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("polyline", { points: "10 9 9 9 8 9" })
2942
+ ] }) }),
2943
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("p", { className: "text-sm text-muted-foreground mb-4", children: emptyMessage ?? `No ${singularLabel.toLowerCase()}s yet.` }),
2944
+ onNewPost && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
2945
+ "button",
2946
+ {
2947
+ onClick: onNewPost,
2948
+ className: "inline-flex items-center gap-1.5 rounded-lg bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground hover:bg-primary/90 transition-colors",
2949
+ children: [
2950
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(IconPlus, {}),
2951
+ newPostLabel ?? `New ${singularLabel}`
2952
+ ]
2953
+ }
2954
+ )
2955
+ ] })
2956
+ ] });
2957
+ }
2958
+
2959
+ // src/components/content/post-filters-bar.tsx
2960
+ var import_jsx_runtime45 = require("react/jsx-runtime");
2961
+ var STATUS_TABS = [
2962
+ { value: "all", label: "All" },
2963
+ { value: "DRAFT", label: "Draft" },
2964
+ { value: "PUBLISHED", label: "Published" },
2965
+ { value: "SCHEDULED", label: "Scheduled" },
2966
+ { value: "ARCHIVED", label: "Archived" }
2967
+ ];
2968
+ function IconSearch() {
2969
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
2970
+ "svg",
2971
+ {
2972
+ width: "14",
2973
+ height: "14",
2974
+ viewBox: "0 0 24 24",
2975
+ fill: "none",
2976
+ stroke: "currentColor",
2977
+ strokeWidth: "2",
2978
+ strokeLinecap: "round",
2979
+ strokeLinejoin: "round",
2980
+ children: [
2981
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("circle", { cx: "11", cy: "11", r: "8" }),
2982
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("line", { x1: "21", y1: "21", x2: "16.65", y2: "16.65" })
2983
+ ]
2984
+ }
2985
+ );
2986
+ }
2987
+ function IconPlus2() {
2988
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
2989
+ "svg",
2990
+ {
2991
+ width: "14",
2992
+ height: "14",
2993
+ viewBox: "0 0 24 24",
2994
+ fill: "none",
2995
+ stroke: "currentColor",
2996
+ strokeWidth: "2",
2997
+ strokeLinecap: "round",
2998
+ strokeLinejoin: "round",
2999
+ children: [
3000
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("line", { x1: "12", y1: "5", x2: "12", y2: "19" }),
3001
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
3002
+ ]
3003
+ }
3004
+ );
3005
+ }
3006
+ function PostFiltersBar({
3007
+ search,
3008
+ onSearch,
3009
+ status,
3010
+ onStatusChange,
3011
+ onNew,
3012
+ newLabel = "New Post",
3013
+ total,
3014
+ typeLabel = "Posts",
3015
+ className
3016
+ }) {
3017
+ return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: cn("space-y-2", className), children: [
3018
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "flex flex-wrap items-center gap-3", children: [
3019
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "relative flex items-center", children: [
3020
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "absolute left-2.5 text-muted-foreground pointer-events-none", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(IconSearch, {}) }),
3021
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3022
+ "input",
3023
+ {
3024
+ type: "text",
3025
+ value: search,
3026
+ onChange: (e) => onSearch(e.target.value),
3027
+ placeholder: `Search ${typeLabel}\u2026`,
3028
+ className: "h-8 pl-8 pr-3 rounded-lg border border-border bg-background text-sm placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary/30 focus:border-primary transition-colors w-56"
3029
+ }
3030
+ )
3031
+ ] }),
3032
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "flex items-center gap-1 rounded-lg bg-muted p-0.5", children: STATUS_TABS.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3033
+ "button",
3034
+ {
3035
+ onClick: () => onStatusChange(tab.value),
3036
+ className: cn(
3037
+ "rounded-md px-2.5 py-1 text-xs font-medium transition-colors",
3038
+ status === tab.value ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"
3039
+ ),
3040
+ children: tab.label
3041
+ },
3042
+ tab.value
3043
+ )) }),
3044
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "flex-1" }),
3045
+ onNew && /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
3046
+ "button",
3047
+ {
3048
+ onClick: onNew,
3049
+ className: "inline-flex items-center gap-1.5 h-8 rounded-lg bg-primary px-3 text-sm font-medium text-primary-foreground hover:bg-primary/90 transition-colors",
3050
+ children: [
3051
+ /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(IconPlus2, {}),
3052
+ newLabel
3053
+ ]
3054
+ }
3055
+ )
3056
+ ] }),
3057
+ total !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("p", { className: "text-xs text-muted-foreground", children: [
3058
+ total,
3059
+ " ",
3060
+ total === 1 ? typeLabel.replace(/s$/, "") : typeLabel
3061
+ ] })
3062
+ ] });
3063
+ }
3064
+
3065
+ // src/components/content/post-editor-shell.tsx
3066
+ var import_jsx_runtime46 = require("react/jsx-runtime");
3067
+ function IconArrowLeft() {
3068
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
3069
+ "svg",
3070
+ {
3071
+ width: "14",
3072
+ height: "14",
3073
+ viewBox: "0 0 24 24",
3074
+ fill: "none",
3075
+ stroke: "currentColor",
3076
+ strokeWidth: "2",
3077
+ strokeLinecap: "round",
3078
+ strokeLinejoin: "round",
3079
+ children: [
3080
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("line", { x1: "19", y1: "12", x2: "5", y2: "12" }),
3081
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("polyline", { points: "12 19 5 12 12 5" })
3082
+ ]
3083
+ }
3084
+ );
3085
+ }
3086
+ function IconSpinner() {
3087
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
3088
+ "svg",
3089
+ {
3090
+ width: "14",
3091
+ height: "14",
3092
+ viewBox: "0 0 24 24",
3093
+ fill: "none",
3094
+ stroke: "currentColor",
3095
+ strokeWidth: "2",
3096
+ strokeLinecap: "round",
3097
+ strokeLinejoin: "round",
3098
+ className: "animate-spin",
3099
+ children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" })
3100
+ }
3101
+ );
3102
+ }
3103
+ function IconMoreHorizontal2() {
3104
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
3105
+ "svg",
3106
+ {
3107
+ width: "16",
3108
+ height: "16",
3109
+ viewBox: "0 0 24 24",
3110
+ fill: "none",
3111
+ stroke: "currentColor",
3112
+ strokeWidth: "2",
3113
+ strokeLinecap: "round",
3114
+ strokeLinejoin: "round",
3115
+ children: [
3116
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("circle", { cx: "5", cy: "12", r: "1", fill: "currentColor" }),
3117
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("circle", { cx: "12", cy: "12", r: "1", fill: "currentColor" }),
3118
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("circle", { cx: "19", cy: "12", r: "1", fill: "currentColor" })
3119
+ ]
3120
+ }
3121
+ );
3122
+ }
3123
+ function PostEditorShell({
3124
+ title,
3125
+ backLabel = "Back",
3126
+ onBack,
3127
+ onSave,
3128
+ onPublish,
3129
+ saving = false,
3130
+ publishing = false,
3131
+ status,
3132
+ children,
3133
+ sidebar,
3134
+ className
3135
+ }) {
3136
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: cn("flex flex-col h-screen bg-background overflow-hidden", className), children: [
3137
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex items-center gap-3 h-14 px-4 border-b border-border bg-card shrink-0", children: [
3138
+ onBack && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
3139
+ "button",
3140
+ {
3141
+ onClick: onBack,
3142
+ className: "inline-flex items-center gap-1.5 rounded-lg px-2.5 py-1.5 text-sm text-muted-foreground hover:bg-accent hover:text-foreground transition-colors",
3143
+ children: [
3144
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(IconArrowLeft, {}),
3145
+ backLabel
3146
+ ]
3147
+ }
3148
+ ),
3149
+ onBack && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "h-5 w-px bg-border" }),
3150
+ title && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "text-sm font-medium text-muted-foreground truncate max-w-xs", children: title }),
3151
+ status && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(PostStatusBadge, { status, size: "sm" }),
3152
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "flex-1" }),
3153
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("button", { className: "inline-flex items-center justify-center h-8 w-8 rounded-lg text-muted-foreground hover:bg-accent hover:text-foreground transition-colors", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(IconMoreHorizontal2, {}) }),
3154
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
3155
+ "button",
3156
+ {
3157
+ onClick: onSave,
3158
+ disabled: saving,
3159
+ className: "inline-flex items-center gap-1.5 h-8 rounded-lg border border-border bg-background px-3 text-sm font-medium hover:bg-accent transition-colors disabled:opacity-60",
3160
+ children: [
3161
+ saving && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(IconSpinner, {}),
3162
+ "Save Draft"
3163
+ ]
3164
+ }
3165
+ ),
3166
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
3167
+ "button",
3168
+ {
3169
+ onClick: onPublish,
3170
+ disabled: publishing,
3171
+ className: "inline-flex items-center gap-1.5 h-8 rounded-lg bg-primary px-3 text-sm font-medium text-primary-foreground hover:bg-primary/90 transition-colors disabled:opacity-60",
3172
+ children: [
3173
+ publishing && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(IconSpinner, {}),
3174
+ "Publish"
3175
+ ]
3176
+ }
3177
+ )
3178
+ ] }),
3179
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex flex-1 overflow-hidden", children: [
3180
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "flex-1 overflow-y-auto p-6", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "max-w-3xl mx-auto", children }) }),
3181
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "w-72 shrink-0 border-l border-border overflow-y-auto p-4", children: sidebar })
3182
+ ] })
3183
+ ] });
3184
+ }
3185
+
3186
+ // src/components/content/slug-input.tsx
3187
+ var import_jsx_runtime47 = require("react/jsx-runtime");
3188
+ function IconRefresh() {
3189
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
3190
+ "svg",
3191
+ {
3192
+ width: "13",
3193
+ height: "13",
3194
+ viewBox: "0 0 24 24",
3195
+ fill: "none",
3196
+ stroke: "currentColor",
3197
+ strokeWidth: "2",
3198
+ strokeLinecap: "round",
3199
+ strokeLinejoin: "round",
3200
+ children: [
3201
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("polyline", { points: "23 4 23 10 17 10" }),
3202
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("polyline", { points: "1 20 1 14 7 14" }),
3203
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("path", { d: "M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15" })
3204
+ ]
3205
+ }
3206
+ );
3207
+ }
3208
+ function SlugInput({
3209
+ value,
3210
+ onChange,
3211
+ onGenerate,
3212
+ prefix,
3213
+ disabled = false,
3214
+ className
3215
+ }) {
3216
+ return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: cn("space-y-1", className), children: [
3217
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex items-center gap-1", children: [
3218
+ prefix && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "shrink-0 text-sm text-muted-foreground select-none", children: prefix }),
3219
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
3220
+ "input",
3221
+ {
3222
+ type: "text",
3223
+ value,
3224
+ onChange: (e) => onChange(e.target.value),
3225
+ disabled,
3226
+ className: cn(
3227
+ "flex-1 h-8 border-0 border-b border-input bg-transparent text-sm focus:outline-none focus:border-primary transition-colors",
3228
+ disabled && "opacity-60 cursor-not-allowed"
3229
+ ),
3230
+ placeholder: "your-slug-here"
3231
+ }
3232
+ ),
3233
+ onGenerate && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
3234
+ "button",
3235
+ {
3236
+ onClick: onGenerate,
3237
+ disabled,
3238
+ title: "Generate slug",
3239
+ className: "inline-flex items-center justify-center h-7 w-7 rounded-md text-muted-foreground hover:bg-accent hover:text-foreground transition-colors disabled:opacity-60",
3240
+ children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(IconRefresh, {})
3241
+ }
3242
+ )
3243
+ ] }),
3244
+ /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("p", { className: "text-[10px] text-muted-foreground", children: "Only lowercase letters, numbers, and hyphens" })
3245
+ ] });
3246
+ }
3247
+
3248
+ // src/components/content/post-sidebar-section.tsx
3249
+ var React22 = __toESM(require("react"));
3250
+ var import_jsx_runtime48 = require("react/jsx-runtime");
3251
+ function IconChevronDown() {
3252
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
3253
+ "svg",
3254
+ {
3255
+ width: "14",
3256
+ height: "14",
3257
+ viewBox: "0 0 24 24",
3258
+ fill: "none",
3259
+ stroke: "currentColor",
3260
+ strokeWidth: "2",
3261
+ strokeLinecap: "round",
3262
+ strokeLinejoin: "round",
3263
+ children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("polyline", { points: "6 9 12 15 18 9" })
3264
+ }
3265
+ );
3266
+ }
3267
+ function PostSidebarSection({
3268
+ title,
3269
+ children,
3270
+ defaultOpen = true,
3271
+ className
3272
+ }) {
3273
+ const [open, setOpen] = React22.useState(defaultOpen);
3274
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: cn("border-b border-border", className), children: [
3275
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
3276
+ "button",
3277
+ {
3278
+ onClick: () => setOpen((v) => !v),
3279
+ className: "flex w-full items-center justify-between py-3 px-0 text-sm font-medium text-foreground hover:text-primary transition-colors",
3280
+ children: [
3281
+ title,
3282
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
3283
+ "span",
3284
+ {
3285
+ className: cn(
3286
+ "text-muted-foreground transition-transform duration-200",
3287
+ open ? "rotate-0" : "-rotate-90"
3288
+ ),
3289
+ children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(IconChevronDown, {})
3290
+ }
3291
+ )
3292
+ ]
3293
+ }
3294
+ ),
3295
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
3296
+ "div",
3297
+ {
3298
+ className: cn(
3299
+ "overflow-hidden transition-all duration-200",
3300
+ open ? "max-h-[9999px] pb-4 opacity-100" : "max-h-0 opacity-0 pointer-events-none"
3301
+ ),
3302
+ children
3303
+ }
3304
+ )
3305
+ ] });
3306
+ }
3307
+
2570
3308
  // src/hooks/index.ts
2571
3309
  var import_react = require("react");
2572
3310
  function useDisclosure(initial = false) {
@@ -2586,9 +3324,9 @@ function usePagination(total, pageSize = 20) {
2586
3324
  }
2587
3325
 
2588
3326
  // src/components/auth/AuthShell.tsx
2589
- var import_jsx_runtime42 = require("react/jsx-runtime");
3327
+ var import_jsx_runtime49 = require("react/jsx-runtime");
2590
3328
  function AuthShell({ children, pattern = "dots", maxWidth = "520px" }) {
2591
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
3329
+ return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(
2592
3330
  "div",
2593
3331
  {
2594
3332
  style: {
@@ -2603,7 +3341,7 @@ function AuthShell({ children, pattern = "dots", maxWidth = "520px" }) {
2603
3341
  overflow: "hidden"
2604
3342
  },
2605
3343
  children: [
2606
- pattern === "dots" && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
3344
+ pattern === "dots" && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
2607
3345
  "div",
2608
3346
  {
2609
3347
  "aria-hidden": true,
@@ -2617,7 +3355,7 @@ function AuthShell({ children, pattern = "dots", maxWidth = "520px" }) {
2617
3355
  }
2618
3356
  }
2619
3357
  ),
2620
- pattern === "grid" && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
3358
+ pattern === "grid" && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
2621
3359
  "div",
2622
3360
  {
2623
3361
  "aria-hidden": true,
@@ -2631,16 +3369,16 @@ function AuthShell({ children, pattern = "dots", maxWidth = "520px" }) {
2631
3369
  }
2632
3370
  }
2633
3371
  ),
2634
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { style: { position: "relative", zIndex: 1, width: "100%", maxWidth }, children })
3372
+ /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { style: { position: "relative", zIndex: 1, width: "100%", maxWidth }, children })
2635
3373
  ]
2636
3374
  }
2637
3375
  );
2638
3376
  }
2639
3377
 
2640
3378
  // src/components/auth/AuthCard.tsx
2641
- var import_jsx_runtime43 = require("react/jsx-runtime");
3379
+ var import_jsx_runtime50 = require("react/jsx-runtime");
2642
3380
  function AuthCard({ children, padding = "24px 28px" }) {
2643
- return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
3381
+ return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
2644
3382
  "div",
2645
3383
  {
2646
3384
  style: {
@@ -2657,10 +3395,10 @@ function AuthCard({ children, padding = "24px 28px" }) {
2657
3395
  }
2658
3396
 
2659
3397
  // src/components/auth/AuthLogo.tsx
2660
- var import_jsx_runtime44 = require("react/jsx-runtime");
3398
+ var import_jsx_runtime51 = require("react/jsx-runtime");
2661
3399
  function AuthLogo({ appName = "Builify CMS", letter = "B", imageUrl, size = 36 }) {
2662
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", gap: "10px", marginBottom: "28px" }, children: [
2663
- imageUrl ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
3400
+ return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", gap: "10px", marginBottom: "28px" }, children: [
3401
+ imageUrl ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
2664
3402
  "img",
2665
3403
  {
2666
3404
  src: imageUrl,
@@ -2669,7 +3407,7 @@ function AuthLogo({ appName = "Builify CMS", letter = "B", imageUrl, size = 36 }
2669
3407
  height: size,
2670
3408
  style: { borderRadius: "calc(var(--radius, 0.5rem) * 1.2)", flexShrink: 0, display: "block" }
2671
3409
  }
2672
- ) : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
3410
+ ) : /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
2673
3411
  "div",
2674
3412
  {
2675
3413
  style: {
@@ -2688,7 +3426,7 @@ function AuthLogo({ appName = "Builify CMS", letter = "B", imageUrl, size = 36 }
2688
3426
  children: letter
2689
3427
  }
2690
3428
  ),
2691
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
3429
+ /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
2692
3430
  "span",
2693
3431
  {
2694
3432
  style: {
@@ -2704,10 +3442,10 @@ function AuthLogo({ appName = "Builify CMS", letter = "B", imageUrl, size = 36 }
2704
3442
  }
2705
3443
 
2706
3444
  // src/components/auth/AuthHeader.tsx
2707
- var import_jsx_runtime45 = require("react/jsx-runtime");
3445
+ var import_jsx_runtime52 = require("react/jsx-runtime");
2708
3446
  function AuthHeader({ title, description }) {
2709
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { style: { marginBottom: "24px", textAlign: "center" }, children: [
2710
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3447
+ return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { style: { marginBottom: "24px", textAlign: "center" }, children: [
3448
+ /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
2711
3449
  "h1",
2712
3450
  {
2713
3451
  style: {
@@ -2720,7 +3458,7 @@ function AuthHeader({ title, description }) {
2720
3458
  children: title
2721
3459
  }
2722
3460
  ),
2723
- description && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3461
+ description && /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
2724
3462
  "p",
2725
3463
  {
2726
3464
  style: {
@@ -2736,12 +3474,12 @@ function AuthHeader({ title, description }) {
2736
3474
  }
2737
3475
 
2738
3476
  // src/components/auth/AuthField.tsx
2739
- var import_jsx_runtime46 = require("react/jsx-runtime");
3477
+ var import_jsx_runtime53 = require("react/jsx-runtime");
2740
3478
  function AuthField({ label, error, hint, rightLabel, id, ...props }) {
2741
3479
  const fieldId = id ?? label.toLowerCase().replace(/\s+/g, "-");
2742
- return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "6px" }, children: [
2743
- /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
2744
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
3480
+ return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "6px" }, children: [
3481
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
3482
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
2745
3483
  "label",
2746
3484
  {
2747
3485
  htmlFor: fieldId,
@@ -2753,9 +3491,9 @@ function AuthField({ label, error, hint, rightLabel, id, ...props }) {
2753
3491
  children: label
2754
3492
  }
2755
3493
  ),
2756
- rightLabel && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { style: { fontSize: "0.8125rem" }, children: rightLabel })
3494
+ rightLabel && /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { style: { fontSize: "0.8125rem" }, children: rightLabel })
2757
3495
  ] }),
2758
- /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
3496
+ /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
2759
3497
  "input",
2760
3498
  {
2761
3499
  id: fieldId,
@@ -2785,13 +3523,13 @@ function AuthField({ label, error, hint, rightLabel, id, ...props }) {
2785
3523
  ...props
2786
3524
  }
2787
3525
  ),
2788
- error && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("p", { style: { fontSize: "0.8rem", color: "var(--destructive)", margin: 0 }, children: error }),
2789
- hint && !error && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("p", { style: { fontSize: "0.8rem", color: "var(--muted-foreground)", margin: 0 }, children: hint })
3526
+ error && /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("p", { style: { fontSize: "0.8rem", color: "var(--destructive)", margin: 0 }, children: error }),
3527
+ hint && !error && /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("p", { style: { fontSize: "0.8rem", color: "var(--muted-foreground)", margin: 0 }, children: hint })
2790
3528
  ] });
2791
3529
  }
2792
3530
 
2793
3531
  // src/components/auth/AuthButton.tsx
2794
- var import_jsx_runtime47 = require("react/jsx-runtime");
3532
+ var import_jsx_runtime54 = require("react/jsx-runtime");
2795
3533
  function AuthButton({
2796
3534
  loading,
2797
3535
  variant = "primary",
@@ -2834,7 +3572,7 @@ function AuthButton({
2834
3572
  color: "var(--foreground)"
2835
3573
  }
2836
3574
  };
2837
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
3575
+ return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
2838
3576
  "button",
2839
3577
  {
2840
3578
  disabled: loading || disabled,
@@ -2846,8 +3584,8 @@ function AuthButton({
2846
3584
  e.currentTarget.style.filter = "none";
2847
3585
  },
2848
3586
  ...props,
2849
- children: loading ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_jsx_runtime47.Fragment, { children: [
2850
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
3587
+ children: loading ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(import_jsx_runtime54.Fragment, { children: [
3588
+ /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
2851
3589
  "span",
2852
3590
  {
2853
3591
  style: {
@@ -2868,19 +3606,19 @@ function AuthButton({
2868
3606
  }
2869
3607
 
2870
3608
  // src/components/auth/AuthDivider.tsx
2871
- var import_jsx_runtime48 = require("react/jsx-runtime");
3609
+ var import_jsx_runtime55 = require("react/jsx-runtime");
2872
3610
  function AuthDivider({ label = "or" }) {
2873
- return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "12px", margin: "20px 0" }, children: [
2874
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { style: { flex: 1, height: 1, background: "var(--border)" } }),
2875
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { style: { fontSize: "0.75rem", color: "var(--muted-foreground)", userSelect: "none" }, children: label }),
2876
- /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { style: { flex: 1, height: 1, background: "var(--border)" } })
3611
+ return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "12px", margin: "20px 0" }, children: [
3612
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { style: { flex: 1, height: 1, background: "var(--border)" } }),
3613
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { style: { fontSize: "0.75rem", color: "var(--muted-foreground)", userSelect: "none" }, children: label }),
3614
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { style: { flex: 1, height: 1, background: "var(--border)" } })
2877
3615
  ] });
2878
3616
  }
2879
3617
 
2880
3618
  // src/components/auth/AuthFootnote.tsx
2881
- var import_jsx_runtime49 = require("react/jsx-runtime");
3619
+ var import_jsx_runtime56 = require("react/jsx-runtime");
2882
3620
  function AuthFootnote({ text, linkText, linkHref }) {
2883
- return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("p", { style: {
3621
+ return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("p", { style: {
2884
3622
  textAlign: "center",
2885
3623
  marginTop: "20px",
2886
3624
  fontSize: "0.8125rem",
@@ -2888,7 +3626,7 @@ function AuthFootnote({ text, linkText, linkHref }) {
2888
3626
  }, children: [
2889
3627
  text,
2890
3628
  " ",
2891
- /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
3629
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
2892
3630
  "a",
2893
3631
  {
2894
3632
  href: linkHref,
@@ -2905,37 +3643,6 @@ function AuthFootnote({ text, linkText, linkHref }) {
2905
3643
  ] });
2906
3644
  }
2907
3645
 
2908
- // src/components/Skeleton.tsx
2909
- var import_jsx_runtime50 = require("react/jsx-runtime");
2910
- function Skeleton2({ width = "100%", height = 16, rounded, style }) {
2911
- return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
2912
- "div",
2913
- {
2914
- style: {
2915
- width,
2916
- height,
2917
- background: "var(--muted, #e5e7eb)",
2918
- borderRadius: rounded ?? "var(--radius, 0.5rem)",
2919
- overflow: "hidden",
2920
- position: "relative",
2921
- flexShrink: 0,
2922
- ...style
2923
- },
2924
- children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
2925
- "div",
2926
- {
2927
- style: {
2928
- position: "absolute",
2929
- inset: 0,
2930
- background: "linear-gradient(90deg, transparent 0%, color-mix(in oklab, var(--background, #fff) 40%, transparent) 50%, transparent 100%)",
2931
- animation: "dashui-shimmer 1.6s ease-in-out infinite"
2932
- }
2933
- }
2934
- )
2935
- }
2936
- );
2937
- }
2938
-
2939
3646
  // src/index.ts
2940
3647
  var import_next_themes2 = require("next-themes");
2941
3648
  // Annotate the CommonJS export names for ESM import in node:
@@ -3006,6 +3713,11 @@ var import_next_themes2 = require("next-themes");
3006
3713
  Popover,
3007
3714
  PopoverContent,
3008
3715
  PopoverTrigger,
3716
+ PostEditorShell,
3717
+ PostFiltersBar,
3718
+ PostListTable,
3719
+ PostSidebarSection,
3720
+ PostStatusBadge,
3009
3721
  SearchBar,
3010
3722
  Select,
3011
3723
  SelectContent,
@@ -3020,6 +3732,7 @@ var import_next_themes2 = require("next-themes");
3020
3732
  Separator,
3021
3733
  Sidebar,
3022
3734
  Skeleton,
3735
+ SlugInput,
3023
3736
  Stats,
3024
3737
  StorageBar,
3025
3738
  Switch,