@kyro-cms/admin 0.9.1 → 0.9.2
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.cjs +1196 -1727
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +891 -1422
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/components/ActionBar.tsx +25 -174
- package/src/components/Admin.tsx +1 -3
- package/src/components/AuditLogsPage.tsx +2 -13
- package/src/components/AutoForm.tsx +160 -265
- package/src/components/DetailView.tsx +38 -66
- package/src/components/FieldRenderer.tsx +1 -1
- package/src/components/ListView.tsx +26 -198
- package/src/components/MediaGallery.tsx +117 -175
- package/src/components/RestPlayground.tsx +54 -47
- package/src/components/fields/BlocksField.tsx +8 -10
- package/src/components/fields/RelationshipBlockField.tsx +2 -3
- package/src/components/fields/RelationshipField.tsx +2 -3
- package/src/components/fix_imports.cjs +23 -0
- package/src/components/fix_imports2.cjs +19 -0
- package/src/components/replace_svgs.cjs +63 -0
- package/src/components/ui/Dropdown.tsx +7 -2
- package/src/components/ui/Modal.tsx +24 -27
- package/src/components/ui/PromptModal.tsx +2 -10
- package/src/components/ui/SlidePanel.tsx +2 -10
- package/src/components/ui/SplitButton.tsx +107 -0
- package/src/components/ui/Toaster.tsx +0 -1
- package/src/components/ui/icons.tsx +1 -0
- package/src/components/users/UsersList.tsx +8 -85
- package/src/hooks/useAutoFormState.ts +89 -161
- package/src/hooks/useQueue.ts +60 -0
- package/src/layouts/AdminLayout.astro +22 -2
- package/src/layouts/AuthLayout.astro +66 -18
- package/src/lib/autoform-store.ts +6 -2
- package/src/lib/globals.ts +5 -3
- package/src/pages/auth/register.astro +5 -2
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import React56, { createContext, lazy, useState, useContext, useRef, useEffect, useCallback, useMemo, Suspense } from 'react';
|
|
2
2
|
import { create, useStore } from 'zustand';
|
|
3
3
|
import { persist, createJSONStorage } from 'zustand/middleware';
|
|
4
|
+
import { GripVertical, Copy, X, Video, Mail, Clock, Database, Users, Tag, Image, Activity, CircleHelp, Sparkles, Blocks, Columns3, Link2, ListOrdered, Box, Heading1, Star, AlignLeft, ChevronDown, File, Code, List, Plus, ChevronRight, ChevronUp, Search, LoaderCircle, Check, RefreshCw, Undo, Redo, Bold, Italic, Underline, Strikethrough, Highlighter, Palette, CheckSquare, Quote, Terminal, Minus, AlignCenter, AlignRight, Link, Minimize2, Maximize2, Grid3X3, FolderPlus, FolderInput, Folder, Trash2, Film, Music, FileText, Archive, Download, Crop, Server, CodeXml, Filter, Pencil, Send, Eye, Info, TriangleAlert, ShieldAlert, CircleCheck, History, CheckCircle2, User, GitCompare, Undo2, ExternalLink, Settings, Shield, Hexagon, Network, Sun, Moon, LogOut, ArrowRight, LayoutDashboard, ArrowUpRight, Webhook, Zap, Pause, Play, Key, Lock, EyeOff, CirclePlay, RefreshCcw, Save, UserPlus, LockOpen } from 'lucide-react';
|
|
4
5
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
5
|
-
import { GripVertical, Copy, X, Video, Mail, Clock, Database, Users, Tag, Image, Activity, CircleHelp, Sparkles, Blocks, Columns3, Link2, ListOrdered, Box, Heading1, Star, AlignLeft, ChevronDown, File, Code, List, Plus, ChevronRight, ChevronUp, Search, LoaderCircle, Check, RefreshCw, Undo, Redo, Bold, Italic, Underline, Strikethrough, Highlighter, Palette, CheckSquare, Quote, Terminal, Minus, AlignCenter, AlignRight, Link, Minimize2, Maximize2, Grid3X3, FolderPlus, FolderInput, Folder, Trash2, Film, Music, FileText, Archive, Download, Crop, CodeXml, Info, TriangleAlert, ShieldAlert, CircleCheck, History, CheckCircle2, User, Eye, GitCompare, Undo2, Settings, Shield, Hexagon, Network, Sun, Moon, LogOut, ArrowRight, LayoutDashboard, ArrowUpRight, Webhook, Zap, Send, Pause, Play, ExternalLink, Key, Lock, EyeOff, CirclePlay, RefreshCcw, Save, UserPlus, LockOpen } from 'lucide-react';
|
|
6
6
|
import { createPortal } from 'react-dom';
|
|
7
7
|
import { useEditor, EditorContent } from '@tiptap/react';
|
|
8
8
|
import StarterKit from '@tiptap/starter-kit';
|
|
@@ -465,7 +465,7 @@ function PageHeader({
|
|
|
465
465
|
children: /* @__PURE__ */ jsx("svg", { className: "w-4 h-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: /* @__PURE__ */ jsx("path", { d: "M19 12H5M12 19l-7-7 7-7" }) })
|
|
466
466
|
}
|
|
467
467
|
),
|
|
468
|
-
breadcrumbs?.map((crumb, i) => /* @__PURE__ */ jsxs(
|
|
468
|
+
breadcrumbs?.map((crumb, i) => /* @__PURE__ */ jsxs(React56.Fragment, { children: [
|
|
469
469
|
i > 0 && /* @__PURE__ */ jsx("span", { className: "opacity-20 text-[10px]", children: "/" }),
|
|
470
470
|
crumb.href || crumb.onClick ? /* @__PURE__ */ jsx(
|
|
471
471
|
"a",
|
|
@@ -489,7 +489,7 @@ function PageHeader({
|
|
|
489
489
|
] }),
|
|
490
490
|
description && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mt-1", children: [
|
|
491
491
|
/* @__PURE__ */ jsx("p", { className: "text-[var(--kyro-text-secondary)] font-medium opacity-60 line-clamp-1", children: description }),
|
|
492
|
-
metadata && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: metadata.map((item, i) => /* @__PURE__ */ jsxs(
|
|
492
|
+
metadata && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: metadata.map((item, i) => /* @__PURE__ */ jsxs(React56.Fragment, { children: [
|
|
493
493
|
i === 0 && /* @__PURE__ */ jsx("span", { className: "opacity-20 ml-1", children: "\xB7" }),
|
|
494
494
|
item
|
|
495
495
|
] }, i)) }),
|
|
@@ -555,6 +555,89 @@ function CountBadge({ count, max = 99 }) {
|
|
|
555
555
|
if (count === 0) return null;
|
|
556
556
|
return /* @__PURE__ */ jsx("span", { className: "inline-flex items-center justify-center min-w-[20px] h-5 px-1.5 text-xs font-medium bg-gray-200 text-gray-700 rounded-full", children: count > max ? `${max}+` : count });
|
|
557
557
|
}
|
|
558
|
+
function Button({
|
|
559
|
+
variant = "secondary",
|
|
560
|
+
size = "md",
|
|
561
|
+
loading = false,
|
|
562
|
+
children,
|
|
563
|
+
className = "",
|
|
564
|
+
disabled,
|
|
565
|
+
...props
|
|
566
|
+
}) {
|
|
567
|
+
const baseClass = "kyro-btn";
|
|
568
|
+
const variantClass = `kyro-btn-${variant}`;
|
|
569
|
+
const sizeClass = `kyro-btn-${size}`;
|
|
570
|
+
return /* @__PURE__ */ jsxs(
|
|
571
|
+
"button",
|
|
572
|
+
{
|
|
573
|
+
type: "button",
|
|
574
|
+
className: `${baseClass} ${variantClass} ${sizeClass} ${className}`,
|
|
575
|
+
disabled: disabled || loading,
|
|
576
|
+
...props,
|
|
577
|
+
children: [
|
|
578
|
+
loading ? /* @__PURE__ */ jsx("span", { className: "kyro-btn-loading", children: /* @__PURE__ */ jsx("svg", { className: "kyro-btn-spinner", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "3", fill: "none", strokeDasharray: "60 30" }) }) }) : null,
|
|
579
|
+
/* @__PURE__ */ jsx("span", { className: loading ? "kyro-btn-text-hidden" : "", children })
|
|
580
|
+
]
|
|
581
|
+
}
|
|
582
|
+
);
|
|
583
|
+
}
|
|
584
|
+
function Pagination({ page, totalPages, totalDocs, limit, onPageChange, onLimitChange }) {
|
|
585
|
+
if (totalPages <= 1) return null;
|
|
586
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4 py-3 border-t border-[var(--kyro-border)]", children: [
|
|
587
|
+
totalDocs !== void 0 && limit ? /* @__PURE__ */ jsxs("span", { className: "text-xs text-[var(--kyro-text-secondary)] font-medium", children: [
|
|
588
|
+
"Showing ",
|
|
589
|
+
(page - 1) * limit + 1,
|
|
590
|
+
" to ",
|
|
591
|
+
Math.min(page * limit, totalDocs),
|
|
592
|
+
" of ",
|
|
593
|
+
totalDocs
|
|
594
|
+
] }) : /* @__PURE__ */ jsx("span", {}),
|
|
595
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
596
|
+
onLimitChange && /* @__PURE__ */ jsxs(
|
|
597
|
+
"select",
|
|
598
|
+
{
|
|
599
|
+
value: limit,
|
|
600
|
+
onChange: (e) => onLimitChange(Number(e.target.value)),
|
|
601
|
+
className: "text-xs border border-[var(--kyro-border)] rounded-lg px-2 py-1 bg-[var(--kyro-bg)] text-[var(--kyro-text-secondary)]",
|
|
602
|
+
children: [
|
|
603
|
+
/* @__PURE__ */ jsx("option", { value: 10, children: "10/page" }),
|
|
604
|
+
/* @__PURE__ */ jsx("option", { value: 25, children: "25/page" }),
|
|
605
|
+
/* @__PURE__ */ jsx("option", { value: 50, children: "50/page" }),
|
|
606
|
+
/* @__PURE__ */ jsx("option", { value: 100, children: "100/page" })
|
|
607
|
+
]
|
|
608
|
+
}
|
|
609
|
+
),
|
|
610
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs text-[var(--kyro-text-secondary)] font-medium", children: [
|
|
611
|
+
"Page ",
|
|
612
|
+
page,
|
|
613
|
+
" of ",
|
|
614
|
+
totalPages
|
|
615
|
+
] }),
|
|
616
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-1", children: [
|
|
617
|
+
/* @__PURE__ */ jsx(
|
|
618
|
+
Button,
|
|
619
|
+
{
|
|
620
|
+
variant: "ghost",
|
|
621
|
+
size: "sm",
|
|
622
|
+
disabled: page <= 1,
|
|
623
|
+
onClick: () => onPageChange(page - 1),
|
|
624
|
+
children: "\u2190 Previous"
|
|
625
|
+
}
|
|
626
|
+
),
|
|
627
|
+
/* @__PURE__ */ jsx(
|
|
628
|
+
Button,
|
|
629
|
+
{
|
|
630
|
+
variant: "ghost",
|
|
631
|
+
size: "sm",
|
|
632
|
+
disabled: page >= totalPages,
|
|
633
|
+
onClick: () => onPageChange(page + 1),
|
|
634
|
+
children: "Next \u2192"
|
|
635
|
+
}
|
|
636
|
+
)
|
|
637
|
+
] })
|
|
638
|
+
] })
|
|
639
|
+
] });
|
|
640
|
+
}
|
|
558
641
|
|
|
559
642
|
// src/lib/resolve-field-value.ts
|
|
560
643
|
function resolveFieldValue(fields2, formData, fieldName) {
|
|
@@ -724,9 +807,9 @@ function ListView({
|
|
|
724
807
|
const displayFields = useMemo(
|
|
725
808
|
() => {
|
|
726
809
|
const fields2 = allFields.filter((f) => !!f.name && visibleColumns.has(f.name));
|
|
727
|
-
if (visibleColumns.has("
|
|
810
|
+
if (visibleColumns.has("status")) {
|
|
728
811
|
fields2.push({
|
|
729
|
-
name: "
|
|
812
|
+
name: "status",
|
|
730
813
|
type: "select",
|
|
731
814
|
label: "Status",
|
|
732
815
|
options: [
|
|
@@ -865,24 +948,7 @@ function ListView({
|
|
|
865
948
|
),
|
|
866
949
|
/* @__PURE__ */ jsxs("div", { className: "surface-tile p-4 flex flex-col lg:flex-row gap-4 items-start lg:items-center", children: [
|
|
867
950
|
/* @__PURE__ */ jsxs("div", { className: "relative flex-1 max-w-md", children: [
|
|
868
|
-
/* @__PURE__ */ jsx(
|
|
869
|
-
"svg",
|
|
870
|
-
{
|
|
871
|
-
className: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--kyro-text-secondary)]",
|
|
872
|
-
fill: "none",
|
|
873
|
-
stroke: "currentColor",
|
|
874
|
-
viewBox: "0 0 24 24",
|
|
875
|
-
children: /* @__PURE__ */ jsx(
|
|
876
|
-
"path",
|
|
877
|
-
{
|
|
878
|
-
strokeLinecap: "round",
|
|
879
|
-
strokeLinejoin: "round",
|
|
880
|
-
strokeWidth: "2",
|
|
881
|
-
d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
|
|
882
|
-
}
|
|
883
|
-
)
|
|
884
|
-
}
|
|
885
|
-
),
|
|
951
|
+
/* @__PURE__ */ jsx(Search, { className: "w-4 h-4" }),
|
|
886
952
|
/* @__PURE__ */ jsx(
|
|
887
953
|
"input",
|
|
888
954
|
{
|
|
@@ -902,24 +968,7 @@ function ListView({
|
|
|
902
968
|
onClick: () => setShowFilters(!showFilters),
|
|
903
969
|
className: `flex items-center gap-2 px-4 py-2 rounded-xl font-bold text-sm transition-all ${showFilters || filters.length > 0 ? "bg-[var(--kyro-sidebar-active)] text-[var(--kyro-sidebar-text-active)]" : "bg-[var(--kyro-surface-accent)] text-[var(--kyro-text-secondary)] hover:text-[var(--kyro-text-primary)]"}`,
|
|
904
970
|
children: [
|
|
905
|
-
/* @__PURE__ */ jsx(
|
|
906
|
-
"svg",
|
|
907
|
-
{
|
|
908
|
-
className: "w-4 h-4",
|
|
909
|
-
fill: "none",
|
|
910
|
-
stroke: "currentColor",
|
|
911
|
-
viewBox: "0 0 24 24",
|
|
912
|
-
children: /* @__PURE__ */ jsx(
|
|
913
|
-
"path",
|
|
914
|
-
{
|
|
915
|
-
strokeLinecap: "round",
|
|
916
|
-
strokeLinejoin: "round",
|
|
917
|
-
strokeWidth: "2",
|
|
918
|
-
d: "M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z"
|
|
919
|
-
}
|
|
920
|
-
)
|
|
921
|
-
}
|
|
922
|
-
),
|
|
971
|
+
/* @__PURE__ */ jsx(Filter, { className: "w-4 h-4" }),
|
|
923
972
|
"Filters",
|
|
924
973
|
filters.length > 0 && /* @__PURE__ */ jsx("span", { className: "ml-1 px-1.5 py-0.5 bg-[var(--kyro-sidebar-text-active)] text-[var(--kyro-sidebar-active)] rounded-full text-xs", children: filters.length })
|
|
925
974
|
]
|
|
@@ -933,24 +982,7 @@ function ListView({
|
|
|
933
982
|
onClick: () => setShowColumns(!showColumns),
|
|
934
983
|
className: "flex items-center gap-2 px-4 py-2 rounded-xl font-bold text-sm bg-[var(--kyro-surface-accent)] text-[var(--kyro-text-secondary)] hover:text-[var(--kyro-text-primary)] transition-all",
|
|
935
984
|
children: [
|
|
936
|
-
/* @__PURE__ */ jsx(
|
|
937
|
-
"svg",
|
|
938
|
-
{
|
|
939
|
-
className: "w-4 h-4",
|
|
940
|
-
fill: "none",
|
|
941
|
-
stroke: "currentColor",
|
|
942
|
-
viewBox: "0 0 24 24",
|
|
943
|
-
children: /* @__PURE__ */ jsx(
|
|
944
|
-
"path",
|
|
945
|
-
{
|
|
946
|
-
strokeLinecap: "round",
|
|
947
|
-
strokeLinejoin: "round",
|
|
948
|
-
strokeWidth: "2",
|
|
949
|
-
d: "M9 17V7m0 10a2 2 0 01-2 2H5a2 2 0 01-2-2V7a2 2 0 012-2h2a2 2 0 012 2m0 10a2 2 0 002 2h2a2 2 0 002-2M9 7a2 2 0 012-2h2a2 2 0 012 2m0 10V7m0 10a2 2 0 002 2h2a2 2 0 002-2V7a2 2 0 00-2-2h-2a2 2 0 00-2 2"
|
|
950
|
-
}
|
|
951
|
-
)
|
|
952
|
-
}
|
|
953
|
-
),
|
|
985
|
+
/* @__PURE__ */ jsx(Columns3, { className: "w-4 h-4" }),
|
|
954
986
|
"Columns"
|
|
955
987
|
]
|
|
956
988
|
}
|
|
@@ -1002,24 +1034,7 @@ function ListView({
|
|
|
1002
1034
|
onClick: addFilter,
|
|
1003
1035
|
className: "flex items-center gap-2 px-3 py-1.5 text-sm font-bold text-[var(--kyro-sidebar-active)] hover:bg-[var(--kyro-surface-accent)] rounded-lg transition-all",
|
|
1004
1036
|
children: [
|
|
1005
|
-
/* @__PURE__ */ jsx(
|
|
1006
|
-
"svg",
|
|
1007
|
-
{
|
|
1008
|
-
className: "w-4 h-4",
|
|
1009
|
-
fill: "none",
|
|
1010
|
-
stroke: "currentColor",
|
|
1011
|
-
viewBox: "0 0 24 24",
|
|
1012
|
-
children: /* @__PURE__ */ jsx(
|
|
1013
|
-
"path",
|
|
1014
|
-
{
|
|
1015
|
-
strokeLinecap: "round",
|
|
1016
|
-
strokeLinejoin: "round",
|
|
1017
|
-
strokeWidth: "2",
|
|
1018
|
-
d: "M12 5v14M5 12h14"
|
|
1019
|
-
}
|
|
1020
|
-
)
|
|
1021
|
-
}
|
|
1022
|
-
),
|
|
1037
|
+
/* @__PURE__ */ jsx(Plus, { className: "w-4 h-4" }),
|
|
1023
1038
|
"Add Filter"
|
|
1024
1039
|
]
|
|
1025
1040
|
}
|
|
@@ -1070,24 +1085,7 @@ function ListView({
|
|
|
1070
1085
|
type: "button",
|
|
1071
1086
|
onClick: () => removeFilter(index),
|
|
1072
1087
|
className: "p-2 text-[var(--kyro-text-muted)] hover:text-red-500 transition-colors",
|
|
1073
|
-
children: /* @__PURE__ */ jsx(
|
|
1074
|
-
"svg",
|
|
1075
|
-
{
|
|
1076
|
-
className: "w-4 h-4",
|
|
1077
|
-
fill: "none",
|
|
1078
|
-
stroke: "currentColor",
|
|
1079
|
-
viewBox: "0 0 24 24",
|
|
1080
|
-
children: /* @__PURE__ */ jsx(
|
|
1081
|
-
"path",
|
|
1082
|
-
{
|
|
1083
|
-
strokeLinecap: "round",
|
|
1084
|
-
strokeLinejoin: "round",
|
|
1085
|
-
strokeWidth: "2",
|
|
1086
|
-
d: "M6 18L18 6M6 6l12 12"
|
|
1087
|
-
}
|
|
1088
|
-
)
|
|
1089
|
-
}
|
|
1090
|
-
)
|
|
1088
|
+
children: /* @__PURE__ */ jsx(X, { className: "w-4 h-4" })
|
|
1091
1089
|
}
|
|
1092
1090
|
)
|
|
1093
1091
|
] }, index)),
|
|
@@ -1107,24 +1105,7 @@ function ListView({
|
|
|
1107
1105
|
onClick: handleBulkDelete,
|
|
1108
1106
|
className: "flex items-center gap-2 px-4 py-2 bg-red-500 text-white rounded-lg font-bold text-sm hover:bg-red-600 transition-all",
|
|
1109
1107
|
children: [
|
|
1110
|
-
/* @__PURE__ */ jsx(
|
|
1111
|
-
"svg",
|
|
1112
|
-
{
|
|
1113
|
-
className: "w-4 h-4",
|
|
1114
|
-
fill: "none",
|
|
1115
|
-
stroke: "currentColor",
|
|
1116
|
-
viewBox: "0 0 24 24",
|
|
1117
|
-
children: /* @__PURE__ */ jsx(
|
|
1118
|
-
"path",
|
|
1119
|
-
{
|
|
1120
|
-
strokeLinecap: "round",
|
|
1121
|
-
strokeLinejoin: "round",
|
|
1122
|
-
strokeWidth: "2",
|
|
1123
|
-
d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
|
|
1124
|
-
}
|
|
1125
|
-
)
|
|
1126
|
-
}
|
|
1127
|
-
),
|
|
1108
|
+
/* @__PURE__ */ jsx(Trash2, { className: "w-4 h-4" }),
|
|
1128
1109
|
"Delete Selected"
|
|
1129
1110
|
]
|
|
1130
1111
|
}
|
|
@@ -1141,24 +1122,7 @@ function ListView({
|
|
|
1141
1122
|
] })
|
|
1142
1123
|
] }),
|
|
1143
1124
|
/* @__PURE__ */ jsx("div", { className: "surface-tile overflow-hidden", children: loading ? /* @__PURE__ */ jsx("div", { className: "space-y-2 p-4", children: /* @__PURE__ */ jsx(Shimmer, { variant: "table-row", count: 8 }) }) : docs.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-16 px-8", children: [
|
|
1144
|
-
/* @__PURE__ */ jsx("div", { className: "w-16 h-16 rounded-2xl bg-[var(--kyro-surface-accent)] flex items-center justify-center mb-4", children: /* @__PURE__ */ jsx(
|
|
1145
|
-
"svg",
|
|
1146
|
-
{
|
|
1147
|
-
className: "w-8 h-8 text-[var(--kyro-text-muted)]",
|
|
1148
|
-
fill: "none",
|
|
1149
|
-
stroke: "currentColor",
|
|
1150
|
-
viewBox: "0 0 24 24",
|
|
1151
|
-
children: /* @__PURE__ */ jsx(
|
|
1152
|
-
"path",
|
|
1153
|
-
{
|
|
1154
|
-
strokeLinecap: "round",
|
|
1155
|
-
strokeLinejoin: "round",
|
|
1156
|
-
strokeWidth: "1.5",
|
|
1157
|
-
d: "M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10"
|
|
1158
|
-
}
|
|
1159
|
-
)
|
|
1160
|
-
}
|
|
1161
|
-
) }),
|
|
1125
|
+
/* @__PURE__ */ jsx("div", { className: "w-16 h-16 rounded-2xl bg-[var(--kyro-surface-accent)] flex items-center justify-center mb-4", children: /* @__PURE__ */ jsx(Archive, { className: "w-4 h-4" }) }),
|
|
1162
1126
|
/* @__PURE__ */ jsx("p", { className: "font-medium text-[var(--kyro-text-primary)] text-base", children: "No documents found" }),
|
|
1163
1127
|
/* @__PURE__ */ jsx("p", { className: "text-sm text-[var(--kyro-text-secondary)] mt-1", children: hasActiveFilters ? "Try adjusting your filters or search query." : `Get started by creating your first ${(collection.singularLabel || collection.label || collectionSlug).toLowerCase()}.` }),
|
|
1164
1128
|
!hasActiveFilters && canCreate && /* @__PURE__ */ jsxs(
|
|
@@ -1168,24 +1132,7 @@ function ListView({
|
|
|
1168
1132
|
onClick: handleCreate,
|
|
1169
1133
|
className: "mt-4 kyro-btn kyro-btn-md kyro-btn-primary shadow-md flex items-center gap-2",
|
|
1170
1134
|
children: [
|
|
1171
|
-
/* @__PURE__ */ jsx(
|
|
1172
|
-
"svg",
|
|
1173
|
-
{
|
|
1174
|
-
className: "w-3.5 h-3.5",
|
|
1175
|
-
fill: "none",
|
|
1176
|
-
stroke: "currentColor",
|
|
1177
|
-
viewBox: "0 0 24 24",
|
|
1178
|
-
children: /* @__PURE__ */ jsx(
|
|
1179
|
-
"path",
|
|
1180
|
-
{
|
|
1181
|
-
strokeLinecap: "round",
|
|
1182
|
-
strokeLinejoin: "round",
|
|
1183
|
-
strokeWidth: "2.5",
|
|
1184
|
-
d: "M12 5v14M5 12h14"
|
|
1185
|
-
}
|
|
1186
|
-
)
|
|
1187
|
-
}
|
|
1188
|
-
),
|
|
1135
|
+
/* @__PURE__ */ jsx(Plus, { className: "w-4 h-4" }),
|
|
1189
1136
|
"Create",
|
|
1190
1137
|
" ",
|
|
1191
1138
|
String(collection.singularLabel || collection.label || collectionSlug)
|
|
@@ -1210,24 +1157,7 @@ function ListView({
|
|
|
1210
1157
|
onClick: () => handleSort(field3.name),
|
|
1211
1158
|
children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1212
1159
|
checkTabbedValue(displayFields, field3.type) ?? (field3.label || field3.name),
|
|
1213
|
-
sort && sort.field === field3.name && /* @__PURE__ */ jsx(
|
|
1214
|
-
"svg",
|
|
1215
|
-
{
|
|
1216
|
-
className: `w-3 h-3 ${sort.direction === "desc" ? "rotate-180" : ""}`,
|
|
1217
|
-
fill: "none",
|
|
1218
|
-
stroke: "currentColor",
|
|
1219
|
-
viewBox: "0 0 24 24",
|
|
1220
|
-
children: /* @__PURE__ */ jsx(
|
|
1221
|
-
"path",
|
|
1222
|
-
{
|
|
1223
|
-
strokeLinecap: "round",
|
|
1224
|
-
strokeLinejoin: "round",
|
|
1225
|
-
strokeWidth: "2",
|
|
1226
|
-
d: "M5 15l7-7 7 7"
|
|
1227
|
-
}
|
|
1228
|
-
)
|
|
1229
|
-
}
|
|
1230
|
-
)
|
|
1160
|
+
sort && sort.field === field3.name && /* @__PURE__ */ jsx(ChevronUp, { className: "w-4 h-4" })
|
|
1231
1161
|
] })
|
|
1232
1162
|
},
|
|
1233
1163
|
field3.name
|
|
@@ -1290,24 +1220,7 @@ function ListView({
|
|
|
1290
1220
|
onClick: () => handleEdit(doc.id),
|
|
1291
1221
|
className: "flex items-center gap-2 px-3 py-1.5 hover:bg-[var(--kyro-surface-accent)] rounded-lg text-sm font-bold text-[var(--kyro-text-secondary)] hover:text-[var(--kyro-text-primary)] transition-all",
|
|
1292
1222
|
title: canUpdate ? "Edit" : "View",
|
|
1293
|
-
children: /* @__PURE__ */ jsx(
|
|
1294
|
-
"svg",
|
|
1295
|
-
{
|
|
1296
|
-
className: "w-4 h-4",
|
|
1297
|
-
fill: "none",
|
|
1298
|
-
stroke: "currentColor",
|
|
1299
|
-
viewBox: "0 0 24 24",
|
|
1300
|
-
children: /* @__PURE__ */ jsx(
|
|
1301
|
-
"path",
|
|
1302
|
-
{
|
|
1303
|
-
strokeLinecap: "round",
|
|
1304
|
-
strokeLinejoin: "round",
|
|
1305
|
-
strokeWidth: "2",
|
|
1306
|
-
d: "M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"
|
|
1307
|
-
}
|
|
1308
|
-
)
|
|
1309
|
-
}
|
|
1310
|
-
)
|
|
1223
|
+
children: /* @__PURE__ */ jsx(Pencil, { className: "w-4 h-4" })
|
|
1311
1224
|
}
|
|
1312
1225
|
),
|
|
1313
1226
|
canDelete && /* @__PURE__ */ jsx(
|
|
@@ -1317,24 +1230,7 @@ function ListView({
|
|
|
1317
1230
|
onClick: () => handleDeleteSingle(doc.id),
|
|
1318
1231
|
className: "inline-flex items-center justify-center w-8 h-8 rounded-md text-[var(--kyro-text-muted)] hover:bg-red-50 hover:text-red-500 dark:hover:bg-red-500/10 transition-colors",
|
|
1319
1232
|
title: "Delete",
|
|
1320
|
-
children: /* @__PURE__ */ jsx(
|
|
1321
|
-
"svg",
|
|
1322
|
-
{
|
|
1323
|
-
className: "w-4 h-4",
|
|
1324
|
-
fill: "none",
|
|
1325
|
-
stroke: "currentColor",
|
|
1326
|
-
viewBox: "0 0 24 24",
|
|
1327
|
-
children: /* @__PURE__ */ jsx(
|
|
1328
|
-
"path",
|
|
1329
|
-
{
|
|
1330
|
-
strokeLinecap: "round",
|
|
1331
|
-
strokeLinejoin: "round",
|
|
1332
|
-
strokeWidth: "2",
|
|
1333
|
-
d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
|
|
1334
|
-
}
|
|
1335
|
-
)
|
|
1336
|
-
}
|
|
1337
|
-
)
|
|
1233
|
+
children: /* @__PURE__ */ jsx(Trash2, { className: "w-4 h-4" })
|
|
1338
1234
|
}
|
|
1339
1235
|
)
|
|
1340
1236
|
] })
|
|
@@ -1345,60 +1241,20 @@ function ListView({
|
|
|
1345
1241
|
doc.id
|
|
1346
1242
|
)) })
|
|
1347
1243
|
] }) }) }),
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
] }),
|
|
1363
|
-
/* @__PURE__ */ jsxs(
|
|
1364
|
-
"select",
|
|
1365
|
-
{
|
|
1366
|
-
value: limit,
|
|
1367
|
-
onChange: (e) => {
|
|
1368
|
-
setLimit(Number(e.target.value));
|
|
1369
|
-
setPage(1);
|
|
1370
|
-
},
|
|
1371
|
-
className: "px-2 py-1 bg-[var(--kyro-bg)] border border-[var(--kyro-border)] rounded-lg text-sm font-medium text-[var(--kyro-text-primary)]",
|
|
1372
|
-
children: [
|
|
1373
|
-
/* @__PURE__ */ jsx("option", { value: 10, children: "10 / page" }),
|
|
1374
|
-
/* @__PURE__ */ jsx("option", { value: 25, children: "25 / page" }),
|
|
1375
|
-
/* @__PURE__ */ jsx("option", { value: 50, children: "50 / page" }),
|
|
1376
|
-
/* @__PURE__ */ jsx("option", { value: 100, children: "100 / page" })
|
|
1377
|
-
]
|
|
1378
|
-
}
|
|
1379
|
-
)
|
|
1380
|
-
] }),
|
|
1381
|
-
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
1382
|
-
page > 1 && /* @__PURE__ */ jsx(
|
|
1383
|
-
"button",
|
|
1384
|
-
{
|
|
1385
|
-
type: "button",
|
|
1386
|
-
onClick: () => setPage(page - 1),
|
|
1387
|
-
className: "px-4 py-2 border border-[var(--kyro-border)] rounded-lg text-sm font-medium text-[var(--kyro-text-primary)] hover:bg-[var(--kyro-surface-accent)] transition-colors",
|
|
1388
|
-
children: "\u2190 Previous"
|
|
1389
|
-
}
|
|
1390
|
-
),
|
|
1391
|
-
page < totalPages && /* @__PURE__ */ jsx(
|
|
1392
|
-
"button",
|
|
1393
|
-
{
|
|
1394
|
-
type: "button",
|
|
1395
|
-
onClick: () => setPage(page + 1),
|
|
1396
|
-
className: "px-4 py-2 bg-[var(--kyro-sidebar-active)] text-[var(--kyro-sidebar-text-active)] rounded-lg text-sm font-bold hover:opacity-90 transition-all",
|
|
1397
|
-
children: "Next \u2192"
|
|
1398
|
-
}
|
|
1399
|
-
)
|
|
1400
|
-
] })
|
|
1401
|
-
] })
|
|
1244
|
+
/* @__PURE__ */ jsx(
|
|
1245
|
+
Pagination,
|
|
1246
|
+
{
|
|
1247
|
+
page,
|
|
1248
|
+
totalPages,
|
|
1249
|
+
totalDocs,
|
|
1250
|
+
limit,
|
|
1251
|
+
onPageChange: setPage,
|
|
1252
|
+
onLimitChange: (newLimit) => {
|
|
1253
|
+
setLimit(newLimit);
|
|
1254
|
+
setPage(1);
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
)
|
|
1402
1258
|
] });
|
|
1403
1259
|
}
|
|
1404
1260
|
function formatCellValue(value, type) {
|
|
@@ -2108,18 +1964,7 @@ function SlidePanel({
|
|
|
2108
1964
|
type: "button",
|
|
2109
1965
|
onClick: onClose,
|
|
2110
1966
|
className: "p-1.5 text-[var(--kyro-text-muted)] hover:text-[var(--kyro-text-primary)] hover:bg-[var(--kyro-surface-accent)] rounded-lg transition-colors",
|
|
2111
|
-
children: /* @__PURE__ */ jsx(
|
|
2112
|
-
"svg",
|
|
2113
|
-
{
|
|
2114
|
-
width: "16",
|
|
2115
|
-
height: "16",
|
|
2116
|
-
viewBox: "0 0 24 24",
|
|
2117
|
-
fill: "none",
|
|
2118
|
-
stroke: "currentColor",
|
|
2119
|
-
strokeWidth: "2",
|
|
2120
|
-
children: /* @__PURE__ */ jsx("path", { d: "M18 6L6 18M6 6l12 12" })
|
|
2121
|
-
}
|
|
2122
|
-
)
|
|
1967
|
+
children: /* @__PURE__ */ jsx(X, { className: "w-4 h-4" })
|
|
2123
1968
|
}
|
|
2124
1969
|
)
|
|
2125
1970
|
] }),
|
|
@@ -2140,54 +1985,158 @@ function SlidePanel({
|
|
|
2140
1985
|
document.body
|
|
2141
1986
|
);
|
|
2142
1987
|
}
|
|
2143
|
-
function
|
|
1988
|
+
function ModalContent({ children }) {
|
|
1989
|
+
return /* @__PURE__ */ jsx("div", { className: "text-[var(--kyro-text-secondary)]", children });
|
|
1990
|
+
}
|
|
1991
|
+
function ModalActions({ children }) {
|
|
1992
|
+
return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-end gap-3 mt-6", children });
|
|
1993
|
+
}
|
|
1994
|
+
function Modal({
|
|
2144
1995
|
open,
|
|
2145
1996
|
onClose,
|
|
2146
|
-
onSubmit,
|
|
2147
1997
|
title,
|
|
2148
|
-
|
|
2149
|
-
|
|
1998
|
+
children,
|
|
1999
|
+
footer,
|
|
2000
|
+
size = "md",
|
|
2001
|
+
variant = "default"
|
|
2150
2002
|
}) {
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2003
|
+
useEffect(() => {
|
|
2004
|
+
const handleEscape = (e) => {
|
|
2005
|
+
if (e.key === "Escape") onClose();
|
|
2006
|
+
};
|
|
2007
|
+
if (open) {
|
|
2008
|
+
document.addEventListener("keydown", handleEscape);
|
|
2009
|
+
document.body.style.overflow = "hidden";
|
|
2158
2010
|
}
|
|
2159
|
-
|
|
2011
|
+
return () => {
|
|
2012
|
+
document.removeEventListener("keydown", handleEscape);
|
|
2013
|
+
document.body.style.overflow = "";
|
|
2014
|
+
};
|
|
2015
|
+
}, [open, onClose]);
|
|
2160
2016
|
if (!open) return null;
|
|
2017
|
+
const sizeClasses = {
|
|
2018
|
+
sm: "max-w-sm",
|
|
2019
|
+
md: "max-w-md",
|
|
2020
|
+
lg: "max-w-lg",
|
|
2021
|
+
full: "w-full h-full max-w-none rounded-none border-0"
|
|
2022
|
+
};
|
|
2023
|
+
const isLightbox = variant === "lightbox";
|
|
2161
2024
|
return createPortal(
|
|
2162
|
-
/* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-[9999] flex items-center justify-center", children: [
|
|
2025
|
+
/* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-[9999] flex items-center justify-center p-4", children: [
|
|
2163
2026
|
/* @__PURE__ */ jsx(
|
|
2164
2027
|
"div",
|
|
2165
2028
|
{
|
|
2166
|
-
className:
|
|
2029
|
+
className: `absolute inset-0 transition-all duration-500 ${isLightbox ? "bg-black/95 backdrop-blur-none" : "bg-[var(--kyro-black)]/40 backdrop-blur-md"}`,
|
|
2167
2030
|
onClick: onClose
|
|
2168
2031
|
}
|
|
2169
2032
|
),
|
|
2170
|
-
/* @__PURE__ */ jsxs(
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
{
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
viewBox: "0 0 24 24",
|
|
2185
|
-
fill: "none",
|
|
2186
|
-
stroke: "currentColor",
|
|
2187
|
-
strokeWidth: "2",
|
|
2188
|
-
children: /* @__PURE__ */ jsx("path", { d: "M18 6L6 18M6 6l12 12" })
|
|
2033
|
+
/* @__PURE__ */ jsxs(
|
|
2034
|
+
"div",
|
|
2035
|
+
{
|
|
2036
|
+
className: `relative ${sizeClasses[size]} ${isLightbox ? "bg-transparent text-white" : "bg-[var(--kyro-surface)]"} ${!isLightbox && size !== "full" ? "rounded-[var(--kyro-radius-lg)]" : ""} shadow-2xl animate-in fade-in zoom-in-95 duration-300 ${!isLightbox ? "border" : ""} ${variant === "danger" ? "border-red-500/30" : "border-[var(--kyro-border)]"} flex flex-col overflow-hidden`,
|
|
2037
|
+
children: [
|
|
2038
|
+
!isLightbox && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-8 py-6 border-b border-[var(--kyro-border)] bg-[var(--kyro-surface-accent)]/50 backdrop-blur-md", children: [
|
|
2039
|
+
/* @__PURE__ */ jsx("h2", { className: "text-xl font-bold text-[var(--kyro-text-primary)]", children: title }),
|
|
2040
|
+
/* @__PURE__ */ jsx(
|
|
2041
|
+
"button",
|
|
2042
|
+
{
|
|
2043
|
+
type: "button",
|
|
2044
|
+
onClick: onClose,
|
|
2045
|
+
className: "p-2 text-[var(--kyro-text-muted)] hover:text-[var(--kyro-text-primary)] rounded-xl hover:bg-[var(--kyro-surface)] transition-all duration-200",
|
|
2046
|
+
children: /* @__PURE__ */ jsx(X, { className: "w-4 h-4" })
|
|
2189
2047
|
}
|
|
2190
2048
|
)
|
|
2049
|
+
] }),
|
|
2050
|
+
/* @__PURE__ */ jsx("div", { className: `flex-1 overflow-auto ${isLightbox ? "" : "px-8 py-8"}`, children }),
|
|
2051
|
+
footer && !isLightbox && /* @__PURE__ */ jsx("div", { className: "flex items-center justify-end gap-3 px-8 py-6 border-t border-[var(--kyro-border)] bg-[var(--kyro-surface-accent)]/50", children: footer })
|
|
2052
|
+
]
|
|
2053
|
+
}
|
|
2054
|
+
)
|
|
2055
|
+
] }),
|
|
2056
|
+
document.body
|
|
2057
|
+
);
|
|
2058
|
+
}
|
|
2059
|
+
function ConfirmModal({
|
|
2060
|
+
open,
|
|
2061
|
+
onClose,
|
|
2062
|
+
onConfirm,
|
|
2063
|
+
title,
|
|
2064
|
+
message,
|
|
2065
|
+
confirmLabel = "Confirm",
|
|
2066
|
+
cancelLabel = "Cancel",
|
|
2067
|
+
variant = "default",
|
|
2068
|
+
loading = false
|
|
2069
|
+
}) {
|
|
2070
|
+
return /* @__PURE__ */ jsx(
|
|
2071
|
+
Modal,
|
|
2072
|
+
{
|
|
2073
|
+
open,
|
|
2074
|
+
onClose,
|
|
2075
|
+
title,
|
|
2076
|
+
size: "sm",
|
|
2077
|
+
footer: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2078
|
+
/* @__PURE__ */ jsx(
|
|
2079
|
+
"button",
|
|
2080
|
+
{
|
|
2081
|
+
type: "button",
|
|
2082
|
+
onClick: onClose,
|
|
2083
|
+
disabled: loading,
|
|
2084
|
+
className: "kyro-btn kyro-btn-md kyro-btn-secondary",
|
|
2085
|
+
children: cancelLabel
|
|
2086
|
+
}
|
|
2087
|
+
),
|
|
2088
|
+
/* @__PURE__ */ jsx(
|
|
2089
|
+
"button",
|
|
2090
|
+
{
|
|
2091
|
+
type: "button",
|
|
2092
|
+
onClick: onConfirm,
|
|
2093
|
+
disabled: loading,
|
|
2094
|
+
className: `kyro-btn kyro-btn-md ${variant === "danger" ? "kyro-btn-danger" : "kyro-btn-primary"}`,
|
|
2095
|
+
children: loading ? "Loading..." : confirmLabel
|
|
2096
|
+
}
|
|
2097
|
+
)
|
|
2098
|
+
] }),
|
|
2099
|
+
children: /* @__PURE__ */ jsx("p", { className: "text-[var(--kyro-text-secondary)]", children: message })
|
|
2100
|
+
}
|
|
2101
|
+
);
|
|
2102
|
+
}
|
|
2103
|
+
function PromptModal({
|
|
2104
|
+
open,
|
|
2105
|
+
onClose,
|
|
2106
|
+
onSubmit,
|
|
2107
|
+
title,
|
|
2108
|
+
placeholder = "",
|
|
2109
|
+
defaultValue = ""
|
|
2110
|
+
}) {
|
|
2111
|
+
const [value, setValue] = useState(defaultValue);
|
|
2112
|
+
const handleSubmit = (e) => {
|
|
2113
|
+
e.preventDefault();
|
|
2114
|
+
if (value.trim()) {
|
|
2115
|
+
onSubmit(value.trim());
|
|
2116
|
+
setValue("");
|
|
2117
|
+
onClose();
|
|
2118
|
+
}
|
|
2119
|
+
};
|
|
2120
|
+
if (!open) return null;
|
|
2121
|
+
return createPortal(
|
|
2122
|
+
/* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-[9999] flex items-center justify-center", children: [
|
|
2123
|
+
/* @__PURE__ */ jsx(
|
|
2124
|
+
"div",
|
|
2125
|
+
{
|
|
2126
|
+
className: "absolute inset-0 bg-black/50 backdrop-blur-sm",
|
|
2127
|
+
onClick: onClose
|
|
2128
|
+
}
|
|
2129
|
+
),
|
|
2130
|
+
/* @__PURE__ */ jsxs("div", { className: "relative w-full max-w-lg mx-4 bg-[var(--kyro-surface)] rounded-lg shadow-2xl animate-in fade-in zoom-in-95 duration-200 border border-[var(--kyro-border)]", children: [
|
|
2131
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-6 py-4 border-b border-[var(--kyro-border)]", children: [
|
|
2132
|
+
/* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-[var(--kyro-text-primary)]", children: title }),
|
|
2133
|
+
/* @__PURE__ */ jsx(
|
|
2134
|
+
"button",
|
|
2135
|
+
{
|
|
2136
|
+
type: "button",
|
|
2137
|
+
onClick: onClose,
|
|
2138
|
+
className: "p-1 text-[var(--kyro-text-muted)] hover:text-[var(--kyro-text-primary)] rounded-lg hover:bg-[var(--kyro-surface-accent)] transition-colors",
|
|
2139
|
+
children: /* @__PURE__ */ jsx(X, { className: "w-4 h-4" })
|
|
2191
2140
|
}
|
|
2192
2141
|
)
|
|
2193
2142
|
] }),
|
|
@@ -2567,24 +2516,7 @@ function MediaGallery({
|
|
|
2567
2516
|
] }) }),
|
|
2568
2517
|
/* @__PURE__ */ jsxs("div", { className: `flex items-center gap-3 flex-wrap lg:flex-nowrap ${pickerMode ? "w-full" : ""}`, children: [
|
|
2569
2518
|
/* @__PURE__ */ jsxs("div", { className: "relative group flex-1 min-w-[200px]", children: [
|
|
2570
|
-
/* @__PURE__ */ jsx(
|
|
2571
|
-
"svg",
|
|
2572
|
-
{
|
|
2573
|
-
className: "absolute left-4 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--kyro-text-secondary)] opacity-40 group-focus-within:opacity-100 transition-opacity",
|
|
2574
|
-
fill: "none",
|
|
2575
|
-
stroke: "currentColor",
|
|
2576
|
-
viewBox: "0 0 24 24",
|
|
2577
|
-
children: /* @__PURE__ */ jsx(
|
|
2578
|
-
"path",
|
|
2579
|
-
{
|
|
2580
|
-
strokeLinecap: "round",
|
|
2581
|
-
strokeLinejoin: "round",
|
|
2582
|
-
strokeWidth: "2.5",
|
|
2583
|
-
d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
|
|
2584
|
-
}
|
|
2585
|
-
)
|
|
2586
|
-
}
|
|
2587
|
-
),
|
|
2519
|
+
/* @__PURE__ */ jsx(Search, { className: "w-4 h-4" }),
|
|
2588
2520
|
/* @__PURE__ */ jsx(
|
|
2589
2521
|
"input",
|
|
2590
2522
|
{
|
|
@@ -2751,45 +2683,11 @@ function MediaGallery({
|
|
|
2751
2683
|
{
|
|
2752
2684
|
onClick: (e) => handleSelectOne(item.id, e),
|
|
2753
2685
|
className: `kyro-btn-primary p-1.5 rounded-lg transition-all ${selectedIds.has(item.id) ? "" : "bg-white/10 text-white hover:bg-white/20"}`,
|
|
2754
|
-
children: /* @__PURE__ */ jsx(
|
|
2755
|
-
"svg",
|
|
2756
|
-
{
|
|
2757
|
-
className: "w-3 h-3",
|
|
2758
|
-
fill: "none",
|
|
2759
|
-
stroke: "currentColor",
|
|
2760
|
-
viewBox: "0 0 24 24",
|
|
2761
|
-
children: /* @__PURE__ */ jsx(
|
|
2762
|
-
"path",
|
|
2763
|
-
{
|
|
2764
|
-
strokeLinecap: "round",
|
|
2765
|
-
strokeLinejoin: "round",
|
|
2766
|
-
strokeWidth: "3",
|
|
2767
|
-
d: "M5 13l4 4L19 7"
|
|
2768
|
-
}
|
|
2769
|
-
)
|
|
2770
|
-
}
|
|
2771
|
-
)
|
|
2686
|
+
children: /* @__PURE__ */ jsx(Check, { className: "w-4 h-4" })
|
|
2772
2687
|
}
|
|
2773
2688
|
) })
|
|
2774
2689
|
] }) }),
|
|
2775
|
-
selectedIds.has(item.id) && /* @__PURE__ */ jsx("div", { className: "absolute top-3 left-3 w-6 h-6 rounded-lg bg-[var(--kyro-primary)] text-white flex items-center justify-center shadow-lg border-2 border-white/20 animate-in zoom-in duration-300", children: /* @__PURE__ */ jsx(
|
|
2776
|
-
"svg",
|
|
2777
|
-
{
|
|
2778
|
-
className: "w-3 h-3",
|
|
2779
|
-
fill: "none",
|
|
2780
|
-
stroke: "currentColor",
|
|
2781
|
-
viewBox: "0 0 24 24",
|
|
2782
|
-
children: /* @__PURE__ */ jsx(
|
|
2783
|
-
"path",
|
|
2784
|
-
{
|
|
2785
|
-
strokeLinecap: "round",
|
|
2786
|
-
strokeLinejoin: "round",
|
|
2787
|
-
strokeWidth: "3",
|
|
2788
|
-
d: "M5 13l4 4L19 7"
|
|
2789
|
-
}
|
|
2790
|
-
)
|
|
2791
|
-
}
|
|
2792
|
-
) })
|
|
2690
|
+
selectedIds.has(item.id) && /* @__PURE__ */ jsx("div", { className: "absolute top-3 left-3 w-6 h-6 rounded-lg bg-[var(--kyro-primary)] text-white flex items-center justify-center shadow-lg border-2 border-white/20 animate-in zoom-in duration-300", children: /* @__PURE__ */ jsx(Check, { className: "w-4 h-4" }) })
|
|
2793
2691
|
]
|
|
2794
2692
|
},
|
|
2795
2693
|
item.id
|
|
@@ -2869,34 +2767,14 @@ function MediaGallery({
|
|
|
2869
2767
|
item.id
|
|
2870
2768
|
)) })
|
|
2871
2769
|
] }) }) }),
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2770
|
+
/* @__PURE__ */ jsx(
|
|
2771
|
+
Pagination,
|
|
2772
|
+
{
|
|
2875
2773
|
page,
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
/* @__PURE__ */ jsx(
|
|
2881
|
-
"button",
|
|
2882
|
-
{
|
|
2883
|
-
disabled: page === 1,
|
|
2884
|
-
onClick: () => setPage(page - 1),
|
|
2885
|
-
className: "px-4 py-2 border border-[var(--kyro-border)] rounded-xl text-xs font-bold text-[var(--kyro-text-secondary)] hover:bg-[var(--kyro-surface-accent)] disabled:opacity-30 transition-all",
|
|
2886
|
-
children: "Previous"
|
|
2887
|
-
}
|
|
2888
|
-
),
|
|
2889
|
-
/* @__PURE__ */ jsx(
|
|
2890
|
-
"button",
|
|
2891
|
-
{
|
|
2892
|
-
disabled: page === totalPages,
|
|
2893
|
-
onClick: () => setPage(page + 1),
|
|
2894
|
-
className: "px-6 py-2 bg-[var(--kyro-sidebar-active)] text-[var(--kyro-sidebar-text-active)] rounded-xl text-xs font-bold shadow-lg hover:opacity-90 disabled:opacity-30 transition-all",
|
|
2895
|
-
children: "Next"
|
|
2896
|
-
}
|
|
2897
|
-
)
|
|
2898
|
-
] })
|
|
2899
|
-
] })
|
|
2774
|
+
totalPages,
|
|
2775
|
+
onPageChange: setPage
|
|
2776
|
+
}
|
|
2777
|
+
)
|
|
2900
2778
|
] })
|
|
2901
2779
|
] }),
|
|
2902
2780
|
!pickerMode && uploading && /* @__PURE__ */ jsx("div", { className: "fixed bottom-12 left-1/2 -translate-x-1/2 z-[60] w-full max-w-lg", children: /* @__PURE__ */ jsxs("div", { className: "bg-[var(--kyro-surface)] border border-[var(--kyro-border)] rounded-[2rem] shadow-2xl p-6 ring-1 ring-white/10 animate-in slide-in-from-bottom-12 duration-700", children: [
|
|
@@ -3122,86 +3000,100 @@ function MediaGallery({
|
|
|
3122
3000
|
] })
|
|
3123
3001
|
}
|
|
3124
3002
|
),
|
|
3125
|
-
showPreview && panelItem &&
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
}
|
|
3143
|
-
)
|
|
3144
|
-
] }),
|
|
3145
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1 w-full flex items-center justify-center p-12", children: panelItem.type === "image" ? /* @__PURE__ */ jsx(
|
|
3146
|
-
"img",
|
|
3147
|
-
{
|
|
3148
|
-
src: getAbsoluteUrl(panelItem.url),
|
|
3149
|
-
alt: "",
|
|
3150
|
-
className: "max-h-full max-w-full object-contain shadow-2xl rounded-lg animate-in zoom-in-95 duration-500"
|
|
3151
|
-
}
|
|
3152
|
-
) : panelItem.type === "video" ? /* @__PURE__ */ jsx(
|
|
3153
|
-
"video",
|
|
3154
|
-
{
|
|
3155
|
-
src: getAbsoluteUrl(panelItem.url),
|
|
3156
|
-
controls: true,
|
|
3157
|
-
autoPlay: true,
|
|
3158
|
-
className: "max-h-full max-w-full rounded-lg shadow-2xl"
|
|
3159
|
-
}
|
|
3160
|
-
) : /* @__PURE__ */ jsxs("div", { className: "text-white text-center", children: [
|
|
3161
|
-
/* @__PURE__ */ jsx(File, { className: "w-24 h-24 mx-auto mb-6 opacity-20" }),
|
|
3162
|
-
/* @__PURE__ */ jsx("p", { className: "text-xl font-bold opacity-50", children: "Preview not available for this file type" })
|
|
3163
|
-
] }) })
|
|
3164
|
-
] }),
|
|
3165
|
-
document.body
|
|
3166
|
-
),
|
|
3167
|
-
!pickerMode && showCrop && panelItem && createPortal(
|
|
3168
|
-
/* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-[9999] bg-black/95 flex flex-col p-8", children: [
|
|
3169
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-8", children: [
|
|
3170
|
-
/* @__PURE__ */ jsx("h3", { className: "text-white font-bold text-2xl tracking-tighter", children: "Crop Image" }),
|
|
3171
|
-
/* @__PURE__ */ jsxs("div", { className: "flex gap-3", children: [
|
|
3172
|
-
/* @__PURE__ */ jsx(
|
|
3173
|
-
"button",
|
|
3174
|
-
{
|
|
3175
|
-
type: "button",
|
|
3176
|
-
onClick: () => setShowCrop(false),
|
|
3177
|
-
className: "px-4 py-2 border border-white/20 text-white/80 hover:bg-white/10 rounded-lg font-bold text-sm transition-colors",
|
|
3178
|
-
children: "Cancel"
|
|
3179
|
-
}
|
|
3180
|
-
),
|
|
3003
|
+
showPreview && panelItem && /* @__PURE__ */ jsxs(
|
|
3004
|
+
Modal,
|
|
3005
|
+
{
|
|
3006
|
+
open: showPreview,
|
|
3007
|
+
onClose: () => setShowPreview(false),
|
|
3008
|
+
title: "",
|
|
3009
|
+
size: "full",
|
|
3010
|
+
variant: "lightbox",
|
|
3011
|
+
children: [
|
|
3012
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between p-6", children: [
|
|
3013
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
3014
|
+
/* @__PURE__ */ jsx("span", { className: "text-white font-bold text-lg tracking-tight", children: panelItem.filename }),
|
|
3015
|
+
/* @__PURE__ */ jsxs("span", { className: "text-white/40 text-[10px] font-bold tracking-widest mt-1", children: [
|
|
3016
|
+
formatFileSize(panelItem.fileSize),
|
|
3017
|
+
" \xB7 ",
|
|
3018
|
+
panelItem.mimeType
|
|
3019
|
+
] })
|
|
3020
|
+
] }),
|
|
3181
3021
|
/* @__PURE__ */ jsx(
|
|
3182
3022
|
"button",
|
|
3183
3023
|
{
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
className: "px-4 py-2 bg-[var(--kyro-sidebar-active)] hover:opacity-90 text-[var(--kyro-sidebar-text-active)] rounded-lg font-bold text-sm transition-colors",
|
|
3188
|
-
children: uploading ? "Saving..." : "Save Crop"
|
|
3024
|
+
onClick: () => setShowPreview(false),
|
|
3025
|
+
className: "p-3 bg-white/10 hover:bg-white/20 text-white rounded-2xl transition-all active:scale-90",
|
|
3026
|
+
children: /* @__PURE__ */ jsx(X, { className: "w-6 h-6" })
|
|
3189
3027
|
}
|
|
3190
3028
|
)
|
|
3191
|
-
] })
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3029
|
+
] }),
|
|
3030
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 w-full flex items-center justify-center p-12", children: panelItem.type === "image" ? /* @__PURE__ */ jsx(
|
|
3031
|
+
"img",
|
|
3032
|
+
{
|
|
3033
|
+
src: getAbsoluteUrl(panelItem.url),
|
|
3034
|
+
alt: "",
|
|
3035
|
+
className: "max-h-full max-w-full object-contain shadow-2xl rounded-lg animate-in zoom-in-95 duration-500"
|
|
3036
|
+
}
|
|
3037
|
+
) : panelItem.type === "video" ? /* @__PURE__ */ jsx(
|
|
3038
|
+
"video",
|
|
3039
|
+
{
|
|
3040
|
+
src: getAbsoluteUrl(panelItem.url),
|
|
3041
|
+
controls: true,
|
|
3042
|
+
autoPlay: true,
|
|
3043
|
+
className: "max-h-full max-w-full rounded-lg shadow-2xl"
|
|
3044
|
+
}
|
|
3045
|
+
) : /* @__PURE__ */ jsxs("div", { className: "text-white text-center", children: [
|
|
3046
|
+
/* @__PURE__ */ jsx(File, { className: "w-24 h-24 mx-auto mb-6 opacity-20" }),
|
|
3047
|
+
/* @__PURE__ */ jsx("p", { className: "text-xl font-bold opacity-50", children: "Preview not available for this file type" })
|
|
3048
|
+
] }) })
|
|
3049
|
+
]
|
|
3050
|
+
}
|
|
3051
|
+
),
|
|
3052
|
+
!pickerMode && showCrop && panelItem && /* @__PURE__ */ jsx(
|
|
3053
|
+
Modal,
|
|
3054
|
+
{
|
|
3055
|
+
open: showCrop,
|
|
3056
|
+
onClose: () => setShowCrop(false),
|
|
3057
|
+
title: "",
|
|
3058
|
+
size: "full",
|
|
3059
|
+
variant: "lightbox",
|
|
3060
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full p-8", children: [
|
|
3061
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-8", children: [
|
|
3062
|
+
/* @__PURE__ */ jsx("h3", { className: "text-white font-bold text-2xl tracking-tighter", children: "Crop Image" }),
|
|
3063
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-3", children: [
|
|
3064
|
+
/* @__PURE__ */ jsx(
|
|
3065
|
+
"button",
|
|
3066
|
+
{
|
|
3067
|
+
type: "button",
|
|
3068
|
+
onClick: () => setShowCrop(false),
|
|
3069
|
+
className: "px-4 py-2 border border-white/20 text-white/80 hover:bg-white/10 rounded-lg font-bold text-sm transition-colors",
|
|
3070
|
+
children: "Cancel"
|
|
3071
|
+
}
|
|
3072
|
+
),
|
|
3073
|
+
/* @__PURE__ */ jsx(
|
|
3074
|
+
"button",
|
|
3075
|
+
{
|
|
3076
|
+
type: "button",
|
|
3077
|
+
disabled: uploading,
|
|
3078
|
+
onClick: onCropComplete,
|
|
3079
|
+
className: "px-4 py-2 bg-[var(--kyro-sidebar-active)] hover:opacity-90 text-[var(--kyro-sidebar-text-active)] rounded-lg font-bold text-sm transition-colors",
|
|
3080
|
+
children: uploading ? "Saving..." : "Save Crop"
|
|
3081
|
+
}
|
|
3082
|
+
)
|
|
3083
|
+
] })
|
|
3084
|
+
] }),
|
|
3085
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 w-full flex items-center justify-center overflow-auto", children: /* @__PURE__ */ jsx(ReactCrop, { crop, onChange: (c) => setCrop(c), children: /* @__PURE__ */ jsx(
|
|
3086
|
+
"img",
|
|
3087
|
+
{
|
|
3088
|
+
ref: imgRef,
|
|
3089
|
+
src: panelItem.url,
|
|
3090
|
+
alt: "Crop preview",
|
|
3091
|
+
className: "max-h-[70vh] object-contain",
|
|
3092
|
+
onLoad: onImageLoad
|
|
3093
|
+
}
|
|
3094
|
+
) }) })
|
|
3095
|
+
] })
|
|
3096
|
+
}
|
|
3205
3097
|
),
|
|
3206
3098
|
!pickerMode && /* @__PURE__ */ jsx(
|
|
3207
3099
|
PromptModal,
|
|
@@ -3213,61 +3105,49 @@ function MediaGallery({
|
|
|
3213
3105
|
placeholder: "Folder name"
|
|
3214
3106
|
}
|
|
3215
3107
|
),
|
|
3216
|
-
!pickerMode &&
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3108
|
+
!pickerMode && /* @__PURE__ */ jsx(
|
|
3109
|
+
Modal,
|
|
3110
|
+
{
|
|
3111
|
+
open: showStorageConfigModal,
|
|
3112
|
+
onClose: () => setShowStorageConfigModal(false),
|
|
3113
|
+
title: "Storage Not Configured",
|
|
3114
|
+
size: "md",
|
|
3115
|
+
children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
3116
|
+
/* @__PURE__ */ jsx("div", { className: "w-16 h-16 mx-auto mb-4 rounded-full bg-[var(--kyro-sidebar-active)] flex items-center justify-center", children: /* @__PURE__ */ jsx(Server, { className: "w-8 h-8 text-[var(--kyro-sidebar-text-active)]" }) }),
|
|
3117
|
+
/* @__PURE__ */ jsx("p", { className: "text-[var(--kyro-text-secondary)] mb-6 text-sm", children: "Before uploading media, you need to configure your storage settings. Choose where files should be stored and how URLs are generated." }),
|
|
3118
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-3", children: [
|
|
3119
|
+
/* @__PURE__ */ jsx(
|
|
3120
|
+
"a",
|
|
3121
|
+
{
|
|
3122
|
+
href: "/settings/storage-settings",
|
|
3123
|
+
className: "flex-1 px-4 py-3 bg-[var(--kyro-sidebar-active)] text-[var(--kyro-sidebar-text-active)] rounded-xl font-bold text-center hover:opacity-90 transition-colors",
|
|
3124
|
+
children: "Configure Storage"
|
|
3125
|
+
}
|
|
3126
|
+
),
|
|
3127
|
+
/* @__PURE__ */ jsx(
|
|
3128
|
+
"button",
|
|
3227
3129
|
{
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3130
|
+
type: "button",
|
|
3131
|
+
onClick: () => {
|
|
3132
|
+
apiPost("/api/globals/storage-settings", {
|
|
3133
|
+
provider: "local",
|
|
3134
|
+
local: {
|
|
3135
|
+
uploadDir: "./public/uploads",
|
|
3136
|
+
baseUrl: "/uploads"
|
|
3137
|
+
}
|
|
3138
|
+
}).then(() => {
|
|
3139
|
+
setShowStorageConfigModal(false);
|
|
3140
|
+
setStorageConfigured(true);
|
|
3141
|
+
window.location.reload();
|
|
3142
|
+
});
|
|
3143
|
+
},
|
|
3144
|
+
className: "flex-1 px-4 py-3 border border-[var(--kyro-border)] text-[var(--kyro-text-secondary)] rounded-xl font-bold hover:bg-[var(--kyro-surface-accent)] transition-colors",
|
|
3145
|
+
children: "Use Defaults"
|
|
3232
3146
|
}
|
|
3233
3147
|
)
|
|
3234
|
-
}
|
|
3235
|
-
) }),
|
|
3236
|
-
/* @__PURE__ */ jsx("h3", { className: "text-xl font-bold text-[var(--kyro-text-primary)] mb-2", children: "Storage Not Configured" }),
|
|
3237
|
-
/* @__PURE__ */ jsx("p", { className: "text-[var(--kyro-text-secondary)] mb-6 text-sm", children: "Before uploading media, you need to configure your storage settings. Choose where files should be stored and how URLs are generated." }),
|
|
3238
|
-
/* @__PURE__ */ jsxs("div", { className: "flex gap-3", children: [
|
|
3239
|
-
/* @__PURE__ */ jsx(
|
|
3240
|
-
"a",
|
|
3241
|
-
{
|
|
3242
|
-
href: "/settings/storage-settings",
|
|
3243
|
-
className: "flex-1 px-4 py-3 bg-[var(--kyro-sidebar-active)] text-[var(--kyro-sidebar-text-active)] rounded-xl font-bold text-center hover:opacity-90 transition-colors",
|
|
3244
|
-
children: "Configure Storage"
|
|
3245
|
-
}
|
|
3246
|
-
),
|
|
3247
|
-
/* @__PURE__ */ jsx(
|
|
3248
|
-
"button",
|
|
3249
|
-
{
|
|
3250
|
-
type: "button",
|
|
3251
|
-
onClick: () => {
|
|
3252
|
-
apiPost("/api/globals/storage-settings", {
|
|
3253
|
-
provider: "local",
|
|
3254
|
-
local: {
|
|
3255
|
-
uploadDir: "./public/uploads",
|
|
3256
|
-
baseUrl: "/uploads"
|
|
3257
|
-
}
|
|
3258
|
-
}).then(() => {
|
|
3259
|
-
setShowStorageConfigModal(false);
|
|
3260
|
-
setStorageConfigured(true);
|
|
3261
|
-
window.location.reload();
|
|
3262
|
-
});
|
|
3263
|
-
},
|
|
3264
|
-
className: "flex-1 px-4 py-3 border border-[var(--kyro-border)] text-[var(--kyro-text-secondary)] rounded-xl font-bold hover:bg-[var(--kyro-surface-accent)] transition-colors",
|
|
3265
|
-
children: "Use Defaults"
|
|
3266
|
-
}
|
|
3267
|
-
)
|
|
3148
|
+
] })
|
|
3268
3149
|
] })
|
|
3269
|
-
|
|
3270
|
-
document.body
|
|
3150
|
+
}
|
|
3271
3151
|
),
|
|
3272
3152
|
!pickerMode && /* @__PURE__ */ jsx(
|
|
3273
3153
|
"input",
|
|
@@ -4861,6 +4741,7 @@ var useAutoFormStore = create()(
|
|
|
4861
4741
|
loadingDiffs: false,
|
|
4862
4742
|
isAutoSaving: false,
|
|
4863
4743
|
autoSaveStatus: "idle",
|
|
4744
|
+
backgroundProcessing: false,
|
|
4864
4745
|
// Auto-save state
|
|
4865
4746
|
lastAutoSaveTime: 0,
|
|
4866
4747
|
lastSavedAt: null,
|
|
@@ -4936,6 +4817,7 @@ var useAutoFormStore = create()(
|
|
|
4936
4817
|
setLoadingDiffs: (loading) => set({ loadingDiffs: loading }),
|
|
4937
4818
|
setIsAutoSaving: (saving) => set({ isAutoSaving: saving }),
|
|
4938
4819
|
setAutoSaveStatus: (status) => set({ autoSaveStatus: status }),
|
|
4820
|
+
setBackgroundProcessing: (processing) => set({ backgroundProcessing: processing }),
|
|
4939
4821
|
setSidebarCollapsed: (collapsed) => set({ sidebarCollapsed: collapsed }),
|
|
4940
4822
|
setLastSavedAt: (time) => set({ lastSavedAt: time }),
|
|
4941
4823
|
setRetryCount: (count) => set({ retryCount: count }),
|
|
@@ -5432,6 +5314,14 @@ function SelectField({
|
|
|
5432
5314
|
}
|
|
5433
5315
|
);
|
|
5434
5316
|
}
|
|
5317
|
+
function EmptyState({ icon, title, description, action }) {
|
|
5318
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-3 justify-center py-16 px-8", children: [
|
|
5319
|
+
icon && /* @__PURE__ */ jsx("div", { className: "w-16 h-16 rounded-2xl bg-[var(--kyro-surface-accent)] flex items-center justify-center mb-4", children: icon }),
|
|
5320
|
+
/* @__PURE__ */ jsx("p", { className: "font-medium text-[var(--kyro-text-primary)] text-base", children: title }),
|
|
5321
|
+
description && /* @__PURE__ */ jsx("p", { className: "text-sm text-[var(--kyro-text-secondary)] mt-1", children: description }),
|
|
5322
|
+
action
|
|
5323
|
+
] });
|
|
5324
|
+
}
|
|
5435
5325
|
function getLabel(opt) {
|
|
5436
5326
|
const mainTabs = opt?.mainTabs;
|
|
5437
5327
|
return opt?.title || mainTabs?.title || opt?.name || opt?.label || opt?.email || opt?.filename || opt?.slug || "Untitled";
|
|
@@ -5647,7 +5537,7 @@ function RelationshipField({
|
|
|
5647
5537
|
}
|
|
5648
5538
|
) })
|
|
5649
5539
|
] }),
|
|
5650
|
-
isOpen && /* @__PURE__ */ jsx("div", { className: "relative z-20 w-full mt-1 border border-[var(--kyro-border)] rounded-lg shadow-lg bg-[var(--kyro-surface)] max-h-64 overflow-auto", children: loading ? /* @__PURE__ */ jsx("div", { className: "p-4 text-center text-sm text-[var(--kyro-text-muted)]", children: "Loading..." }) : options.length === 0 ? /* @__PURE__ */ jsx(
|
|
5540
|
+
isOpen && /* @__PURE__ */ jsx("div", { className: "relative z-20 w-full mt-1 border border-[var(--kyro-border)] rounded-lg shadow-lg bg-[var(--kyro-surface)] max-h-64 overflow-auto", children: loading ? /* @__PURE__ */ jsx("div", { className: "p-4 text-center text-sm text-[var(--kyro-text-muted)]", children: "Loading..." }) : options.length === 0 ? /* @__PURE__ */ jsx(EmptyState, { title: "No results found" }) : /* @__PURE__ */ jsx("div", { className: "py-1", children: options.map((opt) => /* @__PURE__ */ jsxs(
|
|
5651
5541
|
"button",
|
|
5652
5542
|
{
|
|
5653
5543
|
type: "button",
|
|
@@ -6234,7 +6124,7 @@ var ListField = ({
|
|
|
6234
6124
|
onChange,
|
|
6235
6125
|
compact = false
|
|
6236
6126
|
}) => {
|
|
6237
|
-
const [inputValue, setInputValue] =
|
|
6127
|
+
const [inputValue, setInputValue] = React56.useState("");
|
|
6238
6128
|
const handleAdd = () => {
|
|
6239
6129
|
if (inputValue.trim()) {
|
|
6240
6130
|
onChange([...items, inputValue.trim()]);
|
|
@@ -6490,7 +6380,7 @@ var AccordionField = ({
|
|
|
6490
6380
|
onChange,
|
|
6491
6381
|
compact = false
|
|
6492
6382
|
}) => {
|
|
6493
|
-
const [openIndex, setOpenIndex] =
|
|
6383
|
+
const [openIndex, setOpenIndex] = React56.useState(0);
|
|
6494
6384
|
const handleTitleChange = (index, value) => {
|
|
6495
6385
|
const newItems = [...items];
|
|
6496
6386
|
newItems[index] = { ...newItems[index], title: value };
|
|
@@ -6916,7 +6806,7 @@ function ArrayLayout({
|
|
|
6916
6806
|
const firstField = fields2[0];
|
|
6917
6807
|
const labelField = firstField?.name || "user";
|
|
6918
6808
|
const isRelationship = firstField?.type === "relationship";
|
|
6919
|
-
const [openIndex, setOpenIndex] =
|
|
6809
|
+
const [openIndex, setOpenIndex] = React56.useState(0);
|
|
6920
6810
|
function getItemLabel(item) {
|
|
6921
6811
|
for (const key of ["label", "title", "name"]) {
|
|
6922
6812
|
const val = item[key];
|
|
@@ -7271,7 +7161,7 @@ var FieldRenderer = ({
|
|
|
7271
7161
|
{
|
|
7272
7162
|
field: field3,
|
|
7273
7163
|
value,
|
|
7274
|
-
onChange,
|
|
7164
|
+
onChange: onChangeKeystroke,
|
|
7275
7165
|
disabled,
|
|
7276
7166
|
error
|
|
7277
7167
|
}
|
|
@@ -8281,7 +8171,7 @@ var RelationshipBlockField = ({
|
|
|
8281
8171
|
),
|
|
8282
8172
|
/* @__PURE__ */ jsx("div", { className: "absolute right-3 top-1/2 -translate-y-1/2", children: loading && /* @__PURE__ */ jsx(LoaderCircle, { className: "w-4 h-4 text-[var(--kyro-text-muted)] animate-spin" }) })
|
|
8283
8173
|
] }),
|
|
8284
|
-
isOpen && /* @__PURE__ */ jsx("div", { className: "absolute z-20 w-full mt-1 border border-[var(--kyro-border)] rounded-lg shadow-lg bg-[var(--kyro-surface)] max-h-48 overflow-auto", children: loading ? /* @__PURE__ */ jsx("div", { className: "p-3 text-center text-sm text-[var(--kyro-text-muted)]", children: "Loading..." }) : options.length === 0 ? /* @__PURE__ */ jsx(
|
|
8174
|
+
isOpen && /* @__PURE__ */ jsx("div", { className: "absolute z-20 w-full mt-1 border border-[var(--kyro-border)] rounded-lg shadow-lg bg-[var(--kyro-surface)] max-h-48 overflow-auto", children: loading ? /* @__PURE__ */ jsx("div", { className: "p-3 text-center text-sm text-[var(--kyro-text-muted)]", children: "Loading..." }) : options.length === 0 ? /* @__PURE__ */ jsx(EmptyState, { title: "No results found" }) : /* @__PURE__ */ jsx("div", { className: "py-1", children: options.map((opt) => /* @__PURE__ */ jsxs(
|
|
8285
8175
|
"button",
|
|
8286
8176
|
{
|
|
8287
8177
|
type: "button",
|
|
@@ -8731,7 +8621,7 @@ var SortableBlockComponent = ({
|
|
|
8731
8621
|
)
|
|
8732
8622
|
] });
|
|
8733
8623
|
};
|
|
8734
|
-
var SortableBlock =
|
|
8624
|
+
var SortableBlock = React56.memo(SortableBlockComponent);
|
|
8735
8625
|
var BlocksField = ({
|
|
8736
8626
|
field: field3,
|
|
8737
8627
|
value,
|
|
@@ -8810,10 +8700,7 @@ var BlocksField = ({
|
|
|
8810
8700
|
useEffect(() => {
|
|
8811
8701
|
const valueArray = Array.isArray(value) ? value : [];
|
|
8812
8702
|
const lastValueArray = lastValueRef.current || [];
|
|
8813
|
-
|
|
8814
|
-
const lastValueIds = lastValueArray.map((b) => b.id).join(",");
|
|
8815
|
-
if (valueIds !== lastValueIds) {
|
|
8816
|
-
console.log("BlocksField sync: value=", value, "valueIds=", valueIds, "lastValueIds=", lastValueIds);
|
|
8703
|
+
if (JSON.stringify(valueArray) !== JSON.stringify(lastValueArray)) {
|
|
8817
8704
|
const valueArrayCopy = [...valueArray];
|
|
8818
8705
|
prevBlocksLengthRef.current = valueArrayCopy.length;
|
|
8819
8706
|
prevBlockIdsRef.current = new Set(valueArrayCopy.map((b) => b.id));
|
|
@@ -8822,6 +8709,7 @@ var BlocksField = ({
|
|
|
8822
8709
|
isInitializedRef.current = true;
|
|
8823
8710
|
} else if (valueArray.length === 0 && !isInitializedRef.current) {
|
|
8824
8711
|
isInitializedRef.current = true;
|
|
8712
|
+
lastValueRef.current = [];
|
|
8825
8713
|
}
|
|
8826
8714
|
}, [value, field3.name, store]);
|
|
8827
8715
|
const onChangeRef = useRef(onChange);
|
|
@@ -8830,9 +8718,8 @@ var BlocksField = ({
|
|
|
8830
8718
|
if (!onChangeRef.current) return;
|
|
8831
8719
|
const lastValue = lastValueRef.current;
|
|
8832
8720
|
if (!lastValue) return;
|
|
8833
|
-
|
|
8834
|
-
|
|
8835
|
-
if (currentIds !== lastIds) {
|
|
8721
|
+
if (JSON.stringify(blocks2) !== JSON.stringify(lastValue)) {
|
|
8722
|
+
lastValueRef.current = [...blocks2];
|
|
8836
8723
|
onChangeRef.current(blocks2);
|
|
8837
8724
|
}
|
|
8838
8725
|
}, [blocks2]);
|
|
@@ -9067,11 +8954,44 @@ function normalizeUploadFields(value) {
|
|
|
9067
8954
|
}
|
|
9068
8955
|
return value;
|
|
9069
8956
|
}
|
|
9070
|
-
function
|
|
9071
|
-
|
|
9072
|
-
|
|
9073
|
-
|
|
9074
|
-
|
|
8957
|
+
function useQueue() {
|
|
8958
|
+
const queue = useRef([]);
|
|
8959
|
+
const isProcessing = useRef(false);
|
|
8960
|
+
const queueTask = useCallback((fn, options) => {
|
|
8961
|
+
queue.current.push(fn);
|
|
8962
|
+
async function processQueue() {
|
|
8963
|
+
if (isProcessing.current) return;
|
|
8964
|
+
if (typeof options?.beforeProcess === "function") {
|
|
8965
|
+
const shouldContinue = options.beforeProcess();
|
|
8966
|
+
if (shouldContinue === false) return;
|
|
8967
|
+
}
|
|
8968
|
+
while (queue.current.length > 0) {
|
|
8969
|
+
const latestTask = queue.current.pop();
|
|
8970
|
+
queue.current = [];
|
|
8971
|
+
isProcessing.current = true;
|
|
8972
|
+
try {
|
|
8973
|
+
await latestTask();
|
|
8974
|
+
} catch (err) {
|
|
8975
|
+
console.error("Error in queued function:", err);
|
|
8976
|
+
} finally {
|
|
8977
|
+
isProcessing.current = false;
|
|
8978
|
+
if (typeof options?.afterProcess === "function") {
|
|
8979
|
+
options.afterProcess();
|
|
8980
|
+
}
|
|
8981
|
+
}
|
|
8982
|
+
}
|
|
8983
|
+
}
|
|
8984
|
+
processQueue();
|
|
8985
|
+
}, []);
|
|
8986
|
+
return { queueTask };
|
|
8987
|
+
}
|
|
8988
|
+
|
|
8989
|
+
// src/hooks/useAutoFormState.ts
|
|
8990
|
+
function useAutoFormState({
|
|
8991
|
+
config,
|
|
8992
|
+
initialData,
|
|
8993
|
+
collectionSlug,
|
|
8994
|
+
globalSlug,
|
|
9075
8995
|
onChange,
|
|
9076
8996
|
onActionSuccess,
|
|
9077
8997
|
onActionError
|
|
@@ -9117,6 +9037,9 @@ function useAutoFormState({
|
|
|
9117
9037
|
const lastAutoSaveTimeRef = useRef(0);
|
|
9118
9038
|
const autoSaveSkipRef = useRef(false);
|
|
9119
9039
|
const restorePromptedRef = useRef(null);
|
|
9040
|
+
const previousFormDataRef = useRef("");
|
|
9041
|
+
const astroSyncDataRef = useRef("");
|
|
9042
|
+
const { queueTask } = useQueue();
|
|
9120
9043
|
const getDocumentKey = useCallback(
|
|
9121
9044
|
(id) => {
|
|
9122
9045
|
if (globalSlug) return `global:${globalSlug}`;
|
|
@@ -9136,23 +9059,6 @@ function useAutoFormState({
|
|
|
9136
9059
|
},
|
|
9137
9060
|
[lastSavedData.updatedAt, setDraftCache]
|
|
9138
9061
|
);
|
|
9139
|
-
const clearDraftArtifacts = useCallback(async () => {
|
|
9140
|
-
const state = useAutoFormStore.getState();
|
|
9141
|
-
const documentKey = getDocumentKey(state.formData.id);
|
|
9142
|
-
if (documentKey) {
|
|
9143
|
-
clearDraftCache(documentKey);
|
|
9144
|
-
}
|
|
9145
|
-
const draftUrl = globalSlug ? resolveApi(`/api/globals/${globalSlug}/draft`) : collectionSlug && state.formData.id ? resolveApi(`/api/${collectionSlug}/${state.formData.id}/draft`) : null;
|
|
9146
|
-
if (draftUrl && versionsEnabled) {
|
|
9147
|
-
try {
|
|
9148
|
-
await fetchWithAuth(draftUrl, {
|
|
9149
|
-
method: "DELETE"
|
|
9150
|
-
});
|
|
9151
|
-
} catch (err) {
|
|
9152
|
-
console.error("Failed to clear draft snapshot:", err);
|
|
9153
|
-
}
|
|
9154
|
-
}
|
|
9155
|
-
}, [clearDraftCache, collectionSlug, globalSlug, getDocumentKey]);
|
|
9156
9062
|
const fetchVersions = useCallback(async () => {
|
|
9157
9063
|
const url = globalSlug ? resolveApi(`/api/globals/${globalSlug}/versions`) : collectionSlug && formData.id ? resolveApi(`/api/${collectionSlug}/${formData.id}/versions`) : null;
|
|
9158
9064
|
if (!url) return;
|
|
@@ -9177,7 +9083,7 @@ function useAutoFormState({
|
|
|
9177
9083
|
persistBrowserDraft(documentKey, latestFormData);
|
|
9178
9084
|
}
|
|
9179
9085
|
}, [collectionSlug, getDocumentKey, persistBrowserDraft]);
|
|
9180
|
-
const
|
|
9086
|
+
const doAutosaveFetch = useCallback(async (options) => {
|
|
9181
9087
|
const state = useAutoFormStore.getState();
|
|
9182
9088
|
const latestFormData = state.formData;
|
|
9183
9089
|
const currentLastSaved = state.lastSavedData;
|
|
@@ -9194,29 +9100,22 @@ function useAutoFormState({
|
|
|
9194
9100
|
}
|
|
9195
9101
|
setIsAutoSaving(true);
|
|
9196
9102
|
setAutoSaveStatus("saving");
|
|
9103
|
+
state.setBackgroundProcessing(true);
|
|
9197
9104
|
try {
|
|
9198
|
-
const
|
|
9199
|
-
const
|
|
9200
|
-
|
|
9201
|
-
|
|
9202
|
-
|
|
9203
|
-
|
|
9204
|
-
|
|
9205
|
-
|
|
9206
|
-
|
|
9207
|
-
|
|
9208
|
-
|
|
9209
|
-
|
|
9210
|
-
|
|
9211
|
-
body: JSON.stringify({
|
|
9212
|
-
delta: normalizeUploadFields(delta),
|
|
9213
|
-
baseUpdatedAt: currentLastSaved.updatedAt ?? null,
|
|
9214
|
-
draftUpdatedAt
|
|
9215
|
-
})
|
|
9216
|
-
}
|
|
9217
|
-
);
|
|
9105
|
+
const url = globalSlug ? resolveApi(`/api/globals/${globalSlug}?autosave=true`) : resolveApi(`/api/${collectionSlug}/${latestFormData.id}?autosave=true`);
|
|
9106
|
+
const response = await fetchWithAuth(url, {
|
|
9107
|
+
method: "PATCH",
|
|
9108
|
+
headers: {
|
|
9109
|
+
"Content-Type": "application/json",
|
|
9110
|
+
"X-Draft": "true"
|
|
9111
|
+
},
|
|
9112
|
+
keepalive: options?.keepalive,
|
|
9113
|
+
body: JSON.stringify({
|
|
9114
|
+
...normalizeUploadFields(latestFormData),
|
|
9115
|
+
baseUpdatedAt: currentLastSaved.updatedAt ?? null
|
|
9116
|
+
})
|
|
9117
|
+
});
|
|
9218
9118
|
if (response.ok) {
|
|
9219
|
-
const result = await response.json();
|
|
9220
9119
|
lastAutoSaveTimeRef.current = Date.now();
|
|
9221
9120
|
state.setRetryCount(0);
|
|
9222
9121
|
state.setLastSavedAt(Date.now());
|
|
@@ -9225,8 +9124,8 @@ function useAutoFormState({
|
|
|
9225
9124
|
setDraftCache(documentKey, {
|
|
9226
9125
|
data: latestFormData,
|
|
9227
9126
|
baseUpdatedAt: currentLastSaved.updatedAt ?? null,
|
|
9228
|
-
draftUpdatedAt:
|
|
9229
|
-
lastSyncedAt:
|
|
9127
|
+
draftUpdatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
9128
|
+
lastSyncedAt: (await response.clone().json()).data?.updatedAt || (/* @__PURE__ */ new Date()).toISOString()
|
|
9230
9129
|
});
|
|
9231
9130
|
}
|
|
9232
9131
|
setAutoSaveStatus("success");
|
|
@@ -9235,24 +9134,27 @@ function useAutoFormState({
|
|
|
9235
9134
|
setAutoSaveStatus("idle");
|
|
9236
9135
|
}
|
|
9237
9136
|
}, 2e3);
|
|
9137
|
+
} else if (response.status === 409) {
|
|
9138
|
+
setAutoSaveStatus("conflict");
|
|
9238
9139
|
} else {
|
|
9239
9140
|
throw new Error(`Draft auto-save failed with status ${response.status}`);
|
|
9240
9141
|
}
|
|
9241
9142
|
} catch (err) {
|
|
9242
9143
|
console.error("Auto-save failed:", err);
|
|
9243
|
-
const
|
|
9244
|
-
const currentRetryCount =
|
|
9144
|
+
const currentState = useAutoFormStore.getState();
|
|
9145
|
+
const currentRetryCount = currentState.retryCount;
|
|
9245
9146
|
if (currentRetryCount < 5) {
|
|
9246
|
-
|
|
9147
|
+
currentState.setRetryCount(currentRetryCount + 1);
|
|
9247
9148
|
setAutoSaveStatus("retrying");
|
|
9248
9149
|
const delay = Math.min(1e3 * Math.pow(2, currentRetryCount), 6e4);
|
|
9249
9150
|
if (retryTimerRef.current) clearTimeout(retryTimerRef.current);
|
|
9250
|
-
retryTimerRef.current = setTimeout(() =>
|
|
9151
|
+
retryTimerRef.current = setTimeout(() => performAutosave(options), delay);
|
|
9251
9152
|
} else {
|
|
9252
9153
|
setAutoSaveStatus("offline");
|
|
9253
9154
|
}
|
|
9254
9155
|
} finally {
|
|
9255
9156
|
setIsAutoSaving(false);
|
|
9157
|
+
useAutoFormStore.getState().setBackgroundProcessing(false);
|
|
9256
9158
|
}
|
|
9257
9159
|
}, [
|
|
9258
9160
|
collectionSlug,
|
|
@@ -9264,8 +9166,20 @@ function useAutoFormState({
|
|
|
9264
9166
|
setIsAutoSaving,
|
|
9265
9167
|
versionsEnabled
|
|
9266
9168
|
]);
|
|
9169
|
+
const performAutosave = useCallback((options) => {
|
|
9170
|
+
queueTask(
|
|
9171
|
+
() => doAutosaveFetch(options),
|
|
9172
|
+
{
|
|
9173
|
+
beforeProcess: () => {
|
|
9174
|
+
return true;
|
|
9175
|
+
},
|
|
9176
|
+
afterProcess: () => {
|
|
9177
|
+
}
|
|
9178
|
+
}
|
|
9179
|
+
);
|
|
9180
|
+
}, [doAutosaveFetch, queueTask]);
|
|
9267
9181
|
const saveDocument = useCallback(
|
|
9268
|
-
async (dataOverride) => {
|
|
9182
|
+
async (dataOverride, isDraft = true) => {
|
|
9269
9183
|
const state = useAutoFormStore.getState();
|
|
9270
9184
|
const payload = dataOverride || state.formData;
|
|
9271
9185
|
const url = globalSlug ? resolveApi(`/api/globals/${globalSlug}`) : resolveApi(`/api/${collectionSlug}/${payload.id}`);
|
|
@@ -9273,7 +9187,10 @@ function useAutoFormState({
|
|
|
9273
9187
|
url,
|
|
9274
9188
|
{
|
|
9275
9189
|
method: "PATCH",
|
|
9276
|
-
headers: {
|
|
9190
|
+
headers: {
|
|
9191
|
+
"Content-Type": "application/json",
|
|
9192
|
+
"X-Draft": String(isDraft)
|
|
9193
|
+
},
|
|
9277
9194
|
body: JSON.stringify({
|
|
9278
9195
|
...normalizeUploadFields(payload),
|
|
9279
9196
|
baseUpdatedAt: state.lastSavedData.updatedAt ?? null
|
|
@@ -9287,36 +9204,6 @@ function useAutoFormState({
|
|
|
9287
9204
|
},
|
|
9288
9205
|
[collectionSlug, globalSlug, setAutoSaveStatus]
|
|
9289
9206
|
);
|
|
9290
|
-
const publishDocument = useCallback(async () => {
|
|
9291
|
-
const state = useAutoFormStore.getState();
|
|
9292
|
-
const url = globalSlug ? resolveApi(`/api/globals/${globalSlug}/publish`) : resolveApi(`/api/${collectionSlug}/${state.formData.id}/publish`);
|
|
9293
|
-
const response = await fetchWithAuth(
|
|
9294
|
-
url,
|
|
9295
|
-
{
|
|
9296
|
-
method: "POST",
|
|
9297
|
-
headers: { "Content-Type": "application/json" },
|
|
9298
|
-
body: JSON.stringify({
|
|
9299
|
-
baseUpdatedAt: state.lastSavedData.updatedAt ?? null
|
|
9300
|
-
})
|
|
9301
|
-
}
|
|
9302
|
-
);
|
|
9303
|
-
if (response.status === 409) {
|
|
9304
|
-
setAutoSaveStatus("conflict");
|
|
9305
|
-
}
|
|
9306
|
-
return response;
|
|
9307
|
-
}, [collectionSlug, globalSlug, setAutoSaveStatus]);
|
|
9308
|
-
const unpublishDocument = useCallback(async () => {
|
|
9309
|
-
const state = useAutoFormStore.getState();
|
|
9310
|
-
const url = globalSlug ? resolveApi(`/api/globals/${globalSlug}/unpublish`) : resolveApi(`/api/${collectionSlug}/${state.formData.id}/unpublish`);
|
|
9311
|
-
const response = await fetchWithAuth(
|
|
9312
|
-
url,
|
|
9313
|
-
{
|
|
9314
|
-
method: "POST",
|
|
9315
|
-
headers: { "Content-Type": "application/json" }
|
|
9316
|
-
}
|
|
9317
|
-
);
|
|
9318
|
-
return response;
|
|
9319
|
-
}, [collectionSlug, globalSlug]);
|
|
9320
9207
|
useEffect(() => {
|
|
9321
9208
|
const handleToggle = () => {
|
|
9322
9209
|
setSidebarCollapsed(!sidebarCollapsed);
|
|
@@ -9325,13 +9212,16 @@ function useAutoFormState({
|
|
|
9325
9212
|
return () => window.removeEventListener("toggle-sidebar", handleToggle);
|
|
9326
9213
|
}, [sidebarCollapsed, setSidebarCollapsed]);
|
|
9327
9214
|
const lastLoadedSlugRef = useRef(null);
|
|
9215
|
+
const lastInitialDataRef = useRef("");
|
|
9328
9216
|
const initialDataLoadedRef = useRef(false);
|
|
9329
9217
|
useEffect(() => {
|
|
9330
9218
|
const currentSlug = globalSlug || initialData?.id;
|
|
9331
|
-
|
|
9219
|
+
const serialized = JSON.stringify(initialData);
|
|
9220
|
+
if (initialDataLoadedRef.current && lastLoadedSlugRef.current === currentSlug && lastInitialDataRef.current === serialized) return;
|
|
9332
9221
|
loadDocument(initialData || {}, initialData || {});
|
|
9333
9222
|
initialDataLoadedRef.current = true;
|
|
9334
9223
|
lastLoadedSlugRef.current = currentSlug;
|
|
9224
|
+
lastInitialDataRef.current = serialized;
|
|
9335
9225
|
}, [collectionSlug, formData.id, globalSlug, initialData, loadDocument]);
|
|
9336
9226
|
useEffect(() => {
|
|
9337
9227
|
if (!collectionSlug || !initialData?.id) return;
|
|
@@ -9342,24 +9232,9 @@ function useAutoFormState({
|
|
|
9342
9232
|
const maybeRestoreDraft = async () => {
|
|
9343
9233
|
if (!versionsEnabled) return;
|
|
9344
9234
|
const browserDraft = getDraftCache(documentKey);
|
|
9345
|
-
|
|
9346
|
-
|
|
9347
|
-
|
|
9348
|
-
resolveApi(`/api/${collectionSlug}/${initialData.id}/draft`)
|
|
9349
|
-
);
|
|
9350
|
-
if (response.ok) {
|
|
9351
|
-
const result = await response.json();
|
|
9352
|
-
serverDraft = result.data || null;
|
|
9353
|
-
}
|
|
9354
|
-
} catch (err) {
|
|
9355
|
-
console.error("Failed to fetch server draft:", err);
|
|
9356
|
-
}
|
|
9357
|
-
const drafts = [browserDraft, serverDraft].filter(Boolean);
|
|
9358
|
-
const candidate = drafts.sort(
|
|
9359
|
-
(a, b) => new Date(b.draftUpdatedAt).getTime() - new Date(a.draftUpdatedAt).getTime()
|
|
9360
|
-
)[0];
|
|
9361
|
-
if (!candidate) return;
|
|
9362
|
-
if (JSON.stringify(candidate.data) === JSON.stringify(initialData)) {
|
|
9235
|
+
if (!browserDraft) return;
|
|
9236
|
+
if (JSON.stringify(browserDraft.data) === JSON.stringify(initialData)) {
|
|
9237
|
+
clearDraftCache(documentKey);
|
|
9363
9238
|
return;
|
|
9364
9239
|
}
|
|
9365
9240
|
restorePromptedRef.current = documentKey;
|
|
@@ -9371,20 +9246,12 @@ function useAutoFormState({
|
|
|
9371
9246
|
onConfirm: async () => {
|
|
9372
9247
|
if (cancelled) return;
|
|
9373
9248
|
const currentFormData = useAutoFormStore.getState().formData;
|
|
9374
|
-
const mergedData = { ...currentFormData, ...
|
|
9249
|
+
const mergedData = { ...currentFormData, ...browserDraft.data };
|
|
9375
9250
|
setFormData(mergedData);
|
|
9376
9251
|
onActionSuccess?.("Recovered autosaved draft");
|
|
9377
9252
|
},
|
|
9378
9253
|
onCancel: async () => {
|
|
9379
9254
|
clearDraftCache(documentKey);
|
|
9380
|
-
try {
|
|
9381
|
-
await fetchWithAuth(
|
|
9382
|
-
resolveApi(`/api/${collectionSlug}/${initialData.id}/draft`),
|
|
9383
|
-
{ method: "DELETE" }
|
|
9384
|
-
);
|
|
9385
|
-
} catch (err) {
|
|
9386
|
-
console.error("Failed to discard server draft:", err);
|
|
9387
|
-
}
|
|
9388
9255
|
}
|
|
9389
9256
|
});
|
|
9390
9257
|
};
|
|
@@ -9400,7 +9267,8 @@ function useAutoFormState({
|
|
|
9400
9267
|
getDraftCache,
|
|
9401
9268
|
initialData,
|
|
9402
9269
|
onActionSuccess,
|
|
9403
|
-
setFormData
|
|
9270
|
+
setFormData,
|
|
9271
|
+
versionsEnabled
|
|
9404
9272
|
]);
|
|
9405
9273
|
function findFieldDeep(fields2, name) {
|
|
9406
9274
|
for (const f of fields2) {
|
|
@@ -9450,18 +9318,23 @@ function useAutoFormState({
|
|
|
9450
9318
|
if (!state.hasDirtyFields()) return;
|
|
9451
9319
|
if (getLastChangeSource() !== "keystroke") return;
|
|
9452
9320
|
setChangeSource("other");
|
|
9321
|
+
const serialized = JSON.stringify(formData);
|
|
9322
|
+
if (serialized === previousFormDataRef.current) return;
|
|
9453
9323
|
if (localSaveTimerRef.current) clearTimeout(localSaveTimerRef.current);
|
|
9454
|
-
if (serverSaveTimerRef.current) clearTimeout(serverSaveTimerRef.current);
|
|
9455
9324
|
localSaveTimerRef.current = setTimeout(performLocalAutoSave, 1500);
|
|
9456
|
-
serverSaveTimerRef.current
|
|
9457
|
-
|
|
9325
|
+
if (serverSaveTimerRef.current) clearTimeout(serverSaveTimerRef.current);
|
|
9326
|
+
serverSaveTimerRef.current = setTimeout(() => {
|
|
9327
|
+
previousFormDataRef.current = serialized;
|
|
9328
|
+
performAutosave();
|
|
9329
|
+
}, 8e3);
|
|
9330
|
+
}, [formData, sidebarCollapsed, collectionSlug, globalSlug, performLocalAutoSave, performAutosave]);
|
|
9458
9331
|
useEffect(() => {
|
|
9459
9332
|
if (!globalSlug && (!collectionSlug || !formData.id)) return;
|
|
9460
9333
|
const flushDraft = () => {
|
|
9461
9334
|
if (autoSaveSkipRef.current) return;
|
|
9462
9335
|
const state = useAutoFormStore.getState();
|
|
9463
9336
|
if (!state.hasDirtyFields()) return;
|
|
9464
|
-
void
|
|
9337
|
+
void performAutosave({ keepalive: true });
|
|
9465
9338
|
};
|
|
9466
9339
|
const handleVisibilityChange = () => {
|
|
9467
9340
|
if (document.hidden) {
|
|
@@ -9491,11 +9364,14 @@ function useAutoFormState({
|
|
|
9491
9364
|
window.removeEventListener("offline", handleOffline);
|
|
9492
9365
|
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
9493
9366
|
};
|
|
9494
|
-
}, [collectionSlug, globalSlug, formData.id,
|
|
9367
|
+
}, [collectionSlug, globalSlug, formData.id, performAutosave]);
|
|
9495
9368
|
useEffect(() => {
|
|
9369
|
+
const serialized = JSON.stringify(formData);
|
|
9370
|
+
if (serialized === astroSyncDataRef.current) return;
|
|
9371
|
+
astroSyncDataRef.current = serialized;
|
|
9496
9372
|
const hiddenInput = document.getElementById("form-data");
|
|
9497
9373
|
if (hiddenInput) {
|
|
9498
|
-
hiddenInput.value =
|
|
9374
|
+
hiddenInput.value = serialized;
|
|
9499
9375
|
}
|
|
9500
9376
|
onChange?.(formData);
|
|
9501
9377
|
}, [formData, onChange]);
|
|
@@ -9505,18 +9381,14 @@ function useAutoFormState({
|
|
|
9505
9381
|
const documentStatus = (() => {
|
|
9506
9382
|
if (!formData.id && !globalSlug) return "draft";
|
|
9507
9383
|
if (!versionsEnabled) return "published";
|
|
9508
|
-
|
|
9509
|
-
return formData.publishStatus || "published";
|
|
9384
|
+
return formData.status || "published";
|
|
9510
9385
|
})();
|
|
9511
|
-
const hasUnpublishedChanges = (!!formData.id || !!globalSlug) &&
|
|
9386
|
+
const hasUnpublishedChanges = (!!formData.id || !!globalSlug) && documentStatus === "draft";
|
|
9512
9387
|
return {
|
|
9513
9388
|
...store,
|
|
9514
9389
|
fetchVersions,
|
|
9515
|
-
performAutoSave:
|
|
9390
|
+
performAutoSave: performAutosave,
|
|
9516
9391
|
saveDocument,
|
|
9517
|
-
publishDocument,
|
|
9518
|
-
unpublishDocument,
|
|
9519
|
-
clearDraftArtifacts,
|
|
9520
9392
|
autoSaveSkipRef,
|
|
9521
9393
|
lastAutoSaveTimeRef,
|
|
9522
9394
|
documentStatus,
|
|
@@ -9524,129 +9396,120 @@ function useAutoFormState({
|
|
|
9524
9396
|
versionsEnabled
|
|
9525
9397
|
};
|
|
9526
9398
|
}
|
|
9527
|
-
function
|
|
9528
|
-
|
|
9529
|
-
}
|
|
9530
|
-
function ModalActions({ children }) {
|
|
9531
|
-
return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-end gap-3 mt-6", children });
|
|
9532
|
-
}
|
|
9533
|
-
function Modal({
|
|
9534
|
-
open,
|
|
9535
|
-
onClose,
|
|
9536
|
-
title,
|
|
9399
|
+
function Dropdown({
|
|
9400
|
+
trigger,
|
|
9537
9401
|
children,
|
|
9538
|
-
|
|
9539
|
-
|
|
9540
|
-
variant = "default"
|
|
9402
|
+
align = "right",
|
|
9403
|
+
direction = "up"
|
|
9541
9404
|
}) {
|
|
9405
|
+
const [open, setOpen] = useState(false);
|
|
9406
|
+
const ref = useRef(null);
|
|
9542
9407
|
useEffect(() => {
|
|
9543
|
-
const
|
|
9544
|
-
if (
|
|
9408
|
+
const handleClickOutside = (e) => {
|
|
9409
|
+
if (ref.current && !ref.current.contains(e.target)) {
|
|
9410
|
+
setOpen(false);
|
|
9411
|
+
}
|
|
9545
9412
|
};
|
|
9546
9413
|
if (open) {
|
|
9547
|
-
document.addEventListener("
|
|
9548
|
-
document.body.style.overflow = "hidden";
|
|
9414
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
9549
9415
|
}
|
|
9550
|
-
return () =>
|
|
9551
|
-
|
|
9552
|
-
|
|
9553
|
-
}
|
|
9554
|
-
|
|
9555
|
-
|
|
9556
|
-
|
|
9557
|
-
|
|
9558
|
-
|
|
9559
|
-
|
|
9560
|
-
|
|
9561
|
-
|
|
9562
|
-
|
|
9563
|
-
/* @__PURE__ */ jsx(
|
|
9564
|
-
"div",
|
|
9565
|
-
{
|
|
9566
|
-
className: "absolute inset-0 bg-[var(--kyro-black)]/40 backdrop-blur-md transition-all duration-500",
|
|
9567
|
-
onClick: onClose
|
|
9568
|
-
}
|
|
9569
|
-
),
|
|
9570
|
-
/* @__PURE__ */ jsxs(
|
|
9571
|
-
"div",
|
|
9572
|
-
{
|
|
9573
|
-
className: `relative w-full ${sizeClasses[size]} bg-[var(--kyro-surface)] rounded-[var(--kyro-radius-lg)] shadow-2xl animate-in fade-in zoom-in-95 duration-300 border ${variant === "danger" ? "border-red-500/30" : "border-[var(--kyro-border)]"} overflow-hidden`,
|
|
9574
|
-
children: [
|
|
9575
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-8 py-6 border-b border-[var(--kyro-border)] bg-[var(--kyro-surface-accent)]/50 backdrop-blur-md", children: [
|
|
9576
|
-
/* @__PURE__ */ jsx("h2", { className: "text-xl font-bold text-[var(--kyro-text-primary)]", children: title }),
|
|
9577
|
-
/* @__PURE__ */ jsx(
|
|
9578
|
-
"button",
|
|
9579
|
-
{
|
|
9580
|
-
type: "button",
|
|
9581
|
-
onClick: onClose,
|
|
9582
|
-
className: "p-2 text-[var(--kyro-text-muted)] hover:text-[var(--kyro-text-primary)] rounded-xl hover:bg-[var(--kyro-surface)] transition-all duration-200",
|
|
9583
|
-
children: /* @__PURE__ */ jsx(
|
|
9584
|
-
"svg",
|
|
9585
|
-
{
|
|
9586
|
-
width: "20",
|
|
9587
|
-
height: "20",
|
|
9588
|
-
viewBox: "0 0 24 24",
|
|
9589
|
-
fill: "none",
|
|
9590
|
-
stroke: "currentColor",
|
|
9591
|
-
strokeWidth: "2.5",
|
|
9592
|
-
children: /* @__PURE__ */ jsx("path", { d: "M18 6L6 18M6 6l12 12" })
|
|
9593
|
-
}
|
|
9594
|
-
)
|
|
9595
|
-
}
|
|
9596
|
-
)
|
|
9597
|
-
] }),
|
|
9598
|
-
/* @__PURE__ */ jsx("div", { className: "px-8 py-8", children }),
|
|
9599
|
-
footer && /* @__PURE__ */ jsx("div", { className: "flex items-center justify-end gap-3 px-8 py-6 border-t border-[var(--kyro-border)] bg-[var(--kyro-surface-accent)]/50", children: footer })
|
|
9600
|
-
]
|
|
9601
|
-
}
|
|
9602
|
-
)
|
|
9603
|
-
] }),
|
|
9604
|
-
document.body
|
|
9605
|
-
);
|
|
9416
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
9417
|
+
}, [open]);
|
|
9418
|
+
return /* @__PURE__ */ jsxs("div", { className: "relative", ref, children: [
|
|
9419
|
+
/* @__PURE__ */ jsx("div", { onClick: () => setOpen(!open), className: "cursor-pointer", children: trigger }),
|
|
9420
|
+
open && /* @__PURE__ */ jsx(
|
|
9421
|
+
"div",
|
|
9422
|
+
{
|
|
9423
|
+
className: `absolute z-[100] min-w-[200px] py-2 bg-[var(--kyro-surface)] rounded-2xl shadow-2xl border border-[var(--kyro-border)] animate-in fade-in zoom-in-95 duration-100 ${align === "right" ? "right-0" : "left-0"} ${direction === "down" ? "top-full mt-2" : "bottom-full mb-2"}`,
|
|
9424
|
+
onClick: () => setOpen(false),
|
|
9425
|
+
children
|
|
9426
|
+
}
|
|
9427
|
+
)
|
|
9428
|
+
] });
|
|
9606
9429
|
}
|
|
9607
|
-
function
|
|
9608
|
-
|
|
9609
|
-
|
|
9610
|
-
|
|
9611
|
-
|
|
9612
|
-
|
|
9613
|
-
|
|
9614
|
-
cancelLabel = "Cancel",
|
|
9615
|
-
variant = "default",
|
|
9616
|
-
loading = false
|
|
9430
|
+
function DropdownItem({
|
|
9431
|
+
children,
|
|
9432
|
+
onClick,
|
|
9433
|
+
icon,
|
|
9434
|
+
danger,
|
|
9435
|
+
disabled,
|
|
9436
|
+
className = ""
|
|
9617
9437
|
}) {
|
|
9618
|
-
return /* @__PURE__ */ jsx(
|
|
9619
|
-
|
|
9438
|
+
return /* @__PURE__ */ jsx("div", { className: "px-1.5", children: /* @__PURE__ */ jsxs(
|
|
9439
|
+
"button",
|
|
9620
9440
|
{
|
|
9621
|
-
|
|
9622
|
-
|
|
9623
|
-
|
|
9624
|
-
|
|
9625
|
-
|
|
9626
|
-
/* @__PURE__ */ jsx(
|
|
9627
|
-
|
|
9628
|
-
|
|
9629
|
-
type: "button",
|
|
9630
|
-
onClick: onClose,
|
|
9631
|
-
disabled: loading,
|
|
9632
|
-
className: "kyro-btn kyro-btn-md kyro-btn-secondary",
|
|
9633
|
-
children: cancelLabel
|
|
9634
|
-
}
|
|
9635
|
-
),
|
|
9636
|
-
/* @__PURE__ */ jsx(
|
|
9637
|
-
"button",
|
|
9638
|
-
{
|
|
9639
|
-
type: "button",
|
|
9640
|
-
onClick: onConfirm,
|
|
9641
|
-
disabled: loading,
|
|
9642
|
-
className: `kyro-btn kyro-btn-md ${variant === "danger" ? "kyro-btn-danger" : "kyro-btn-primary"}`,
|
|
9643
|
-
children: loading ? "Loading..." : confirmLabel
|
|
9644
|
-
}
|
|
9645
|
-
)
|
|
9646
|
-
] }),
|
|
9647
|
-
children: /* @__PURE__ */ jsx("p", { className: "text-[var(--kyro-text-secondary)]", children: message })
|
|
9441
|
+
type: "button",
|
|
9442
|
+
onClick,
|
|
9443
|
+
disabled,
|
|
9444
|
+
className: `w-full flex items-center gap-3 px-3 py-2.5 text-[11px] font-medium tracking-wide text-left transition-all rounded-xl ${danger ? "text-red-500 hover:bg-red-500/10" : "text-[var(--kyro-text-secondary)] hover:text-[var(--kyro-text-primary)] hover:bg-[var(--kyro-surface-accent)]"} ${disabled ? "opacity-50 cursor-not-allowed" : ""} ${className}`,
|
|
9445
|
+
children: [
|
|
9446
|
+
icon && /* @__PURE__ */ jsx("span", { className: "w-4 h-4 opacity-70", children: icon }),
|
|
9447
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1", children })
|
|
9448
|
+
]
|
|
9648
9449
|
}
|
|
9649
|
-
);
|
|
9450
|
+
) });
|
|
9451
|
+
}
|
|
9452
|
+
function DropdownSeparator() {
|
|
9453
|
+
return /* @__PURE__ */ jsx("div", { className: "my-1 border-t border-[var(--kyro-border)] opacity-50" });
|
|
9454
|
+
}
|
|
9455
|
+
function SplitButton({
|
|
9456
|
+
status,
|
|
9457
|
+
saveStatus,
|
|
9458
|
+
hasChanges,
|
|
9459
|
+
onPublish,
|
|
9460
|
+
children,
|
|
9461
|
+
disabled,
|
|
9462
|
+
direction = "down"
|
|
9463
|
+
}) {
|
|
9464
|
+
const isPublishedIdle = status === "published" && !hasChanges && saveStatus !== "saving" && saveStatus !== "error";
|
|
9465
|
+
const isDisabled = disabled || saveStatus === "saving" || isPublishedIdle;
|
|
9466
|
+
const btnBase = "kyro-btn kyro-btn-sm text-[11px] font-regular tracking-widest transition-all duration-300 rounded-lg";
|
|
9467
|
+
const getBtnClass = () => {
|
|
9468
|
+
if (saveStatus === "saving") return `${btnBase} bg-[var(--kyro-primary)]/70 border-[var(--kyro-primary)]/70 text-[var(--kyro-sidebar-text-active)] cursor-wait`;
|
|
9469
|
+
if (saveStatus === "saved") return `${btnBase} bg-[var(--kyro-success)] border-[var(--kyro-success)] text-[var(--kyro-sidebar-text-active)]`;
|
|
9470
|
+
if (saveStatus === "error") return `${btnBase} bg-[var(--kyro-error)] border-[var(--kyro-error)] text-[var(--kyro-sidebar-text-active)]`;
|
|
9471
|
+
if (isPublishedIdle) return `${btnBase} bg-[var(--kyro-gray-200)] border-[var(--kyro-gray-200)] text-[var(--kyro-text-muted)] cursor-not-allowed`;
|
|
9472
|
+
return `${btnBase} bg-[var(--kyro-primary)] border-[var(--kyro-primary)] hover:bg-[var(--kyro-primary-hover)]`;
|
|
9473
|
+
};
|
|
9474
|
+
const chevronBase = "kyro-btn kyro-btn-md px-2 rounded-l-none border-l-[1px] border-white/20 transition-all duration-300";
|
|
9475
|
+
const getChevronClass = () => {
|
|
9476
|
+
if (saveStatus === "saving") return `${chevronBase} bg-[var(--kyro-primary)]/70 text-[var(--kyro-sidebar-text-active)] border-[var(--kyro-primary)]/70`;
|
|
9477
|
+
if (saveStatus === "saved") return `${chevronBase} bg-[var(--kyro-success)] text-[var(--kyro-sidebar-text-active)] border-[var(--kyro-success)]`;
|
|
9478
|
+
if (saveStatus === "error") return `${chevronBase} bg-[var(--kyro-error)] text-[var(--kyro-sidebar-text-active)] border-[var(--kyro-error)]`;
|
|
9479
|
+
if (isPublishedIdle) return `${chevronBase} bg-[var(--kyro-gray-200)] text-[var(--kyro-text-muted)] border-[var(--kyro-gray-200)]`;
|
|
9480
|
+
return `${chevronBase} bg-[var(--kyro-primary)] text-[var(--kyro-sidebar-text-active)] border-[var(--kyro-primary)] hover:bg-[var(--kyro-primary-hover)]`;
|
|
9481
|
+
};
|
|
9482
|
+
const getLabel2 = () => {
|
|
9483
|
+
if (saveStatus === "saving") return "Publishing...";
|
|
9484
|
+
if (saveStatus === "saved") return "Published \u2713";
|
|
9485
|
+
if (saveStatus === "error") return "Retry";
|
|
9486
|
+
if (isPublishedIdle) return "Published";
|
|
9487
|
+
return "Publish Changes";
|
|
9488
|
+
};
|
|
9489
|
+
return /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center", children: [
|
|
9490
|
+
/* @__PURE__ */ jsxs(
|
|
9491
|
+
"button",
|
|
9492
|
+
{
|
|
9493
|
+
type: "button",
|
|
9494
|
+
onClick: onPublish,
|
|
9495
|
+
disabled: isDisabled,
|
|
9496
|
+
className: `${getBtnClass()} ${!children ? "rounded-r-lg border-r border-[var(--kyro-border)]" : ""}`,
|
|
9497
|
+
children: [
|
|
9498
|
+
saveStatus === "saving" && /* @__PURE__ */ jsx(Spinner, { size: "sm", className: "inline mr-1.5" }),
|
|
9499
|
+
isPublishedIdle && /* @__PURE__ */ jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", className: "inline mr-1", children: /* @__PURE__ */ jsx("polyline", { points: "20 6 9 17 4 12" }) }),
|
|
9500
|
+
getLabel2()
|
|
9501
|
+
]
|
|
9502
|
+
}
|
|
9503
|
+
),
|
|
9504
|
+
children && /* @__PURE__ */ jsx(
|
|
9505
|
+
Dropdown,
|
|
9506
|
+
{
|
|
9507
|
+
trigger: /* @__PURE__ */ jsx("button", { type: "button", className: getChevronClass(), disabled: saveStatus === "saving", children: /* @__PURE__ */ jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" }) }) }),
|
|
9508
|
+
direction,
|
|
9509
|
+
children
|
|
9510
|
+
}
|
|
9511
|
+
)
|
|
9512
|
+
] });
|
|
9650
9513
|
}
|
|
9651
9514
|
var SeoPreview = ({ title, description, slug }) => /* @__PURE__ */ jsxs("div", { className: "bg-[var(--kyro-surface)] border border-[var(--kyro-border)] rounded-lg p-6 max-w-2xl shadow-sm transition-colors duration-300", children: [
|
|
9652
9515
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-2", children: [
|
|
@@ -9755,8 +9618,6 @@ function AutoForm({
|
|
|
9755
9618
|
setAutoSaveStatus,
|
|
9756
9619
|
fetchVersions,
|
|
9757
9620
|
saveDocument,
|
|
9758
|
-
publishDocument,
|
|
9759
|
-
clearDraftArtifacts,
|
|
9760
9621
|
autoSaveSkipRef,
|
|
9761
9622
|
lastAutoSaveTimeRef,
|
|
9762
9623
|
documentStatus,
|
|
@@ -9774,7 +9635,13 @@ function AutoForm({
|
|
|
9774
9635
|
const menuRef = useRef(null);
|
|
9775
9636
|
const scheduleRef = useRef(null);
|
|
9776
9637
|
const [showSchedulePicker, setShowSchedulePicker] = useState(false);
|
|
9638
|
+
const [localSaveStatus, setLocalSaveStatus] = useState("idle");
|
|
9639
|
+
const [now, setNow] = useState(Date.now());
|
|
9777
9640
|
const disabled = propDisabled;
|
|
9641
|
+
useEffect(() => {
|
|
9642
|
+
const id = setInterval(() => setNow(Date.now()), 1e4);
|
|
9643
|
+
return () => clearInterval(id);
|
|
9644
|
+
}, []);
|
|
9778
9645
|
const resolveAdminFlag = (value, currentData) => {
|
|
9779
9646
|
if (typeof value === "function") {
|
|
9780
9647
|
try {
|
|
@@ -9969,18 +9836,16 @@ function AutoForm({
|
|
|
9969
9836
|
message: "Unpublish this document?",
|
|
9970
9837
|
onConfirm: async () => {
|
|
9971
9838
|
try {
|
|
9972
|
-
const response = await
|
|
9973
|
-
|
|
9974
|
-
|
|
9975
|
-
method: "POST"
|
|
9976
|
-
}
|
|
9839
|
+
const response = await saveDocument(
|
|
9840
|
+
{ ...formData, status: "draft" },
|
|
9841
|
+
false
|
|
9977
9842
|
);
|
|
9978
|
-
if (response
|
|
9843
|
+
if (response?.ok) {
|
|
9979
9844
|
onActionSuccess?.("Document unpublished successfully");
|
|
9980
9845
|
location.reload();
|
|
9981
9846
|
} else {
|
|
9982
|
-
const error = await response
|
|
9983
|
-
toast.error(error
|
|
9847
|
+
const error = await response?.json().catch(() => ({}));
|
|
9848
|
+
toast.error(error?.error || "Failed to unpublish");
|
|
9984
9849
|
}
|
|
9985
9850
|
} catch (err) {
|
|
9986
9851
|
toast.error("Failed to unpublish");
|
|
@@ -9991,12 +9856,7 @@ function AutoForm({
|
|
|
9991
9856
|
const handleSaveDraft = async () => {
|
|
9992
9857
|
const isNewDoc = !formData.id;
|
|
9993
9858
|
autoSaveSkipRef.current = true;
|
|
9994
|
-
|
|
9995
|
-
const originalText = btn?.textContent || "";
|
|
9996
|
-
if (btn) {
|
|
9997
|
-
btn.textContent = "Saving...";
|
|
9998
|
-
btn.setAttribute("disabled", "true");
|
|
9999
|
-
}
|
|
9859
|
+
setLocalSaveStatus("saving");
|
|
10000
9860
|
try {
|
|
10001
9861
|
const data = normalizeUploadFields({ ...formData });
|
|
10002
9862
|
const isPost = isNewDoc && !globalSlug;
|
|
@@ -10012,9 +9872,12 @@ function AutoForm({
|
|
|
10012
9872
|
setLastSavedData({ ...formData, ...savedData });
|
|
10013
9873
|
lastAutoSaveTimeRef.current = Date.now();
|
|
10014
9874
|
setAutoSaveStatus("success");
|
|
10015
|
-
|
|
9875
|
+
setLocalSaveStatus("saved");
|
|
10016
9876
|
if (versionsEnabled) fetchVersions();
|
|
10017
|
-
setTimeout(() =>
|
|
9877
|
+
setTimeout(() => {
|
|
9878
|
+
setAutoSaveStatus("idle");
|
|
9879
|
+
setLocalSaveStatus("idle");
|
|
9880
|
+
}, 2e3);
|
|
10018
9881
|
onActionSuccess?.(
|
|
10019
9882
|
isPost ? "Document created successfully" : "Changes saved"
|
|
10020
9883
|
);
|
|
@@ -10028,78 +9891,63 @@ function AutoForm({
|
|
|
10028
9891
|
if (response.status === 409) {
|
|
10029
9892
|
setAutoSaveStatus("conflict");
|
|
10030
9893
|
}
|
|
9894
|
+
setLocalSaveStatus("error");
|
|
10031
9895
|
toast.error(error.error || "Failed to save");
|
|
9896
|
+
setTimeout(() => setLocalSaveStatus("idle"), 3e3);
|
|
10032
9897
|
}
|
|
10033
9898
|
} catch (err) {
|
|
9899
|
+
setLocalSaveStatus("error");
|
|
10034
9900
|
toast.error("Failed to save document");
|
|
9901
|
+
setTimeout(() => setLocalSaveStatus("idle"), 3e3);
|
|
10035
9902
|
} finally {
|
|
10036
9903
|
autoSaveSkipRef.current = false;
|
|
10037
|
-
if (btn) {
|
|
10038
|
-
btn.textContent = originalText;
|
|
10039
|
-
btn.removeAttribute("disabled");
|
|
10040
|
-
}
|
|
10041
9904
|
}
|
|
10042
9905
|
};
|
|
10043
9906
|
const handlePublish = async () => {
|
|
10044
9907
|
const isNewDoc = !formData.id;
|
|
10045
9908
|
autoSaveSkipRef.current = true;
|
|
10046
|
-
|
|
10047
|
-
const originalText = btn?.textContent || "";
|
|
10048
|
-
if (btn) {
|
|
10049
|
-
btn.textContent = "Publishing...";
|
|
10050
|
-
btn.setAttribute("disabled", "true");
|
|
10051
|
-
}
|
|
9909
|
+
setLocalSaveStatus("saving");
|
|
10052
9910
|
try {
|
|
10053
9911
|
if (isNewDoc && !globalSlug) {
|
|
10054
|
-
const
|
|
9912
|
+
const data2 = normalizeUploadFields({ ...formData });
|
|
10055
9913
|
const response2 = await fetchWithAuth(`/api/${collectionSlug}`, {
|
|
10056
9914
|
method: "POST",
|
|
10057
9915
|
headers: { "Content-Type": "application/json" },
|
|
10058
|
-
body: JSON.stringify(
|
|
9916
|
+
body: JSON.stringify(data2)
|
|
10059
9917
|
});
|
|
10060
9918
|
if (!response2.ok) {
|
|
10061
9919
|
const error = await response2.json().catch(() => ({}));
|
|
10062
9920
|
if (response2.status === 409) setAutoSaveStatus("conflict");
|
|
9921
|
+
setLocalSaveStatus("error");
|
|
10063
9922
|
toast.error(error.error || "Failed to create document");
|
|
9923
|
+
setTimeout(() => setLocalSaveStatus("idle"), 3e3);
|
|
10064
9924
|
return;
|
|
10065
9925
|
}
|
|
10066
9926
|
const result = await response2.json();
|
|
10067
|
-
const savedData = result.data ||
|
|
9927
|
+
const savedData = result.data || data2;
|
|
10068
9928
|
setFormData({ ...formData, ...savedData });
|
|
10069
9929
|
setLastSavedData({ ...formData, ...savedData });
|
|
10070
|
-
} else if (hasUnsavedChanges) {
|
|
10071
|
-
const response2 = await saveDocument(formData);
|
|
10072
|
-
if (!response2.ok) {
|
|
10073
|
-
const error = await response2.json().catch(() => ({}));
|
|
10074
|
-
if (response2.status === 409) setAutoSaveStatus("conflict");
|
|
10075
|
-
toast.error(error.error || "Failed to save before publishing");
|
|
10076
|
-
return;
|
|
10077
|
-
}
|
|
10078
|
-
const result = await response2.json();
|
|
10079
|
-
if (result.data) {
|
|
10080
|
-
setFormData({ ...formData, ...result.data });
|
|
10081
|
-
setLastSavedData({ ...formData, ...result.data });
|
|
10082
|
-
}
|
|
10083
9930
|
}
|
|
10084
|
-
const
|
|
10085
|
-
|
|
10086
|
-
|
|
9931
|
+
const data = normalizeUploadFields({ ...formData });
|
|
9932
|
+
const response = await saveDocument(data, false);
|
|
9933
|
+
if (response?.ok) {
|
|
9934
|
+
setLocalSaveStatus("saved");
|
|
10087
9935
|
onActionSuccess?.("Published successfully");
|
|
10088
|
-
await new Promise((r) => setTimeout(r,
|
|
9936
|
+
await new Promise((r) => setTimeout(r, 1e3));
|
|
10089
9937
|
location.reload();
|
|
10090
9938
|
} else {
|
|
10091
|
-
const error = await response
|
|
10092
|
-
if (response
|
|
10093
|
-
|
|
9939
|
+
const error = await response?.json().catch(() => ({}));
|
|
9940
|
+
if (response?.status === 409) setAutoSaveStatus("conflict");
|
|
9941
|
+
setLocalSaveStatus("error");
|
|
9942
|
+
toast.error(error?.error || "Failed to publish");
|
|
9943
|
+
setTimeout(() => setLocalSaveStatus("idle"), 3e3);
|
|
10094
9944
|
}
|
|
10095
9945
|
} catch (err) {
|
|
9946
|
+
setLocalSaveStatus("error");
|
|
10096
9947
|
toast.error("Failed to publish");
|
|
9948
|
+
setTimeout(() => setLocalSaveStatus("idle"), 3e3);
|
|
10097
9949
|
} finally {
|
|
10098
9950
|
autoSaveSkipRef.current = false;
|
|
10099
|
-
if (btn) {
|
|
10100
|
-
btn.textContent = originalText;
|
|
10101
|
-
btn.removeAttribute("disabled");
|
|
10102
|
-
}
|
|
10103
9951
|
}
|
|
10104
9952
|
};
|
|
10105
9953
|
const handleSchedulePublish = async (scheduledFor) => {
|
|
@@ -10416,12 +10264,12 @@ function AutoForm({
|
|
|
10416
10264
|
const docTitle = String(
|
|
10417
10265
|
formData.mainTabs?.title || (typeof formData.title === "object" ? "" : formData.title) || (typeof formData.name === "object" ? "" : formData.name) || "Untitled"
|
|
10418
10266
|
);
|
|
10419
|
-
const docStatus = documentStatus ?? formData.
|
|
10267
|
+
const docStatus = documentStatus ?? formData.status ?? "draft";
|
|
10420
10268
|
const isNew = !formData.id;
|
|
10421
10269
|
const lastModified = formData.updatedAt ? new Date(formData.updatedAt).toLocaleString() : "Just now";
|
|
10422
10270
|
const createdAt = formData.createdAt ? new Date(formData.createdAt).toLocaleString() : "Just now";
|
|
10423
|
-
|
|
10424
|
-
const statusLabel = hasUnpublishedChanges ?
|
|
10271
|
+
!formData.id || documentStatus === "draft";
|
|
10272
|
+
const statusLabel = hasUnpublishedChanges ? "Draft (unpublished changes)" : docStatus === "published" ? "Published" : "Draft";
|
|
10425
10273
|
const statusColor = docStatus === "published" && !hasUnsavedChanges ? "bg-[var(--kyro-success)]" : hasUnpublishedChanges ? "bg-[var(--kyro-warning)]" : "bg-[var(--kyro-text-muted)]";
|
|
10426
10274
|
const statusBadgeBg = docStatus === "published" && !hasUnpublishedChanges ? "bg-[var(--kyro-success)]/10 text-[var(--kyro-success)] border-[var(--kyro-success)]/20" : hasUnpublishedChanges ? "bg-[var(--kyro-warning)]/10 text-[var(--kyro-warning)] border-[var(--kyro-warning)]/20" : "bg-[var(--kyro-text-muted)]/10 text-[var(--kyro-text-muted)] border-[var(--kyro-text-muted)]/20";
|
|
10427
10275
|
return /* @__PURE__ */ jsxs("header", { className: "surface-tile px-8 py-6 flex items-center justify-between sticky top-0 z-50 border-b border-[var(--kyro-border)] mb-8 bg-[var(--kyro-surface)] backdrop-blur-md", children: [
|
|
@@ -10432,24 +10280,7 @@ function AutoForm({
|
|
|
10432
10280
|
{
|
|
10433
10281
|
href: `/${collectionSlug}`,
|
|
10434
10282
|
className: "p-2 border border-[var(--kyro-border)] rounded-xl hover:bg-[var(--kyro-bg-secondary)] transition-colors",
|
|
10435
|
-
children: /* @__PURE__ */ jsx(
|
|
10436
|
-
"svg",
|
|
10437
|
-
{
|
|
10438
|
-
className: "w-4 h-4",
|
|
10439
|
-
fill: "none",
|
|
10440
|
-
stroke: "currentColor",
|
|
10441
|
-
viewBox: "0 0 24 24",
|
|
10442
|
-
children: /* @__PURE__ */ jsx(
|
|
10443
|
-
"path",
|
|
10444
|
-
{
|
|
10445
|
-
strokeLinecap: "round",
|
|
10446
|
-
strokeLinejoin: "round",
|
|
10447
|
-
strokeWidth: "2.5",
|
|
10448
|
-
d: "M15 19l-7-7 7-7"
|
|
10449
|
-
}
|
|
10450
|
-
)
|
|
10451
|
-
}
|
|
10452
|
-
)
|
|
10283
|
+
children: /* @__PURE__ */ jsx(ChevronRight, { className: "w-4 h-4" })
|
|
10453
10284
|
}
|
|
10454
10285
|
),
|
|
10455
10286
|
/* @__PURE__ */ jsx("h1", { className: "text-xl font-bold tracking-tighter", children: docTitle }),
|
|
@@ -10492,18 +10323,7 @@ function AutoForm({
|
|
|
10492
10323
|
"Saving draft..."
|
|
10493
10324
|
] }),
|
|
10494
10325
|
autoSaveStatus === "success" && /* @__PURE__ */ jsxs("span", { className: "text-[var(--kyro-success)] flex items-center gap-1", children: [
|
|
10495
|
-
/* @__PURE__ */ jsx(
|
|
10496
|
-
"svg",
|
|
10497
|
-
{
|
|
10498
|
-
width: "12",
|
|
10499
|
-
height: "12",
|
|
10500
|
-
viewBox: "0 0 24 24",
|
|
10501
|
-
fill: "none",
|
|
10502
|
-
stroke: "currentColor",
|
|
10503
|
-
strokeWidth: "3",
|
|
10504
|
-
children: /* @__PURE__ */ jsx("path", { d: "M20 6L9 17l-5-5" })
|
|
10505
|
-
}
|
|
10506
|
-
),
|
|
10326
|
+
/* @__PURE__ */ jsx(Check, { className: "w-4 h-4" }),
|
|
10507
10327
|
lastSavedAt ? `Saved ${Math.floor((Date.now() - lastSavedAt) / 6e4)}m ago` : "Draft saved"
|
|
10508
10328
|
] }),
|
|
10509
10329
|
autoSaveStatus === "retrying" && /* @__PURE__ */ jsxs("span", { className: "text-[var(--kyro-warning)] flex items-center gap-1.5", children: [
|
|
@@ -10563,13 +10383,23 @@ function AutoForm({
|
|
|
10563
10383
|
onClick: async () => {
|
|
10564
10384
|
setFormData(lastSavedData);
|
|
10565
10385
|
markSaved();
|
|
10566
|
-
await clearDraftArtifacts();
|
|
10567
10386
|
},
|
|
10568
10387
|
className: "text-[var(--kyro-primary)] hover:underline",
|
|
10569
10388
|
children: "Revert changes"
|
|
10570
10389
|
}
|
|
10571
10390
|
)
|
|
10572
10391
|
] }),
|
|
10392
|
+
lastSavedAt && autoSaveStatus !== "saving" && autoSaveStatus !== "retrying" && autoSaveStatus !== "success" && /* @__PURE__ */ jsxs("span", { className: "border-l border-[var(--kyro-border)] pl-4", children: [
|
|
10393
|
+
"Draft saved ",
|
|
10394
|
+
(() => {
|
|
10395
|
+
const diffMs = now - lastSavedAt;
|
|
10396
|
+
const diffMin = Math.floor(diffMs / 6e4);
|
|
10397
|
+
const diffSec = Math.floor(diffMs / 1e3);
|
|
10398
|
+
if (diffMin >= 1) return `${diffMin}m ago`;
|
|
10399
|
+
if (diffSec >= 5) return `${diffSec}s ago`;
|
|
10400
|
+
return "just now";
|
|
10401
|
+
})()
|
|
10402
|
+
] }),
|
|
10573
10403
|
/* @__PURE__ */ jsxs("span", { className: "border-l border-[var(--kyro-border)] pl-4", children: [
|
|
10574
10404
|
"Modified ",
|
|
10575
10405
|
lastModified
|
|
@@ -10601,18 +10431,7 @@ function AutoForm({
|
|
|
10601
10431
|
className: `kyro-btn p-2.5 rounded-xl transition-all flex items-center gap-2 ${showPreview ? "shadow-lg" : "text-[var(--kyro-text-secondary)] hover:bg-[var(--kyro-bg-secondary)]"}`,
|
|
10602
10432
|
title: "Live Preview",
|
|
10603
10433
|
children: [
|
|
10604
|
-
/* @__PURE__ */ jsx(
|
|
10605
|
-
"svg",
|
|
10606
|
-
{
|
|
10607
|
-
width: "20",
|
|
10608
|
-
height: "20",
|
|
10609
|
-
viewBox: "0 0 24 24",
|
|
10610
|
-
fill: "none",
|
|
10611
|
-
stroke: "currentColor",
|
|
10612
|
-
strokeWidth: "2",
|
|
10613
|
-
children: /* @__PURE__ */ jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6M15 3h6v6M10 14L21 3" })
|
|
10614
|
-
}
|
|
10615
|
-
),
|
|
10434
|
+
/* @__PURE__ */ jsx(ExternalLink, { className: "w-4 h-4" }),
|
|
10616
10435
|
showPreview && /* @__PURE__ */ jsx("span", { className: "text-[10px] font-bold tracking-widest pr-1", children: "Active" })
|
|
10617
10436
|
]
|
|
10618
10437
|
}
|
|
@@ -10643,164 +10462,98 @@ function AutoForm({
|
|
|
10643
10462
|
)
|
|
10644
10463
|
}
|
|
10645
10464
|
),
|
|
10646
|
-
|
|
10647
|
-
|
|
10648
|
-
|
|
10649
|
-
|
|
10650
|
-
|
|
10651
|
-
|
|
10465
|
+
/* @__PURE__ */ jsx(
|
|
10466
|
+
SplitButton,
|
|
10467
|
+
{
|
|
10468
|
+
status: documentStatus,
|
|
10469
|
+
saveStatus: localSaveStatus,
|
|
10470
|
+
hasChanges: hasUnsavedChanges,
|
|
10471
|
+
onPublish: handlePublish,
|
|
10472
|
+
disabled: localSaveStatus === "saving"
|
|
10473
|
+
}
|
|
10474
|
+
),
|
|
10475
|
+
!isNew && /* @__PURE__ */ jsxs(
|
|
10476
|
+
Dropdown,
|
|
10477
|
+
{
|
|
10478
|
+
trigger: /* @__PURE__ */ jsx(
|
|
10652
10479
|
"button",
|
|
10653
10480
|
{
|
|
10654
|
-
id: "btn-publish",
|
|
10655
10481
|
type: "button",
|
|
10656
|
-
|
|
10657
|
-
|
|
10658
|
-
children:
|
|
10482
|
+
className: "kyro-btn p-2.5 rounded-xl border border-[var(--kyro-border)] hover:bg-[var(--kyro-bg-secondary)] transition-all",
|
|
10483
|
+
title: "More actions",
|
|
10484
|
+
children: /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: [
|
|
10485
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "5", r: "1.5" }),
|
|
10486
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "1.5" }),
|
|
10487
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "19", r: "1.5" })
|
|
10488
|
+
] })
|
|
10659
10489
|
}
|
|
10660
10490
|
),
|
|
10661
|
-
|
|
10662
|
-
|
|
10663
|
-
|
|
10664
|
-
|
|
10665
|
-
|
|
10666
|
-
|
|
10667
|
-
|
|
10668
|
-
|
|
10669
|
-
|
|
10670
|
-
] }),
|
|
10671
|
-
isMenuOpen && /* @__PURE__ */ jsxs("div", { className: "absolute right-0 top-full mt-2 w-56 rounded-lg border border-[var(--kyro-border)] bg-[var(--kyro-surface)] shadow-2xl z-50 overflow-hidden", children: [
|
|
10672
|
-
/* @__PURE__ */ jsxs(
|
|
10673
|
-
"button",
|
|
10674
|
-
{
|
|
10675
|
-
type: "button",
|
|
10676
|
-
onClick: () => {
|
|
10677
|
-
handleSaveDraft();
|
|
10678
|
-
setIsMenuOpen(false);
|
|
10679
|
-
},
|
|
10680
|
-
className: "w-full px-4 py-2.5 text-left text-xs font-medium text-[var(--kyro-text-primary)] hover:bg-[var(--kyro-surface-accent)] flex items-center gap-3 transition-colors",
|
|
10681
|
-
children: [
|
|
10682
|
-
/* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
10683
|
-
/* @__PURE__ */ jsx("path", { d: "M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z" }),
|
|
10684
|
-
/* @__PURE__ */ jsx("polyline", { points: "17 21 17 13 7 13 7 21" }),
|
|
10685
|
-
/* @__PURE__ */ jsx("polyline", { points: "7 3 7 8 15 8" })
|
|
10491
|
+
direction: "down",
|
|
10492
|
+
children: [
|
|
10493
|
+
!globalSlug && /* @__PURE__ */ jsx(
|
|
10494
|
+
DropdownItem,
|
|
10495
|
+
{
|
|
10496
|
+
onClick: handleCreateNew,
|
|
10497
|
+
icon: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
10498
|
+
/* @__PURE__ */ jsx("line", { x1: "12", y1: "5", x2: "12", y2: "19" }),
|
|
10499
|
+
/* @__PURE__ */ jsx("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
|
|
10686
10500
|
] }),
|
|
10687
|
-
"
|
|
10688
|
-
|
|
10689
|
-
|
|
10690
|
-
|
|
10691
|
-
|
|
10692
|
-
|
|
10693
|
-
|
|
10694
|
-
|
|
10695
|
-
|
|
10696
|
-
|
|
10697
|
-
|
|
10698
|
-
|
|
10699
|
-
|
|
10700
|
-
|
|
10701
|
-
|
|
10702
|
-
|
|
10703
|
-
|
|
10704
|
-
|
|
10705
|
-
|
|
10706
|
-
/* @__PURE__ */ jsxs(
|
|
10707
|
-
"button",
|
|
10708
|
-
{
|
|
10709
|
-
type: "button",
|
|
10710
|
-
onClick: () => {
|
|
10711
|
-
setIsMenuOpen(false);
|
|
10712
|
-
setShowSchedulePicker(true);
|
|
10713
|
-
},
|
|
10714
|
-
className: "w-full px-4 py-2.5 text-left text-xs font-medium text-[var(--kyro-text-primary)] hover:bg-[var(--kyro-surface-accent)] flex items-center gap-3 transition-colors",
|
|
10715
|
-
children: [
|
|
10716
|
-
/* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
10501
|
+
children: "Create New"
|
|
10502
|
+
}
|
|
10503
|
+
),
|
|
10504
|
+
!globalSlug && /* @__PURE__ */ jsx(
|
|
10505
|
+
DropdownItem,
|
|
10506
|
+
{
|
|
10507
|
+
onClick: handleDuplicate,
|
|
10508
|
+
icon: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
10509
|
+
/* @__PURE__ */ jsx("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", ry: "2" }),
|
|
10510
|
+
/* @__PURE__ */ jsx("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
|
|
10511
|
+
] }),
|
|
10512
|
+
children: "Duplicate"
|
|
10513
|
+
}
|
|
10514
|
+
),
|
|
10515
|
+
/* @__PURE__ */ jsx(
|
|
10516
|
+
DropdownItem,
|
|
10517
|
+
{
|
|
10518
|
+
onClick: () => setShowSchedulePicker(true),
|
|
10519
|
+
icon: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
10717
10520
|
/* @__PURE__ */ jsx("rect", { x: "3", y: "4", width: "18", height: "18", rx: "2", ry: "2" }),
|
|
10718
10521
|
/* @__PURE__ */ jsx("line", { x1: "16", y1: "2", x2: "16", y2: "6" }),
|
|
10719
10522
|
/* @__PURE__ */ jsx("line", { x1: "8", y1: "2", x2: "8", y2: "6" }),
|
|
10720
10523
|
/* @__PURE__ */ jsx("line", { x1: "3", y1: "10", x2: "21", y2: "10" })
|
|
10721
10524
|
] }),
|
|
10722
|
-
"Schedule Publish"
|
|
10723
|
-
]
|
|
10724
|
-
}
|
|
10725
|
-
),
|
|
10726
|
-
/* @__PURE__ */ jsx("div", { className: "h-px bg-[var(--kyro-border)]" }),
|
|
10727
|
-
!globalSlug && /* @__PURE__ */ jsxs(
|
|
10728
|
-
"button",
|
|
10729
|
-
{
|
|
10730
|
-
type: "button",
|
|
10731
|
-
onClick: () => {
|
|
10732
|
-
handleCreateNew();
|
|
10733
|
-
setIsMenuOpen(false);
|
|
10734
|
-
},
|
|
10735
|
-
className: "w-full px-4 py-2.5 text-left text-xs font-medium text-[var(--kyro-text-primary)] hover:bg-[var(--kyro-surface-accent)] flex items-center gap-3 transition-colors",
|
|
10736
|
-
children: [
|
|
10737
|
-
/* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
10738
|
-
/* @__PURE__ */ jsx("line", { x1: "12", y1: "5", x2: "12", y2: "19" }),
|
|
10739
|
-
/* @__PURE__ */ jsx("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
|
|
10740
|
-
] }),
|
|
10741
|
-
"Create New"
|
|
10742
|
-
]
|
|
10743
|
-
}
|
|
10744
|
-
),
|
|
10745
|
-
!isNew && !globalSlug && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
10746
|
-
/* @__PURE__ */ jsxs(
|
|
10747
|
-
"button",
|
|
10748
|
-
{
|
|
10749
|
-
type: "button",
|
|
10750
|
-
onClick: () => {
|
|
10751
|
-
handleDuplicate();
|
|
10752
|
-
setIsMenuOpen(false);
|
|
10753
|
-
},
|
|
10754
|
-
className: "w-full px-4 py-2.5 text-left text-xs font-medium text-[var(--kyro-text-primary)] hover:bg-[var(--kyro-surface-accent)] flex items-center gap-3 transition-colors",
|
|
10755
|
-
children: [
|
|
10756
|
-
/* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
10757
|
-
/* @__PURE__ */ jsx("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", ry: "2" }),
|
|
10758
|
-
/* @__PURE__ */ jsx("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
|
|
10759
|
-
] }),
|
|
10760
|
-
"Duplicate"
|
|
10761
|
-
]
|
|
10525
|
+
children: "Schedule Publish"
|
|
10762
10526
|
}
|
|
10763
10527
|
),
|
|
10764
|
-
documentStatus === "published" && /* @__PURE__ */
|
|
10765
|
-
|
|
10528
|
+
documentStatus === "published" && /* @__PURE__ */ jsx(
|
|
10529
|
+
DropdownItem,
|
|
10766
10530
|
{
|
|
10767
|
-
|
|
10768
|
-
|
|
10769
|
-
|
|
10770
|
-
|
|
10771
|
-
},
|
|
10772
|
-
|
|
10773
|
-
children: [
|
|
10774
|
-
/* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
10775
|
-
/* @__PURE__ */ jsx("path", { d: "M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24" }),
|
|
10776
|
-
/* @__PURE__ */ jsx("line", { x1: "1", y1: "1", x2: "23", y2: "23" })
|
|
10777
|
-
] }),
|
|
10778
|
-
"Unpublish"
|
|
10779
|
-
]
|
|
10531
|
+
onClick: handleUnpublish,
|
|
10532
|
+
icon: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
10533
|
+
/* @__PURE__ */ jsx("path", { d: "M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24" }),
|
|
10534
|
+
/* @__PURE__ */ jsx("line", { x1: "1", y1: "1", x2: "23", y2: "23" })
|
|
10535
|
+
] }),
|
|
10536
|
+
children: "Unpublish"
|
|
10780
10537
|
}
|
|
10781
10538
|
),
|
|
10782
|
-
/* @__PURE__ */
|
|
10783
|
-
|
|
10784
|
-
|
|
10785
|
-
|
|
10786
|
-
|
|
10787
|
-
|
|
10788
|
-
|
|
10789
|
-
|
|
10790
|
-
},
|
|
10791
|
-
className: "w-full px-4 py-2.5 text-left text-xs font-medium text-red-600 hover:bg-red-50 flex items-center gap-3 transition-colors",
|
|
10792
|
-
children: [
|
|
10793
|
-
/* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
10539
|
+
!globalSlug && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
10540
|
+
/* @__PURE__ */ jsx(DropdownSeparator, {}),
|
|
10541
|
+
/* @__PURE__ */ jsx(
|
|
10542
|
+
DropdownItem,
|
|
10543
|
+
{
|
|
10544
|
+
onClick: handleDelete,
|
|
10545
|
+
danger: true,
|
|
10546
|
+
icon: /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
10794
10547
|
/* @__PURE__ */ jsx("polyline", { points: "3 6 5 6 21 6" }),
|
|
10795
10548
|
/* @__PURE__ */ jsx("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })
|
|
10796
10549
|
] }),
|
|
10797
|
-
"Delete"
|
|
10798
|
-
|
|
10799
|
-
|
|
10800
|
-
)
|
|
10801
|
-
]
|
|
10802
|
-
|
|
10803
|
-
|
|
10550
|
+
children: "Delete"
|
|
10551
|
+
}
|
|
10552
|
+
)
|
|
10553
|
+
] })
|
|
10554
|
+
]
|
|
10555
|
+
}
|
|
10556
|
+
),
|
|
10804
10557
|
showSchedulePicker && /* @__PURE__ */ jsx("div", { ref: scheduleRef, className: "relative", children: /* @__PURE__ */ jsxs("div", { className: "absolute right-0 top-2 p-4 rounded-lg border border-[var(--kyro-border)] bg-[var(--kyro-surface)] shadow-2xl z-50", children: [
|
|
10805
10558
|
/* @__PURE__ */ jsx("p", { className: "text-xs font-medium mb-2", children: "Schedule Publish" }),
|
|
10806
10559
|
/* @__PURE__ */ jsx(
|
|
@@ -10920,17 +10673,7 @@ function AutoForm({
|
|
|
10920
10673
|
type: "button",
|
|
10921
10674
|
onClick: () => setCompareDiffs([]),
|
|
10922
10675
|
className: "p-1 rounded hover:bg-[var(--kyro-surface-accent)] text-[var(--kyro-text-muted)]",
|
|
10923
|
-
children: /* @__PURE__ */ jsx(
|
|
10924
|
-
"svg",
|
|
10925
|
-
{
|
|
10926
|
-
className: "w-3.5 h-3.5",
|
|
10927
|
-
viewBox: "0 0 24 24",
|
|
10928
|
-
fill: "none",
|
|
10929
|
-
stroke: "currentColor",
|
|
10930
|
-
strokeWidth: "2.5",
|
|
10931
|
-
children: /* @__PURE__ */ jsx("path", { d: "M18 6L6 18M6 6l12 12" })
|
|
10932
|
-
}
|
|
10933
|
-
)
|
|
10676
|
+
children: /* @__PURE__ */ jsx(X, { className: "w-4 h-4" })
|
|
10934
10677
|
}
|
|
10935
10678
|
)
|
|
10936
10679
|
] }),
|
|
@@ -10961,17 +10704,7 @@ function AutoForm({
|
|
|
10961
10704
|
"div",
|
|
10962
10705
|
{
|
|
10963
10706
|
className: `w-4 h-4 rounded-full border ${isSelected ? "border-[var(--kyro-primary)] bg-[var(--kyro-primary)]" : "border-[var(--kyro-border)]"}`,
|
|
10964
|
-
children: isSelected && /* @__PURE__ */ jsx(
|
|
10965
|
-
"svg",
|
|
10966
|
-
{
|
|
10967
|
-
className: "w-full h-full text-white p-0.5",
|
|
10968
|
-
viewBox: "0 0 24 24",
|
|
10969
|
-
fill: "none",
|
|
10970
|
-
stroke: "currentColor",
|
|
10971
|
-
strokeWidth: "3",
|
|
10972
|
-
children: /* @__PURE__ */ jsx("path", { d: "M20 6L9 17l-5-5" })
|
|
10973
|
-
}
|
|
10974
|
-
)
|
|
10707
|
+
children: isSelected && /* @__PURE__ */ jsx(Check, { className: "w-4 h-4" })
|
|
10975
10708
|
}
|
|
10976
10709
|
) : /* @__PURE__ */ jsx("span", { className: "text-[10px] font-bold text-[var(--kyro-text-muted)] w-5", children: versions.length - i }) }),
|
|
10977
10710
|
/* @__PURE__ */ jsxs("div", { className: "col-span-4 min-w-0", children: [
|
|
@@ -11064,18 +10797,7 @@ function AutoForm({
|
|
|
11064
10797
|
"div",
|
|
11065
10798
|
{
|
|
11066
10799
|
className: `w-4 h-4 rounded border transition-all flex items-center justify-center ${item.checked ? "bg-[var(--kyro-primary)] border-[var(--kyro-primary)]" : "border-[var(--kyro-border)] group-hover:border-[var(--kyro-text-secondary)]"}`,
|
|
11067
|
-
children: item.checked && /* @__PURE__ */ jsx(
|
|
11068
|
-
"svg",
|
|
11069
|
-
{
|
|
11070
|
-
width: "10",
|
|
11071
|
-
height: "10",
|
|
11072
|
-
viewBox: "0 0 24 24",
|
|
11073
|
-
fill: "none",
|
|
11074
|
-
stroke: "white",
|
|
11075
|
-
strokeWidth: "4",
|
|
11076
|
-
children: /* @__PURE__ */ jsx("path", { d: "M20 6L9 17l-5-5" })
|
|
11077
|
-
}
|
|
11078
|
-
)
|
|
10800
|
+
children: item.checked && /* @__PURE__ */ jsx(Check, { className: "w-4 h-4" })
|
|
11079
10801
|
}
|
|
11080
10802
|
),
|
|
11081
10803
|
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-[var(--kyro-text-secondary)] group-hover:text-[var(--kyro-text-primary)] transition-colors", children: item.label })
|
|
@@ -11110,7 +10832,7 @@ function AutoForm({
|
|
|
11110
10832
|
"Saving..."
|
|
11111
10833
|
] }),
|
|
11112
10834
|
autoSaveStatus === "success" && /* @__PURE__ */ jsxs("span", { className: "text-[var(--kyro-success)] flex items-center gap-1", children: [
|
|
11113
|
-
/* @__PURE__ */ jsx(
|
|
10835
|
+
/* @__PURE__ */ jsx(Check, { className: "w-4 h-4" }),
|
|
11114
10836
|
lastSavedAt ? `Saved ${Math.floor((Date.now() - lastSavedAt) / 6e4)}m ago` : "Saved"
|
|
11115
10837
|
] }),
|
|
11116
10838
|
autoSaveStatus === "retrying" && /* @__PURE__ */ jsxs("span", { className: "text-[var(--kyro-warning)] flex items-center gap-1.5", children: [
|
|
@@ -11135,85 +10857,29 @@ function AutoForm({
|
|
|
11135
10857
|
type: "button",
|
|
11136
10858
|
style: { width: 0, height: 0, opacity: 0, padding: 0, margin: 0, border: "none", position: "absolute" },
|
|
11137
10859
|
onClick: async () => {
|
|
11138
|
-
console.log("[AutoForm] Hidden save button clicked");
|
|
11139
10860
|
try {
|
|
11140
10861
|
const response = await saveDocument();
|
|
11141
10862
|
if (response.ok) {
|
|
11142
|
-
const result = await response.json();
|
|
11143
|
-
const savedData = result.data || formData;
|
|
11144
|
-
setFormData({ ...formData, ...savedData });
|
|
11145
|
-
setLastSavedData({ ...formData, ...savedData });
|
|
11146
|
-
onActionSuccess?.("Changes saved");
|
|
11147
|
-
}
|
|
11148
|
-
} catch (e) {
|
|
11149
|
-
console.error("Save error exception:", e);
|
|
11150
|
-
onActionError?.("Save failed: " + e.message);
|
|
11151
|
-
}
|
|
11152
|
-
}
|
|
11153
|
-
}
|
|
11154
|
-
)
|
|
11155
|
-
] }),
|
|
11156
|
-
/* @__PURE__ */ jsxs("main", { className: "w-full", children: [
|
|
11157
|
-
view === "edit" && renderEditView(),
|
|
11158
|
-
view === "version" && renderVersionView(),
|
|
11159
|
-
view === "api" && renderApiView()
|
|
11160
|
-
] })
|
|
11161
|
-
] });
|
|
11162
|
-
}
|
|
11163
|
-
function Dropdown({
|
|
11164
|
-
trigger,
|
|
11165
|
-
children,
|
|
11166
|
-
align = "right"
|
|
11167
|
-
}) {
|
|
11168
|
-
const [open, setOpen] = useState(false);
|
|
11169
|
-
const ref = useRef(null);
|
|
11170
|
-
useEffect(() => {
|
|
11171
|
-
const handleClickOutside = (e) => {
|
|
11172
|
-
if (ref.current && !ref.current.contains(e.target)) {
|
|
11173
|
-
setOpen(false);
|
|
11174
|
-
}
|
|
11175
|
-
};
|
|
11176
|
-
if (open) {
|
|
11177
|
-
document.addEventListener("mousedown", handleClickOutside);
|
|
11178
|
-
}
|
|
11179
|
-
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
11180
|
-
}, [open]);
|
|
11181
|
-
return /* @__PURE__ */ jsxs("div", { className: "relative", ref, children: [
|
|
11182
|
-
/* @__PURE__ */ jsx("div", { onClick: () => setOpen(!open), className: "cursor-pointer", children: trigger }),
|
|
11183
|
-
open && /* @__PURE__ */ jsx(
|
|
11184
|
-
"div",
|
|
11185
|
-
{
|
|
11186
|
-
className: `absolute z-[100] mt-2 min-w-[200px] py-2 bg-[var(--kyro-surface)] rounded-2xl shadow-2xl border border-[var(--kyro-border)] animate-in fade-in zoom-in-95 duration-100 ${align === "right" ? "right-0 bottom-full mb-2" : "left-0 bottom-full mb-2"}`,
|
|
11187
|
-
onClick: () => setOpen(false),
|
|
11188
|
-
children
|
|
11189
|
-
}
|
|
11190
|
-
)
|
|
11191
|
-
] });
|
|
11192
|
-
}
|
|
11193
|
-
function DropdownItem({
|
|
11194
|
-
children,
|
|
11195
|
-
onClick,
|
|
11196
|
-
icon,
|
|
11197
|
-
danger,
|
|
11198
|
-
disabled,
|
|
11199
|
-
className = ""
|
|
11200
|
-
}) {
|
|
11201
|
-
return /* @__PURE__ */ jsx("div", { className: "px-1.5", children: /* @__PURE__ */ jsxs(
|
|
11202
|
-
"button",
|
|
11203
|
-
{
|
|
11204
|
-
type: "button",
|
|
11205
|
-
onClick,
|
|
11206
|
-
disabled,
|
|
11207
|
-
className: `w-full flex items-center gap-3 px-3 py-2.5 text-[11px] font-medium tracking-wide text-left transition-all rounded-xl ${danger ? "text-red-500 hover:bg-red-500/10" : "text-[var(--kyro-text-secondary)] hover:text-[var(--kyro-text-primary)] hover:bg-[var(--kyro-surface-accent)]"} ${disabled ? "opacity-50 cursor-not-allowed" : ""} ${className}`,
|
|
11208
|
-
children: [
|
|
11209
|
-
icon && /* @__PURE__ */ jsx("span", { className: "w-4 h-4 opacity-70", children: icon }),
|
|
11210
|
-
/* @__PURE__ */ jsx("span", { className: "flex-1", children })
|
|
11211
|
-
]
|
|
11212
|
-
}
|
|
11213
|
-
) });
|
|
11214
|
-
}
|
|
11215
|
-
function DropdownSeparator() {
|
|
11216
|
-
return /* @__PURE__ */ jsx("div", { className: "my-1 border-t border-[var(--kyro-border)] opacity-50" });
|
|
10863
|
+
const result = await response.json();
|
|
10864
|
+
const savedData = result.data || formData;
|
|
10865
|
+
setFormData({ ...formData, ...savedData });
|
|
10866
|
+
setLastSavedData({ ...formData, ...savedData });
|
|
10867
|
+
onActionSuccess?.("Changes saved");
|
|
10868
|
+
}
|
|
10869
|
+
} catch (e) {
|
|
10870
|
+
console.error("Save error exception:", e);
|
|
10871
|
+
onActionError?.("Save failed: " + e.message);
|
|
10872
|
+
}
|
|
10873
|
+
}
|
|
10874
|
+
}
|
|
10875
|
+
)
|
|
10876
|
+
] }),
|
|
10877
|
+
/* @__PURE__ */ jsxs("main", { className: "w-full", children: [
|
|
10878
|
+
view === "edit" && renderEditView(),
|
|
10879
|
+
view === "version" && renderVersionView(),
|
|
10880
|
+
view === "api" && renderApiView()
|
|
10881
|
+
] })
|
|
10882
|
+
] });
|
|
11217
10883
|
}
|
|
11218
10884
|
function ActionBar({
|
|
11219
10885
|
status,
|
|
@@ -11236,82 +10902,27 @@ function ActionBar({
|
|
|
11236
10902
|
if (hasChanges) return "Unsaved changes";
|
|
11237
10903
|
return null;
|
|
11238
10904
|
};
|
|
11239
|
-
const getSaveButtonClass = () => {
|
|
11240
|
-
const base = "kyro-btn kyro-btn-md text-[11px] font-bold tracking-widest transition-all duration-300";
|
|
11241
|
-
if (saveStatus === "saving") return `${base} bg-[var(--kyro-gray-400)] text-white opacity-70 cursor-wait`;
|
|
11242
|
-
if (saveStatus === "saved") return `${base} bg-[var(--kyro-success)] border-[var(--kyro-success)] text-white shadow-[0_0_15px_rgba(34,197,94,0.3)]`;
|
|
11243
|
-
if (saveStatus === "error") return `${base} bg-[var(--kyro-error)] border-[var(--kyro-error)] text-white shadow-[0_0_15px_rgba(239,68,68,0.3)]`;
|
|
11244
|
-
if (hasChanges) return `${base} bg-[var(--kyro-warning)] border-[var(--kyro-warning)] text-black shadow-[0_0_15px_rgba(255,174,0,0.3)] animate-pulse`;
|
|
11245
|
-
return `${base} bg-[var(--kyro-gray-500)] border-[var(--kyro-gray-500)] text-white hover:bg-[var(--kyro-gray-600)]`;
|
|
11246
|
-
};
|
|
11247
10905
|
const getStatusBadge = () => {
|
|
11248
10906
|
const statusConfig2 = {
|
|
11249
10907
|
draft: {
|
|
11250
10908
|
label: "Draft",
|
|
11251
10909
|
class: "bg-gray-100 text-gray-600 border-gray-200",
|
|
11252
|
-
icon: /* @__PURE__ */ jsx(
|
|
11253
|
-
"svg",
|
|
11254
|
-
{
|
|
11255
|
-
width: "12",
|
|
11256
|
-
height: "12",
|
|
11257
|
-
viewBox: "0 0 24 24",
|
|
11258
|
-
fill: "none",
|
|
11259
|
-
stroke: "currentColor",
|
|
11260
|
-
strokeWidth: "2.5",
|
|
11261
|
-
children: /* @__PURE__ */ jsx("path", { d: "M12 2v20M2 12h20" })
|
|
11262
|
-
}
|
|
11263
|
-
)
|
|
10910
|
+
icon: /* @__PURE__ */ jsx(Plus, { className: "w-3 h-3" })
|
|
11264
10911
|
},
|
|
11265
10912
|
published: {
|
|
11266
10913
|
label: "Published",
|
|
11267
10914
|
class: "bg-green-100 text-green-700 border-green-200",
|
|
11268
|
-
icon: /* @__PURE__ */ jsx(
|
|
11269
|
-
"svg",
|
|
11270
|
-
{
|
|
11271
|
-
width: "12",
|
|
11272
|
-
height: "12",
|
|
11273
|
-
viewBox: "0 0 24 24",
|
|
11274
|
-
fill: "none",
|
|
11275
|
-
stroke: "currentColor",
|
|
11276
|
-
strokeWidth: "2.5",
|
|
11277
|
-
children: /* @__PURE__ */ jsx("path", { d: "M22 2L11 13M22 2l-7 20-4-9-9-4 20-7z" })
|
|
11278
|
-
}
|
|
11279
|
-
)
|
|
10915
|
+
icon: /* @__PURE__ */ jsx(Send, { className: "w-3 h-3" })
|
|
11280
10916
|
},
|
|
11281
10917
|
scheduled: {
|
|
11282
10918
|
label: "Scheduled",
|
|
11283
10919
|
class: "bg-blue-100 text-blue-700 border-blue-200",
|
|
11284
|
-
icon: /* @__PURE__ */
|
|
11285
|
-
"svg",
|
|
11286
|
-
{
|
|
11287
|
-
width: "12",
|
|
11288
|
-
height: "12",
|
|
11289
|
-
viewBox: "0 0 24 24",
|
|
11290
|
-
fill: "none",
|
|
11291
|
-
stroke: "currentColor",
|
|
11292
|
-
strokeWidth: "2.5",
|
|
11293
|
-
children: [
|
|
11294
|
-
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
|
|
11295
|
-
/* @__PURE__ */ jsx("path", { d: "M12 6v6l4 2" })
|
|
11296
|
-
]
|
|
11297
|
-
}
|
|
11298
|
-
)
|
|
10920
|
+
icon: /* @__PURE__ */ jsx(Clock, { className: "w-3 h-3" })
|
|
11299
10921
|
},
|
|
11300
10922
|
archived: {
|
|
11301
10923
|
label: "Archived",
|
|
11302
10924
|
class: "bg-yellow-100 text-yellow-700 border-yellow-200",
|
|
11303
|
-
icon: /* @__PURE__ */ jsx(
|
|
11304
|
-
"svg",
|
|
11305
|
-
{
|
|
11306
|
-
width: "12",
|
|
11307
|
-
height: "12",
|
|
11308
|
-
viewBox: "0 0 24 24",
|
|
11309
|
-
fill: "none",
|
|
11310
|
-
stroke: "currentColor",
|
|
11311
|
-
strokeWidth: "2.5",
|
|
11312
|
-
children: /* @__PURE__ */ jsx("path", { d: "M21 8v13H3V8M1 3h22v5H1zM10 12h4" })
|
|
11313
|
-
}
|
|
11314
|
-
)
|
|
10925
|
+
icon: /* @__PURE__ */ jsx(Archive, { className: "w-3 h-3" })
|
|
11315
10926
|
}
|
|
11316
10927
|
};
|
|
11317
10928
|
const config = statusConfig2[status];
|
|
@@ -11337,7 +10948,7 @@ function ActionBar({
|
|
|
11337
10948
|
getSaveStatusText() && /* @__PURE__ */ jsxs(
|
|
11338
10949
|
"span",
|
|
11339
10950
|
{
|
|
11340
|
-
className: `text-sm ${saveStatus === "error" ? "text-
|
|
10951
|
+
className: `text-sm ${saveStatus === "error" ? "text-[var(--kyro-error)]" : "text-[var(--kyro-text-muted)]"}`,
|
|
11341
10952
|
children: [
|
|
11342
10953
|
saveStatus === "saving" ? /* @__PURE__ */ jsx(Spinner, { size: "sm", className: "inline mr-1" }) : null,
|
|
11343
10954
|
getSaveStatusText()
|
|
@@ -11346,7 +10957,7 @@ function ActionBar({
|
|
|
11346
10957
|
)
|
|
11347
10958
|
] }),
|
|
11348
10959
|
/* @__PURE__ */ jsxs("div", { className: "text-xs space-y-0.5", children: [
|
|
11349
|
-
updatedAt && /* @__PURE__ */ jsxs("div", { className: "text-
|
|
10960
|
+
updatedAt && /* @__PURE__ */ jsxs("div", { className: "text-[var(--kyro-text-muted)]", children: [
|
|
11350
10961
|
"Updated: ",
|
|
11351
10962
|
formatDate2(updatedAt)
|
|
11352
10963
|
] }),
|
|
@@ -11363,20 +10974,9 @@ function ActionBar({
|
|
|
11363
10974
|
type: "button",
|
|
11364
10975
|
onClick: onPublish,
|
|
11365
10976
|
disabled: saveStatus === "saving",
|
|
11366
|
-
className: "kyro-btn
|
|
10977
|
+
className: "kyro-btn kyro-btn-primary kyro-btn-md flex items-center gap-2",
|
|
11367
10978
|
children: [
|
|
11368
|
-
/* @__PURE__ */ jsx(
|
|
11369
|
-
"svg",
|
|
11370
|
-
{
|
|
11371
|
-
width: "16",
|
|
11372
|
-
height: "16",
|
|
11373
|
-
viewBox: "0 0 24 24",
|
|
11374
|
-
fill: "none",
|
|
11375
|
-
stroke: "currentColor",
|
|
11376
|
-
strokeWidth: "2.5",
|
|
11377
|
-
children: /* @__PURE__ */ jsx("path", { d: "M22 2L11 13M22 2l-7 20-4-9-9-4 20-7z" })
|
|
11378
|
-
}
|
|
11379
|
-
),
|
|
10979
|
+
/* @__PURE__ */ jsx(Send, { className: "w-4 h-4" }),
|
|
11380
10980
|
"Publish"
|
|
11381
10981
|
]
|
|
11382
10982
|
}
|
|
@@ -11387,114 +10987,39 @@ function ActionBar({
|
|
|
11387
10987
|
type: "button",
|
|
11388
10988
|
onClick: onUnpublish,
|
|
11389
10989
|
disabled: saveStatus === "saving",
|
|
11390
|
-
className: "kyro-btn kyro-btn-
|
|
10990
|
+
className: "kyro-btn kyro-btn-secondary kyro-btn-md flex items-center gap-2",
|
|
11391
10991
|
children: [
|
|
11392
|
-
/* @__PURE__ */ jsx(
|
|
11393
|
-
"svg",
|
|
11394
|
-
{
|
|
11395
|
-
width: "16",
|
|
11396
|
-
height: "16",
|
|
11397
|
-
viewBox: "0 0 24 24",
|
|
11398
|
-
fill: "none",
|
|
11399
|
-
stroke: "currentColor",
|
|
11400
|
-
strokeWidth: "2.5",
|
|
11401
|
-
children: /* @__PURE__ */ jsx("path", { d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8M3 3v5h5" })
|
|
11402
|
-
}
|
|
11403
|
-
),
|
|
10992
|
+
/* @__PURE__ */ jsx(Undo, { className: "w-4 h-4" }),
|
|
11404
10993
|
"Unpublish"
|
|
11405
10994
|
]
|
|
11406
10995
|
}
|
|
11407
10996
|
),
|
|
11408
|
-
status === "published" && !hasChanges && saveStatus !== "saving" && saveStatus !== "error" ? /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1.5 px-4 py-2 rounded-lg text-[11px] font-bold tracking-widest bg-green-100 text-green-700 border border-green-200 cursor-not-allowed shadow-sm", children: [
|
|
11409
|
-
/* @__PURE__ */ jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: /* @__PURE__ */ jsx("path", { d: "M22 2L11 13M22 2l-7 20-4-9-9-4 20-7z" }) }),
|
|
11410
|
-
"Published"
|
|
11411
|
-
] }) : /* @__PURE__ */ jsx(
|
|
11412
|
-
"button",
|
|
11413
|
-
{
|
|
11414
|
-
type: "button",
|
|
11415
|
-
onClick: onSave,
|
|
11416
|
-
disabled: saveStatus === "saving" || !hasChanges && saveStatus !== "error",
|
|
11417
|
-
className: getSaveButtonClass(),
|
|
11418
|
-
children: saveStatus === "saving" ? "Saving..." : saveStatus === "saved" ? "Saved" : hasChanges && status === "published" ? "Save Draft" : status === "draft" && hasChanges ? "Save Draft" : "Save"
|
|
11419
|
-
}
|
|
11420
|
-
),
|
|
11421
10997
|
/* @__PURE__ */ jsxs(
|
|
11422
|
-
|
|
10998
|
+
SplitButton,
|
|
11423
10999
|
{
|
|
11424
|
-
|
|
11425
|
-
|
|
11426
|
-
|
|
11427
|
-
|
|
11428
|
-
height: "16",
|
|
11429
|
-
viewBox: "0 0 24 24",
|
|
11430
|
-
fill: "none",
|
|
11431
|
-
stroke: "currentColor",
|
|
11432
|
-
strokeWidth: "2",
|
|
11433
|
-
children: [
|
|
11434
|
-
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "1" }),
|
|
11435
|
-
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "5", r: "1" }),
|
|
11436
|
-
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "19", r: "1" })
|
|
11437
|
-
]
|
|
11438
|
-
}
|
|
11439
|
-
) }),
|
|
11000
|
+
status,
|
|
11001
|
+
saveStatus,
|
|
11002
|
+
hasChanges,
|
|
11003
|
+
onPublish: onSave,
|
|
11440
11004
|
children: [
|
|
11441
11005
|
onDuplicate && /* @__PURE__ */ jsx(
|
|
11442
11006
|
DropdownItem,
|
|
11443
11007
|
{
|
|
11444
|
-
|
|
11445
|
-
icon: /* @__PURE__ */ jsxs(
|
|
11446
|
-
"svg",
|
|
11447
|
-
{
|
|
11448
|
-
viewBox: "0 0 24 24",
|
|
11449
|
-
fill: "none",
|
|
11450
|
-
stroke: "currentColor",
|
|
11451
|
-
strokeWidth: "2",
|
|
11452
|
-
children: [
|
|
11453
|
-
/* @__PURE__ */ jsx("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2" }),
|
|
11454
|
-
/* @__PURE__ */ jsx("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
|
|
11455
|
-
]
|
|
11456
|
-
}
|
|
11457
|
-
),
|
|
11008
|
+
icon: /* @__PURE__ */ jsx(Copy, { className: "w-4 h-4" }),
|
|
11458
11009
|
children: "Duplicate"
|
|
11459
11010
|
}
|
|
11460
11011
|
),
|
|
11461
11012
|
onViewHistory && /* @__PURE__ */ jsx(
|
|
11462
11013
|
DropdownItem,
|
|
11463
11014
|
{
|
|
11464
|
-
|
|
11465
|
-
icon: /* @__PURE__ */ jsxs(
|
|
11466
|
-
"svg",
|
|
11467
|
-
{
|
|
11468
|
-
viewBox: "0 0 24 24",
|
|
11469
|
-
fill: "none",
|
|
11470
|
-
stroke: "currentColor",
|
|
11471
|
-
strokeWidth: "2",
|
|
11472
|
-
children: [
|
|
11473
|
-
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
|
|
11474
|
-
/* @__PURE__ */ jsx("polyline", { points: "12,6 12,12 16,14" })
|
|
11475
|
-
]
|
|
11476
|
-
}
|
|
11477
|
-
),
|
|
11015
|
+
icon: /* @__PURE__ */ jsx(Clock, { className: "w-4 h-4" }),
|
|
11478
11016
|
children: "View History"
|
|
11479
11017
|
}
|
|
11480
11018
|
),
|
|
11481
11019
|
onPreview && /* @__PURE__ */ jsx(
|
|
11482
11020
|
DropdownItem,
|
|
11483
11021
|
{
|
|
11484
|
-
|
|
11485
|
-
icon: /* @__PURE__ */ jsxs(
|
|
11486
|
-
"svg",
|
|
11487
|
-
{
|
|
11488
|
-
viewBox: "0 0 24 24",
|
|
11489
|
-
fill: "none",
|
|
11490
|
-
stroke: "currentColor",
|
|
11491
|
-
strokeWidth: "2",
|
|
11492
|
-
children: [
|
|
11493
|
-
/* @__PURE__ */ jsx("path", { d: "M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" }),
|
|
11494
|
-
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "3" })
|
|
11495
|
-
]
|
|
11496
|
-
}
|
|
11497
|
-
),
|
|
11022
|
+
icon: /* @__PURE__ */ jsx(Eye, { className: "w-4 h-4" }),
|
|
11498
11023
|
children: "Preview"
|
|
11499
11024
|
}
|
|
11500
11025
|
),
|
|
@@ -11504,16 +11029,7 @@ function ActionBar({
|
|
|
11504
11029
|
{
|
|
11505
11030
|
onClick: onDelete,
|
|
11506
11031
|
danger: true,
|
|
11507
|
-
icon: /* @__PURE__ */ jsx(
|
|
11508
|
-
"svg",
|
|
11509
|
-
{
|
|
11510
|
-
viewBox: "0 0 24 24",
|
|
11511
|
-
fill: "none",
|
|
11512
|
-
stroke: "currentColor",
|
|
11513
|
-
strokeWidth: "2",
|
|
11514
|
-
children: /* @__PURE__ */ jsx("path", { d: "M3 6h18M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })
|
|
11515
|
-
}
|
|
11516
|
-
),
|
|
11032
|
+
icon: /* @__PURE__ */ jsx(Trash2, { className: "w-4 h-4" }),
|
|
11517
11033
|
children: "Delete"
|
|
11518
11034
|
}
|
|
11519
11035
|
)
|
|
@@ -11523,62 +11039,6 @@ function ActionBar({
|
|
|
11523
11039
|
] })
|
|
11524
11040
|
] });
|
|
11525
11041
|
}
|
|
11526
|
-
function Toast({ type, message, onClose }) {
|
|
11527
|
-
const [isPaused, setIsPaused] = React54.useState(false);
|
|
11528
|
-
const timerRef = React54.useRef(null);
|
|
11529
|
-
const startTimer = () => {
|
|
11530
|
-
if (timerRef.current) clearTimeout(timerRef.current);
|
|
11531
|
-
timerRef.current = setTimeout(onClose, 5e3);
|
|
11532
|
-
};
|
|
11533
|
-
const clearTimer = () => {
|
|
11534
|
-
if (timerRef.current) clearTimeout(timerRef.current);
|
|
11535
|
-
};
|
|
11536
|
-
React54.useEffect(() => {
|
|
11537
|
-
if (!isPaused) {
|
|
11538
|
-
startTimer();
|
|
11539
|
-
} else {
|
|
11540
|
-
clearTimer();
|
|
11541
|
-
}
|
|
11542
|
-
return clearTimer;
|
|
11543
|
-
}, [isPaused, onClose]);
|
|
11544
|
-
const Icon = {
|
|
11545
|
-
success: CircleCheck,
|
|
11546
|
-
error: ShieldAlert,
|
|
11547
|
-
warning: TriangleAlert,
|
|
11548
|
-
info: Info
|
|
11549
|
-
}[type];
|
|
11550
|
-
return /* @__PURE__ */ jsxs(
|
|
11551
|
-
"div",
|
|
11552
|
-
{
|
|
11553
|
-
className: `kyro-toast kyro-toast-${type} group animate-in fade-in slide-in-from-right-4 duration-300`,
|
|
11554
|
-
onMouseEnter: () => setIsPaused(true),
|
|
11555
|
-
onMouseLeave: () => setIsPaused(false),
|
|
11556
|
-
children: [
|
|
11557
|
-
/* @__PURE__ */ jsx("div", { className: "kyro-toast-accent" }),
|
|
11558
|
-
/* @__PURE__ */ jsx("div", { className: "kyro-toast-icon-container", children: /* @__PURE__ */ jsx(Icon, { className: "w-4 h-4" }) }),
|
|
11559
|
-
/* @__PURE__ */ jsx("div", { className: "kyro-toast-content", children: /* @__PURE__ */ jsx("p", { className: "kyro-toast-message", children: message }) }),
|
|
11560
|
-
/* @__PURE__ */ jsx(
|
|
11561
|
-
"button",
|
|
11562
|
-
{
|
|
11563
|
-
type: "button",
|
|
11564
|
-
className: "kyro-toast-close group-hover:opacity-100 opacity-40 transition-opacity",
|
|
11565
|
-
onClick: onClose,
|
|
11566
|
-
children: /* @__PURE__ */ jsx(X, { className: "w-3.5 h-3.5" })
|
|
11567
|
-
}
|
|
11568
|
-
)
|
|
11569
|
-
]
|
|
11570
|
-
}
|
|
11571
|
-
);
|
|
11572
|
-
}
|
|
11573
|
-
function ToastProvider({ children }) {
|
|
11574
|
-
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
11575
|
-
}
|
|
11576
|
-
function useToast() {
|
|
11577
|
-
const addToast = useToastStore((state) => state.addToast);
|
|
11578
|
-
const removeToast = useToastStore((state) => state.removeToast);
|
|
11579
|
-
const toasts = useToastStore((state) => state.toasts);
|
|
11580
|
-
return { toasts, addToast, removeToast };
|
|
11581
|
-
}
|
|
11582
11042
|
function DetailView({
|
|
11583
11043
|
config,
|
|
11584
11044
|
collection,
|
|
@@ -11590,7 +11050,6 @@ function DetailView({
|
|
|
11590
11050
|
onError,
|
|
11591
11051
|
mode = "collection"
|
|
11592
11052
|
}) {
|
|
11593
|
-
const { addToast } = useToast();
|
|
11594
11053
|
const { confirm, alert } = useUIStore();
|
|
11595
11054
|
const [data, setData] = useState({});
|
|
11596
11055
|
const [originalData, setOriginalData] = useState({});
|
|
@@ -11631,7 +11090,7 @@ function DetailView({
|
|
|
11631
11090
|
const docData = result.data || {};
|
|
11632
11091
|
setData(docData);
|
|
11633
11092
|
setOriginalData(docData);
|
|
11634
|
-
setStatus(docData?.
|
|
11093
|
+
setStatus(docData?.status || result.status || "draft");
|
|
11635
11094
|
setCreatedAt(result.createdAt || docData.createdAt || null);
|
|
11636
11095
|
setUpdatedAt(result.updatedAt || docData.updatedAt || null);
|
|
11637
11096
|
setPublishedAt(result.publishedAt || docData.publishedAt || null);
|
|
@@ -11661,21 +11120,23 @@ function DetailView({
|
|
|
11661
11120
|
try {
|
|
11662
11121
|
setSaveStatus("saving");
|
|
11663
11122
|
const endpoint = mode === "global" ? `/api/globals/${slug}` : `/api/${slug}/${documentId}`;
|
|
11664
|
-
const
|
|
11123
|
+
const isDraft = status === "draft" || data?.status === "draft";
|
|
11124
|
+
const result = await apiPatch(endpoint, data, { autoToast: false, headers: { "X-Draft": String(isDraft) } });
|
|
11665
11125
|
const savedData = result && (result.data || result) || data;
|
|
11666
11126
|
if (!isAutosave) {
|
|
11667
11127
|
setOriginalData(savedData);
|
|
11668
11128
|
onSave();
|
|
11669
11129
|
}
|
|
11670
11130
|
setData(savedData);
|
|
11671
|
-
setStatus(savedData?.
|
|
11131
|
+
setStatus(savedData?.status || status);
|
|
11672
11132
|
setSaveStatus("saved");
|
|
11673
11133
|
setUpdatedAt((/* @__PURE__ */ new Date()).toISOString());
|
|
11674
11134
|
setJustSaved(true);
|
|
11675
11135
|
setTimeout(() => setJustSaved(false), 3e3);
|
|
11676
11136
|
if (!isAutosave) {
|
|
11677
|
-
const
|
|
11678
|
-
|
|
11137
|
+
const isDraft2 = status === "draft" || savedData?.status === "draft";
|
|
11138
|
+
if (isDraft2) toast.warning("Draft saved");
|
|
11139
|
+
else toast.success("Updated");
|
|
11679
11140
|
}
|
|
11680
11141
|
setTimeout(() => {
|
|
11681
11142
|
setSaveStatus("idle");
|
|
@@ -11684,24 +11145,28 @@ function DetailView({
|
|
|
11684
11145
|
setSaveStatus("error");
|
|
11685
11146
|
if (!isAutosave) {
|
|
11686
11147
|
onError("Failed to save changes");
|
|
11687
|
-
|
|
11148
|
+
toast.error("Failed to save changes");
|
|
11688
11149
|
}
|
|
11689
11150
|
} finally {
|
|
11690
11151
|
setSaving(false);
|
|
11691
11152
|
}
|
|
11692
11153
|
},
|
|
11693
|
-
[data, mode, slug, documentId, onSave, onError]
|
|
11154
|
+
[data, mode, slug, documentId, status, onSave, onError]
|
|
11694
11155
|
);
|
|
11695
11156
|
const handlePublish = async () => {
|
|
11696
11157
|
try {
|
|
11697
11158
|
setSaving(true);
|
|
11698
|
-
await
|
|
11159
|
+
await apiPatch(`/api/${slug}/${documentId}`, data, {
|
|
11160
|
+
autoToast: false,
|
|
11161
|
+
headers: { "X-Draft": "false" }
|
|
11162
|
+
});
|
|
11699
11163
|
setStatus("published");
|
|
11700
11164
|
setPublishedAt((/* @__PURE__ */ new Date()).toISOString());
|
|
11701
|
-
|
|
11165
|
+
toast.success("Published successfully");
|
|
11166
|
+
onSave();
|
|
11702
11167
|
} catch {
|
|
11703
11168
|
onError("Failed to publish");
|
|
11704
|
-
|
|
11169
|
+
toast.error("Failed to publish");
|
|
11705
11170
|
} finally {
|
|
11706
11171
|
setSaving(false);
|
|
11707
11172
|
}
|
|
@@ -11709,12 +11174,16 @@ function DetailView({
|
|
|
11709
11174
|
const handleUnpublish = async () => {
|
|
11710
11175
|
try {
|
|
11711
11176
|
setSaving(true);
|
|
11712
|
-
await
|
|
11177
|
+
await apiPatch(`/api/${slug}/${documentId}`, { status: "draft" }, {
|
|
11178
|
+
autoToast: false,
|
|
11179
|
+
headers: { "X-Draft": "false" }
|
|
11180
|
+
});
|
|
11713
11181
|
setStatus("draft");
|
|
11714
|
-
|
|
11182
|
+
toast.warning("Document unpublished");
|
|
11183
|
+
onSave();
|
|
11715
11184
|
} catch {
|
|
11716
11185
|
onError("Failed to unpublish");
|
|
11717
|
-
|
|
11186
|
+
toast.error("Failed to unpublish");
|
|
11718
11187
|
} finally {
|
|
11719
11188
|
setSaving(false);
|
|
11720
11189
|
}
|
|
@@ -11723,11 +11192,11 @@ function DetailView({
|
|
|
11723
11192
|
try {
|
|
11724
11193
|
setSaving(true);
|
|
11725
11194
|
await apiPost(`/api/${slug}/${documentId}/duplicate`, void 0, { autoToast: false });
|
|
11726
|
-
|
|
11195
|
+
toast.success("Document duplicated");
|
|
11727
11196
|
} catch (err) {
|
|
11728
11197
|
const message = err instanceof Error ? err.message : "Failed to duplicate document";
|
|
11729
11198
|
onError(message);
|
|
11730
|
-
|
|
11199
|
+
toast.error(message);
|
|
11731
11200
|
} finally {
|
|
11732
11201
|
setSaving(false);
|
|
11733
11202
|
}
|
|
@@ -11742,10 +11211,10 @@ function DetailView({
|
|
|
11742
11211
|
setDeleting(true);
|
|
11743
11212
|
await apiDelete(`/api/${slug}/${documentId}`, { autoToast: false });
|
|
11744
11213
|
onDelete?.();
|
|
11745
|
-
|
|
11214
|
+
toast.error("Document deleted");
|
|
11746
11215
|
} catch (err) {
|
|
11747
11216
|
const message = err instanceof Error ? err.message : "Failed to delete document";
|
|
11748
|
-
|
|
11217
|
+
toast.error(message);
|
|
11749
11218
|
} finally {
|
|
11750
11219
|
setDeleting(false);
|
|
11751
11220
|
}
|
|
@@ -11828,8 +11297,8 @@ function DetailView({
|
|
|
11828
11297
|
layout: isSingleLayout ? "single" : "split",
|
|
11829
11298
|
globalSlug: mode === "global" ? slug : void 0,
|
|
11830
11299
|
collectionSlug: mode === "collection" ? slug : void 0,
|
|
11831
|
-
onActionSuccess: (message) =>
|
|
11832
|
-
onActionError: (message) =>
|
|
11300
|
+
onActionSuccess: (message) => toast.success(message),
|
|
11301
|
+
onActionError: (message) => toast.error(message),
|
|
11833
11302
|
documentStatus: status,
|
|
11834
11303
|
justSaved
|
|
11835
11304
|
}
|
|
@@ -11844,44 +11313,14 @@ function DetailView({
|
|
|
11844
11313
|
children: "Delete"
|
|
11845
11314
|
}
|
|
11846
11315
|
),
|
|
11847
|
-
|
|
11848
|
-
|
|
11849
|
-
"Published"
|
|
11850
|
-
] }) : /* @__PURE__ */ jsxs(
|
|
11851
|
-
"button",
|
|
11316
|
+
/* @__PURE__ */ jsx(
|
|
11317
|
+
SplitButton,
|
|
11852
11318
|
{
|
|
11853
|
-
|
|
11854
|
-
|
|
11855
|
-
|
|
11856
|
-
|
|
11857
|
-
|
|
11858
|
-
saving ? /* @__PURE__ */ jsx(
|
|
11859
|
-
"svg",
|
|
11860
|
-
{
|
|
11861
|
-
className: "w-4 h-4 animate-spin",
|
|
11862
|
-
viewBox: "0 0 24 24",
|
|
11863
|
-
fill: "none",
|
|
11864
|
-
stroke: "currentColor",
|
|
11865
|
-
strokeWidth: "2",
|
|
11866
|
-
children: /* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" })
|
|
11867
|
-
}
|
|
11868
|
-
) : /* @__PURE__ */ jsxs(
|
|
11869
|
-
"svg",
|
|
11870
|
-
{
|
|
11871
|
-
className: "w-4 h-4",
|
|
11872
|
-
viewBox: "0 0 24 24",
|
|
11873
|
-
fill: "none",
|
|
11874
|
-
stroke: "currentColor",
|
|
11875
|
-
strokeWidth: "2",
|
|
11876
|
-
children: [
|
|
11877
|
-
/* @__PURE__ */ jsx("path", { d: "M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z" }),
|
|
11878
|
-
/* @__PURE__ */ jsx("polyline", { points: "17 21 17 13 7 13 7 21" }),
|
|
11879
|
-
/* @__PURE__ */ jsx("polyline", { points: "7 3 7 8 15 8" })
|
|
11880
|
-
]
|
|
11881
|
-
}
|
|
11882
|
-
),
|
|
11883
|
-
saving ? "Saving..." : mode === "global" ? "Save Configuration" : "Save Document"
|
|
11884
|
-
]
|
|
11319
|
+
status,
|
|
11320
|
+
saveStatus: saving ? "saving" : "idle",
|
|
11321
|
+
hasChanges,
|
|
11322
|
+
onPublish: () => handleSave(false),
|
|
11323
|
+
disabled: saving
|
|
11885
11324
|
}
|
|
11886
11325
|
)
|
|
11887
11326
|
] })
|
|
@@ -12011,6 +11450,62 @@ function CreateView({
|
|
|
12011
11450
|
) }) }) }) })
|
|
12012
11451
|
] });
|
|
12013
11452
|
}
|
|
11453
|
+
function Toast({ type, message, onClose }) {
|
|
11454
|
+
const [isPaused, setIsPaused] = React56.useState(false);
|
|
11455
|
+
const timerRef = React56.useRef(null);
|
|
11456
|
+
const startTimer = () => {
|
|
11457
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
11458
|
+
timerRef.current = setTimeout(onClose, 5e3);
|
|
11459
|
+
};
|
|
11460
|
+
const clearTimer = () => {
|
|
11461
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
11462
|
+
};
|
|
11463
|
+
React56.useEffect(() => {
|
|
11464
|
+
if (!isPaused) {
|
|
11465
|
+
startTimer();
|
|
11466
|
+
} else {
|
|
11467
|
+
clearTimer();
|
|
11468
|
+
}
|
|
11469
|
+
return clearTimer;
|
|
11470
|
+
}, [isPaused, onClose]);
|
|
11471
|
+
const Icon = {
|
|
11472
|
+
success: CircleCheck,
|
|
11473
|
+
error: ShieldAlert,
|
|
11474
|
+
warning: TriangleAlert,
|
|
11475
|
+
info: Info
|
|
11476
|
+
}[type];
|
|
11477
|
+
return /* @__PURE__ */ jsxs(
|
|
11478
|
+
"div",
|
|
11479
|
+
{
|
|
11480
|
+
className: `kyro-toast kyro-toast-${type} group animate-in fade-in slide-in-from-right-4 duration-300`,
|
|
11481
|
+
onMouseEnter: () => setIsPaused(true),
|
|
11482
|
+
onMouseLeave: () => setIsPaused(false),
|
|
11483
|
+
children: [
|
|
11484
|
+
/* @__PURE__ */ jsx("div", { className: "kyro-toast-accent" }),
|
|
11485
|
+
/* @__PURE__ */ jsx("div", { className: "kyro-toast-icon-container", children: /* @__PURE__ */ jsx(Icon, { className: "w-4 h-4" }) }),
|
|
11486
|
+
/* @__PURE__ */ jsx("div", { className: "kyro-toast-content", children: /* @__PURE__ */ jsx("p", { className: "kyro-toast-message", children: message }) }),
|
|
11487
|
+
/* @__PURE__ */ jsx(
|
|
11488
|
+
"button",
|
|
11489
|
+
{
|
|
11490
|
+
type: "button",
|
|
11491
|
+
className: "kyro-toast-close group-hover:opacity-100 opacity-40 transition-opacity",
|
|
11492
|
+
onClick: onClose,
|
|
11493
|
+
children: /* @__PURE__ */ jsx(X, { className: "w-3.5 h-3.5" })
|
|
11494
|
+
}
|
|
11495
|
+
)
|
|
11496
|
+
]
|
|
11497
|
+
}
|
|
11498
|
+
);
|
|
11499
|
+
}
|
|
11500
|
+
function ToastProvider({ children }) {
|
|
11501
|
+
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
11502
|
+
}
|
|
11503
|
+
function useToast() {
|
|
11504
|
+
const addToast = useToastStore((state) => state.addToast);
|
|
11505
|
+
const removeToast = useToastStore((state) => state.removeToast);
|
|
11506
|
+
const toasts = useToastStore((state) => state.toasts);
|
|
11507
|
+
return { toasts, addToast, removeToast };
|
|
11508
|
+
}
|
|
12014
11509
|
function LoginPage({ onAuth, theme = "light" }) {
|
|
12015
11510
|
const [mode, setMode] = useState("login");
|
|
12016
11511
|
const [email, setEmail] = useState("");
|
|
@@ -14324,7 +13819,7 @@ function Admin({ config, theme = "light", onThemeChange }) {
|
|
|
14324
13819
|
);
|
|
14325
13820
|
}
|
|
14326
13821
|
};
|
|
14327
|
-
return /* @__PURE__ */ jsx(ThemeProvider, { ...{ mode: theme, onChange: onThemeChange }, children: /* @__PURE__ */
|
|
13822
|
+
return /* @__PURE__ */ jsx(ThemeProvider, { ...{ mode: theme, onChange: onThemeChange }, children: /* @__PURE__ */ jsxs("div", { className: "kyro-admin min-h-screen bg-[var(--kyro-bg)] text-[var(--kyro-text-primary)]", children: [
|
|
14328
13823
|
/* @__PURE__ */ jsx("div", { className: "flex h-screen overflow-hidden", children: /* @__PURE__ */ jsx("main", { className: "flex-1 flex flex-col min-w-0 overflow-hidden", children: /* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto", children: [
|
|
14329
13824
|
/* @__PURE__ */ jsx(
|
|
14330
13825
|
CommandPalette,
|
|
@@ -14348,7 +13843,7 @@ function Admin({ config, theme = "light", onThemeChange }) {
|
|
|
14348
13843
|
},
|
|
14349
13844
|
t.id
|
|
14350
13845
|
)) })
|
|
14351
|
-
] }) })
|
|
13846
|
+
] }) });
|
|
14352
13847
|
}
|
|
14353
13848
|
function BulkActionsBar({
|
|
14354
13849
|
selectedCount,
|
|
@@ -14579,32 +14074,6 @@ function Header({ title, onMenuClick, actions }) {
|
|
|
14579
14074
|
] })
|
|
14580
14075
|
] });
|
|
14581
14076
|
}
|
|
14582
|
-
function Button({
|
|
14583
|
-
variant = "secondary",
|
|
14584
|
-
size = "md",
|
|
14585
|
-
loading = false,
|
|
14586
|
-
children,
|
|
14587
|
-
className = "",
|
|
14588
|
-
disabled,
|
|
14589
|
-
...props
|
|
14590
|
-
}) {
|
|
14591
|
-
const baseClass = "kyro-btn";
|
|
14592
|
-
const variantClass = `kyro-btn-${variant}`;
|
|
14593
|
-
const sizeClass = `kyro-btn-${size}`;
|
|
14594
|
-
return /* @__PURE__ */ jsxs(
|
|
14595
|
-
"button",
|
|
14596
|
-
{
|
|
14597
|
-
type: "button",
|
|
14598
|
-
className: `${baseClass} ${variantClass} ${sizeClass} ${className}`,
|
|
14599
|
-
disabled: disabled || loading,
|
|
14600
|
-
...props,
|
|
14601
|
-
children: [
|
|
14602
|
-
loading ? /* @__PURE__ */ jsx("span", { className: "kyro-btn-loading", children: /* @__PURE__ */ jsx("svg", { className: "kyro-btn-spinner", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "3", fill: "none", strokeDasharray: "60 30" }) }) }) : null,
|
|
14603
|
-
/* @__PURE__ */ jsx("span", { className: loading ? "kyro-btn-text-hidden" : "", children })
|
|
14604
|
-
]
|
|
14605
|
-
}
|
|
14606
|
-
);
|
|
14607
|
-
}
|
|
14608
14077
|
|
|
14609
14078
|
// src/hooks/lifecycle.ts
|
|
14610
14079
|
var registry = {
|