@webdevarif/dashui 0.2.5 → 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 +772 -67
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +769 -70
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -2439,10 +2439,734 @@ function ConfirmDialog({
|
|
|
2439
2439
|
] }) });
|
|
2440
2440
|
}
|
|
2441
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
|
+
|
|
2442
3166
|
// src/hooks/index.ts
|
|
2443
|
-
import { useState as
|
|
3167
|
+
import { useState as useState7 } from "react";
|
|
2444
3168
|
function useDisclosure(initial = false) {
|
|
2445
|
-
const [isOpen, setIsOpen] =
|
|
3169
|
+
const [isOpen, setIsOpen] = useState7(initial);
|
|
2446
3170
|
return {
|
|
2447
3171
|
isOpen,
|
|
2448
3172
|
open: () => setIsOpen(true),
|
|
@@ -2452,15 +3176,15 @@ function useDisclosure(initial = false) {
|
|
|
2452
3176
|
};
|
|
2453
3177
|
}
|
|
2454
3178
|
function usePagination(total, pageSize = 20) {
|
|
2455
|
-
const [page, setPage] =
|
|
3179
|
+
const [page, setPage] = useState7(1);
|
|
2456
3180
|
const totalPages = Math.ceil(total / pageSize);
|
|
2457
3181
|
return { page, setPage, pageSize, total, totalPages };
|
|
2458
3182
|
}
|
|
2459
3183
|
|
|
2460
3184
|
// src/components/auth/AuthShell.tsx
|
|
2461
|
-
import { jsx as
|
|
3185
|
+
import { jsx as jsx49, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
2462
3186
|
function AuthShell({ children, pattern = "dots", maxWidth = "520px" }) {
|
|
2463
|
-
return /* @__PURE__ */
|
|
3187
|
+
return /* @__PURE__ */ jsxs33(
|
|
2464
3188
|
"div",
|
|
2465
3189
|
{
|
|
2466
3190
|
style: {
|
|
@@ -2475,7 +3199,7 @@ function AuthShell({ children, pattern = "dots", maxWidth = "520px" }) {
|
|
|
2475
3199
|
overflow: "hidden"
|
|
2476
3200
|
},
|
|
2477
3201
|
children: [
|
|
2478
|
-
pattern === "dots" && /* @__PURE__ */
|
|
3202
|
+
pattern === "dots" && /* @__PURE__ */ jsx49(
|
|
2479
3203
|
"div",
|
|
2480
3204
|
{
|
|
2481
3205
|
"aria-hidden": true,
|
|
@@ -2489,7 +3213,7 @@ function AuthShell({ children, pattern = "dots", maxWidth = "520px" }) {
|
|
|
2489
3213
|
}
|
|
2490
3214
|
}
|
|
2491
3215
|
),
|
|
2492
|
-
pattern === "grid" && /* @__PURE__ */
|
|
3216
|
+
pattern === "grid" && /* @__PURE__ */ jsx49(
|
|
2493
3217
|
"div",
|
|
2494
3218
|
{
|
|
2495
3219
|
"aria-hidden": true,
|
|
@@ -2503,16 +3227,16 @@ function AuthShell({ children, pattern = "dots", maxWidth = "520px" }) {
|
|
|
2503
3227
|
}
|
|
2504
3228
|
}
|
|
2505
3229
|
),
|
|
2506
|
-
/* @__PURE__ */
|
|
3230
|
+
/* @__PURE__ */ jsx49("div", { style: { position: "relative", zIndex: 1, width: "100%", maxWidth }, children })
|
|
2507
3231
|
]
|
|
2508
3232
|
}
|
|
2509
3233
|
);
|
|
2510
3234
|
}
|
|
2511
3235
|
|
|
2512
3236
|
// src/components/auth/AuthCard.tsx
|
|
2513
|
-
import { jsx as
|
|
3237
|
+
import { jsx as jsx50 } from "react/jsx-runtime";
|
|
2514
3238
|
function AuthCard({ children, padding = "24px 28px" }) {
|
|
2515
|
-
return /* @__PURE__ */
|
|
3239
|
+
return /* @__PURE__ */ jsx50(
|
|
2516
3240
|
"div",
|
|
2517
3241
|
{
|
|
2518
3242
|
style: {
|
|
@@ -2529,10 +3253,10 @@ function AuthCard({ children, padding = "24px 28px" }) {
|
|
|
2529
3253
|
}
|
|
2530
3254
|
|
|
2531
3255
|
// src/components/auth/AuthLogo.tsx
|
|
2532
|
-
import { jsx as
|
|
3256
|
+
import { jsx as jsx51, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
2533
3257
|
function AuthLogo({ appName = "Builify CMS", letter = "B", imageUrl, size = 36 }) {
|
|
2534
|
-
return /* @__PURE__ */
|
|
2535
|
-
imageUrl ? /* @__PURE__ */
|
|
3258
|
+
return /* @__PURE__ */ jsxs34("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", gap: "10px", marginBottom: "28px" }, children: [
|
|
3259
|
+
imageUrl ? /* @__PURE__ */ jsx51(
|
|
2536
3260
|
"img",
|
|
2537
3261
|
{
|
|
2538
3262
|
src: imageUrl,
|
|
@@ -2541,7 +3265,7 @@ function AuthLogo({ appName = "Builify CMS", letter = "B", imageUrl, size = 36 }
|
|
|
2541
3265
|
height: size,
|
|
2542
3266
|
style: { borderRadius: "calc(var(--radius, 0.5rem) * 1.2)", flexShrink: 0, display: "block" }
|
|
2543
3267
|
}
|
|
2544
|
-
) : /* @__PURE__ */
|
|
3268
|
+
) : /* @__PURE__ */ jsx51(
|
|
2545
3269
|
"div",
|
|
2546
3270
|
{
|
|
2547
3271
|
style: {
|
|
@@ -2560,7 +3284,7 @@ function AuthLogo({ appName = "Builify CMS", letter = "B", imageUrl, size = 36 }
|
|
|
2560
3284
|
children: letter
|
|
2561
3285
|
}
|
|
2562
3286
|
),
|
|
2563
|
-
/* @__PURE__ */
|
|
3287
|
+
/* @__PURE__ */ jsx51(
|
|
2564
3288
|
"span",
|
|
2565
3289
|
{
|
|
2566
3290
|
style: {
|
|
@@ -2576,10 +3300,10 @@ function AuthLogo({ appName = "Builify CMS", letter = "B", imageUrl, size = 36 }
|
|
|
2576
3300
|
}
|
|
2577
3301
|
|
|
2578
3302
|
// src/components/auth/AuthHeader.tsx
|
|
2579
|
-
import { jsx as
|
|
3303
|
+
import { jsx as jsx52, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
2580
3304
|
function AuthHeader({ title, description }) {
|
|
2581
|
-
return /* @__PURE__ */
|
|
2582
|
-
/* @__PURE__ */
|
|
3305
|
+
return /* @__PURE__ */ jsxs35("div", { style: { marginBottom: "24px", textAlign: "center" }, children: [
|
|
3306
|
+
/* @__PURE__ */ jsx52(
|
|
2583
3307
|
"h1",
|
|
2584
3308
|
{
|
|
2585
3309
|
style: {
|
|
@@ -2592,7 +3316,7 @@ function AuthHeader({ title, description }) {
|
|
|
2592
3316
|
children: title
|
|
2593
3317
|
}
|
|
2594
3318
|
),
|
|
2595
|
-
description && /* @__PURE__ */
|
|
3319
|
+
description && /* @__PURE__ */ jsx52(
|
|
2596
3320
|
"p",
|
|
2597
3321
|
{
|
|
2598
3322
|
style: {
|
|
@@ -2608,12 +3332,12 @@ function AuthHeader({ title, description }) {
|
|
|
2608
3332
|
}
|
|
2609
3333
|
|
|
2610
3334
|
// src/components/auth/AuthField.tsx
|
|
2611
|
-
import { jsx as
|
|
3335
|
+
import { jsx as jsx53, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
2612
3336
|
function AuthField({ label, error, hint, rightLabel, id, ...props }) {
|
|
2613
3337
|
const fieldId = id ?? label.toLowerCase().replace(/\s+/g, "-");
|
|
2614
|
-
return /* @__PURE__ */
|
|
2615
|
-
/* @__PURE__ */
|
|
2616
|
-
/* @__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(
|
|
2617
3341
|
"label",
|
|
2618
3342
|
{
|
|
2619
3343
|
htmlFor: fieldId,
|
|
@@ -2625,9 +3349,9 @@ function AuthField({ label, error, hint, rightLabel, id, ...props }) {
|
|
|
2625
3349
|
children: label
|
|
2626
3350
|
}
|
|
2627
3351
|
),
|
|
2628
|
-
rightLabel && /* @__PURE__ */
|
|
3352
|
+
rightLabel && /* @__PURE__ */ jsx53("span", { style: { fontSize: "0.8125rem" }, children: rightLabel })
|
|
2629
3353
|
] }),
|
|
2630
|
-
/* @__PURE__ */
|
|
3354
|
+
/* @__PURE__ */ jsx53(
|
|
2631
3355
|
"input",
|
|
2632
3356
|
{
|
|
2633
3357
|
id: fieldId,
|
|
@@ -2657,13 +3381,13 @@ function AuthField({ label, error, hint, rightLabel, id, ...props }) {
|
|
|
2657
3381
|
...props
|
|
2658
3382
|
}
|
|
2659
3383
|
),
|
|
2660
|
-
error && /* @__PURE__ */
|
|
2661
|
-
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 })
|
|
2662
3386
|
] });
|
|
2663
3387
|
}
|
|
2664
3388
|
|
|
2665
3389
|
// src/components/auth/AuthButton.tsx
|
|
2666
|
-
import { Fragment as Fragment5, jsx as
|
|
3390
|
+
import { Fragment as Fragment5, jsx as jsx54, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
2667
3391
|
function AuthButton({
|
|
2668
3392
|
loading,
|
|
2669
3393
|
variant = "primary",
|
|
@@ -2706,7 +3430,7 @@ function AuthButton({
|
|
|
2706
3430
|
color: "var(--foreground)"
|
|
2707
3431
|
}
|
|
2708
3432
|
};
|
|
2709
|
-
return /* @__PURE__ */
|
|
3433
|
+
return /* @__PURE__ */ jsx54(
|
|
2710
3434
|
"button",
|
|
2711
3435
|
{
|
|
2712
3436
|
disabled: loading || disabled,
|
|
@@ -2718,8 +3442,8 @@ function AuthButton({
|
|
|
2718
3442
|
e.currentTarget.style.filter = "none";
|
|
2719
3443
|
},
|
|
2720
3444
|
...props,
|
|
2721
|
-
children: loading ? /* @__PURE__ */
|
|
2722
|
-
/* @__PURE__ */
|
|
3445
|
+
children: loading ? /* @__PURE__ */ jsxs37(Fragment5, { children: [
|
|
3446
|
+
/* @__PURE__ */ jsx54(
|
|
2723
3447
|
"span",
|
|
2724
3448
|
{
|
|
2725
3449
|
style: {
|
|
@@ -2740,19 +3464,19 @@ function AuthButton({
|
|
|
2740
3464
|
}
|
|
2741
3465
|
|
|
2742
3466
|
// src/components/auth/AuthDivider.tsx
|
|
2743
|
-
import { jsx as
|
|
3467
|
+
import { jsx as jsx55, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
2744
3468
|
function AuthDivider({ label = "or" }) {
|
|
2745
|
-
return /* @__PURE__ */
|
|
2746
|
-
/* @__PURE__ */
|
|
2747
|
-
/* @__PURE__ */
|
|
2748
|
-
/* @__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)" } })
|
|
2749
3473
|
] });
|
|
2750
3474
|
}
|
|
2751
3475
|
|
|
2752
3476
|
// src/components/auth/AuthFootnote.tsx
|
|
2753
|
-
import { jsx as
|
|
3477
|
+
import { jsx as jsx56, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
2754
3478
|
function AuthFootnote({ text, linkText, linkHref }) {
|
|
2755
|
-
return /* @__PURE__ */
|
|
3479
|
+
return /* @__PURE__ */ jsxs39("p", { style: {
|
|
2756
3480
|
textAlign: "center",
|
|
2757
3481
|
marginTop: "20px",
|
|
2758
3482
|
fontSize: "0.8125rem",
|
|
@@ -2760,7 +3484,7 @@ function AuthFootnote({ text, linkText, linkHref }) {
|
|
|
2760
3484
|
}, children: [
|
|
2761
3485
|
text,
|
|
2762
3486
|
" ",
|
|
2763
|
-
/* @__PURE__ */
|
|
3487
|
+
/* @__PURE__ */ jsx56(
|
|
2764
3488
|
"a",
|
|
2765
3489
|
{
|
|
2766
3490
|
href: linkHref,
|
|
@@ -2777,37 +3501,6 @@ function AuthFootnote({ text, linkText, linkHref }) {
|
|
|
2777
3501
|
] });
|
|
2778
3502
|
}
|
|
2779
3503
|
|
|
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
3504
|
// src/index.ts
|
|
2812
3505
|
import { ThemeProvider, useTheme as useTheme2 } from "next-themes";
|
|
2813
3506
|
export {
|
|
@@ -2877,6 +3570,11 @@ export {
|
|
|
2877
3570
|
Popover,
|
|
2878
3571
|
PopoverContent,
|
|
2879
3572
|
PopoverTrigger,
|
|
3573
|
+
PostEditorShell,
|
|
3574
|
+
PostFiltersBar,
|
|
3575
|
+
PostListTable,
|
|
3576
|
+
PostSidebarSection,
|
|
3577
|
+
PostStatusBadge,
|
|
2880
3578
|
SearchBar,
|
|
2881
3579
|
Select,
|
|
2882
3580
|
SelectContent,
|
|
@@ -2891,6 +3589,7 @@ export {
|
|
|
2891
3589
|
Separator3 as Separator,
|
|
2892
3590
|
Sidebar,
|
|
2893
3591
|
Skeleton2 as Skeleton,
|
|
3592
|
+
SlugInput,
|
|
2894
3593
|
Stats,
|
|
2895
3594
|
StorageBar,
|
|
2896
3595
|
Switch,
|