@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.d.mts +82 -1
- package/dist/index.d.ts +82 -1
- package/dist/index.js +783 -70
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +780 -73
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1913,14 +1913,22 @@ function MediaPickerDialog({
|
|
|
1913
1913
|
const fileInputRef = React20.useRef(null);
|
|
1914
1914
|
const dragCounterRef = React20.useRef(0);
|
|
1915
1915
|
React20.useEffect(() => {
|
|
1916
|
-
if (open) {
|
|
1917
|
-
setLocalSelected(new Set(initialSelected));
|
|
1918
|
-
} else {
|
|
1916
|
+
if (!open) {
|
|
1919
1917
|
setLocalSelected(/* @__PURE__ */ new Set());
|
|
1920
1918
|
setIsDragging(false);
|
|
1921
1919
|
dragCounterRef.current = 0;
|
|
1922
1920
|
}
|
|
1923
1921
|
}, [open]);
|
|
1922
|
+
const prevInitialRef = React20.useRef("");
|
|
1923
|
+
React20.useEffect(() => {
|
|
1924
|
+
if (!open) return;
|
|
1925
|
+
const key = initialSelected.join(",");
|
|
1926
|
+
if (key === prevInitialRef.current) return;
|
|
1927
|
+
prevInitialRef.current = key;
|
|
1928
|
+
if (initialSelected.length > 0) {
|
|
1929
|
+
setLocalSelected(new Set(initialSelected));
|
|
1930
|
+
}
|
|
1931
|
+
}, [open, initialSelected]);
|
|
1924
1932
|
const handleDragEnter = (e) => {
|
|
1925
1933
|
e.preventDefault();
|
|
1926
1934
|
e.stopPropagation();
|
|
@@ -2431,10 +2439,734 @@ function ConfirmDialog({
|
|
|
2431
2439
|
] }) });
|
|
2432
2440
|
}
|
|
2433
2441
|
|
|
2442
|
+
// src/components/content/post-status-badge.tsx
|
|
2443
|
+
import { jsx as jsx42, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
2444
|
+
var statusConfig = {
|
|
2445
|
+
DRAFT: {
|
|
2446
|
+
label: "Draft",
|
|
2447
|
+
container: "bg-muted text-muted-foreground",
|
|
2448
|
+
dot: "bg-gray-400"
|
|
2449
|
+
},
|
|
2450
|
+
PUBLISHED: {
|
|
2451
|
+
label: "Published",
|
|
2452
|
+
container: "bg-primary/10 text-primary",
|
|
2453
|
+
dot: "bg-primary animate-pulse"
|
|
2454
|
+
},
|
|
2455
|
+
SCHEDULED: {
|
|
2456
|
+
label: "Scheduled",
|
|
2457
|
+
container: "bg-blue-50 text-blue-600 dark:bg-blue-950 dark:text-blue-400",
|
|
2458
|
+
dot: "bg-blue-500 dark:bg-blue-400"
|
|
2459
|
+
},
|
|
2460
|
+
ARCHIVED: {
|
|
2461
|
+
label: "Archived",
|
|
2462
|
+
container: "bg-amber-50 text-amber-600 dark:bg-amber-950 dark:text-amber-400",
|
|
2463
|
+
dot: "bg-amber-500 dark:bg-amber-400"
|
|
2464
|
+
}
|
|
2465
|
+
};
|
|
2466
|
+
var sizeConfig = {
|
|
2467
|
+
sm: "text-[10px] px-1.5 py-0.5",
|
|
2468
|
+
md: "text-xs px-2 py-1"
|
|
2469
|
+
};
|
|
2470
|
+
function PostStatusBadge({
|
|
2471
|
+
status,
|
|
2472
|
+
size = "md",
|
|
2473
|
+
className
|
|
2474
|
+
}) {
|
|
2475
|
+
const config = statusConfig[status];
|
|
2476
|
+
return /* @__PURE__ */ jsxs27(
|
|
2477
|
+
"span",
|
|
2478
|
+
{
|
|
2479
|
+
className: cn(
|
|
2480
|
+
"inline-flex items-center gap-1.5 rounded-full font-medium",
|
|
2481
|
+
config.container,
|
|
2482
|
+
sizeConfig[size],
|
|
2483
|
+
className
|
|
2484
|
+
),
|
|
2485
|
+
children: [
|
|
2486
|
+
/* @__PURE__ */ jsx42(
|
|
2487
|
+
"span",
|
|
2488
|
+
{
|
|
2489
|
+
className: cn("inline-block rounded-full", config.dot, {
|
|
2490
|
+
"w-1.5 h-1.5": size === "md",
|
|
2491
|
+
"w-1 h-1": size === "sm"
|
|
2492
|
+
})
|
|
2493
|
+
}
|
|
2494
|
+
),
|
|
2495
|
+
config.label
|
|
2496
|
+
]
|
|
2497
|
+
}
|
|
2498
|
+
);
|
|
2499
|
+
}
|
|
2500
|
+
|
|
2501
|
+
// src/components/content/post-list-table.tsx
|
|
2502
|
+
import * as React21 from "react";
|
|
2503
|
+
|
|
2504
|
+
// src/components/Skeleton.tsx
|
|
2505
|
+
import { jsx as jsx43 } from "react/jsx-runtime";
|
|
2506
|
+
function Skeleton2({ width = "100%", height = 16, rounded, style }) {
|
|
2507
|
+
return /* @__PURE__ */ jsx43(
|
|
2508
|
+
"div",
|
|
2509
|
+
{
|
|
2510
|
+
style: {
|
|
2511
|
+
width,
|
|
2512
|
+
height,
|
|
2513
|
+
background: "var(--muted, #e5e7eb)",
|
|
2514
|
+
borderRadius: rounded ?? "var(--radius, 0.5rem)",
|
|
2515
|
+
overflow: "hidden",
|
|
2516
|
+
position: "relative",
|
|
2517
|
+
flexShrink: 0,
|
|
2518
|
+
...style
|
|
2519
|
+
},
|
|
2520
|
+
children: /* @__PURE__ */ jsx43(
|
|
2521
|
+
"div",
|
|
2522
|
+
{
|
|
2523
|
+
style: {
|
|
2524
|
+
position: "absolute",
|
|
2525
|
+
inset: 0,
|
|
2526
|
+
background: "linear-gradient(90deg, transparent 0%, color-mix(in oklab, var(--background, #fff) 40%, transparent) 50%, transparent 100%)",
|
|
2527
|
+
animation: "dashui-shimmer 1.6s ease-in-out infinite"
|
|
2528
|
+
}
|
|
2529
|
+
}
|
|
2530
|
+
)
|
|
2531
|
+
}
|
|
2532
|
+
);
|
|
2533
|
+
}
|
|
2534
|
+
|
|
2535
|
+
// src/components/content/post-list-table.tsx
|
|
2536
|
+
import { jsx as jsx44, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
2537
|
+
function IconEdit() {
|
|
2538
|
+
return /* @__PURE__ */ jsxs28("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2539
|
+
/* @__PURE__ */ jsx44("path", { d: "M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" }),
|
|
2540
|
+
/* @__PURE__ */ jsx44("path", { d: "M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" })
|
|
2541
|
+
] });
|
|
2542
|
+
}
|
|
2543
|
+
function IconTrash() {
|
|
2544
|
+
return /* @__PURE__ */ jsxs28("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2545
|
+
/* @__PURE__ */ jsx44("polyline", { points: "3 6 5 6 21 6" }),
|
|
2546
|
+
/* @__PURE__ */ jsx44("path", { d: "M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6" }),
|
|
2547
|
+
/* @__PURE__ */ jsx44("path", { d: "M10 11v6" }),
|
|
2548
|
+
/* @__PURE__ */ jsx44("path", { d: "M14 11v6" }),
|
|
2549
|
+
/* @__PURE__ */ jsx44("path", { d: "M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2" })
|
|
2550
|
+
] });
|
|
2551
|
+
}
|
|
2552
|
+
function IconCopy() {
|
|
2553
|
+
return /* @__PURE__ */ jsxs28("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2554
|
+
/* @__PURE__ */ jsx44("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", ry: "2" }),
|
|
2555
|
+
/* @__PURE__ */ jsx44("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
|
|
2556
|
+
] });
|
|
2557
|
+
}
|
|
2558
|
+
function IconMoreHorizontal() {
|
|
2559
|
+
return /* @__PURE__ */ jsxs28("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2560
|
+
/* @__PURE__ */ jsx44("circle", { cx: "5", cy: "12", r: "1", fill: "currentColor" }),
|
|
2561
|
+
/* @__PURE__ */ jsx44("circle", { cx: "12", cy: "12", r: "1", fill: "currentColor" }),
|
|
2562
|
+
/* @__PURE__ */ jsx44("circle", { cx: "19", cy: "12", r: "1", fill: "currentColor" })
|
|
2563
|
+
] });
|
|
2564
|
+
}
|
|
2565
|
+
function IconChevronRight() {
|
|
2566
|
+
return /* @__PURE__ */ jsx44("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx44("polyline", { points: "9 18 15 12 9 6" }) });
|
|
2567
|
+
}
|
|
2568
|
+
function IconImage() {
|
|
2569
|
+
return /* @__PURE__ */ jsxs28("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2570
|
+
/* @__PURE__ */ jsx44("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }),
|
|
2571
|
+
/* @__PURE__ */ jsx44("circle", { cx: "8.5", cy: "8.5", r: "1.5" }),
|
|
2572
|
+
/* @__PURE__ */ jsx44("polyline", { points: "21 15 16 10 5 21" })
|
|
2573
|
+
] });
|
|
2574
|
+
}
|
|
2575
|
+
function IconPlus() {
|
|
2576
|
+
return /* @__PURE__ */ jsxs28("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2577
|
+
/* @__PURE__ */ jsx44("line", { x1: "12", y1: "5", x2: "12", y2: "19" }),
|
|
2578
|
+
/* @__PURE__ */ jsx44("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
|
|
2579
|
+
] });
|
|
2580
|
+
}
|
|
2581
|
+
function formatDate(date) {
|
|
2582
|
+
return new Date(date).toLocaleDateString("en-US", {
|
|
2583
|
+
year: "numeric",
|
|
2584
|
+
month: "short",
|
|
2585
|
+
day: "numeric"
|
|
2586
|
+
});
|
|
2587
|
+
}
|
|
2588
|
+
function getInitials(name) {
|
|
2589
|
+
return name.split(" ").slice(0, 2).map((w) => w[0]?.toUpperCase() ?? "").join("");
|
|
2590
|
+
}
|
|
2591
|
+
function RowActions({ post, onEdit, onDelete, onDuplicate, onStatusChange }) {
|
|
2592
|
+
const [open, setOpen] = React21.useState(false);
|
|
2593
|
+
const [statusOpen, setStatusOpen] = React21.useState(false);
|
|
2594
|
+
const ref = React21.useRef(null);
|
|
2595
|
+
React21.useEffect(() => {
|
|
2596
|
+
if (!open) return;
|
|
2597
|
+
function handleClick(e) {
|
|
2598
|
+
if (ref.current && !ref.current.contains(e.target)) {
|
|
2599
|
+
setOpen(false);
|
|
2600
|
+
setStatusOpen(false);
|
|
2601
|
+
}
|
|
2602
|
+
}
|
|
2603
|
+
document.addEventListener("mousedown", handleClick);
|
|
2604
|
+
return () => document.removeEventListener("mousedown", handleClick);
|
|
2605
|
+
}, [open]);
|
|
2606
|
+
const statusOptions = [
|
|
2607
|
+
{ label: "Draft", value: "DRAFT" },
|
|
2608
|
+
{ label: "Publish", value: "PUBLISHED" },
|
|
2609
|
+
{ label: "Archive", value: "ARCHIVED" }
|
|
2610
|
+
];
|
|
2611
|
+
return /* @__PURE__ */ jsxs28("div", { className: "relative flex items-center gap-1", ref, children: [
|
|
2612
|
+
/* @__PURE__ */ jsx44(
|
|
2613
|
+
"button",
|
|
2614
|
+
{
|
|
2615
|
+
onClick: () => onEdit?.(post.id),
|
|
2616
|
+
className: "inline-flex items-center justify-center h-7 w-7 rounded-md text-muted-foreground hover:bg-accent hover:text-foreground transition-colors",
|
|
2617
|
+
title: "Edit",
|
|
2618
|
+
children: /* @__PURE__ */ jsx44(IconEdit, {})
|
|
2619
|
+
}
|
|
2620
|
+
),
|
|
2621
|
+
/* @__PURE__ */ jsx44(
|
|
2622
|
+
"button",
|
|
2623
|
+
{
|
|
2624
|
+
onClick: () => {
|
|
2625
|
+
setOpen((v) => !v);
|
|
2626
|
+
setStatusOpen(false);
|
|
2627
|
+
},
|
|
2628
|
+
className: "inline-flex items-center justify-center h-7 w-7 rounded-md text-muted-foreground hover:bg-accent hover:text-foreground transition-colors",
|
|
2629
|
+
title: "More actions",
|
|
2630
|
+
children: /* @__PURE__ */ jsx44(IconMoreHorizontal, {})
|
|
2631
|
+
}
|
|
2632
|
+
),
|
|
2633
|
+
open && /* @__PURE__ */ jsxs28("div", { className: "absolute right-0 top-8 z-50 min-w-[160px] rounded-lg border border-border bg-card shadow-md py-1", children: [
|
|
2634
|
+
/* @__PURE__ */ jsxs28(
|
|
2635
|
+
"button",
|
|
2636
|
+
{
|
|
2637
|
+
onClick: () => {
|
|
2638
|
+
onDuplicate?.(post.id);
|
|
2639
|
+
setOpen(false);
|
|
2640
|
+
},
|
|
2641
|
+
className: "flex w-full items-center gap-2 px-3 py-1.5 text-sm hover:bg-accent transition-colors",
|
|
2642
|
+
children: [
|
|
2643
|
+
/* @__PURE__ */ jsx44(IconCopy, {}),
|
|
2644
|
+
"Duplicate"
|
|
2645
|
+
]
|
|
2646
|
+
}
|
|
2647
|
+
),
|
|
2648
|
+
/* @__PURE__ */ jsxs28("div", { className: "relative", children: [
|
|
2649
|
+
/* @__PURE__ */ jsxs28(
|
|
2650
|
+
"button",
|
|
2651
|
+
{
|
|
2652
|
+
onMouseEnter: () => setStatusOpen(true),
|
|
2653
|
+
onMouseLeave: () => setStatusOpen(false),
|
|
2654
|
+
onClick: () => setStatusOpen((v) => !v),
|
|
2655
|
+
className: "flex w-full items-center justify-between gap-2 px-3 py-1.5 text-sm hover:bg-accent transition-colors",
|
|
2656
|
+
children: [
|
|
2657
|
+
/* @__PURE__ */ jsx44("span", { children: "Change status" }),
|
|
2658
|
+
/* @__PURE__ */ jsx44(IconChevronRight, {})
|
|
2659
|
+
]
|
|
2660
|
+
}
|
|
2661
|
+
),
|
|
2662
|
+
statusOpen && /* @__PURE__ */ jsx44(
|
|
2663
|
+
"div",
|
|
2664
|
+
{
|
|
2665
|
+
className: "absolute left-full top-0 z-50 min-w-[130px] rounded-lg border border-border bg-card shadow-md py-1",
|
|
2666
|
+
onMouseEnter: () => setStatusOpen(true),
|
|
2667
|
+
onMouseLeave: () => setStatusOpen(false),
|
|
2668
|
+
children: statusOptions.map((opt) => /* @__PURE__ */ jsx44(
|
|
2669
|
+
"button",
|
|
2670
|
+
{
|
|
2671
|
+
onClick: () => {
|
|
2672
|
+
onStatusChange?.(post.id, opt.value);
|
|
2673
|
+
setOpen(false);
|
|
2674
|
+
setStatusOpen(false);
|
|
2675
|
+
},
|
|
2676
|
+
className: cn(
|
|
2677
|
+
"flex w-full items-center gap-2 px-3 py-1.5 text-sm hover:bg-accent transition-colors",
|
|
2678
|
+
post.status === opt.value && "text-primary font-medium"
|
|
2679
|
+
),
|
|
2680
|
+
children: opt.label
|
|
2681
|
+
},
|
|
2682
|
+
opt.value
|
|
2683
|
+
))
|
|
2684
|
+
}
|
|
2685
|
+
)
|
|
2686
|
+
] }),
|
|
2687
|
+
/* @__PURE__ */ jsx44("div", { className: "my-1 border-t border-border" }),
|
|
2688
|
+
/* @__PURE__ */ jsxs28(
|
|
2689
|
+
"button",
|
|
2690
|
+
{
|
|
2691
|
+
onClick: () => {
|
|
2692
|
+
onDelete?.(post.id);
|
|
2693
|
+
setOpen(false);
|
|
2694
|
+
},
|
|
2695
|
+
className: "flex w-full items-center gap-2 px-3 py-1.5 text-sm text-destructive hover:bg-destructive/10 transition-colors",
|
|
2696
|
+
children: [
|
|
2697
|
+
/* @__PURE__ */ jsx44(IconTrash, {}),
|
|
2698
|
+
"Delete"
|
|
2699
|
+
]
|
|
2700
|
+
}
|
|
2701
|
+
)
|
|
2702
|
+
] })
|
|
2703
|
+
] });
|
|
2704
|
+
}
|
|
2705
|
+
function SkeletonRow() {
|
|
2706
|
+
return /* @__PURE__ */ jsxs28("tr", { children: [
|
|
2707
|
+
/* @__PURE__ */ jsx44("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsx44(Skeleton2, { className: "w-10 h-10 rounded-lg" }) }),
|
|
2708
|
+
/* @__PURE__ */ jsxs28("td", { className: "px-4 py-3", children: [
|
|
2709
|
+
/* @__PURE__ */ jsx44(Skeleton2, { className: "h-4 w-40 mb-1.5" }),
|
|
2710
|
+
/* @__PURE__ */ jsx44(Skeleton2, { className: "h-3 w-24" })
|
|
2711
|
+
] }),
|
|
2712
|
+
/* @__PURE__ */ jsx44("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsx44(Skeleton2, { className: "h-5 w-20 rounded-full" }) }),
|
|
2713
|
+
/* @__PURE__ */ jsx44("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsxs28("div", { className: "flex items-center gap-2", children: [
|
|
2714
|
+
/* @__PURE__ */ jsx44(Skeleton2, { className: "w-6 h-6 rounded-full" }),
|
|
2715
|
+
/* @__PURE__ */ jsx44(Skeleton2, { className: "h-4 w-20" })
|
|
2716
|
+
] }) }),
|
|
2717
|
+
/* @__PURE__ */ jsx44("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsx44(Skeleton2, { className: "h-4 w-24" }) }),
|
|
2718
|
+
/* @__PURE__ */ jsx44("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsxs28("div", { className: "flex gap-1", children: [
|
|
2719
|
+
/* @__PURE__ */ jsx44(Skeleton2, { className: "w-7 h-7 rounded-md" }),
|
|
2720
|
+
/* @__PURE__ */ jsx44(Skeleton2, { className: "w-7 h-7 rounded-md" })
|
|
2721
|
+
] }) })
|
|
2722
|
+
] });
|
|
2723
|
+
}
|
|
2724
|
+
function PostListTable({
|
|
2725
|
+
posts,
|
|
2726
|
+
loading = false,
|
|
2727
|
+
singularLabel = "Post",
|
|
2728
|
+
onEdit,
|
|
2729
|
+
onDelete,
|
|
2730
|
+
onDuplicate,
|
|
2731
|
+
onStatusChange,
|
|
2732
|
+
emptyMessage,
|
|
2733
|
+
emptyIcon,
|
|
2734
|
+
onNewPost,
|
|
2735
|
+
newPostLabel,
|
|
2736
|
+
className
|
|
2737
|
+
}) {
|
|
2738
|
+
const isEmpty = !loading && posts.length === 0;
|
|
2739
|
+
return /* @__PURE__ */ jsxs28("div", { className: cn("w-full overflow-x-auto rounded-lg border border-border bg-card", className), children: [
|
|
2740
|
+
/* @__PURE__ */ jsxs28("table", { className: "w-full text-sm", children: [
|
|
2741
|
+
/* @__PURE__ */ jsx44("thead", { children: /* @__PURE__ */ jsxs28("tr", { className: "border-b border-border bg-muted/40", children: [
|
|
2742
|
+
/* @__PURE__ */ jsx44("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground w-14", children: "Image" }),
|
|
2743
|
+
/* @__PURE__ */ jsx44("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Title" }),
|
|
2744
|
+
/* @__PURE__ */ jsx44("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Status" }),
|
|
2745
|
+
/* @__PURE__ */ jsx44("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Author" }),
|
|
2746
|
+
/* @__PURE__ */ jsx44("th", { className: "px-4 py-2.5 text-left text-xs font-medium text-muted-foreground", children: "Date" }),
|
|
2747
|
+
/* @__PURE__ */ jsx44("th", { className: "px-4 py-2.5 text-right text-xs font-medium text-muted-foreground", children: "Actions" })
|
|
2748
|
+
] }) }),
|
|
2749
|
+
/* @__PURE__ */ jsx44("tbody", { children: loading ? Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ jsx44(SkeletonRow, {}, i)) : isEmpty ? null : posts.map((post) => {
|
|
2750
|
+
const date = post.status === "PUBLISHED" && post.publishedAt ? formatDate(post.publishedAt) : formatDate(post.createdAt);
|
|
2751
|
+
return /* @__PURE__ */ jsxs28(
|
|
2752
|
+
"tr",
|
|
2753
|
+
{
|
|
2754
|
+
className: "border-b border-border last:border-0 hover:bg-muted/30 transition-colors",
|
|
2755
|
+
children: [
|
|
2756
|
+
/* @__PURE__ */ jsx44("td", { className: "px-4 py-3", children: post.featuredImageUrl ? /* @__PURE__ */ jsx44(
|
|
2757
|
+
"img",
|
|
2758
|
+
{
|
|
2759
|
+
src: post.featuredImageUrl,
|
|
2760
|
+
alt: post.title,
|
|
2761
|
+
className: "w-10 h-10 rounded-lg object-cover"
|
|
2762
|
+
}
|
|
2763
|
+
) : /* @__PURE__ */ jsx44("div", { className: "w-10 h-10 rounded-lg bg-muted flex items-center justify-center text-muted-foreground", children: /* @__PURE__ */ jsx44(IconImage, {}) }) }),
|
|
2764
|
+
/* @__PURE__ */ jsxs28("td", { className: "px-4 py-3", children: [
|
|
2765
|
+
/* @__PURE__ */ jsx44("div", { className: "font-medium text-foreground leading-tight truncate max-w-[240px]", children: post.title }),
|
|
2766
|
+
/* @__PURE__ */ jsxs28("div", { className: "text-xs text-muted-foreground mt-0.5 truncate max-w-[240px]", children: [
|
|
2767
|
+
"/",
|
|
2768
|
+
post.slug
|
|
2769
|
+
] })
|
|
2770
|
+
] }),
|
|
2771
|
+
/* @__PURE__ */ jsx44("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsx44(PostStatusBadge, { status: post.status, size: "sm" }) }),
|
|
2772
|
+
/* @__PURE__ */ jsx44("td", { className: "px-4 py-3", children: post.author ? /* @__PURE__ */ jsxs28("div", { className: "flex items-center gap-2", children: [
|
|
2773
|
+
/* @__PURE__ */ jsx44("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) }),
|
|
2774
|
+
/* @__PURE__ */ jsx44("span", { className: "text-sm text-foreground truncate max-w-[100px]", children: post.author })
|
|
2775
|
+
] }) : /* @__PURE__ */ jsx44("span", { className: "text-muted-foreground text-xs", children: "\u2014" }) }),
|
|
2776
|
+
/* @__PURE__ */ jsx44("td", { className: "px-4 py-3 text-sm text-muted-foreground whitespace-nowrap", children: date }),
|
|
2777
|
+
/* @__PURE__ */ jsx44("td", { className: "px-4 py-3", children: /* @__PURE__ */ jsx44("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx44(
|
|
2778
|
+
RowActions,
|
|
2779
|
+
{
|
|
2780
|
+
post,
|
|
2781
|
+
onEdit,
|
|
2782
|
+
onDelete,
|
|
2783
|
+
onDuplicate,
|
|
2784
|
+
onStatusChange
|
|
2785
|
+
}
|
|
2786
|
+
) }) })
|
|
2787
|
+
]
|
|
2788
|
+
},
|
|
2789
|
+
post.id
|
|
2790
|
+
);
|
|
2791
|
+
}) })
|
|
2792
|
+
] }),
|
|
2793
|
+
isEmpty && /* @__PURE__ */ jsxs28("div", { className: "flex flex-col items-center justify-center py-16 px-6 text-center", children: [
|
|
2794
|
+
/* @__PURE__ */ jsx44("div", { className: "text-muted-foreground mb-3", children: emptyIcon ?? /* @__PURE__ */ jsxs28("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: [
|
|
2795
|
+
/* @__PURE__ */ jsx44("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
|
|
2796
|
+
/* @__PURE__ */ jsx44("polyline", { points: "14 2 14 8 20 8" }),
|
|
2797
|
+
/* @__PURE__ */ jsx44("line", { x1: "16", y1: "13", x2: "8", y2: "13" }),
|
|
2798
|
+
/* @__PURE__ */ jsx44("line", { x1: "16", y1: "17", x2: "8", y2: "17" }),
|
|
2799
|
+
/* @__PURE__ */ jsx44("polyline", { points: "10 9 9 9 8 9" })
|
|
2800
|
+
] }) }),
|
|
2801
|
+
/* @__PURE__ */ jsx44("p", { className: "text-sm text-muted-foreground mb-4", children: emptyMessage ?? `No ${singularLabel.toLowerCase()}s yet.` }),
|
|
2802
|
+
onNewPost && /* @__PURE__ */ jsxs28(
|
|
2803
|
+
"button",
|
|
2804
|
+
{
|
|
2805
|
+
onClick: onNewPost,
|
|
2806
|
+
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",
|
|
2807
|
+
children: [
|
|
2808
|
+
/* @__PURE__ */ jsx44(IconPlus, {}),
|
|
2809
|
+
newPostLabel ?? `New ${singularLabel}`
|
|
2810
|
+
]
|
|
2811
|
+
}
|
|
2812
|
+
)
|
|
2813
|
+
] })
|
|
2814
|
+
] });
|
|
2815
|
+
}
|
|
2816
|
+
|
|
2817
|
+
// src/components/content/post-filters-bar.tsx
|
|
2818
|
+
import { jsx as jsx45, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
2819
|
+
var STATUS_TABS = [
|
|
2820
|
+
{ value: "all", label: "All" },
|
|
2821
|
+
{ value: "DRAFT", label: "Draft" },
|
|
2822
|
+
{ value: "PUBLISHED", label: "Published" },
|
|
2823
|
+
{ value: "SCHEDULED", label: "Scheduled" },
|
|
2824
|
+
{ value: "ARCHIVED", label: "Archived" }
|
|
2825
|
+
];
|
|
2826
|
+
function IconSearch() {
|
|
2827
|
+
return /* @__PURE__ */ jsxs29(
|
|
2828
|
+
"svg",
|
|
2829
|
+
{
|
|
2830
|
+
width: "14",
|
|
2831
|
+
height: "14",
|
|
2832
|
+
viewBox: "0 0 24 24",
|
|
2833
|
+
fill: "none",
|
|
2834
|
+
stroke: "currentColor",
|
|
2835
|
+
strokeWidth: "2",
|
|
2836
|
+
strokeLinecap: "round",
|
|
2837
|
+
strokeLinejoin: "round",
|
|
2838
|
+
children: [
|
|
2839
|
+
/* @__PURE__ */ jsx45("circle", { cx: "11", cy: "11", r: "8" }),
|
|
2840
|
+
/* @__PURE__ */ jsx45("line", { x1: "21", y1: "21", x2: "16.65", y2: "16.65" })
|
|
2841
|
+
]
|
|
2842
|
+
}
|
|
2843
|
+
);
|
|
2844
|
+
}
|
|
2845
|
+
function IconPlus2() {
|
|
2846
|
+
return /* @__PURE__ */ jsxs29(
|
|
2847
|
+
"svg",
|
|
2848
|
+
{
|
|
2849
|
+
width: "14",
|
|
2850
|
+
height: "14",
|
|
2851
|
+
viewBox: "0 0 24 24",
|
|
2852
|
+
fill: "none",
|
|
2853
|
+
stroke: "currentColor",
|
|
2854
|
+
strokeWidth: "2",
|
|
2855
|
+
strokeLinecap: "round",
|
|
2856
|
+
strokeLinejoin: "round",
|
|
2857
|
+
children: [
|
|
2858
|
+
/* @__PURE__ */ jsx45("line", { x1: "12", y1: "5", x2: "12", y2: "19" }),
|
|
2859
|
+
/* @__PURE__ */ jsx45("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
|
|
2860
|
+
]
|
|
2861
|
+
}
|
|
2862
|
+
);
|
|
2863
|
+
}
|
|
2864
|
+
function PostFiltersBar({
|
|
2865
|
+
search,
|
|
2866
|
+
onSearch,
|
|
2867
|
+
status,
|
|
2868
|
+
onStatusChange,
|
|
2869
|
+
onNew,
|
|
2870
|
+
newLabel = "New Post",
|
|
2871
|
+
total,
|
|
2872
|
+
typeLabel = "Posts",
|
|
2873
|
+
className
|
|
2874
|
+
}) {
|
|
2875
|
+
return /* @__PURE__ */ jsxs29("div", { className: cn("space-y-2", className), children: [
|
|
2876
|
+
/* @__PURE__ */ jsxs29("div", { className: "flex flex-wrap items-center gap-3", children: [
|
|
2877
|
+
/* @__PURE__ */ jsxs29("div", { className: "relative flex items-center", children: [
|
|
2878
|
+
/* @__PURE__ */ jsx45("span", { className: "absolute left-2.5 text-muted-foreground pointer-events-none", children: /* @__PURE__ */ jsx45(IconSearch, {}) }),
|
|
2879
|
+
/* @__PURE__ */ jsx45(
|
|
2880
|
+
"input",
|
|
2881
|
+
{
|
|
2882
|
+
type: "text",
|
|
2883
|
+
value: search,
|
|
2884
|
+
onChange: (e) => onSearch(e.target.value),
|
|
2885
|
+
placeholder: `Search ${typeLabel}\u2026`,
|
|
2886
|
+
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"
|
|
2887
|
+
}
|
|
2888
|
+
)
|
|
2889
|
+
] }),
|
|
2890
|
+
/* @__PURE__ */ jsx45("div", { className: "flex items-center gap-1 rounded-lg bg-muted p-0.5", children: STATUS_TABS.map((tab) => /* @__PURE__ */ jsx45(
|
|
2891
|
+
"button",
|
|
2892
|
+
{
|
|
2893
|
+
onClick: () => onStatusChange(tab.value),
|
|
2894
|
+
className: cn(
|
|
2895
|
+
"rounded-md px-2.5 py-1 text-xs font-medium transition-colors",
|
|
2896
|
+
status === tab.value ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"
|
|
2897
|
+
),
|
|
2898
|
+
children: tab.label
|
|
2899
|
+
},
|
|
2900
|
+
tab.value
|
|
2901
|
+
)) }),
|
|
2902
|
+
/* @__PURE__ */ jsx45("div", { className: "flex-1" }),
|
|
2903
|
+
onNew && /* @__PURE__ */ jsxs29(
|
|
2904
|
+
"button",
|
|
2905
|
+
{
|
|
2906
|
+
onClick: onNew,
|
|
2907
|
+
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",
|
|
2908
|
+
children: [
|
|
2909
|
+
/* @__PURE__ */ jsx45(IconPlus2, {}),
|
|
2910
|
+
newLabel
|
|
2911
|
+
]
|
|
2912
|
+
}
|
|
2913
|
+
)
|
|
2914
|
+
] }),
|
|
2915
|
+
total !== void 0 && /* @__PURE__ */ jsxs29("p", { className: "text-xs text-muted-foreground", children: [
|
|
2916
|
+
total,
|
|
2917
|
+
" ",
|
|
2918
|
+
total === 1 ? typeLabel.replace(/s$/, "") : typeLabel
|
|
2919
|
+
] })
|
|
2920
|
+
] });
|
|
2921
|
+
}
|
|
2922
|
+
|
|
2923
|
+
// src/components/content/post-editor-shell.tsx
|
|
2924
|
+
import { jsx as jsx46, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
2925
|
+
function IconArrowLeft() {
|
|
2926
|
+
return /* @__PURE__ */ jsxs30(
|
|
2927
|
+
"svg",
|
|
2928
|
+
{
|
|
2929
|
+
width: "14",
|
|
2930
|
+
height: "14",
|
|
2931
|
+
viewBox: "0 0 24 24",
|
|
2932
|
+
fill: "none",
|
|
2933
|
+
stroke: "currentColor",
|
|
2934
|
+
strokeWidth: "2",
|
|
2935
|
+
strokeLinecap: "round",
|
|
2936
|
+
strokeLinejoin: "round",
|
|
2937
|
+
children: [
|
|
2938
|
+
/* @__PURE__ */ jsx46("line", { x1: "19", y1: "12", x2: "5", y2: "12" }),
|
|
2939
|
+
/* @__PURE__ */ jsx46("polyline", { points: "12 19 5 12 12 5" })
|
|
2940
|
+
]
|
|
2941
|
+
}
|
|
2942
|
+
);
|
|
2943
|
+
}
|
|
2944
|
+
function IconSpinner() {
|
|
2945
|
+
return /* @__PURE__ */ jsx46(
|
|
2946
|
+
"svg",
|
|
2947
|
+
{
|
|
2948
|
+
width: "14",
|
|
2949
|
+
height: "14",
|
|
2950
|
+
viewBox: "0 0 24 24",
|
|
2951
|
+
fill: "none",
|
|
2952
|
+
stroke: "currentColor",
|
|
2953
|
+
strokeWidth: "2",
|
|
2954
|
+
strokeLinecap: "round",
|
|
2955
|
+
strokeLinejoin: "round",
|
|
2956
|
+
className: "animate-spin",
|
|
2957
|
+
children: /* @__PURE__ */ jsx46("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" })
|
|
2958
|
+
}
|
|
2959
|
+
);
|
|
2960
|
+
}
|
|
2961
|
+
function IconMoreHorizontal2() {
|
|
2962
|
+
return /* @__PURE__ */ jsxs30(
|
|
2963
|
+
"svg",
|
|
2964
|
+
{
|
|
2965
|
+
width: "16",
|
|
2966
|
+
height: "16",
|
|
2967
|
+
viewBox: "0 0 24 24",
|
|
2968
|
+
fill: "none",
|
|
2969
|
+
stroke: "currentColor",
|
|
2970
|
+
strokeWidth: "2",
|
|
2971
|
+
strokeLinecap: "round",
|
|
2972
|
+
strokeLinejoin: "round",
|
|
2973
|
+
children: [
|
|
2974
|
+
/* @__PURE__ */ jsx46("circle", { cx: "5", cy: "12", r: "1", fill: "currentColor" }),
|
|
2975
|
+
/* @__PURE__ */ jsx46("circle", { cx: "12", cy: "12", r: "1", fill: "currentColor" }),
|
|
2976
|
+
/* @__PURE__ */ jsx46("circle", { cx: "19", cy: "12", r: "1", fill: "currentColor" })
|
|
2977
|
+
]
|
|
2978
|
+
}
|
|
2979
|
+
);
|
|
2980
|
+
}
|
|
2981
|
+
function PostEditorShell({
|
|
2982
|
+
title,
|
|
2983
|
+
backLabel = "Back",
|
|
2984
|
+
onBack,
|
|
2985
|
+
onSave,
|
|
2986
|
+
onPublish,
|
|
2987
|
+
saving = false,
|
|
2988
|
+
publishing = false,
|
|
2989
|
+
status,
|
|
2990
|
+
children,
|
|
2991
|
+
sidebar,
|
|
2992
|
+
className
|
|
2993
|
+
}) {
|
|
2994
|
+
return /* @__PURE__ */ jsxs30("div", { className: cn("flex flex-col h-screen bg-background overflow-hidden", className), children: [
|
|
2995
|
+
/* @__PURE__ */ jsxs30("div", { className: "flex items-center gap-3 h-14 px-4 border-b border-border bg-card shrink-0", children: [
|
|
2996
|
+
onBack && /* @__PURE__ */ jsxs30(
|
|
2997
|
+
"button",
|
|
2998
|
+
{
|
|
2999
|
+
onClick: onBack,
|
|
3000
|
+
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",
|
|
3001
|
+
children: [
|
|
3002
|
+
/* @__PURE__ */ jsx46(IconArrowLeft, {}),
|
|
3003
|
+
backLabel
|
|
3004
|
+
]
|
|
3005
|
+
}
|
|
3006
|
+
),
|
|
3007
|
+
onBack && /* @__PURE__ */ jsx46("div", { className: "h-5 w-px bg-border" }),
|
|
3008
|
+
title && /* @__PURE__ */ jsx46("span", { className: "text-sm font-medium text-muted-foreground truncate max-w-xs", children: title }),
|
|
3009
|
+
status && /* @__PURE__ */ jsx46(PostStatusBadge, { status, size: "sm" }),
|
|
3010
|
+
/* @__PURE__ */ jsx46("div", { className: "flex-1" }),
|
|
3011
|
+
/* @__PURE__ */ jsx46("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__ */ jsx46(IconMoreHorizontal2, {}) }),
|
|
3012
|
+
/* @__PURE__ */ jsxs30(
|
|
3013
|
+
"button",
|
|
3014
|
+
{
|
|
3015
|
+
onClick: onSave,
|
|
3016
|
+
disabled: saving,
|
|
3017
|
+
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",
|
|
3018
|
+
children: [
|
|
3019
|
+
saving && /* @__PURE__ */ jsx46(IconSpinner, {}),
|
|
3020
|
+
"Save Draft"
|
|
3021
|
+
]
|
|
3022
|
+
}
|
|
3023
|
+
),
|
|
3024
|
+
/* @__PURE__ */ jsxs30(
|
|
3025
|
+
"button",
|
|
3026
|
+
{
|
|
3027
|
+
onClick: onPublish,
|
|
3028
|
+
disabled: publishing,
|
|
3029
|
+
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",
|
|
3030
|
+
children: [
|
|
3031
|
+
publishing && /* @__PURE__ */ jsx46(IconSpinner, {}),
|
|
3032
|
+
"Publish"
|
|
3033
|
+
]
|
|
3034
|
+
}
|
|
3035
|
+
)
|
|
3036
|
+
] }),
|
|
3037
|
+
/* @__PURE__ */ jsxs30("div", { className: "flex flex-1 overflow-hidden", children: [
|
|
3038
|
+
/* @__PURE__ */ jsx46("div", { className: "flex-1 overflow-y-auto p-6", children: /* @__PURE__ */ jsx46("div", { className: "max-w-3xl mx-auto", children }) }),
|
|
3039
|
+
/* @__PURE__ */ jsx46("div", { className: "w-72 shrink-0 border-l border-border overflow-y-auto p-4", children: sidebar })
|
|
3040
|
+
] })
|
|
3041
|
+
] });
|
|
3042
|
+
}
|
|
3043
|
+
|
|
3044
|
+
// src/components/content/slug-input.tsx
|
|
3045
|
+
import { jsx as jsx47, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
3046
|
+
function IconRefresh() {
|
|
3047
|
+
return /* @__PURE__ */ jsxs31(
|
|
3048
|
+
"svg",
|
|
3049
|
+
{
|
|
3050
|
+
width: "13",
|
|
3051
|
+
height: "13",
|
|
3052
|
+
viewBox: "0 0 24 24",
|
|
3053
|
+
fill: "none",
|
|
3054
|
+
stroke: "currentColor",
|
|
3055
|
+
strokeWidth: "2",
|
|
3056
|
+
strokeLinecap: "round",
|
|
3057
|
+
strokeLinejoin: "round",
|
|
3058
|
+
children: [
|
|
3059
|
+
/* @__PURE__ */ jsx47("polyline", { points: "23 4 23 10 17 10" }),
|
|
3060
|
+
/* @__PURE__ */ jsx47("polyline", { points: "1 20 1 14 7 14" }),
|
|
3061
|
+
/* @__PURE__ */ jsx47("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" })
|
|
3062
|
+
]
|
|
3063
|
+
}
|
|
3064
|
+
);
|
|
3065
|
+
}
|
|
3066
|
+
function SlugInput({
|
|
3067
|
+
value,
|
|
3068
|
+
onChange,
|
|
3069
|
+
onGenerate,
|
|
3070
|
+
prefix,
|
|
3071
|
+
disabled = false,
|
|
3072
|
+
className
|
|
3073
|
+
}) {
|
|
3074
|
+
return /* @__PURE__ */ jsxs31("div", { className: cn("space-y-1", className), children: [
|
|
3075
|
+
/* @__PURE__ */ jsxs31("div", { className: "flex items-center gap-1", children: [
|
|
3076
|
+
prefix && /* @__PURE__ */ jsx47("span", { className: "shrink-0 text-sm text-muted-foreground select-none", children: prefix }),
|
|
3077
|
+
/* @__PURE__ */ jsx47(
|
|
3078
|
+
"input",
|
|
3079
|
+
{
|
|
3080
|
+
type: "text",
|
|
3081
|
+
value,
|
|
3082
|
+
onChange: (e) => onChange(e.target.value),
|
|
3083
|
+
disabled,
|
|
3084
|
+
className: cn(
|
|
3085
|
+
"flex-1 h-8 border-0 border-b border-input bg-transparent text-sm focus:outline-none focus:border-primary transition-colors",
|
|
3086
|
+
disabled && "opacity-60 cursor-not-allowed"
|
|
3087
|
+
),
|
|
3088
|
+
placeholder: "your-slug-here"
|
|
3089
|
+
}
|
|
3090
|
+
),
|
|
3091
|
+
onGenerate && /* @__PURE__ */ jsx47(
|
|
3092
|
+
"button",
|
|
3093
|
+
{
|
|
3094
|
+
onClick: onGenerate,
|
|
3095
|
+
disabled,
|
|
3096
|
+
title: "Generate slug",
|
|
3097
|
+
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",
|
|
3098
|
+
children: /* @__PURE__ */ jsx47(IconRefresh, {})
|
|
3099
|
+
}
|
|
3100
|
+
)
|
|
3101
|
+
] }),
|
|
3102
|
+
/* @__PURE__ */ jsx47("p", { className: "text-[10px] text-muted-foreground", children: "Only lowercase letters, numbers, and hyphens" })
|
|
3103
|
+
] });
|
|
3104
|
+
}
|
|
3105
|
+
|
|
3106
|
+
// src/components/content/post-sidebar-section.tsx
|
|
3107
|
+
import * as React22 from "react";
|
|
3108
|
+
import { jsx as jsx48, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
3109
|
+
function IconChevronDown() {
|
|
3110
|
+
return /* @__PURE__ */ jsx48(
|
|
3111
|
+
"svg",
|
|
3112
|
+
{
|
|
3113
|
+
width: "14",
|
|
3114
|
+
height: "14",
|
|
3115
|
+
viewBox: "0 0 24 24",
|
|
3116
|
+
fill: "none",
|
|
3117
|
+
stroke: "currentColor",
|
|
3118
|
+
strokeWidth: "2",
|
|
3119
|
+
strokeLinecap: "round",
|
|
3120
|
+
strokeLinejoin: "round",
|
|
3121
|
+
children: /* @__PURE__ */ jsx48("polyline", { points: "6 9 12 15 18 9" })
|
|
3122
|
+
}
|
|
3123
|
+
);
|
|
3124
|
+
}
|
|
3125
|
+
function PostSidebarSection({
|
|
3126
|
+
title,
|
|
3127
|
+
children,
|
|
3128
|
+
defaultOpen = true,
|
|
3129
|
+
className
|
|
3130
|
+
}) {
|
|
3131
|
+
const [open, setOpen] = React22.useState(defaultOpen);
|
|
3132
|
+
return /* @__PURE__ */ jsxs32("div", { className: cn("border-b border-border", className), children: [
|
|
3133
|
+
/* @__PURE__ */ jsxs32(
|
|
3134
|
+
"button",
|
|
3135
|
+
{
|
|
3136
|
+
onClick: () => setOpen((v) => !v),
|
|
3137
|
+
className: "flex w-full items-center justify-between py-3 px-0 text-sm font-medium text-foreground hover:text-primary transition-colors",
|
|
3138
|
+
children: [
|
|
3139
|
+
title,
|
|
3140
|
+
/* @__PURE__ */ jsx48(
|
|
3141
|
+
"span",
|
|
3142
|
+
{
|
|
3143
|
+
className: cn(
|
|
3144
|
+
"text-muted-foreground transition-transform duration-200",
|
|
3145
|
+
open ? "rotate-0" : "-rotate-90"
|
|
3146
|
+
),
|
|
3147
|
+
children: /* @__PURE__ */ jsx48(IconChevronDown, {})
|
|
3148
|
+
}
|
|
3149
|
+
)
|
|
3150
|
+
]
|
|
3151
|
+
}
|
|
3152
|
+
),
|
|
3153
|
+
/* @__PURE__ */ jsx48(
|
|
3154
|
+
"div",
|
|
3155
|
+
{
|
|
3156
|
+
className: cn(
|
|
3157
|
+
"overflow-hidden transition-all duration-200",
|
|
3158
|
+
open ? "max-h-[9999px] pb-4 opacity-100" : "max-h-0 opacity-0 pointer-events-none"
|
|
3159
|
+
),
|
|
3160
|
+
children
|
|
3161
|
+
}
|
|
3162
|
+
)
|
|
3163
|
+
] });
|
|
3164
|
+
}
|
|
3165
|
+
|
|
2434
3166
|
// src/hooks/index.ts
|
|
2435
|
-
import { useState as
|
|
3167
|
+
import { useState as useState7 } from "react";
|
|
2436
3168
|
function useDisclosure(initial = false) {
|
|
2437
|
-
const [isOpen, setIsOpen] =
|
|
3169
|
+
const [isOpen, setIsOpen] = useState7(initial);
|
|
2438
3170
|
return {
|
|
2439
3171
|
isOpen,
|
|
2440
3172
|
open: () => setIsOpen(true),
|
|
@@ -2444,15 +3176,15 @@ function useDisclosure(initial = false) {
|
|
|
2444
3176
|
};
|
|
2445
3177
|
}
|
|
2446
3178
|
function usePagination(total, pageSize = 20) {
|
|
2447
|
-
const [page, setPage] =
|
|
3179
|
+
const [page, setPage] = useState7(1);
|
|
2448
3180
|
const totalPages = Math.ceil(total / pageSize);
|
|
2449
3181
|
return { page, setPage, pageSize, total, totalPages };
|
|
2450
3182
|
}
|
|
2451
3183
|
|
|
2452
3184
|
// src/components/auth/AuthShell.tsx
|
|
2453
|
-
import { jsx as
|
|
3185
|
+
import { jsx as jsx49, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
2454
3186
|
function AuthShell({ children, pattern = "dots", maxWidth = "520px" }) {
|
|
2455
|
-
return /* @__PURE__ */
|
|
3187
|
+
return /* @__PURE__ */ jsxs33(
|
|
2456
3188
|
"div",
|
|
2457
3189
|
{
|
|
2458
3190
|
style: {
|
|
@@ -2467,7 +3199,7 @@ function AuthShell({ children, pattern = "dots", maxWidth = "520px" }) {
|
|
|
2467
3199
|
overflow: "hidden"
|
|
2468
3200
|
},
|
|
2469
3201
|
children: [
|
|
2470
|
-
pattern === "dots" && /* @__PURE__ */
|
|
3202
|
+
pattern === "dots" && /* @__PURE__ */ jsx49(
|
|
2471
3203
|
"div",
|
|
2472
3204
|
{
|
|
2473
3205
|
"aria-hidden": true,
|
|
@@ -2481,7 +3213,7 @@ function AuthShell({ children, pattern = "dots", maxWidth = "520px" }) {
|
|
|
2481
3213
|
}
|
|
2482
3214
|
}
|
|
2483
3215
|
),
|
|
2484
|
-
pattern === "grid" && /* @__PURE__ */
|
|
3216
|
+
pattern === "grid" && /* @__PURE__ */ jsx49(
|
|
2485
3217
|
"div",
|
|
2486
3218
|
{
|
|
2487
3219
|
"aria-hidden": true,
|
|
@@ -2495,16 +3227,16 @@ function AuthShell({ children, pattern = "dots", maxWidth = "520px" }) {
|
|
|
2495
3227
|
}
|
|
2496
3228
|
}
|
|
2497
3229
|
),
|
|
2498
|
-
/* @__PURE__ */
|
|
3230
|
+
/* @__PURE__ */ jsx49("div", { style: { position: "relative", zIndex: 1, width: "100%", maxWidth }, children })
|
|
2499
3231
|
]
|
|
2500
3232
|
}
|
|
2501
3233
|
);
|
|
2502
3234
|
}
|
|
2503
3235
|
|
|
2504
3236
|
// src/components/auth/AuthCard.tsx
|
|
2505
|
-
import { jsx as
|
|
3237
|
+
import { jsx as jsx50 } from "react/jsx-runtime";
|
|
2506
3238
|
function AuthCard({ children, padding = "24px 28px" }) {
|
|
2507
|
-
return /* @__PURE__ */
|
|
3239
|
+
return /* @__PURE__ */ jsx50(
|
|
2508
3240
|
"div",
|
|
2509
3241
|
{
|
|
2510
3242
|
style: {
|
|
@@ -2521,10 +3253,10 @@ function AuthCard({ children, padding = "24px 28px" }) {
|
|
|
2521
3253
|
}
|
|
2522
3254
|
|
|
2523
3255
|
// src/components/auth/AuthLogo.tsx
|
|
2524
|
-
import { jsx as
|
|
3256
|
+
import { jsx as jsx51, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
2525
3257
|
function AuthLogo({ appName = "Builify CMS", letter = "B", imageUrl, size = 36 }) {
|
|
2526
|
-
return /* @__PURE__ */
|
|
2527
|
-
imageUrl ? /* @__PURE__ */
|
|
3258
|
+
return /* @__PURE__ */ jsxs34("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", gap: "10px", marginBottom: "28px" }, children: [
|
|
3259
|
+
imageUrl ? /* @__PURE__ */ jsx51(
|
|
2528
3260
|
"img",
|
|
2529
3261
|
{
|
|
2530
3262
|
src: imageUrl,
|
|
@@ -2533,7 +3265,7 @@ function AuthLogo({ appName = "Builify CMS", letter = "B", imageUrl, size = 36 }
|
|
|
2533
3265
|
height: size,
|
|
2534
3266
|
style: { borderRadius: "calc(var(--radius, 0.5rem) * 1.2)", flexShrink: 0, display: "block" }
|
|
2535
3267
|
}
|
|
2536
|
-
) : /* @__PURE__ */
|
|
3268
|
+
) : /* @__PURE__ */ jsx51(
|
|
2537
3269
|
"div",
|
|
2538
3270
|
{
|
|
2539
3271
|
style: {
|
|
@@ -2552,7 +3284,7 @@ function AuthLogo({ appName = "Builify CMS", letter = "B", imageUrl, size = 36 }
|
|
|
2552
3284
|
children: letter
|
|
2553
3285
|
}
|
|
2554
3286
|
),
|
|
2555
|
-
/* @__PURE__ */
|
|
3287
|
+
/* @__PURE__ */ jsx51(
|
|
2556
3288
|
"span",
|
|
2557
3289
|
{
|
|
2558
3290
|
style: {
|
|
@@ -2568,10 +3300,10 @@ function AuthLogo({ appName = "Builify CMS", letter = "B", imageUrl, size = 36 }
|
|
|
2568
3300
|
}
|
|
2569
3301
|
|
|
2570
3302
|
// src/components/auth/AuthHeader.tsx
|
|
2571
|
-
import { jsx as
|
|
3303
|
+
import { jsx as jsx52, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
2572
3304
|
function AuthHeader({ title, description }) {
|
|
2573
|
-
return /* @__PURE__ */
|
|
2574
|
-
/* @__PURE__ */
|
|
3305
|
+
return /* @__PURE__ */ jsxs35("div", { style: { marginBottom: "24px", textAlign: "center" }, children: [
|
|
3306
|
+
/* @__PURE__ */ jsx52(
|
|
2575
3307
|
"h1",
|
|
2576
3308
|
{
|
|
2577
3309
|
style: {
|
|
@@ -2584,7 +3316,7 @@ function AuthHeader({ title, description }) {
|
|
|
2584
3316
|
children: title
|
|
2585
3317
|
}
|
|
2586
3318
|
),
|
|
2587
|
-
description && /* @__PURE__ */
|
|
3319
|
+
description && /* @__PURE__ */ jsx52(
|
|
2588
3320
|
"p",
|
|
2589
3321
|
{
|
|
2590
3322
|
style: {
|
|
@@ -2600,12 +3332,12 @@ function AuthHeader({ title, description }) {
|
|
|
2600
3332
|
}
|
|
2601
3333
|
|
|
2602
3334
|
// src/components/auth/AuthField.tsx
|
|
2603
|
-
import { jsx as
|
|
3335
|
+
import { jsx as jsx53, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
2604
3336
|
function AuthField({ label, error, hint, rightLabel, id, ...props }) {
|
|
2605
3337
|
const fieldId = id ?? label.toLowerCase().replace(/\s+/g, "-");
|
|
2606
|
-
return /* @__PURE__ */
|
|
2607
|
-
/* @__PURE__ */
|
|
2608
|
-
/* @__PURE__ */
|
|
3338
|
+
return /* @__PURE__ */ jsxs36("div", { style: { display: "flex", flexDirection: "column", gap: "6px" }, children: [
|
|
3339
|
+
/* @__PURE__ */ jsxs36("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
|
|
3340
|
+
/* @__PURE__ */ jsx53(
|
|
2609
3341
|
"label",
|
|
2610
3342
|
{
|
|
2611
3343
|
htmlFor: fieldId,
|
|
@@ -2617,9 +3349,9 @@ function AuthField({ label, error, hint, rightLabel, id, ...props }) {
|
|
|
2617
3349
|
children: label
|
|
2618
3350
|
}
|
|
2619
3351
|
),
|
|
2620
|
-
rightLabel && /* @__PURE__ */
|
|
3352
|
+
rightLabel && /* @__PURE__ */ jsx53("span", { style: { fontSize: "0.8125rem" }, children: rightLabel })
|
|
2621
3353
|
] }),
|
|
2622
|
-
/* @__PURE__ */
|
|
3354
|
+
/* @__PURE__ */ jsx53(
|
|
2623
3355
|
"input",
|
|
2624
3356
|
{
|
|
2625
3357
|
id: fieldId,
|
|
@@ -2649,13 +3381,13 @@ function AuthField({ label, error, hint, rightLabel, id, ...props }) {
|
|
|
2649
3381
|
...props
|
|
2650
3382
|
}
|
|
2651
3383
|
),
|
|
2652
|
-
error && /* @__PURE__ */
|
|
2653
|
-
hint && !error && /* @__PURE__ */
|
|
3384
|
+
error && /* @__PURE__ */ jsx53("p", { style: { fontSize: "0.8rem", color: "var(--destructive)", margin: 0 }, children: error }),
|
|
3385
|
+
hint && !error && /* @__PURE__ */ jsx53("p", { style: { fontSize: "0.8rem", color: "var(--muted-foreground)", margin: 0 }, children: hint })
|
|
2654
3386
|
] });
|
|
2655
3387
|
}
|
|
2656
3388
|
|
|
2657
3389
|
// src/components/auth/AuthButton.tsx
|
|
2658
|
-
import { Fragment as Fragment5, jsx as
|
|
3390
|
+
import { Fragment as Fragment5, jsx as jsx54, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
2659
3391
|
function AuthButton({
|
|
2660
3392
|
loading,
|
|
2661
3393
|
variant = "primary",
|
|
@@ -2698,7 +3430,7 @@ function AuthButton({
|
|
|
2698
3430
|
color: "var(--foreground)"
|
|
2699
3431
|
}
|
|
2700
3432
|
};
|
|
2701
|
-
return /* @__PURE__ */
|
|
3433
|
+
return /* @__PURE__ */ jsx54(
|
|
2702
3434
|
"button",
|
|
2703
3435
|
{
|
|
2704
3436
|
disabled: loading || disabled,
|
|
@@ -2710,8 +3442,8 @@ function AuthButton({
|
|
|
2710
3442
|
e.currentTarget.style.filter = "none";
|
|
2711
3443
|
},
|
|
2712
3444
|
...props,
|
|
2713
|
-
children: loading ? /* @__PURE__ */
|
|
2714
|
-
/* @__PURE__ */
|
|
3445
|
+
children: loading ? /* @__PURE__ */ jsxs37(Fragment5, { children: [
|
|
3446
|
+
/* @__PURE__ */ jsx54(
|
|
2715
3447
|
"span",
|
|
2716
3448
|
{
|
|
2717
3449
|
style: {
|
|
@@ -2732,19 +3464,19 @@ function AuthButton({
|
|
|
2732
3464
|
}
|
|
2733
3465
|
|
|
2734
3466
|
// src/components/auth/AuthDivider.tsx
|
|
2735
|
-
import { jsx as
|
|
3467
|
+
import { jsx as jsx55, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
2736
3468
|
function AuthDivider({ label = "or" }) {
|
|
2737
|
-
return /* @__PURE__ */
|
|
2738
|
-
/* @__PURE__ */
|
|
2739
|
-
/* @__PURE__ */
|
|
2740
|
-
/* @__PURE__ */
|
|
3469
|
+
return /* @__PURE__ */ jsxs38("div", { style: { display: "flex", alignItems: "center", gap: "12px", margin: "20px 0" }, children: [
|
|
3470
|
+
/* @__PURE__ */ jsx55("div", { style: { flex: 1, height: 1, background: "var(--border)" } }),
|
|
3471
|
+
/* @__PURE__ */ jsx55("span", { style: { fontSize: "0.75rem", color: "var(--muted-foreground)", userSelect: "none" }, children: label }),
|
|
3472
|
+
/* @__PURE__ */ jsx55("div", { style: { flex: 1, height: 1, background: "var(--border)" } })
|
|
2741
3473
|
] });
|
|
2742
3474
|
}
|
|
2743
3475
|
|
|
2744
3476
|
// src/components/auth/AuthFootnote.tsx
|
|
2745
|
-
import { jsx as
|
|
3477
|
+
import { jsx as jsx56, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
2746
3478
|
function AuthFootnote({ text, linkText, linkHref }) {
|
|
2747
|
-
return /* @__PURE__ */
|
|
3479
|
+
return /* @__PURE__ */ jsxs39("p", { style: {
|
|
2748
3480
|
textAlign: "center",
|
|
2749
3481
|
marginTop: "20px",
|
|
2750
3482
|
fontSize: "0.8125rem",
|
|
@@ -2752,7 +3484,7 @@ function AuthFootnote({ text, linkText, linkHref }) {
|
|
|
2752
3484
|
}, children: [
|
|
2753
3485
|
text,
|
|
2754
3486
|
" ",
|
|
2755
|
-
/* @__PURE__ */
|
|
3487
|
+
/* @__PURE__ */ jsx56(
|
|
2756
3488
|
"a",
|
|
2757
3489
|
{
|
|
2758
3490
|
href: linkHref,
|
|
@@ -2769,37 +3501,6 @@ function AuthFootnote({ text, linkText, linkHref }) {
|
|
|
2769
3501
|
] });
|
|
2770
3502
|
}
|
|
2771
3503
|
|
|
2772
|
-
// src/components/Skeleton.tsx
|
|
2773
|
-
import { jsx as jsx50 } from "react/jsx-runtime";
|
|
2774
|
-
function Skeleton2({ width = "100%", height = 16, rounded, style }) {
|
|
2775
|
-
return /* @__PURE__ */ jsx50(
|
|
2776
|
-
"div",
|
|
2777
|
-
{
|
|
2778
|
-
style: {
|
|
2779
|
-
width,
|
|
2780
|
-
height,
|
|
2781
|
-
background: "var(--muted, #e5e7eb)",
|
|
2782
|
-
borderRadius: rounded ?? "var(--radius, 0.5rem)",
|
|
2783
|
-
overflow: "hidden",
|
|
2784
|
-
position: "relative",
|
|
2785
|
-
flexShrink: 0,
|
|
2786
|
-
...style
|
|
2787
|
-
},
|
|
2788
|
-
children: /* @__PURE__ */ jsx50(
|
|
2789
|
-
"div",
|
|
2790
|
-
{
|
|
2791
|
-
style: {
|
|
2792
|
-
position: "absolute",
|
|
2793
|
-
inset: 0,
|
|
2794
|
-
background: "linear-gradient(90deg, transparent 0%, color-mix(in oklab, var(--background, #fff) 40%, transparent) 50%, transparent 100%)",
|
|
2795
|
-
animation: "dashui-shimmer 1.6s ease-in-out infinite"
|
|
2796
|
-
}
|
|
2797
|
-
}
|
|
2798
|
-
)
|
|
2799
|
-
}
|
|
2800
|
-
);
|
|
2801
|
-
}
|
|
2802
|
-
|
|
2803
3504
|
// src/index.ts
|
|
2804
3505
|
import { ThemeProvider, useTheme as useTheme2 } from "next-themes";
|
|
2805
3506
|
export {
|
|
@@ -2869,6 +3570,11 @@ export {
|
|
|
2869
3570
|
Popover,
|
|
2870
3571
|
PopoverContent,
|
|
2871
3572
|
PopoverTrigger,
|
|
3573
|
+
PostEditorShell,
|
|
3574
|
+
PostFiltersBar,
|
|
3575
|
+
PostListTable,
|
|
3576
|
+
PostSidebarSection,
|
|
3577
|
+
PostStatusBadge,
|
|
2872
3578
|
SearchBar,
|
|
2873
3579
|
Select,
|
|
2874
3580
|
SelectContent,
|
|
@@ -2883,6 +3589,7 @@ export {
|
|
|
2883
3589
|
Separator3 as Separator,
|
|
2884
3590
|
Sidebar,
|
|
2885
3591
|
Skeleton2 as Skeleton,
|
|
3592
|
+
SlugInput,
|
|
2886
3593
|
Stats,
|
|
2887
3594
|
StorageBar,
|
|
2888
3595
|
Switch,
|