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