@kyro-cms/admin 0.9.4 → 0.9.5
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 +940 -564
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +42 -23
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +623 -247
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/ActionBar.tsx +254 -70
- package/src/components/Admin.tsx +3 -16
- package/src/components/ApiKeysManager.tsx +1 -0
- package/src/components/AuditLogsPage.tsx +3 -3
- package/src/components/AutoForm.tsx +51 -34
- package/src/components/DetailView.tsx +37 -13
- package/src/components/ListView.tsx +2 -2
- package/src/components/LoginPage.tsx +5 -30
- package/src/components/MediaGallery.tsx +120 -13
- package/src/components/Sidebar.astro +6 -2
- package/src/components/UserManagement.tsx +4 -4
- package/src/components/WebhookManager.tsx +4 -4
- package/src/components/fields/BlocksField.tsx +12 -14
- package/src/components/ui/PageHeader.tsx +205 -83
- package/src/components/ui/Pagination.tsx +2 -2
- package/src/components/ui/SlidePanel.tsx +4 -4
- package/src/components/ui/Toast.tsx +1 -2
- package/src/layouts/AdminLayout.astro +49 -4
- package/src/lib/useResourceManager.ts +1 -0
- package/src/styles/main.css +34 -19
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var React = require('react');
|
|
4
4
|
var zustand = require('zustand');
|
|
5
5
|
var middleware = require('zustand/middleware');
|
|
6
6
|
var lucideReact = require('lucide-react');
|
|
@@ -41,7 +41,7 @@ var worker_threads = require('worker_threads');
|
|
|
41
41
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
42
42
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
43
43
|
|
|
44
|
-
var
|
|
44
|
+
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
45
45
|
var StarterKit__default = /*#__PURE__*/_interopDefault(StarterKit);
|
|
46
46
|
var Link4__default = /*#__PURE__*/_interopDefault(Link4);
|
|
47
47
|
var Image3__default = /*#__PURE__*/_interopDefault(Image3);
|
|
@@ -458,6 +458,84 @@ function Shimmer({ variant, count = 1, className = "" }) {
|
|
|
458
458
|
i
|
|
459
459
|
)) });
|
|
460
460
|
}
|
|
461
|
+
function BackButton({ back }) {
|
|
462
|
+
if (back.href) {
|
|
463
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
464
|
+
"a",
|
|
465
|
+
{
|
|
466
|
+
href: back.href,
|
|
467
|
+
onClick: (e) => {
|
|
468
|
+
if (back.onClick) {
|
|
469
|
+
e.preventDefault();
|
|
470
|
+
back.onClick();
|
|
471
|
+
}
|
|
472
|
+
},
|
|
473
|
+
className: "p-1.5 rounded-lg hover:bg-[var(--kyro-surface-accent)] text-[var(--kyro-text-secondary)] transition-all",
|
|
474
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-4 h-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M19 12H5M12 19l-7-7 7-7" }) })
|
|
475
|
+
}
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
479
|
+
"button",
|
|
480
|
+
{
|
|
481
|
+
type: "button",
|
|
482
|
+
onClick: back.onClick,
|
|
483
|
+
className: "p-1.5 rounded-lg hover:bg-[var(--kyro-surface-accent)] text-[var(--kyro-text-secondary)] transition-all",
|
|
484
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-4 h-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M19 12H5M12 19l-7-7 7-7" }) })
|
|
485
|
+
}
|
|
486
|
+
);
|
|
487
|
+
}
|
|
488
|
+
function DesktopBreadcrumbs({ breadcrumbs }) {
|
|
489
|
+
return breadcrumbs?.map((crumb, i) => /* @__PURE__ */ jsxRuntime.jsxs(React__default.default.Fragment, { children: [
|
|
490
|
+
i > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "opacity-20 text-[10px]", children: "/" }),
|
|
491
|
+
crumb.href || crumb.onClick ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
492
|
+
"a",
|
|
493
|
+
{
|
|
494
|
+
href: crumb.href,
|
|
495
|
+
onClick: (e) => {
|
|
496
|
+
if (crumb.onClick) {
|
|
497
|
+
e.preventDefault();
|
|
498
|
+
crumb.onClick();
|
|
499
|
+
}
|
|
500
|
+
},
|
|
501
|
+
className: "text-[10px] font-bold tracking-widest text-[var(--kyro-text-secondary)] hover:text-[var(--kyro-primary)] transition-all",
|
|
502
|
+
children: crumb.label
|
|
503
|
+
}
|
|
504
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-bold tracking-widest opacity-40", children: crumb.label })
|
|
505
|
+
] }, i));
|
|
506
|
+
}
|
|
507
|
+
function ActionsSlot({ actions }) {
|
|
508
|
+
if (Array.isArray(actions)) {
|
|
509
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-3", children: actions.map((act, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
510
|
+
"button",
|
|
511
|
+
{
|
|
512
|
+
type: "button",
|
|
513
|
+
onClick: act.onClick,
|
|
514
|
+
className: `flex items-center gap-2 px-6 py-2.5 rounded-xl font-bold text-sm transition-all shadow-lg shadow-[var(--kyro-primary)]/10 ${act.variant === "outline" ? "border border-[var(--kyro-border)] text-[var(--kyro-text-secondary)] hover:bg-[var(--kyro-surface-accent)]" : act.variant === "ghost" ? "text-[var(--kyro-text-secondary)] hover:bg-[var(--kyro-surface-accent)] shadow-none" : "kyro-btn-primary hover:opacity-90"} ${act.className || ""}`,
|
|
515
|
+
children: [
|
|
516
|
+
act.icon && /* @__PURE__ */ jsxRuntime.jsx(act.icon, { className: "w-4 h-4" }),
|
|
517
|
+
act.label
|
|
518
|
+
]
|
|
519
|
+
},
|
|
520
|
+
i
|
|
521
|
+
)) });
|
|
522
|
+
}
|
|
523
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: actions });
|
|
524
|
+
}
|
|
525
|
+
function SingleAction({ action }) {
|
|
526
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
527
|
+
"button",
|
|
528
|
+
{
|
|
529
|
+
type: "button",
|
|
530
|
+
onClick: action.onClick,
|
|
531
|
+
className: `kyro-btn kyro-btn-primary flex items-center gap-2 px-6 py-2.5 rounded-xl font-bold text-sm hover:opacity-90 transition-all shadow-lg shadow-[var(--kyro-primary)]/10 w-full lg:w-auto justify-center ${action.className || ""}`,
|
|
532
|
+
children: [
|
|
533
|
+
action.icon && /* @__PURE__ */ jsxRuntime.jsx(action.icon, { className: "w-4 h-4" }),
|
|
534
|
+
action.label
|
|
535
|
+
]
|
|
536
|
+
}
|
|
537
|
+
);
|
|
538
|
+
}
|
|
461
539
|
function PageHeader({
|
|
462
540
|
title,
|
|
463
541
|
description,
|
|
@@ -469,80 +547,79 @@ function PageHeader({
|
|
|
469
547
|
actions,
|
|
470
548
|
children
|
|
471
549
|
}) {
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
e.preventDefault();
|
|
498
|
-
crumb.onClick();
|
|
550
|
+
const lastBreadcrumb = breadcrumbs?.[breadcrumbs.length - 1];
|
|
551
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "surface-tile px-3 md:px-6 py-3 md:pt-4 mb-4 md:mb-8", children: [
|
|
552
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "md:hidden space-y-2", children: [
|
|
553
|
+
(breadcrumbs || back) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
554
|
+
back && /* @__PURE__ */ jsxRuntime.jsx(BackButton, { back }),
|
|
555
|
+
/* @__PURE__ */ jsxRuntime.jsxs("details", { className: "group [&::-webkit-details-marker]:hidden flex-1 min-w-0", children: [
|
|
556
|
+
/* @__PURE__ */ jsxRuntime.jsxs("summary", { className: "flex items-center gap-2 cursor-pointer list-none", children: [
|
|
557
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 text-[10px] font-bold tracking-widest text-[var(--kyro-text-secondary)] truncate", children: lastBreadcrumb?.label || "" }),
|
|
558
|
+
/* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-3 h-3 text-[var(--kyro-text-secondary)] opacity-40 group-open:rotate-180 transition-transform", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 9l6 6 6-6" }) })
|
|
559
|
+
] }),
|
|
560
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 pt-2 border-t border-[var(--kyro-border)] space-y-2", children: [
|
|
561
|
+
breadcrumbs && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: breadcrumbs.map((crumb, i) => /* @__PURE__ */ jsxRuntime.jsxs(React__default.default.Fragment, { children: [
|
|
562
|
+
i > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "opacity-20 text-[10px]", children: "/" }),
|
|
563
|
+
crumb.href || crumb.onClick ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
564
|
+
"a",
|
|
565
|
+
{
|
|
566
|
+
href: crumb.href,
|
|
567
|
+
onClick: (e) => {
|
|
568
|
+
if (crumb.onClick) {
|
|
569
|
+
e.preventDefault();
|
|
570
|
+
crumb.onClick();
|
|
571
|
+
}
|
|
572
|
+
},
|
|
573
|
+
className: "text-[10px] font-bold tracking-widest text-[var(--kyro-text-secondary)] hover:text-[var(--kyro-primary)] transition-all",
|
|
574
|
+
children: crumb.label
|
|
499
575
|
}
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
] }
|
|
576
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-bold tracking-widest opacity-40", children: crumb.label })
|
|
577
|
+
] }, i)) }),
|
|
578
|
+
metadata && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2 flex-wrap", children: metadata.map((item, i) => /* @__PURE__ */ jsxRuntime.jsx(React__default.default.Fragment, { children: item }, i)) }),
|
|
579
|
+
children
|
|
580
|
+
] })
|
|
581
|
+
] })
|
|
506
582
|
] }),
|
|
507
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-
|
|
508
|
-
Icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "w-
|
|
509
|
-
title && /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-
|
|
583
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
584
|
+
Icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "w-5 h-5 text-[var(--kyro-primary)] shrink-0" }),
|
|
585
|
+
title && /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-lg font-bold tracking-tighter text-[var(--kyro-text-primary)] truncate", children: title }),
|
|
586
|
+
metadata && !description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-2 w-2 rounded-full bg-[var(--kyro-primary)] shrink-0" })
|
|
510
587
|
] }),
|
|
511
|
-
description && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2
|
|
512
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[var(--kyro-text-secondary)] font-medium opacity-60 line-clamp-1", children: description }),
|
|
513
|
-
metadata && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: metadata.map((item, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
588
|
+
description && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-x-2 gap-y-1", children: [
|
|
589
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[var(--kyro-text-secondary)] font-medium opacity-60 line-clamp-1 min-w-0 text-xs", children: description }),
|
|
590
|
+
metadata && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: metadata.map((item, i) => /* @__PURE__ */ jsxRuntime.jsxs(React__default.default.Fragment, { children: [
|
|
514
591
|
i === 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "opacity-20 ml-1", children: "\xB7" }),
|
|
515
592
|
item
|
|
516
|
-
] }, i)) })
|
|
517
|
-
children
|
|
593
|
+
] }, i)) })
|
|
518
594
|
] })
|
|
519
595
|
] }),
|
|
520
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-
|
|
521
|
-
|
|
522
|
-
"
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
)
|
|
596
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "hidden md:flex md:flex-row md:items-center justify-between gap-6", children: [
|
|
597
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
598
|
+
(breadcrumbs || back) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-3", children: [
|
|
599
|
+
back && /* @__PURE__ */ jsxRuntime.jsx(BackButton, { back }),
|
|
600
|
+
breadcrumbs && /* @__PURE__ */ jsxRuntime.jsx(DesktopBreadcrumbs, { breadcrumbs })
|
|
601
|
+
] }),
|
|
602
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
603
|
+
Icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "w-6 h-6 text-[var(--kyro-primary)]" }),
|
|
604
|
+
title && /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-bold tracking-tighter text-[var(--kyro-text-primary)] truncate", children: title })
|
|
605
|
+
] }),
|
|
606
|
+
(description || metadata) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-x-2 gap-y-1 mt-1", children: [
|
|
607
|
+
description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[var(--kyro-text-secondary)] font-medium opacity-60 line-clamp-1 min-w-0", children: description }),
|
|
608
|
+
metadata && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: metadata.map((item, i) => /* @__PURE__ */ jsxRuntime.jsxs(React__default.default.Fragment, { children: [
|
|
609
|
+
i === 0 && (description || i > 0) && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "opacity-20 ml-1", children: "\xB7" }),
|
|
610
|
+
item
|
|
611
|
+
] }, i)) }),
|
|
612
|
+
children
|
|
613
|
+
] })
|
|
614
|
+
] }),
|
|
615
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 flex-wrap shrink-0", children: [
|
|
616
|
+
actions && /* @__PURE__ */ jsxRuntime.jsx(ActionsSlot, { actions }),
|
|
617
|
+
action && /* @__PURE__ */ jsxRuntime.jsx(SingleAction, { action })
|
|
618
|
+
] })
|
|
619
|
+
] }),
|
|
620
|
+
(actions || action) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "md:hidden flex items-center gap-2 mt-3 pt-3 border-t border-[var(--kyro-border)]", children: [
|
|
621
|
+
action && /* @__PURE__ */ jsxRuntime.jsx(SingleAction, { action }),
|
|
622
|
+
actions && /* @__PURE__ */ jsxRuntime.jsx(ActionsSlot, { actions })
|
|
546
623
|
] })
|
|
547
624
|
] });
|
|
548
625
|
}
|
|
@@ -604,7 +681,7 @@ function Button({
|
|
|
604
681
|
}
|
|
605
682
|
function Pagination({ page, totalPages, totalDocs, limit, onPageChange, onLimitChange }) {
|
|
606
683
|
if (totalPages <= 1) return null;
|
|
607
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-4 py-3 border-t border-[var(--kyro-border)]", children: [
|
|
684
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col sm:flex-row items-center justify-between gap-3 px-4 py-3 border-t border-[var(--kyro-border)]", children: [
|
|
608
685
|
totalDocs !== void 0 && limit ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-[var(--kyro-text-secondary)] font-medium", children: [
|
|
609
686
|
"Showing ",
|
|
610
687
|
(page - 1) * limit + 1,
|
|
@@ -613,7 +690,7 @@ function Pagination({ page, totalPages, totalDocs, limit, onPageChange, onLimitC
|
|
|
613
690
|
" of ",
|
|
614
691
|
totalDocs
|
|
615
692
|
] }) : /* @__PURE__ */ jsxRuntime.jsx("span", {}),
|
|
616
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
693
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 flex-wrap justify-center", children: [
|
|
617
694
|
onLimitChange && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
618
695
|
"select",
|
|
619
696
|
{
|
|
@@ -730,14 +807,14 @@ function ListView({
|
|
|
730
807
|
window.location.href = `${adminPath}/${collectionSlug}/${id}`;
|
|
731
808
|
}
|
|
732
809
|
};
|
|
733
|
-
const [docs, setDocs] =
|
|
734
|
-
const [totalDocs, setTotalDocs] =
|
|
735
|
-
const [loading, setLoading] =
|
|
736
|
-
const [page, setPage] =
|
|
737
|
-
const [limit, setLimit] =
|
|
738
|
-
const [selectedIds, setSelectedIds] =
|
|
739
|
-
const [search, setSearch] =
|
|
740
|
-
const [filters, setFilters] =
|
|
810
|
+
const [docs, setDocs] = React.useState(initialDocs);
|
|
811
|
+
const [totalDocs, setTotalDocs] = React.useState(initialTotal);
|
|
812
|
+
const [loading, setLoading] = React.useState(false);
|
|
813
|
+
const [page, setPage] = React.useState(1);
|
|
814
|
+
const [limit, setLimit] = React.useState(10);
|
|
815
|
+
const [selectedIds, setSelectedIds] = React.useState(/* @__PURE__ */ new Set());
|
|
816
|
+
const [search, setSearch] = React.useState("");
|
|
817
|
+
const [filters, setFilters] = React.useState([]);
|
|
741
818
|
const { confirm, alert } = useUIStore();
|
|
742
819
|
const addFilter = () => {
|
|
743
820
|
setFilters([...filters, { field: "", operator: "equals", value: "" }]);
|
|
@@ -753,9 +830,9 @@ function ListView({
|
|
|
753
830
|
const updateFilter = (index, updates) => {
|
|
754
831
|
setFilters(filters.map((f, i) => i === index ? { ...f, ...updates } : f));
|
|
755
832
|
};
|
|
756
|
-
const [sort, setSort] =
|
|
757
|
-
const [showFilters, setShowFilters] =
|
|
758
|
-
const [showColumns, setShowColumns] =
|
|
833
|
+
const [sort, setSort] = React.useState(null);
|
|
834
|
+
const [showFilters, setShowFilters] = React.useState(false);
|
|
835
|
+
const [showColumns, setShowColumns] = React.useState(false);
|
|
759
836
|
function flattenFields(fields2) {
|
|
760
837
|
const result = [];
|
|
761
838
|
for (const field3 of fields2 || []) {
|
|
@@ -774,12 +851,12 @@ function ListView({
|
|
|
774
851
|
}
|
|
775
852
|
return result;
|
|
776
853
|
}
|
|
777
|
-
const allFields =
|
|
854
|
+
const allFields = React.useMemo(
|
|
778
855
|
() => flattenFields(collection.fields),
|
|
779
856
|
[collection.fields]
|
|
780
857
|
);
|
|
781
858
|
const titleField = typeof collection.admin?.useAsTitle === "string" ? collection.admin.useAsTitle : allFields.find((f) => f.type !== "group" && typeof f.name === "string")?.name;
|
|
782
|
-
const [visibleColumns, setVisibleColumns] =
|
|
859
|
+
const [visibleColumns, setVisibleColumns] = React.useState(() => {
|
|
783
860
|
let cols;
|
|
784
861
|
if (collection.admin?.defaultColumns) {
|
|
785
862
|
cols = [...collection.admin?.defaultColumns || []];
|
|
@@ -794,7 +871,7 @@ function ListView({
|
|
|
794
871
|
}
|
|
795
872
|
return new Set(cols);
|
|
796
873
|
});
|
|
797
|
-
const toggleColumn =
|
|
874
|
+
const toggleColumn = React.useCallback((fieldName) => {
|
|
798
875
|
setVisibleColumns((prev) => {
|
|
799
876
|
const next = new Set(prev);
|
|
800
877
|
if (next.has(fieldName)) {
|
|
@@ -813,7 +890,7 @@ function ListView({
|
|
|
813
890
|
}
|
|
814
891
|
return fieldName;
|
|
815
892
|
}
|
|
816
|
-
const handleSort =
|
|
893
|
+
const handleSort = React.useCallback((fieldName) => {
|
|
817
894
|
const resolvedField = resolveSortField(fieldName);
|
|
818
895
|
setSort((prev) => {
|
|
819
896
|
if (prev && prev.field === resolvedField) {
|
|
@@ -825,7 +902,7 @@ function ListView({
|
|
|
825
902
|
return { field: resolvedField, direction: "asc" };
|
|
826
903
|
});
|
|
827
904
|
}, []);
|
|
828
|
-
const displayFields =
|
|
905
|
+
const displayFields = React.useMemo(
|
|
829
906
|
() => {
|
|
830
907
|
const fields2 = allFields.filter((f) => !!f.name && visibleColumns.has(f.name));
|
|
831
908
|
if (visibleColumns.has("status")) {
|
|
@@ -855,7 +932,7 @@ function ListView({
|
|
|
855
932
|
const val = resolveFieldValue(collection.fields, doc, field3.name);
|
|
856
933
|
return val ?? null;
|
|
857
934
|
}
|
|
858
|
-
const fetchDocs =
|
|
935
|
+
const fetchDocs = React.useCallback(async () => {
|
|
859
936
|
setLoading(true);
|
|
860
937
|
try {
|
|
861
938
|
const params = new URLSearchParams({
|
|
@@ -880,13 +957,13 @@ function ListView({
|
|
|
880
957
|
setLoading(false);
|
|
881
958
|
}
|
|
882
959
|
}, [collectionSlug, page, limit, search, sort, filters]);
|
|
883
|
-
|
|
960
|
+
React.useEffect(() => {
|
|
884
961
|
if (docs.length === 0 && initialTotal === 0) {
|
|
885
962
|
fetchDocs();
|
|
886
963
|
}
|
|
887
964
|
}, []);
|
|
888
|
-
const isFirstRender =
|
|
889
|
-
|
|
965
|
+
const isFirstRender = React.useRef(true);
|
|
966
|
+
React.useEffect(() => {
|
|
890
967
|
if (isFirstRender.current) {
|
|
891
968
|
isFirstRender.current = false;
|
|
892
969
|
return;
|
|
@@ -968,7 +1045,7 @@ function ListView({
|
|
|
968
1045
|
}
|
|
969
1046
|
),
|
|
970
1047
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "surface-tile p-4 flex flex-col lg:flex-row gap-4 items-start lg:items-center", children: [
|
|
971
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex-1 max-w-md", children: [
|
|
1048
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex-1 w-full lg:max-w-md", children: [
|
|
972
1049
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "w-4 h-4" }),
|
|
973
1050
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
974
1051
|
"input",
|
|
@@ -1161,7 +1238,7 @@ function ListView({
|
|
|
1161
1238
|
}
|
|
1162
1239
|
)
|
|
1163
1240
|
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full text-left", children: [
|
|
1164
|
-
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "text-[var(--kyro-text-secondary)] font-bold text-[10px] tracking-[0.3em] border-b border-[var(--kyro-border)]", children: [
|
|
1241
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "text-[var(--kyro-text-secondary)] font-bold text-[10px] tracking-[0.3em] border-b border-[var(--kyro-border)] whitespace-nowrap", children: [
|
|
1165
1242
|
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-4 py-4 w-10", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1166
1243
|
"input",
|
|
1167
1244
|
{
|
|
@@ -1349,26 +1426,26 @@ function UploadField({
|
|
|
1349
1426
|
onChange,
|
|
1350
1427
|
disabled
|
|
1351
1428
|
}) {
|
|
1352
|
-
const inputRef =
|
|
1353
|
-
const urlInputRef =
|
|
1354
|
-
const [uploading, setUploading] =
|
|
1355
|
-
const [showPicker, setShowPicker] =
|
|
1356
|
-
const [isPickerFullscreen, setIsPickerFullscreen] =
|
|
1357
|
-
const [mediaItems, setMediaItems] =
|
|
1358
|
-
const [folders, setFolders] =
|
|
1359
|
-
const [selectedFolder, setSelectedFolder] =
|
|
1360
|
-
const [mediaLoading, setMediaLoading] =
|
|
1361
|
-
const [pickerSearch, setPickerSearch] =
|
|
1362
|
-
const [showUrlInput, setShowUrlInput] =
|
|
1363
|
-
const [urlValue, setUrlValue] =
|
|
1364
|
-
const [urlError, setUrlError] =
|
|
1365
|
-
const [selectedItems, setSelectedItems] =
|
|
1429
|
+
const inputRef = React.useRef(null);
|
|
1430
|
+
const urlInputRef = React.useRef(null);
|
|
1431
|
+
const [uploading, setUploading] = React.useState(false);
|
|
1432
|
+
const [showPicker, setShowPicker] = React.useState(false);
|
|
1433
|
+
const [isPickerFullscreen, setIsPickerFullscreen] = React.useState(false);
|
|
1434
|
+
const [mediaItems, setMediaItems] = React.useState([]);
|
|
1435
|
+
const [folders, setFolders] = React.useState([]);
|
|
1436
|
+
const [selectedFolder, setSelectedFolder] = React.useState("");
|
|
1437
|
+
const [mediaLoading, setMediaLoading] = React.useState(false);
|
|
1438
|
+
const [pickerSearch, setPickerSearch] = React.useState("");
|
|
1439
|
+
const [showUrlInput, setShowUrlInput] = React.useState(false);
|
|
1440
|
+
const [urlValue, setUrlValue] = React.useState("");
|
|
1441
|
+
const [urlError, setUrlError] = React.useState("");
|
|
1442
|
+
const [selectedItems, setSelectedItems] = React.useState([]);
|
|
1366
1443
|
const fieldLabel = field3?.label || field3?.name || "File";
|
|
1367
1444
|
const maxCount = field3.maxCount ?? (field3.hasMany ? 999 : 1);
|
|
1368
1445
|
const isMultiple = maxCount > 1;
|
|
1369
1446
|
const currentValue = Array.isArray(value) ? value : value ? [value] : [];
|
|
1370
1447
|
const canAddMore = currentValue.length < maxCount;
|
|
1371
|
-
|
|
1448
|
+
React.useEffect(() => {
|
|
1372
1449
|
const fetchMissingDetails = async () => {
|
|
1373
1450
|
const idsToFetch = currentValue.filter((item) => typeof item === "string").map((id) => id);
|
|
1374
1451
|
const objectIdsToFetch = currentValue.filter(
|
|
@@ -1402,7 +1479,7 @@ function UploadField({
|
|
|
1402
1479
|
};
|
|
1403
1480
|
fetchMissingDetails();
|
|
1404
1481
|
}, [value]);
|
|
1405
|
-
|
|
1482
|
+
React.useEffect(() => {
|
|
1406
1483
|
if (showPicker) {
|
|
1407
1484
|
loadFolders();
|
|
1408
1485
|
loadMedia();
|
|
@@ -1528,7 +1605,7 @@ function UploadField({
|
|
|
1528
1605
|
newValue.splice(index, 1);
|
|
1529
1606
|
onChange(isMultiple ? newValue : newValue[0] || null);
|
|
1530
1607
|
};
|
|
1531
|
-
const filteredMedia =
|
|
1608
|
+
const filteredMedia = React.useMemo(() => {
|
|
1532
1609
|
return mediaItems.filter((item) => {
|
|
1533
1610
|
return !pickerSearch || item.filename?.toLowerCase().includes(pickerSearch.toLowerCase()) || item.title?.toLowerCase().includes(pickerSearch.toLowerCase());
|
|
1534
1611
|
});
|
|
@@ -1935,12 +2012,12 @@ function SlidePanel({
|
|
|
1935
2012
|
showOverlay = false,
|
|
1936
2013
|
accentClass
|
|
1937
2014
|
}) {
|
|
1938
|
-
const panelRef =
|
|
1939
|
-
const [hydrated, setHydrated] =
|
|
1940
|
-
|
|
2015
|
+
const panelRef = React.useRef(null);
|
|
2016
|
+
const [hydrated, setHydrated] = React.useState(false);
|
|
2017
|
+
React.useEffect(() => {
|
|
1941
2018
|
setHydrated(true);
|
|
1942
2019
|
}, []);
|
|
1943
|
-
|
|
2020
|
+
React.useEffect(() => {
|
|
1944
2021
|
const handleEscape = (e) => {
|
|
1945
2022
|
if (e.key === "Escape") onClose();
|
|
1946
2023
|
};
|
|
@@ -1954,10 +2031,10 @@ function SlidePanel({
|
|
|
1954
2031
|
};
|
|
1955
2032
|
}, [open, onClose]);
|
|
1956
2033
|
const widthClasses = {
|
|
1957
|
-
sm: "w-[320px]",
|
|
1958
|
-
md: "w-[400px]",
|
|
1959
|
-
lg: "w-[550px]",
|
|
1960
|
-
xl: "w-[700px]"
|
|
2034
|
+
sm: "w-full sm:w-[320px]",
|
|
2035
|
+
md: "w-full sm:w-[400px]",
|
|
2036
|
+
lg: "w-full sm:w-[550px]",
|
|
2037
|
+
xl: "w-full sm:w-[700px]"
|
|
1961
2038
|
};
|
|
1962
2039
|
if (!open || !hydrated) return null;
|
|
1963
2040
|
return reactDom.createPortal(
|
|
@@ -2021,7 +2098,7 @@ function Modal({
|
|
|
2021
2098
|
size = "md",
|
|
2022
2099
|
variant = "default"
|
|
2023
2100
|
}) {
|
|
2024
|
-
|
|
2101
|
+
React.useEffect(() => {
|
|
2025
2102
|
const handleEscape = (e) => {
|
|
2026
2103
|
if (e.key === "Escape") onClose();
|
|
2027
2104
|
};
|
|
@@ -2129,7 +2206,7 @@ function PromptModal({
|
|
|
2129
2206
|
placeholder = "",
|
|
2130
2207
|
defaultValue = ""
|
|
2131
2208
|
}) {
|
|
2132
|
-
const [value, setValue] =
|
|
2209
|
+
const [value, setValue] = React.useState(defaultValue);
|
|
2133
2210
|
const handleSubmit = (e) => {
|
|
2134
2211
|
e.preventDefault();
|
|
2135
2212
|
if (value.trim()) {
|
|
@@ -2242,35 +2319,36 @@ function MediaGallery({
|
|
|
2242
2319
|
const canUpload = permissions?.media?.create !== false;
|
|
2243
2320
|
const canDelete = permissions?.media?.delete !== false;
|
|
2244
2321
|
const canUpdate = permissions?.media?.update !== false;
|
|
2245
|
-
const [items, setItems] =
|
|
2246
|
-
const [loading, setLoading] =
|
|
2247
|
-
const [folders, setFolders] =
|
|
2248
|
-
const [currentFolder, setCurrentFolder] =
|
|
2249
|
-
const [search, setSearch] =
|
|
2250
|
-
const [filter, setFilter] =
|
|
2251
|
-
const [view, setView] =
|
|
2252
|
-
const [panelItem, setPanelItem] =
|
|
2253
|
-
const [showPreview, setShowPreview] =
|
|
2254
|
-
const [showCrop, setShowCrop] =
|
|
2255
|
-
const [uploading, setUploading] =
|
|
2256
|
-
const [uploadProgress, setUploadProgress] =
|
|
2322
|
+
const [items, setItems] = React.useState([]);
|
|
2323
|
+
const [loading, setLoading] = React.useState(true);
|
|
2324
|
+
const [folders, setFolders] = React.useState([]);
|
|
2325
|
+
const [currentFolder, setCurrentFolder] = React.useState("");
|
|
2326
|
+
const [search, setSearch] = React.useState("");
|
|
2327
|
+
const [filter, setFilter] = React.useState("all");
|
|
2328
|
+
const [view, setView] = React.useState("grid");
|
|
2329
|
+
const [panelItem, setPanelItem] = React.useState(null);
|
|
2330
|
+
const [showPreview, setShowPreview] = React.useState(false);
|
|
2331
|
+
const [showCrop, setShowCrop] = React.useState(false);
|
|
2332
|
+
const [uploading, setUploading] = React.useState(false);
|
|
2333
|
+
const [uploadProgress, setUploadProgress] = React.useState(
|
|
2257
2334
|
{}
|
|
2258
2335
|
);
|
|
2259
|
-
const [showNewFolderModal, setShowNewFolderModal] =
|
|
2260
|
-
const [
|
|
2261
|
-
const [
|
|
2262
|
-
const [
|
|
2263
|
-
const [
|
|
2264
|
-
const [
|
|
2265
|
-
const [
|
|
2336
|
+
const [showNewFolderModal, setShowNewFolderModal] = React.useState(false);
|
|
2337
|
+
const [showMobileFilters, setShowMobileFilters] = React.useState(false);
|
|
2338
|
+
const [storageConfigured, setStorageConfigured] = React.useState(null);
|
|
2339
|
+
const [storageChecked, setStorageChecked] = React.useState(false);
|
|
2340
|
+
const [showStorageConfigModal, setShowStorageConfigModal] = React.useState(false);
|
|
2341
|
+
const [page, setPage] = React.useState(1);
|
|
2342
|
+
const [total, setTotal] = React.useState(0);
|
|
2343
|
+
const [totalPages, setTotalPages] = React.useState(1);
|
|
2266
2344
|
const limit = 40;
|
|
2267
|
-
const [selectedIds, setSelectedIds] =
|
|
2345
|
+
const [selectedIds, setSelectedIds] = React.useState(/* @__PURE__ */ new Set());
|
|
2268
2346
|
const { confirm, alert } = useUIStore();
|
|
2269
|
-
const [isDragging, setIsDragging] =
|
|
2270
|
-
const fileInputRef =
|
|
2271
|
-
const [crop, setCrop] =
|
|
2272
|
-
const imgRef =
|
|
2273
|
-
const loadMedia =
|
|
2347
|
+
const [isDragging, setIsDragging] = React.useState(false);
|
|
2348
|
+
const fileInputRef = React.useRef(null);
|
|
2349
|
+
const [crop, setCrop] = React.useState();
|
|
2350
|
+
const imgRef = React.useRef(null);
|
|
2351
|
+
const loadMedia = React.useCallback(async () => {
|
|
2274
2352
|
setLoading(true);
|
|
2275
2353
|
try {
|
|
2276
2354
|
const params = new URLSearchParams({
|
|
@@ -2293,7 +2371,7 @@ function MediaGallery({
|
|
|
2293
2371
|
setLoading(false);
|
|
2294
2372
|
}
|
|
2295
2373
|
}, [page, currentFolder, search, filter]);
|
|
2296
|
-
const loadFolders =
|
|
2374
|
+
const loadFolders = React.useCallback(async () => {
|
|
2297
2375
|
try {
|
|
2298
2376
|
const result = await apiGet(withCacheBust("/api/media/folders"));
|
|
2299
2377
|
setFolders(Array.isArray(result) ? result : result.folders || []);
|
|
@@ -2301,7 +2379,7 @@ function MediaGallery({
|
|
|
2301
2379
|
console.error("Failed to load folders:", error);
|
|
2302
2380
|
}
|
|
2303
2381
|
}, []);
|
|
2304
|
-
const checkStorage =
|
|
2382
|
+
const checkStorage = React.useCallback(async () => {
|
|
2305
2383
|
try {
|
|
2306
2384
|
const res = await apiGet("/api/globals/storage-settings");
|
|
2307
2385
|
const isConfigured = !!res?.data?.provider;
|
|
@@ -2310,23 +2388,23 @@ function MediaGallery({
|
|
|
2310
2388
|
setStorageConfigured(false);
|
|
2311
2389
|
}
|
|
2312
2390
|
}, []);
|
|
2313
|
-
|
|
2391
|
+
React.useEffect(() => {
|
|
2314
2392
|
if (!pickerMode) checkStorage();
|
|
2315
2393
|
}, [checkStorage, pickerMode]);
|
|
2316
|
-
|
|
2394
|
+
React.useEffect(() => {
|
|
2317
2395
|
if (pickerMode) return;
|
|
2318
2396
|
if (storageConfigured === false && !storageChecked) {
|
|
2319
2397
|
setStorageChecked(true);
|
|
2320
2398
|
setShowStorageConfigModal(true);
|
|
2321
2399
|
}
|
|
2322
2400
|
}, [pickerMode, storageConfigured, storageChecked]);
|
|
2323
|
-
|
|
2401
|
+
React.useEffect(() => {
|
|
2324
2402
|
loadMedia();
|
|
2325
2403
|
}, [loadMedia]);
|
|
2326
|
-
|
|
2404
|
+
React.useEffect(() => {
|
|
2327
2405
|
loadFolders();
|
|
2328
2406
|
}, [loadFolders]);
|
|
2329
|
-
|
|
2407
|
+
React.useEffect(() => {
|
|
2330
2408
|
if (pickerMode) return;
|
|
2331
2409
|
const handlePaste = (e) => {
|
|
2332
2410
|
const files = e.clipboardData?.files;
|
|
@@ -2410,6 +2488,7 @@ function MediaGallery({
|
|
|
2410
2488
|
await apiPost("/api/media/folders", { name });
|
|
2411
2489
|
loadFolders();
|
|
2412
2490
|
setShowNewFolderModal(false);
|
|
2491
|
+
toast.success(`Folder "${name}" created`);
|
|
2413
2492
|
} catch (error) {
|
|
2414
2493
|
console.error("Failed to create folder:", error);
|
|
2415
2494
|
toast.error("Failed to create folder");
|
|
@@ -2427,6 +2506,7 @@ function MediaGallery({
|
|
|
2427
2506
|
if (currentFolder === folder) setCurrentFolder("");
|
|
2428
2507
|
loadFolders();
|
|
2429
2508
|
loadMedia();
|
|
2509
|
+
toast.success(`Folder "${folder}" deleted`);
|
|
2430
2510
|
} catch (error) {
|
|
2431
2511
|
console.error("Failed to delete folder:", error);
|
|
2432
2512
|
toast.error("Failed to delete folder");
|
|
@@ -2441,8 +2521,10 @@ function MediaGallery({
|
|
|
2441
2521
|
if (panelItem?.id === id) {
|
|
2442
2522
|
setPanelItem(result.doc);
|
|
2443
2523
|
}
|
|
2524
|
+
toast.success("Metadata updated");
|
|
2444
2525
|
} catch (error) {
|
|
2445
2526
|
console.error("Failed to update metadata:", error);
|
|
2527
|
+
toast.error("Failed to update metadata");
|
|
2446
2528
|
}
|
|
2447
2529
|
};
|
|
2448
2530
|
const onImageLoad = (e) => {
|
|
@@ -2491,6 +2573,7 @@ function MediaGallery({
|
|
|
2491
2573
|
await apiUpload("/api/media", formData);
|
|
2492
2574
|
loadMedia();
|
|
2493
2575
|
setShowCrop(false);
|
|
2576
|
+
toast.success("Cropped image saved");
|
|
2494
2577
|
}
|
|
2495
2578
|
}
|
|
2496
2579
|
} catch (err) {
|
|
@@ -2500,7 +2583,7 @@ function MediaGallery({
|
|
|
2500
2583
|
setUploading(false);
|
|
2501
2584
|
}
|
|
2502
2585
|
};
|
|
2503
|
-
const stats =
|
|
2586
|
+
const stats = React.useMemo(() => {
|
|
2504
2587
|
return items.reduce(
|
|
2505
2588
|
(acc, item) => {
|
|
2506
2589
|
acc.totalSize += item.fileSize || 0;
|
|
@@ -2526,7 +2609,7 @@ function MediaGallery({
|
|
|
2526
2609
|
}
|
|
2527
2610
|
},
|
|
2528
2611
|
children: [
|
|
2529
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex flex-col lg:flex-row lg:items-center justify-between gap-6 border-b border-[var(--kyro-border)] backdrop-blur-md sticky top-0
|
|
2612
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex flex-col lg:flex-row lg:items-center justify-between gap-6 border-b border-[var(--kyro-border)] backdrop-blur-md sticky top-0 ${pickerMode ? "p-2" : "p-6 rounded-xl surface-tile"}`, children: [
|
|
2530
2613
|
!pickerMode && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2531
2614
|
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-xl font-bold tracking-tighter text-[var(--kyro-text-primary)]", children: "Media Library" }),
|
|
2532
2615
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-3 mt-1", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[10px] font-bold tracking-widest text-[var(--kyro-text-secondary)] opacity-50", children: [
|
|
@@ -2537,7 +2620,7 @@ function MediaGallery({
|
|
|
2537
2620
|
] }) }),
|
|
2538
2621
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex items-center gap-3 flex-wrap lg:flex-nowrap ${pickerMode ? "w-full" : ""}`, children: [
|
|
2539
2622
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative group flex-1 min-w-[200px]", children: [
|
|
2540
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "w-4 h-4" }),
|
|
2623
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-[var(--kyro-text-muted)]" }),
|
|
2541
2624
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2542
2625
|
"input",
|
|
2543
2626
|
{
|
|
@@ -2550,21 +2633,31 @@ function MediaGallery({
|
|
|
2550
2633
|
)
|
|
2551
2634
|
] }),
|
|
2552
2635
|
!pickerMode && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2553
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex
|
|
2554
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2636
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2637
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex bg-[var(--kyro-surface-accent)] p-1 rounded-xl border border-[var(--kyro-border)]", children: [
|
|
2638
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2639
|
+
"button",
|
|
2640
|
+
{
|
|
2641
|
+
onClick: () => setView("grid"),
|
|
2642
|
+
className: `p-2 rounded-lg transition-all ${view === "grid" ? "bg-[var(--kyro-surface)] shadow-sm text-[var(--kyro-text-primary)]" : "text-[var(--kyro-text-secondary)] opacity-50 hover:opacity-100"}`,
|
|
2643
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Grid3X3, { className: "w-4 h-4" })
|
|
2644
|
+
}
|
|
2645
|
+
),
|
|
2646
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2647
|
+
"button",
|
|
2648
|
+
{
|
|
2649
|
+
onClick: () => setView("list"),
|
|
2650
|
+
className: `p-2 rounded-lg transition-all ${view === "list" ? "bg-[var(--kyro-surface)] shadow-sm text-[var(--kyro-text-primary)]" : "text-[var(--kyro-text-secondary)] opacity-50 hover:opacity-100"}`,
|
|
2651
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.File, { className: "w-4 h-4" })
|
|
2652
|
+
}
|
|
2653
|
+
)
|
|
2654
|
+
] }),
|
|
2562
2655
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2563
2656
|
"button",
|
|
2564
2657
|
{
|
|
2565
|
-
onClick: () =>
|
|
2566
|
-
className:
|
|
2567
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.
|
|
2658
|
+
onClick: () => setShowMobileFilters(true),
|
|
2659
|
+
className: "md:hidden p-2 rounded-xl bg-[var(--kyro-surface-accent)] border border-[var(--kyro-border)] text-[var(--kyro-text-secondary)] hover:text-[var(--kyro-text-primary)] transition-colors",
|
|
2660
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Filter, { className: "w-4 h-4" })
|
|
2568
2661
|
}
|
|
2569
2662
|
)
|
|
2570
2663
|
] }),
|
|
@@ -2863,6 +2956,105 @@ function MediaGallery({
|
|
|
2863
2956
|
)
|
|
2864
2957
|
] })
|
|
2865
2958
|
] }),
|
|
2959
|
+
showMobileFilters && !pickerMode && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fixed inset-0 z-[70] md:hidden", children: [
|
|
2960
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2961
|
+
"div",
|
|
2962
|
+
{
|
|
2963
|
+
className: "fixed inset-0 bg-black/50 backdrop-blur-sm",
|
|
2964
|
+
onClick: () => setShowMobileFilters(false)
|
|
2965
|
+
}
|
|
2966
|
+
),
|
|
2967
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fixed bottom-0 left-0 right-0 bg-[var(--kyro-surface)] rounded-t-3xl shadow-2xl max-h-[70vh] overflow-y-auto animate-in slide-in-from-bottom-12 duration-300", children: [
|
|
2968
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "sticky top-0 bg-[var(--kyro-surface)] z-10 flex items-center justify-between p-6 pb-4 border-b border-[var(--kyro-border)]", children: [
|
|
2969
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-sm font-bold tracking-tight text-[var(--kyro-text-primary)]", children: "Filters" }),
|
|
2970
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2971
|
+
"button",
|
|
2972
|
+
{
|
|
2973
|
+
onClick: () => setShowMobileFilters(false),
|
|
2974
|
+
className: "p-2 rounded-xl hover:bg-[var(--kyro-surface-accent)] transition-colors text-[var(--kyro-text-muted)]",
|
|
2975
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-4 h-4" })
|
|
2976
|
+
}
|
|
2977
|
+
)
|
|
2978
|
+
] }),
|
|
2979
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-6 space-y-8", children: [
|
|
2980
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2981
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-bold tracking-[0.2em] text-[var(--kyro-text-secondary)] opacity-40 block mb-4", children: "Quick Filters" }),
|
|
2982
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: ["all", "image", "video", "audio", "document", "archive"].map((t) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2983
|
+
"button",
|
|
2984
|
+
{
|
|
2985
|
+
onClick: () => {
|
|
2986
|
+
setFilter(t);
|
|
2987
|
+
setShowMobileFilters(false);
|
|
2988
|
+
},
|
|
2989
|
+
className: `px-4 py-2 rounded-xl text-[11px] font-bold capitalize transition-all border ${filter === t ? "bg-[var(--kyro-sidebar-active)] text-[var(--kyro-sidebar-text-active)] border-transparent" : "bg-[var(--kyro-surface-accent)] text-[var(--kyro-text-secondary)] border-[var(--kyro-border)] hover:border-[var(--kyro-text-muted)]"}`,
|
|
2990
|
+
children: t
|
|
2991
|
+
},
|
|
2992
|
+
t
|
|
2993
|
+
)) })
|
|
2994
|
+
] }),
|
|
2995
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2996
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-4", children: [
|
|
2997
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-bold tracking-[0.2em] text-[var(--kyro-text-secondary)] opacity-40", children: "Folders" }),
|
|
2998
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2999
|
+
"button",
|
|
3000
|
+
{
|
|
3001
|
+
onClick: () => {
|
|
3002
|
+
setShowNewFolderModal(true);
|
|
3003
|
+
setShowMobileFilters(false);
|
|
3004
|
+
},
|
|
3005
|
+
className: "p-1.5 hover:bg-[var(--kyro-surface-accent)] rounded-lg transition-colors text-[var(--kyro-text-primary)]",
|
|
3006
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FolderPlus, { className: "w-4 h-4" })
|
|
3007
|
+
}
|
|
3008
|
+
)
|
|
3009
|
+
] }),
|
|
3010
|
+
/* @__PURE__ */ jsxRuntime.jsxs("nav", { className: "space-y-1", children: [
|
|
3011
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3012
|
+
"button",
|
|
3013
|
+
{
|
|
3014
|
+
onClick: () => {
|
|
3015
|
+
setCurrentFolder("");
|
|
3016
|
+
setShowMobileFilters(false);
|
|
3017
|
+
},
|
|
3018
|
+
className: `w-full flex items-center gap-3 px-4 py-2.5 rounded-xl text-xs font-bold transition-all ${currentFolder === "" ? "bg-[var(--kyro-sidebar-active)] text-[var(--kyro-sidebar-text-active)] shadow-md" : "text-[var(--kyro-text-secondary)] hover:bg-[var(--kyro-surface-accent)] hover:text-[var(--kyro-text-primary)]"}`,
|
|
3019
|
+
children: [
|
|
3020
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.FolderInput, { className: "w-4 h-4 opacity-70" }),
|
|
3021
|
+
"All Assets"
|
|
3022
|
+
]
|
|
3023
|
+
}
|
|
3024
|
+
),
|
|
3025
|
+
folders.map((folder) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "group relative", children: [
|
|
3026
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3027
|
+
"button",
|
|
3028
|
+
{
|
|
3029
|
+
onClick: () => {
|
|
3030
|
+
setCurrentFolder(folder);
|
|
3031
|
+
setShowMobileFilters(false);
|
|
3032
|
+
},
|
|
3033
|
+
className: `w-full flex items-center gap-3 px-4 py-2.5 rounded-xl text-xs font-bold transition-all ${currentFolder === folder ? "bg-[var(--kyro-sidebar-active)] text-[var(--kyro-sidebar-text-active)] shadow-md" : "text-[var(--kyro-text-secondary)] hover:bg-[var(--kyro-surface-accent)] hover:text-[var(--kyro-text-primary)]"}`,
|
|
3034
|
+
children: [
|
|
3035
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-4 h-4 flex items-center justify-center opacity-70", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Folder, { fill: currentFolder === folder ? "currentColor" : "none" }) }),
|
|
3036
|
+
folder
|
|
3037
|
+
]
|
|
3038
|
+
}
|
|
3039
|
+
),
|
|
3040
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3041
|
+
"button",
|
|
3042
|
+
{
|
|
3043
|
+
onClick: (e) => {
|
|
3044
|
+
e.stopPropagation();
|
|
3045
|
+
handleDeleteFolder(folder);
|
|
3046
|
+
setShowMobileFilters(false);
|
|
3047
|
+
},
|
|
3048
|
+
className: "absolute right-2 top-1/2 -translate-y-1/2 p-1.5 text-red-500 opacity-0 group-hover:opacity-100 transition-all hover:bg-red-50 rounded-lg",
|
|
3049
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "w-3.5 h-3.5" })
|
|
3050
|
+
}
|
|
3051
|
+
)
|
|
3052
|
+
] }, folder))
|
|
3053
|
+
] })
|
|
3054
|
+
] })
|
|
3055
|
+
] })
|
|
3056
|
+
] })
|
|
3057
|
+
] }),
|
|
2866
3058
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2867
3059
|
SlidePanel,
|
|
2868
3060
|
{
|
|
@@ -3160,6 +3352,8 @@ function MediaGallery({
|
|
|
3160
3352
|
setShowStorageConfigModal(false);
|
|
3161
3353
|
setStorageConfigured(true);
|
|
3162
3354
|
window.location.reload();
|
|
3355
|
+
}).catch(() => {
|
|
3356
|
+
toast.error("Failed to configure storage");
|
|
3163
3357
|
});
|
|
3164
3358
|
},
|
|
3165
3359
|
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",
|
|
@@ -3205,9 +3399,9 @@ var MenuBar = ({
|
|
|
3205
3399
|
setIsExpanded,
|
|
3206
3400
|
onOpenMediaPicker
|
|
3207
3401
|
}) => {
|
|
3208
|
-
const [activeDropdown, setActiveDropdown] =
|
|
3209
|
-
const menuBarRef =
|
|
3210
|
-
|
|
3402
|
+
const [activeDropdown, setActiveDropdown] = React.useState(null);
|
|
3403
|
+
const menuBarRef = React.useRef(null);
|
|
3404
|
+
React.useEffect(() => {
|
|
3211
3405
|
function handleClickOutside(event) {
|
|
3212
3406
|
if (menuBarRef.current && !menuBarRef.current.contains(event.target)) {
|
|
3213
3407
|
setActiveDropdown(null);
|
|
@@ -3667,14 +3861,14 @@ function RichTextField({
|
|
|
3667
3861
|
error,
|
|
3668
3862
|
disabled
|
|
3669
3863
|
}) {
|
|
3670
|
-
const [isExpanded, setIsExpanded] =
|
|
3671
|
-
const [panelWidth, setPanelWidth] =
|
|
3672
|
-
const [isMediaPickerOpen, setIsMediaPickerOpen] =
|
|
3673
|
-
const [isMounted, setIsMounted] =
|
|
3674
|
-
|
|
3864
|
+
const [isExpanded, setIsExpanded] = React.useState(false);
|
|
3865
|
+
const [panelWidth, setPanelWidth] = React.useState(0);
|
|
3866
|
+
const [isMediaPickerOpen, setIsMediaPickerOpen] = React.useState(false);
|
|
3867
|
+
const [isMounted, setIsMounted] = React.useState(false);
|
|
3868
|
+
React.useEffect(() => {
|
|
3675
3869
|
setIsMounted(true);
|
|
3676
3870
|
}, []);
|
|
3677
|
-
|
|
3871
|
+
React.useEffect(() => {
|
|
3678
3872
|
if (!isExpanded) {
|
|
3679
3873
|
setPanelWidth(0);
|
|
3680
3874
|
return;
|
|
@@ -3740,7 +3934,7 @@ function RichTextField({
|
|
|
3740
3934
|
}
|
|
3741
3935
|
}
|
|
3742
3936
|
});
|
|
3743
|
-
|
|
3937
|
+
React.useEffect(() => {
|
|
3744
3938
|
if (editor && value && JSON.stringify(value) !== JSON.stringify(editor.getJSON())) {
|
|
3745
3939
|
editor.commands.setContent(value);
|
|
3746
3940
|
}
|
|
@@ -4009,9 +4203,9 @@ function mergeThemes(base, overrides) {
|
|
|
4009
4203
|
fields: base.fields ? { ...base.fields, ...overrides.fields } : overrides.fields
|
|
4010
4204
|
};
|
|
4011
4205
|
}
|
|
4012
|
-
var ThemeContext =
|
|
4206
|
+
var ThemeContext = React.createContext(null);
|
|
4013
4207
|
function useTheme() {
|
|
4014
|
-
const context =
|
|
4208
|
+
const context = React.useContext(ThemeContext);
|
|
4015
4209
|
if (!context) {
|
|
4016
4210
|
return {
|
|
4017
4211
|
mode: "light",
|
|
@@ -4122,16 +4316,16 @@ function ThemeProvider({
|
|
|
4122
4316
|
light: lightOverrides,
|
|
4123
4317
|
dark: darkOverrides
|
|
4124
4318
|
}) {
|
|
4125
|
-
const [mode, setMode] =
|
|
4126
|
-
const [baseLight, setBaseLight] =
|
|
4319
|
+
const [mode, setMode] = React.useState(defaultMode);
|
|
4320
|
+
const [baseLight, setBaseLight] = React.useState(
|
|
4127
4321
|
lightOverrides || {}
|
|
4128
4322
|
);
|
|
4129
|
-
const [baseDark, setBaseDark] =
|
|
4323
|
+
const [baseDark, setBaseDark] = React.useState(
|
|
4130
4324
|
darkOverrides || {}
|
|
4131
4325
|
);
|
|
4132
4326
|
const lightTheme = mergeThemes(LIGHT_THEME, baseLight);
|
|
4133
4327
|
const darkTheme = mergeThemes(DARK_THEME, baseDark);
|
|
4134
|
-
const getResolvedTheme =
|
|
4328
|
+
const getResolvedTheme = React.useCallback(() => {
|
|
4135
4329
|
if (mode === "system") {
|
|
4136
4330
|
if (typeof window !== "undefined") {
|
|
4137
4331
|
return window.matchMedia("(prefers-color-scheme: dark)").matches ? darkTheme : lightTheme;
|
|
@@ -4140,13 +4334,13 @@ function ThemeProvider({
|
|
|
4140
4334
|
}
|
|
4141
4335
|
return mode === "dark" ? darkTheme : lightTheme;
|
|
4142
4336
|
}, [mode, lightTheme, darkTheme]);
|
|
4143
|
-
const [theme, setTheme] =
|
|
4144
|
-
|
|
4337
|
+
const [theme, setTheme] = React.useState(getResolvedTheme());
|
|
4338
|
+
React.useEffect(() => {
|
|
4145
4339
|
const resolved = getResolvedTheme();
|
|
4146
4340
|
setTheme(resolved);
|
|
4147
4341
|
applyThemeToDOM(resolved);
|
|
4148
4342
|
}, [getResolvedTheme]);
|
|
4149
|
-
|
|
4343
|
+
React.useEffect(() => {
|
|
4150
4344
|
if (mode !== "system") return;
|
|
4151
4345
|
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
4152
4346
|
const handler = () => {
|
|
@@ -4157,11 +4351,11 @@ function ThemeProvider({
|
|
|
4157
4351
|
mediaQuery.addEventListener("change", handler);
|
|
4158
4352
|
return () => mediaQuery.removeEventListener("change", handler);
|
|
4159
4353
|
}, [mode, getResolvedTheme]);
|
|
4160
|
-
const updateTheme =
|
|
4354
|
+
const updateTheme = React.useCallback((overrides) => {
|
|
4161
4355
|
setBaseLight((prev) => ({ ...prev, ...overrides }));
|
|
4162
4356
|
setBaseDark((prev) => ({ ...prev, ...overrides }));
|
|
4163
4357
|
}, []);
|
|
4164
|
-
const getCssVar =
|
|
4358
|
+
const getCssVar = React.useCallback((key) => `var(--kyro-${key})`, []);
|
|
4165
4359
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4166
4360
|
ThemeContext.Provider,
|
|
4167
4361
|
{
|
|
@@ -4180,7 +4374,7 @@ function ThemeProvider({
|
|
|
4180
4374
|
}
|
|
4181
4375
|
var LightThemeProvider = (props) => /* @__PURE__ */ jsxRuntime.jsx(ThemeProvider, { defaultMode: "light", ...props });
|
|
4182
4376
|
var DarkThemeProvider = (props) => /* @__PURE__ */ jsxRuntime.jsx(ThemeProvider, { defaultMode: "dark", ...props });
|
|
4183
|
-
var CodeMirrorEditor =
|
|
4377
|
+
var CodeMirrorEditor = React.lazy(
|
|
4184
4378
|
() => import('@uiw/react-codemirror').then((mod) => ({ default: mod.default }))
|
|
4185
4379
|
);
|
|
4186
4380
|
var LANGUAGES = [
|
|
@@ -4232,16 +4426,16 @@ var CodeField = ({
|
|
|
4232
4426
|
error,
|
|
4233
4427
|
disabled
|
|
4234
4428
|
}) => {
|
|
4235
|
-
const [isMounted, setIsMounted] =
|
|
4236
|
-
const [isDark, setIsDark] =
|
|
4237
|
-
const [extensions, setExtensions] =
|
|
4238
|
-
const [loading, setLoading] =
|
|
4239
|
-
const [copied, setCopied] =
|
|
4240
|
-
const [isFullScreen, setIsFullScreen] =
|
|
4429
|
+
const [isMounted, setIsMounted] = React.useState(false);
|
|
4430
|
+
const [isDark, setIsDark] = React.useState(false);
|
|
4431
|
+
const [extensions, setExtensions] = React.useState([]);
|
|
4432
|
+
const [loading, setLoading] = React.useState(false);
|
|
4433
|
+
const [copied, setCopied] = React.useState(false);
|
|
4434
|
+
const [isFullScreen, setIsFullScreen] = React.useState(false);
|
|
4241
4435
|
const { theme } = useTheme();
|
|
4242
4436
|
const accent = theme.colors?.accent || theme.colors?.primary || "#6366f1";
|
|
4243
4437
|
const language = field3.language?.toLowerCase() || "javascript";
|
|
4244
|
-
|
|
4438
|
+
React.useEffect(() => {
|
|
4245
4439
|
setIsMounted(true);
|
|
4246
4440
|
setIsDark(document.documentElement.classList.contains("dark"));
|
|
4247
4441
|
const observer = new MutationObserver(() => {
|
|
@@ -4253,7 +4447,7 @@ var CodeField = ({
|
|
|
4253
4447
|
});
|
|
4254
4448
|
return () => observer.disconnect();
|
|
4255
4449
|
}, []);
|
|
4256
|
-
|
|
4450
|
+
React.useEffect(() => {
|
|
4257
4451
|
if (!isMounted) return;
|
|
4258
4452
|
const loadExtensions = async () => {
|
|
4259
4453
|
setLoading(true);
|
|
@@ -4270,16 +4464,16 @@ var CodeField = ({
|
|
|
4270
4464
|
};
|
|
4271
4465
|
loadExtensions();
|
|
4272
4466
|
}, [language, isMounted]);
|
|
4273
|
-
const handleChange =
|
|
4467
|
+
const handleChange = React.useCallback(
|
|
4274
4468
|
(val) => onChange?.(val),
|
|
4275
4469
|
[onChange]
|
|
4276
4470
|
);
|
|
4277
|
-
const handleCopy =
|
|
4471
|
+
const handleCopy = React.useCallback(() => {
|
|
4278
4472
|
navigator.clipboard.writeText(value);
|
|
4279
4473
|
setCopied(true);
|
|
4280
4474
|
setTimeout(() => setCopied(false), 1500);
|
|
4281
4475
|
}, [value]);
|
|
4282
|
-
const toggleFullScreen =
|
|
4476
|
+
const toggleFullScreen = React.useCallback(() => {
|
|
4283
4477
|
setIsFullScreen((prev) => !prev);
|
|
4284
4478
|
document.body.style.overflow = !isFullScreen ? "hidden" : "";
|
|
4285
4479
|
}, [isFullScreen]);
|
|
@@ -4369,7 +4563,7 @@ var CodeField = ({
|
|
|
4369
4563
|
}
|
|
4370
4564
|
),
|
|
4371
4565
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4372
|
-
|
|
4566
|
+
React.Suspense,
|
|
4373
4567
|
{
|
|
4374
4568
|
fallback: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4375
4569
|
"div",
|
|
@@ -4489,18 +4683,18 @@ var MarkdownField = ({
|
|
|
4489
4683
|
error,
|
|
4490
4684
|
disabled
|
|
4491
4685
|
}) => {
|
|
4492
|
-
const [showPreview, setShowPreview] =
|
|
4493
|
-
const [isMounted, setIsMounted] =
|
|
4494
|
-
|
|
4686
|
+
const [showPreview, setShowPreview] = React.useState(false);
|
|
4687
|
+
const [isMounted, setIsMounted] = React.useState(false);
|
|
4688
|
+
React.useEffect(() => {
|
|
4495
4689
|
setIsMounted(true);
|
|
4496
4690
|
}, []);
|
|
4497
|
-
const handleChange =
|
|
4691
|
+
const handleChange = React.useCallback(
|
|
4498
4692
|
(e) => {
|
|
4499
4693
|
onChange?.(e.target.value);
|
|
4500
4694
|
},
|
|
4501
4695
|
[onChange]
|
|
4502
4696
|
);
|
|
4503
|
-
const wordCount =
|
|
4697
|
+
const wordCount = React.useMemo(() => {
|
|
4504
4698
|
if (!value) return 0;
|
|
4505
4699
|
return value.trim().split(/\s+/).filter(Boolean).length;
|
|
4506
4700
|
}, [value]);
|
|
@@ -4605,8 +4799,8 @@ function SecretField({
|
|
|
4605
4799
|
error,
|
|
4606
4800
|
disabled
|
|
4607
4801
|
}) {
|
|
4608
|
-
const [copied, setCopied] =
|
|
4609
|
-
const [regenerating, setRegenerating] =
|
|
4802
|
+
const [copied, setCopied] = React.useState(false);
|
|
4803
|
+
const [regenerating, setRegenerating] = React.useState(false);
|
|
4610
4804
|
const fullValue = value ?? "";
|
|
4611
4805
|
const displayValue = fullValue.length > 8 ? fullValue.slice(0, -8) + "*".repeat(8) : fullValue;
|
|
4612
4806
|
const handleCopy = async () => {
|
|
@@ -5354,22 +5548,22 @@ function RelationshipField({
|
|
|
5354
5548
|
error,
|
|
5355
5549
|
disabled
|
|
5356
5550
|
}) {
|
|
5357
|
-
const [isOpen, setIsOpen] =
|
|
5358
|
-
const [search, setSearch] =
|
|
5359
|
-
const [options, setOptions] =
|
|
5360
|
-
const [loading, setLoading] =
|
|
5361
|
-
const [selectedDocs, setSelectedDocs] =
|
|
5362
|
-
const fetchedIdsRef =
|
|
5363
|
-
const containerRef =
|
|
5364
|
-
const onChangeRef =
|
|
5551
|
+
const [isOpen, setIsOpen] = React.useState(false);
|
|
5552
|
+
const [search, setSearch] = React.useState("");
|
|
5553
|
+
const [options, setOptions] = React.useState([]);
|
|
5554
|
+
const [loading, setLoading] = React.useState(false);
|
|
5555
|
+
const [selectedDocs, setSelectedDocs] = React.useState([]);
|
|
5556
|
+
const fetchedIdsRef = React.useRef(/* @__PURE__ */ new Set());
|
|
5557
|
+
const containerRef = React.useRef(null);
|
|
5558
|
+
const onChangeRef = React.useRef(() => {
|
|
5365
5559
|
});
|
|
5366
5560
|
onChangeRef.current = onChange || (() => {
|
|
5367
5561
|
});
|
|
5368
5562
|
const isMultiple = field3.hasMany;
|
|
5369
5563
|
const relationTo = Array.isArray(field3.relationTo) ? field3.relationTo : [field3.relationTo];
|
|
5370
5564
|
const isPolymorphic = relationTo.length > 1;
|
|
5371
|
-
const [activeRelation, setActiveRelation] =
|
|
5372
|
-
const extractIds =
|
|
5565
|
+
const [activeRelation, setActiveRelation] = React.useState(relationTo[0]);
|
|
5566
|
+
const extractIds = React.useCallback(() => {
|
|
5373
5567
|
if (!value) return [];
|
|
5374
5568
|
const items = isMultiple ? Array.isArray(value) ? value : [] : value ? [value] : [];
|
|
5375
5569
|
return items.map((item) => {
|
|
@@ -5379,7 +5573,7 @@ function RelationshipField({
|
|
|
5379
5573
|
return String(item);
|
|
5380
5574
|
}).filter(Boolean);
|
|
5381
5575
|
}, [value, isMultiple]);
|
|
5382
|
-
const fetchSelectedDocs =
|
|
5576
|
+
const fetchSelectedDocs = React.useCallback((ids) => {
|
|
5383
5577
|
if (ids.length === 0) return;
|
|
5384
5578
|
ids.forEach((id) => {
|
|
5385
5579
|
if (fetchedIdsRef.current.has(id)) return;
|
|
@@ -5406,11 +5600,11 @@ function RelationshipField({
|
|
|
5406
5600
|
});
|
|
5407
5601
|
});
|
|
5408
5602
|
}, [isPolymorphic, value, activeRelation, isMultiple]);
|
|
5409
|
-
|
|
5603
|
+
React.useEffect(() => {
|
|
5410
5604
|
const ids = extractIds();
|
|
5411
5605
|
fetchSelectedDocs(ids);
|
|
5412
5606
|
}, [extractIds, fetchSelectedDocs]);
|
|
5413
|
-
const fetchOptions =
|
|
5607
|
+
const fetchOptions = React.useCallback((query = "") => {
|
|
5414
5608
|
setLoading(true);
|
|
5415
5609
|
const searchFields = ["title", "name", "label", "email"];
|
|
5416
5610
|
const url = `/api/${activeRelation}?${buildSearchQuery(query, searchFields)}`;
|
|
@@ -5427,13 +5621,13 @@ function RelationshipField({
|
|
|
5427
5621
|
setLoading(false);
|
|
5428
5622
|
});
|
|
5429
5623
|
}, [activeRelation]);
|
|
5430
|
-
|
|
5624
|
+
React.useEffect(() => {
|
|
5431
5625
|
if (isOpen) {
|
|
5432
5626
|
setOptions([]);
|
|
5433
5627
|
fetchOptions(search);
|
|
5434
5628
|
}
|
|
5435
5629
|
}, [isOpen, activeRelation]);
|
|
5436
|
-
|
|
5630
|
+
React.useEffect(() => {
|
|
5437
5631
|
const handleClickOutside = (event) => {
|
|
5438
5632
|
if (containerRef.current && !containerRef.current.contains(event.target)) {
|
|
5439
5633
|
setIsOpen(false);
|
|
@@ -5581,7 +5775,7 @@ function RelationshipField({
|
|
|
5581
5775
|
] });
|
|
5582
5776
|
}
|
|
5583
5777
|
var RelationshipField_default = RelationshipField;
|
|
5584
|
-
var BlocksContext =
|
|
5778
|
+
var BlocksContext = React.createContext(null);
|
|
5585
5779
|
function createBlocksStore(allowedBlocks = [], dynamicCategories = []) {
|
|
5586
5780
|
return vanilla.createStore((set, get) => ({
|
|
5587
5781
|
blocks: [],
|
|
@@ -5736,7 +5930,7 @@ function getDefaultData(type) {
|
|
|
5736
5930
|
return defaults[type] || {};
|
|
5737
5931
|
}
|
|
5738
5932
|
function useBlockById(id) {
|
|
5739
|
-
const store =
|
|
5933
|
+
const store = React.useContext(BlocksContext);
|
|
5740
5934
|
if (!store) return void 0;
|
|
5741
5935
|
return zustand.useStore(store, (state) => {
|
|
5742
5936
|
const findRecursive = (blocksList) => {
|
|
@@ -5761,7 +5955,7 @@ function useBlockById(id) {
|
|
|
5761
5955
|
});
|
|
5762
5956
|
}
|
|
5763
5957
|
function useBlockActions() {
|
|
5764
|
-
const store =
|
|
5958
|
+
const store = React.useContext(BlocksContext);
|
|
5765
5959
|
if (!store) {
|
|
5766
5960
|
throw new Error("useBlockActions must be used within a BlocksContext.Provider");
|
|
5767
5961
|
}
|
|
@@ -6145,7 +6339,7 @@ var ListField = ({
|
|
|
6145
6339
|
onChange,
|
|
6146
6340
|
compact = false
|
|
6147
6341
|
}) => {
|
|
6148
|
-
const [inputValue, setInputValue] =
|
|
6342
|
+
const [inputValue, setInputValue] = React__default.default.useState("");
|
|
6149
6343
|
const handleAdd = () => {
|
|
6150
6344
|
if (inputValue.trim()) {
|
|
6151
6345
|
onChange([...items, inputValue.trim()]);
|
|
@@ -6401,7 +6595,7 @@ var AccordionField = ({
|
|
|
6401
6595
|
onChange,
|
|
6402
6596
|
compact = false
|
|
6403
6597
|
}) => {
|
|
6404
|
-
const [openIndex, setOpenIndex] =
|
|
6598
|
+
const [openIndex, setOpenIndex] = React__default.default.useState(0);
|
|
6405
6599
|
const handleTitleChange = (index, value) => {
|
|
6406
6600
|
const newItems = [...items];
|
|
6407
6601
|
newItems[index] = { ...newItems[index], title: value };
|
|
@@ -6827,7 +7021,7 @@ function ArrayLayout({
|
|
|
6827
7021
|
const firstField = fields2[0];
|
|
6828
7022
|
const labelField = firstField?.name || "user";
|
|
6829
7023
|
const isRelationship = firstField?.type === "relationship";
|
|
6830
|
-
const [openIndex, setOpenIndex] =
|
|
7024
|
+
const [openIndex, setOpenIndex] = React__default.default.useState(0);
|
|
6831
7025
|
function getItemLabel(item) {
|
|
6832
7026
|
for (const key of ["label", "title", "name"]) {
|
|
6833
7027
|
const val = item[key];
|
|
@@ -7367,11 +7561,11 @@ var ChildBlocksTree = ({
|
|
|
7367
7561
|
depth = 0,
|
|
7368
7562
|
maxDepth = MAX_DEPTH
|
|
7369
7563
|
}) => {
|
|
7370
|
-
const [showAddModal, setShowAddModal] =
|
|
7371
|
-
const [expandedIds, setExpandedIds] =
|
|
7372
|
-
const [editingBlockId, setEditingBlockId] =
|
|
7373
|
-
const [confirmDeleteId, setConfirmDeleteId] =
|
|
7374
|
-
const store =
|
|
7564
|
+
const [showAddModal, setShowAddModal] = React.useState(false);
|
|
7565
|
+
const [expandedIds, setExpandedIds] = React.useState(/* @__PURE__ */ new Set());
|
|
7566
|
+
const [editingBlockId, setEditingBlockId] = React.useState(null);
|
|
7567
|
+
const [confirmDeleteId, setConfirmDeleteId] = React.useState(null);
|
|
7568
|
+
const store = React.useContext(BlocksContext);
|
|
7375
7569
|
if (!store) throw new Error("ChildBlocksTree must be used within a BlocksContext");
|
|
7376
7570
|
const dynamicCategories = zustand.useStore(store, (s) => s.dynamicCategories);
|
|
7377
7571
|
const allowedBlocks = zustand.useStore(store, (s) => s.allowedBlocks);
|
|
@@ -7588,11 +7782,11 @@ var NestedChildBlocks = ({
|
|
|
7588
7782
|
depth,
|
|
7589
7783
|
maxDepth
|
|
7590
7784
|
}) => {
|
|
7591
|
-
const [showAddModal, setShowAddModal] =
|
|
7592
|
-
const [expandedIds, setExpandedIds] =
|
|
7593
|
-
const [editingBlockId, setEditingBlockId] =
|
|
7594
|
-
const [confirmDeleteId, setConfirmDeleteId] =
|
|
7595
|
-
const store =
|
|
7785
|
+
const [showAddModal, setShowAddModal] = React.useState(false);
|
|
7786
|
+
const [expandedIds, setExpandedIds] = React.useState(/* @__PURE__ */ new Set());
|
|
7787
|
+
const [editingBlockId, setEditingBlockId] = React.useState(null);
|
|
7788
|
+
const [confirmDeleteId, setConfirmDeleteId] = React.useState(null);
|
|
7789
|
+
const store = React.useContext(BlocksContext);
|
|
7596
7790
|
if (!store) throw new Error("NestedChildBlocks must be used within a BlocksContext");
|
|
7597
7791
|
const dynamicCategories = zustand.useStore(store, (s) => s.dynamicCategories);
|
|
7598
7792
|
const allowedBlocks = zustand.useStore(store, (s) => s.allowedBlocks);
|
|
@@ -8096,13 +8290,13 @@ var RelationshipBlockField = ({
|
|
|
8096
8290
|
onChange,
|
|
8097
8291
|
compact = false
|
|
8098
8292
|
}) => {
|
|
8099
|
-
const [isOpen, setIsOpen] =
|
|
8100
|
-
const [search, setSearch] =
|
|
8101
|
-
const [options, setOptions] =
|
|
8102
|
-
const [loading, setLoading] =
|
|
8103
|
-
const [collections2, setCollections] =
|
|
8104
|
-
const [loadingCollections, setLoadingCollections] =
|
|
8105
|
-
|
|
8293
|
+
const [isOpen, setIsOpen] = React.useState(false);
|
|
8294
|
+
const [search, setSearch] = React.useState("");
|
|
8295
|
+
const [options, setOptions] = React.useState([]);
|
|
8296
|
+
const [loading, setLoading] = React.useState(false);
|
|
8297
|
+
const [collections2, setCollections] = React.useState([]);
|
|
8298
|
+
const [loadingCollections, setLoadingCollections] = React.useState(true);
|
|
8299
|
+
React.useEffect(() => {
|
|
8106
8300
|
apiGet("/api/collections").then((data) => {
|
|
8107
8301
|
setCollections(
|
|
8108
8302
|
(data.collections || []).map((c) => c.slug || c.name || c)
|
|
@@ -8118,7 +8312,7 @@ var RelationshipBlockField = ({
|
|
|
8118
8312
|
setLoading(false);
|
|
8119
8313
|
}).catch(() => setLoading(false));
|
|
8120
8314
|
};
|
|
8121
|
-
|
|
8315
|
+
React.useEffect(() => {
|
|
8122
8316
|
if (isOpen) fetchOptions(search);
|
|
8123
8317
|
}, [isOpen, search, relationTo, labelField]);
|
|
8124
8318
|
const getLabel2 = (opt) => {
|
|
@@ -8448,7 +8642,7 @@ var SortableBlockComponent = ({
|
|
|
8448
8642
|
} = sortable.useSortable({ id: block3.id });
|
|
8449
8643
|
const { removeBlock } = useBlockActions();
|
|
8450
8644
|
const isEditing = editingBlockId === block3.id;
|
|
8451
|
-
const [showDeleteConfirm, setShowDeleteConfirm] =
|
|
8645
|
+
const [showDeleteConfirm, setShowDeleteConfirm] = React.useState(false);
|
|
8452
8646
|
const style = {
|
|
8453
8647
|
transform: utilities.CSS.Transform.toString(transform),
|
|
8454
8648
|
transition,
|
|
@@ -8541,11 +8735,11 @@ var SortableBlockComponent = ({
|
|
|
8541
8735
|
)
|
|
8542
8736
|
] });
|
|
8543
8737
|
}
|
|
8544
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: setNodeRef, style, className: "relative group pl-8 mb-2", children: [
|
|
8738
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: setNodeRef, style, className: "relative group md:pl-8 mb-2", children: [
|
|
8545
8739
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8546
8740
|
"div",
|
|
8547
8741
|
{
|
|
8548
|
-
className: "absolute left-0 top-1/2 -translate-y-1/2 p-1.5 cursor-grab active:cursor-grabbing text-[var(--kyro-text-muted)] opacity-0 group-hover:opacity-100 transition-opacity hover:bg-[var(--kyro-surface-accent)] rounded",
|
|
8742
|
+
className: "hidden md:absolute left-0 top-1/2 -translate-y-1/2 p-1.5 cursor-grab active:cursor-grabbing text-[var(--kyro-text-muted)] opacity-0 group-hover:opacity-100 transition-opacity hover:bg-[var(--kyro-surface-accent)] rounded",
|
|
8549
8743
|
...attributes,
|
|
8550
8744
|
...listeners,
|
|
8551
8745
|
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.GripVertical, { className: "w-4 h-4" })
|
|
@@ -8642,7 +8836,7 @@ var SortableBlockComponent = ({
|
|
|
8642
8836
|
)
|
|
8643
8837
|
] });
|
|
8644
8838
|
};
|
|
8645
|
-
var SortableBlock =
|
|
8839
|
+
var SortableBlock = React__default.default.memo(SortableBlockComponent);
|
|
8646
8840
|
var BlocksField = ({
|
|
8647
8841
|
field: field3,
|
|
8648
8842
|
value,
|
|
@@ -8653,9 +8847,9 @@ var BlocksField = ({
|
|
|
8653
8847
|
documentStatus,
|
|
8654
8848
|
justSaved
|
|
8655
8849
|
}) => {
|
|
8656
|
-
const [isDrawerOpen, setIsDrawerOpen] =
|
|
8657
|
-
const [isDropdownOpen, setIsDropdownOpen] =
|
|
8658
|
-
const dropdownRef =
|
|
8850
|
+
const [isDrawerOpen, setIsDrawerOpen] = React.useState(false);
|
|
8851
|
+
const [isDropdownOpen, setIsDropdownOpen] = React.useState(false);
|
|
8852
|
+
const dropdownRef = React.useRef(null);
|
|
8659
8853
|
const pickerMode = field3.admin?.pickerMode || "drawer";
|
|
8660
8854
|
const allowedBlocks = field3.blocks || [];
|
|
8661
8855
|
const groupedBlocks = allowedBlocks.reduce((acc, block3) => {
|
|
@@ -8685,18 +8879,18 @@ var BlocksField = ({
|
|
|
8685
8879
|
title,
|
|
8686
8880
|
blocks: blocks3
|
|
8687
8881
|
}));
|
|
8688
|
-
const storeRef =
|
|
8882
|
+
const storeRef = React.useRef(null);
|
|
8689
8883
|
if (!storeRef.current) {
|
|
8690
8884
|
storeRef.current = createBlocksStore(allowedBlocks, dynamicCategories);
|
|
8691
8885
|
}
|
|
8692
8886
|
const store = storeRef.current;
|
|
8693
8887
|
const blocks2 = zustand.useStore(store, (s) => s.blocks);
|
|
8694
|
-
const [activeDrag, setActiveDrag] =
|
|
8695
|
-
const [editingBlockId, setEditingBlockId] =
|
|
8696
|
-
const prevBlocksLengthRef =
|
|
8697
|
-
const prevBlockIdsRef =
|
|
8698
|
-
const isInitializedRef =
|
|
8699
|
-
|
|
8888
|
+
const [activeDrag, setActiveDrag] = React.useState(null);
|
|
8889
|
+
const [editingBlockId, setEditingBlockId] = React.useState(null);
|
|
8890
|
+
const prevBlocksLengthRef = React.useRef(blocks2.length);
|
|
8891
|
+
const prevBlockIdsRef = React.useRef(new Set(blocks2.map((b) => b.id)));
|
|
8892
|
+
const isInitializedRef = React.useRef(false);
|
|
8893
|
+
React.useEffect(() => {
|
|
8700
8894
|
if (isInitializedRef.current) {
|
|
8701
8895
|
if (blocks2.length > prevBlocksLengthRef.current) {
|
|
8702
8896
|
const newBlock = blocks2.find((b) => b.id && !prevBlockIdsRef.current.has(b.id));
|
|
@@ -8708,7 +8902,7 @@ var BlocksField = ({
|
|
|
8708
8902
|
prevBlocksLengthRef.current = blocks2.length;
|
|
8709
8903
|
prevBlockIdsRef.current = new Set(blocks2.map((b) => b.id));
|
|
8710
8904
|
}, [blocks2]);
|
|
8711
|
-
|
|
8905
|
+
React.useEffect(() => {
|
|
8712
8906
|
if (onBlocksChange) {
|
|
8713
8907
|
store.getState().setOnBlocksChange(onBlocksChange);
|
|
8714
8908
|
}
|
|
@@ -8717,8 +8911,8 @@ var BlocksField = ({
|
|
|
8717
8911
|
});
|
|
8718
8912
|
};
|
|
8719
8913
|
}, [onBlocksChange, store]);
|
|
8720
|
-
const lastValueRef =
|
|
8721
|
-
|
|
8914
|
+
const lastValueRef = React.useRef(null);
|
|
8915
|
+
React.useEffect(() => {
|
|
8722
8916
|
const valueArray = Array.isArray(value) ? value : [];
|
|
8723
8917
|
const lastValueArray = lastValueRef.current || [];
|
|
8724
8918
|
if (JSON.stringify(valueArray) !== JSON.stringify(lastValueArray)) {
|
|
@@ -8733,9 +8927,9 @@ var BlocksField = ({
|
|
|
8733
8927
|
lastValueRef.current = [];
|
|
8734
8928
|
}
|
|
8735
8929
|
}, [value, field3.name, store]);
|
|
8736
|
-
const onChangeRef =
|
|
8930
|
+
const onChangeRef = React.useRef(onChange);
|
|
8737
8931
|
onChangeRef.current = onChange;
|
|
8738
|
-
|
|
8932
|
+
React.useEffect(() => {
|
|
8739
8933
|
if (!onChangeRef.current) return;
|
|
8740
8934
|
const lastValue = lastValueRef.current;
|
|
8741
8935
|
if (!lastValue) return;
|
|
@@ -8744,13 +8938,13 @@ var BlocksField = ({
|
|
|
8744
8938
|
onChangeRef.current(blocks2);
|
|
8745
8939
|
}
|
|
8746
8940
|
}, [blocks2]);
|
|
8747
|
-
const handleAddBlock =
|
|
8941
|
+
const handleAddBlock = React.useCallback(
|
|
8748
8942
|
(blockType) => {
|
|
8749
8943
|
store.getState().addBlock(blockType);
|
|
8750
8944
|
},
|
|
8751
8945
|
[store]
|
|
8752
8946
|
);
|
|
8753
|
-
const duplicateBlock =
|
|
8947
|
+
const duplicateBlock = React.useCallback(
|
|
8754
8948
|
(blockId) => {
|
|
8755
8949
|
const blockIndex = blocks2.findIndex((b) => b.id === blockId);
|
|
8756
8950
|
if (blockIndex === -1) return;
|
|
@@ -8815,7 +9009,7 @@ var BlocksField = ({
|
|
|
8815
9009
|
};
|
|
8816
9010
|
const activeBlock = activeDrag ? blockCategories.flatMap((cat) => cat.blocks).find((b) => `drawer-${b.type}` === activeDrag.id) || blocks2.find((b) => b.id === activeDrag.id) : null;
|
|
8817
9011
|
activeBlock ? "label" in activeBlock ? activeBlock.label : activeBlock.type : "Block";
|
|
8818
|
-
|
|
9012
|
+
React.useEffect(() => {
|
|
8819
9013
|
if (!isDropdownOpen) return;
|
|
8820
9014
|
const handleClick = (e) => {
|
|
8821
9015
|
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
|
|
@@ -8976,9 +9170,9 @@ function normalizeUploadFields(value) {
|
|
|
8976
9170
|
return value;
|
|
8977
9171
|
}
|
|
8978
9172
|
function useQueue() {
|
|
8979
|
-
const queue =
|
|
8980
|
-
const isProcessing =
|
|
8981
|
-
const queueTask =
|
|
9173
|
+
const queue = React.useRef([]);
|
|
9174
|
+
const isProcessing = React.useRef(false);
|
|
9175
|
+
const queueTask = React.useCallback((fn, options) => {
|
|
8982
9176
|
queue.current.push(fn);
|
|
8983
9177
|
async function processQueue() {
|
|
8984
9178
|
if (isProcessing.current) return;
|
|
@@ -9041,27 +9235,27 @@ function useAutoFormState({
|
|
|
9041
9235
|
} = store;
|
|
9042
9236
|
const versionsEnabled = !!config.versions;
|
|
9043
9237
|
const currentContextKey = globalSlug || initialData?.id || collectionSlug;
|
|
9044
|
-
const needsResetRef =
|
|
9238
|
+
const needsResetRef = React.useRef(false);
|
|
9045
9239
|
if (!globalSlug && currentContextKey && formData && Object.keys(formData).length > 0 && formData.id !== currentContextKey) {
|
|
9046
9240
|
needsResetRef.current = true;
|
|
9047
9241
|
}
|
|
9048
|
-
|
|
9242
|
+
React.useEffect(() => {
|
|
9049
9243
|
if (needsResetRef.current) {
|
|
9050
9244
|
needsResetRef.current = false;
|
|
9051
9245
|
resetForm();
|
|
9052
9246
|
}
|
|
9053
9247
|
}, [resetForm]);
|
|
9054
|
-
const localSaveTimerRef =
|
|
9055
|
-
const serverSaveTimerRef =
|
|
9056
|
-
const retryTimerRef =
|
|
9057
|
-
const isOnlineRef =
|
|
9058
|
-
const lastAutoSaveTimeRef =
|
|
9059
|
-
const autoSaveSkipRef =
|
|
9060
|
-
const restorePromptedRef =
|
|
9061
|
-
const previousFormDataRef =
|
|
9062
|
-
const astroSyncDataRef =
|
|
9248
|
+
const localSaveTimerRef = React.useRef(null);
|
|
9249
|
+
const serverSaveTimerRef = React.useRef(null);
|
|
9250
|
+
const retryTimerRef = React.useRef(null);
|
|
9251
|
+
const isOnlineRef = React.useRef(typeof navigator !== "undefined" ? navigator.onLine : true);
|
|
9252
|
+
const lastAutoSaveTimeRef = React.useRef(0);
|
|
9253
|
+
const autoSaveSkipRef = React.useRef(false);
|
|
9254
|
+
const restorePromptedRef = React.useRef(null);
|
|
9255
|
+
const previousFormDataRef = React.useRef("");
|
|
9256
|
+
const astroSyncDataRef = React.useRef("");
|
|
9063
9257
|
const { queueTask } = useQueue();
|
|
9064
|
-
const getDocumentKey =
|
|
9258
|
+
const getDocumentKey = React.useCallback(
|
|
9065
9259
|
(id) => {
|
|
9066
9260
|
if (globalSlug) return `global:${globalSlug}`;
|
|
9067
9261
|
if (collectionSlug && id) return `${collectionSlug}:${id}`;
|
|
@@ -9069,7 +9263,7 @@ function useAutoFormState({
|
|
|
9069
9263
|
},
|
|
9070
9264
|
[collectionSlug, globalSlug]
|
|
9071
9265
|
);
|
|
9072
|
-
const persistBrowserDraft =
|
|
9266
|
+
const persistBrowserDraft = React.useCallback(
|
|
9073
9267
|
(documentKey, data, options) => {
|
|
9074
9268
|
setDraftCache(documentKey, {
|
|
9075
9269
|
data,
|
|
@@ -9080,7 +9274,7 @@ function useAutoFormState({
|
|
|
9080
9274
|
},
|
|
9081
9275
|
[lastSavedData.updatedAt, setDraftCache]
|
|
9082
9276
|
);
|
|
9083
|
-
const fetchVersions =
|
|
9277
|
+
const fetchVersions = React.useCallback(async () => {
|
|
9084
9278
|
const url = globalSlug ? resolveApi(`/api/globals/${globalSlug}/versions`) : collectionSlug && formData.id ? resolveApi(`/api/${collectionSlug}/${formData.id}/versions`) : null;
|
|
9085
9279
|
if (!url) return;
|
|
9086
9280
|
setLoadingVersions(true);
|
|
@@ -9094,7 +9288,7 @@ function useAutoFormState({
|
|
|
9094
9288
|
setLoadingVersions(false);
|
|
9095
9289
|
}
|
|
9096
9290
|
}, [formData.id, collectionSlug, globalSlug, setLoadingVersions, setVersions]);
|
|
9097
|
-
const performLocalAutoSave =
|
|
9291
|
+
const performLocalAutoSave = React.useCallback(() => {
|
|
9098
9292
|
const state = useAutoFormStore.getState();
|
|
9099
9293
|
const latestFormData = state.formData;
|
|
9100
9294
|
if (autoSaveSkipRef.current || !collectionSlug || !latestFormData.id) return;
|
|
@@ -9104,7 +9298,7 @@ function useAutoFormState({
|
|
|
9104
9298
|
persistBrowserDraft(documentKey, latestFormData);
|
|
9105
9299
|
}
|
|
9106
9300
|
}, [collectionSlug, getDocumentKey, persistBrowserDraft]);
|
|
9107
|
-
const doAutosaveFetch =
|
|
9301
|
+
const doAutosaveFetch = React.useCallback(async (options) => {
|
|
9108
9302
|
const state = useAutoFormStore.getState();
|
|
9109
9303
|
const latestFormData = state.formData;
|
|
9110
9304
|
const currentLastSaved = state.lastSavedData;
|
|
@@ -9187,7 +9381,7 @@ function useAutoFormState({
|
|
|
9187
9381
|
setIsAutoSaving,
|
|
9188
9382
|
versionsEnabled
|
|
9189
9383
|
]);
|
|
9190
|
-
const performAutosave =
|
|
9384
|
+
const performAutosave = React.useCallback((options) => {
|
|
9191
9385
|
queueTask(
|
|
9192
9386
|
() => doAutosaveFetch(options),
|
|
9193
9387
|
{
|
|
@@ -9199,7 +9393,7 @@ function useAutoFormState({
|
|
|
9199
9393
|
}
|
|
9200
9394
|
);
|
|
9201
9395
|
}, [doAutosaveFetch, queueTask]);
|
|
9202
|
-
const saveDocument =
|
|
9396
|
+
const saveDocument = React.useCallback(
|
|
9203
9397
|
async (dataOverride, isDraft = true) => {
|
|
9204
9398
|
const state = useAutoFormStore.getState();
|
|
9205
9399
|
const payload = dataOverride || state.formData;
|
|
@@ -9225,17 +9419,17 @@ function useAutoFormState({
|
|
|
9225
9419
|
},
|
|
9226
9420
|
[collectionSlug, globalSlug, setAutoSaveStatus]
|
|
9227
9421
|
);
|
|
9228
|
-
|
|
9422
|
+
React.useEffect(() => {
|
|
9229
9423
|
const handleToggle = () => {
|
|
9230
9424
|
setSidebarCollapsed(!sidebarCollapsed);
|
|
9231
9425
|
};
|
|
9232
9426
|
window.addEventListener("toggle-sidebar", handleToggle);
|
|
9233
9427
|
return () => window.removeEventListener("toggle-sidebar", handleToggle);
|
|
9234
9428
|
}, [sidebarCollapsed, setSidebarCollapsed]);
|
|
9235
|
-
const lastLoadedSlugRef =
|
|
9236
|
-
const lastInitialDataRef =
|
|
9237
|
-
const initialDataLoadedRef =
|
|
9238
|
-
|
|
9429
|
+
const lastLoadedSlugRef = React.useRef(null);
|
|
9430
|
+
const lastInitialDataRef = React.useRef("");
|
|
9431
|
+
const initialDataLoadedRef = React.useRef(false);
|
|
9432
|
+
React.useEffect(() => {
|
|
9239
9433
|
const currentSlug = globalSlug || initialData?.id;
|
|
9240
9434
|
const serialized = JSON.stringify(initialData);
|
|
9241
9435
|
if (initialDataLoadedRef.current && lastLoadedSlugRef.current === currentSlug && lastInitialDataRef.current === serialized) return;
|
|
@@ -9244,7 +9438,7 @@ function useAutoFormState({
|
|
|
9244
9438
|
lastLoadedSlugRef.current = currentSlug;
|
|
9245
9439
|
lastInitialDataRef.current = serialized;
|
|
9246
9440
|
}, [collectionSlug, formData.id, globalSlug, initialData, loadDocument]);
|
|
9247
|
-
|
|
9441
|
+
React.useEffect(() => {
|
|
9248
9442
|
if (!collectionSlug || !initialData?.id) return;
|
|
9249
9443
|
const documentKey = getDocumentKey(initialData.id);
|
|
9250
9444
|
if (!documentKey) return;
|
|
@@ -9307,7 +9501,7 @@ function useAutoFormState({
|
|
|
9307
9501
|
}
|
|
9308
9502
|
return void 0;
|
|
9309
9503
|
}
|
|
9310
|
-
|
|
9504
|
+
React.useEffect(() => {
|
|
9311
9505
|
const fields2 = config.fields;
|
|
9312
9506
|
const metaTitleField = findFieldDeep(fields2, "metaTitle");
|
|
9313
9507
|
if (!metaTitleField) return;
|
|
@@ -9317,7 +9511,7 @@ function useAutoFormState({
|
|
|
9317
9511
|
setField("metaTitle", titleStr);
|
|
9318
9512
|
}
|
|
9319
9513
|
}, [formData, config.fields, setField]);
|
|
9320
|
-
|
|
9514
|
+
React.useEffect(() => {
|
|
9321
9515
|
const fields2 = config.fields;
|
|
9322
9516
|
const slugField = fields2.find(
|
|
9323
9517
|
(f) => f.name === "slug" && f.admin?.autoGenerate
|
|
@@ -9332,7 +9526,7 @@ function useAutoFormState({
|
|
|
9332
9526
|
}
|
|
9333
9527
|
}
|
|
9334
9528
|
}, [formData, isSlugLocked, config.fields, setField]);
|
|
9335
|
-
|
|
9529
|
+
React.useEffect(() => {
|
|
9336
9530
|
if (sidebarCollapsed) return;
|
|
9337
9531
|
if (!globalSlug && (!collectionSlug || !formData.id)) return;
|
|
9338
9532
|
const state = useAutoFormStore.getState();
|
|
@@ -9349,7 +9543,7 @@ function useAutoFormState({
|
|
|
9349
9543
|
performAutosave();
|
|
9350
9544
|
}, 8e3);
|
|
9351
9545
|
}, [formData, sidebarCollapsed, collectionSlug, globalSlug, performLocalAutoSave, performAutosave]);
|
|
9352
|
-
|
|
9546
|
+
React.useEffect(() => {
|
|
9353
9547
|
if (!globalSlug && (!collectionSlug || !formData.id)) return;
|
|
9354
9548
|
const flushDraft = () => {
|
|
9355
9549
|
if (autoSaveSkipRef.current) return;
|
|
@@ -9386,7 +9580,7 @@ function useAutoFormState({
|
|
|
9386
9580
|
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
9387
9581
|
};
|
|
9388
9582
|
}, [collectionSlug, globalSlug, formData.id, performAutosave]);
|
|
9389
|
-
|
|
9583
|
+
React.useEffect(() => {
|
|
9390
9584
|
const serialized = JSON.stringify(formData);
|
|
9391
9585
|
if (serialized === astroSyncDataRef.current) return;
|
|
9392
9586
|
astroSyncDataRef.current = serialized;
|
|
@@ -9396,7 +9590,7 @@ function useAutoFormState({
|
|
|
9396
9590
|
}
|
|
9397
9591
|
onChange?.(formData);
|
|
9398
9592
|
}, [formData, onChange]);
|
|
9399
|
-
|
|
9593
|
+
React.useEffect(() => {
|
|
9400
9594
|
if (globalSlug || formData.id) fetchVersions();
|
|
9401
9595
|
}, [formData.id, globalSlug, fetchVersions]);
|
|
9402
9596
|
const documentStatus = (() => {
|
|
@@ -9423,9 +9617,9 @@ function Dropdown({
|
|
|
9423
9617
|
align = "right",
|
|
9424
9618
|
direction = "up"
|
|
9425
9619
|
}) {
|
|
9426
|
-
const [open, setOpen] =
|
|
9427
|
-
const ref =
|
|
9428
|
-
|
|
9620
|
+
const [open, setOpen] = React.useState(false);
|
|
9621
|
+
const ref = React.useRef(null);
|
|
9622
|
+
React.useEffect(() => {
|
|
9429
9623
|
const handleClickOutside = (e) => {
|
|
9430
9624
|
if (ref.current && !ref.current.contains(e.target)) {
|
|
9431
9625
|
setOpen(false);
|
|
@@ -9552,7 +9746,7 @@ function TabsLayout({
|
|
|
9552
9746
|
onTabDataChange,
|
|
9553
9747
|
renderField
|
|
9554
9748
|
}) {
|
|
9555
|
-
const [activeTab, setActiveTab] =
|
|
9749
|
+
const [activeTab, setActiveTab] = React.useState(0);
|
|
9556
9750
|
const fieldTabs = field3.tabs || [];
|
|
9557
9751
|
const currentTab = fieldTabs[activeTab] || fieldTabs[0];
|
|
9558
9752
|
const tabData = field3.name ? formData[field3.name] || {} : formData;
|
|
@@ -9653,13 +9847,13 @@ function AutoForm({
|
|
|
9653
9847
|
onActionSuccess,
|
|
9654
9848
|
onActionError
|
|
9655
9849
|
});
|
|
9656
|
-
const menuRef =
|
|
9657
|
-
const scheduleRef =
|
|
9658
|
-
const [showSchedulePicker, setShowSchedulePicker] =
|
|
9659
|
-
const [localSaveStatus, setLocalSaveStatus] =
|
|
9660
|
-
const [now, setNow] =
|
|
9850
|
+
const menuRef = React.useRef(null);
|
|
9851
|
+
const scheduleRef = React.useRef(null);
|
|
9852
|
+
const [showSchedulePicker, setShowSchedulePicker] = React.useState(false);
|
|
9853
|
+
const [localSaveStatus, setLocalSaveStatus] = React.useState("idle");
|
|
9854
|
+
const [now, setNow] = React.useState(Date.now());
|
|
9661
9855
|
const disabled = propDisabled;
|
|
9662
|
-
|
|
9856
|
+
React.useEffect(() => {
|
|
9663
9857
|
const id = setInterval(() => setNow(Date.now()), 1e4);
|
|
9664
9858
|
return () => clearInterval(id);
|
|
9665
9859
|
}, []);
|
|
@@ -9737,7 +9931,7 @@ function AutoForm({
|
|
|
9737
9931
|
return [...prev, versionId];
|
|
9738
9932
|
});
|
|
9739
9933
|
};
|
|
9740
|
-
|
|
9934
|
+
React.useEffect(() => {
|
|
9741
9935
|
const handleShortcuts = (e) => {
|
|
9742
9936
|
if ((e.metaKey || e.ctrlKey) && e.key === "s") {
|
|
9743
9937
|
e.preventDefault();
|
|
@@ -9760,12 +9954,12 @@ function AutoForm({
|
|
|
9760
9954
|
window.addEventListener("keydown", handleShortcuts);
|
|
9761
9955
|
return () => window.removeEventListener("keydown", handleShortcuts);
|
|
9762
9956
|
}, []);
|
|
9763
|
-
|
|
9957
|
+
React.useEffect(() => {
|
|
9764
9958
|
const handler = () => setView("version");
|
|
9765
9959
|
window.addEventListener("kyro:show-version-history", handler);
|
|
9766
9960
|
return () => window.removeEventListener("kyro:show-version-history", handler);
|
|
9767
9961
|
}, []);
|
|
9768
|
-
|
|
9962
|
+
React.useEffect(() => {
|
|
9769
9963
|
const handleClickOutside = (e) => {
|
|
9770
9964
|
if (menuRef.current && !menuRef.current.contains(e.target)) {
|
|
9771
9965
|
setIsMenuOpen(false);
|
|
@@ -9776,7 +9970,7 @@ function AutoForm({
|
|
|
9776
9970
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
9777
9971
|
}
|
|
9778
9972
|
}, [isMenuOpen]);
|
|
9779
|
-
|
|
9973
|
+
React.useEffect(() => {
|
|
9780
9974
|
const handleClickOutside = (e) => {
|
|
9781
9975
|
if (scheduleRef.current && !scheduleRef.current.contains(e.target)) {
|
|
9782
9976
|
setShowSchedulePicker(false);
|
|
@@ -10061,7 +10255,7 @@ function AutoForm({
|
|
|
10061
10255
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
10062
10256
|
"div",
|
|
10063
10257
|
{
|
|
10064
|
-
className: "kyro-form-row flex gap-6 items-end",
|
|
10258
|
+
className: "kyro-form-row flex flex-col md:flex-row gap-4 md:gap-6 items-start md:items-end w-full",
|
|
10065
10259
|
children: rowFields?.map((f) => {
|
|
10066
10260
|
const fAdmin = f.admin || {};
|
|
10067
10261
|
const actionUrl = fAdmin?.action;
|
|
@@ -10293,24 +10487,24 @@ function AutoForm({
|
|
|
10293
10487
|
const statusLabel = hasUnpublishedChanges ? "Draft (unpublished changes)" : docStatus === "published" ? "Published" : "Draft";
|
|
10294
10488
|
const statusColor = docStatus === "published" && !hasUnsavedChanges ? "bg-[var(--kyro-success)]" : hasUnpublishedChanges ? "bg-[var(--kyro-warning)]" : "bg-[var(--kyro-text-muted)]";
|
|
10295
10489
|
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";
|
|
10296
|
-
return /* @__PURE__ */ jsxRuntime.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: [
|
|
10297
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
10298
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
10490
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "surface-tile px-3 md:px-8 py-2 md:py-6 flex items-center justify-between max-md:static sticky top-0 z-50 border-b border-[var(--kyro-border)] mb-0 md:mb-8 bg-[var(--kyro-surface)] backdrop-blur-md", children: [
|
|
10491
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1 md:gap-2 min-w-0", children: [
|
|
10492
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 md:gap-3 flex-wrap min-w-0", children: [
|
|
10299
10493
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
10300
10494
|
"a",
|
|
10301
10495
|
{
|
|
10302
10496
|
href: `/${collectionSlug}`,
|
|
10303
|
-
className: "p-2 border border-[var(--kyro-border)] rounded-xl hover:bg-[var(--kyro-bg-secondary)] transition-colors",
|
|
10497
|
+
className: "p-1.5 md:p-2 border-0 md:border border-[var(--kyro-border)] rounded-xl hover:bg-[var(--kyro-bg-secondary)] transition-colors shrink-0",
|
|
10304
10498
|
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "w-4 h-4" })
|
|
10305
10499
|
}
|
|
10306
10500
|
),
|
|
10307
|
-
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-bold tracking-tighter", children: docTitle }),
|
|
10308
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: `inline-flex items-center gap-1.5 px-2 rounded-full text-[10px] font-regular border ${statusBadgeBg}`, children: [
|
|
10501
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-lg md:text-xl font-bold tracking-tighter truncate min-w-0", children: docTitle }),
|
|
10502
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: `shrink-0 inline-flex items-center gap-1.5 px-2 rounded-full text-[10px] font-regular border ${statusBadgeBg}`, children: [
|
|
10309
10503
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `h-1.5 w-1.5 rounded-full ${statusColor}` }),
|
|
10310
10504
|
statusLabel
|
|
10311
10505
|
] })
|
|
10312
10506
|
] }),
|
|
10313
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4 text-[11px] font-medium tracking-wide opacity-60 ml-12", children: [
|
|
10507
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4 text-[11px] font-medium tracking-wide opacity-60 md:ml-12", children: [
|
|
10314
10508
|
autoSaveStatus === "saving" && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1.5 text-[var(--kyro-text-muted)]", children: [
|
|
10315
10509
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
10316
10510
|
"svg",
|
|
@@ -10431,7 +10625,7 @@ function AutoForm({
|
|
|
10431
10625
|
] })
|
|
10432
10626
|
] })
|
|
10433
10627
|
] }),
|
|
10434
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-6", children: [
|
|
10628
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-md:hidden flex items-center gap-6", children: [
|
|
10435
10629
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1 bg-[var(--kyro-bg-secondary)] p-1 rounded-xl border border-[var(--kyro-border)]", children: ["edit", "version", "api"].map((v) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
10436
10630
|
"button",
|
|
10437
10631
|
{
|
|
@@ -10616,15 +10810,15 @@ function AutoForm({
|
|
|
10616
10810
|
};
|
|
10617
10811
|
const renderEditView = () => {
|
|
10618
10812
|
if (layout === "single") {
|
|
10619
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full space-y-8", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "surface-tile p-8 space-y-8", children: config.fields.map((f) => renderField(f)) }) });
|
|
10813
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full space-y-6 md:space-y-8", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "surface-tile p-4 md:p-8 space-y-6 md:space-y-8", children: config.fields.map((f) => renderField(f)) }) });
|
|
10620
10814
|
}
|
|
10621
10815
|
const hasSidebarFields = config.fields.some((f) => f.admin?.position === "sidebar") && !showPreview;
|
|
10622
10816
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10623
10817
|
"div",
|
|
10624
10818
|
{
|
|
10625
|
-
className: `w-full mx-auto grid gap-8 pb-32 transition-all duration-700 ${showPreview ? "grid-cols-1 lg:grid-cols-2" : sidebarCollapsed || !hasSidebarFields ? "grid-cols-1" : "grid-cols-1 lg:grid-cols-[1fr_380px]"}`,
|
|
10819
|
+
className: `w-full mx-auto grid gap-4 md:gap-8 pb-32 transition-all duration-700 ${showPreview ? "grid-cols-1 lg:grid-cols-2" : sidebarCollapsed || !hasSidebarFields ? "grid-cols-1" : "grid-cols-1 lg:grid-cols-[1fr_380px]"}`,
|
|
10626
10820
|
children: [
|
|
10627
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-8 animate-in fade-in slide-in-from-left-4 duration-500", children: config.tabs ? renderField({ type: "tabs", tabs: config.tabs }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "surface-tile p-8 space-y-8", children: config.fields.filter(
|
|
10821
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-6 md:space-y-8 animate-in fade-in slide-in-from-left-4 duration-500", children: config.tabs ? renderField({ type: "tabs", tabs: config.tabs }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "surface-tile p-4 md:p-8 space-y-6 md:space-y-8", children: config.fields.filter(
|
|
10628
10822
|
(f) => !f.admin?.position || f.admin.position === "main"
|
|
10629
10823
|
).map((f) => renderField(f)) }) }),
|
|
10630
10824
|
showPreview ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "sticky top-36 h-[calc(100vh-280px)] animate-in fade-in slide-in-from-right-10 duration-700", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full h-full rounded-3xl border border-[var(--kyro-border)] bg-[var(--kyro-bg-secondary)] shadow-2xl overflow-hidden relative group", children: [
|
|
@@ -10641,9 +10835,18 @@ function AutoForm({
|
|
|
10641
10835
|
}
|
|
10642
10836
|
),
|
|
10643
10837
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 bg-transparent pointer-events-none border-[12px] border-[var(--kyro-surface)] rounded-3xl" })
|
|
10644
|
-
] }) }) : sidebarCollapsed ? null : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-6 animate-in fade-in slide-in-from-right-4 duration-500", children: config.fields.some((f) => f.admin?.position === "sidebar") && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10645
|
-
/* @__PURE__ */ jsxRuntime.
|
|
10646
|
-
|
|
10838
|
+
] }) }) : sidebarCollapsed ? null : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-4 md:space-y-6 animate-in fade-in slide-in-from-right-4 duration-500", children: config.fields.some((f) => f.admin?.position === "sidebar") && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
10839
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "hidden lg:block surface-tile p-6 space-y-6", children: [
|
|
10840
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-[10px] font-bold tracking-[0.2em] opacity-40", children: "Settings" }),
|
|
10841
|
+
config.fields.filter((f) => f.admin?.position === "sidebar").map((f) => renderField(f))
|
|
10842
|
+
] }),
|
|
10843
|
+
/* @__PURE__ */ jsxRuntime.jsxs("details", { className: "lg:hidden surface-tile p-4 space-y-4 group", children: [
|
|
10844
|
+
/* @__PURE__ */ jsxRuntime.jsxs("summary", { className: "cursor-pointer font-semibold text-xs tracking-widest opacity-40 text-[var(--kyro-text-secondary)] select-none flex items-center gap-2", children: [
|
|
10845
|
+
/* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-3 h-3 transition-transform group-open:rotate-90", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9 18l6-6-6-6" }) }),
|
|
10846
|
+
"Settings"
|
|
10847
|
+
] }),
|
|
10848
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-4 pt-4 border-t border-[var(--kyro-border)]", children: config.fields.filter((f) => f.admin?.position === "sidebar").map((f) => renderField(f)) })
|
|
10849
|
+
] })
|
|
10647
10850
|
] }) })
|
|
10648
10851
|
]
|
|
10649
10852
|
}
|
|
@@ -10895,7 +11098,7 @@ function AutoForm({
|
|
|
10895
11098
|
}
|
|
10896
11099
|
)
|
|
10897
11100
|
] }),
|
|
10898
|
-
/* @__PURE__ */ jsxRuntime.jsxs("main", { className: "w-full", children: [
|
|
11101
|
+
/* @__PURE__ */ jsxRuntime.jsxs("main", { className: "w-full pt-6 md:pt-0", children: [
|
|
10899
11102
|
view === "edit" && renderEditView(),
|
|
10900
11103
|
view === "version" && renderVersionView(),
|
|
10901
11104
|
view === "api" && renderApiView()
|
|
@@ -10913,9 +11116,13 @@ function ActionBar({
|
|
|
10913
11116
|
onViewHistory,
|
|
10914
11117
|
onPreview,
|
|
10915
11118
|
onDelete,
|
|
11119
|
+
onBack,
|
|
11120
|
+
onToggleSidebar,
|
|
10916
11121
|
publishedAt,
|
|
10917
11122
|
updatedAt
|
|
10918
11123
|
}) {
|
|
11124
|
+
const view = useAutoFormStore((s) => s.view) || "edit";
|
|
11125
|
+
const setView = useAutoFormStore((s) => s.setView);
|
|
10919
11126
|
const getSaveStatusText = () => {
|
|
10920
11127
|
if (saveStatus === "saving") return "Saving...";
|
|
10921
11128
|
if (saveStatus === "saved") return "Saved";
|
|
@@ -10962,101 +11169,268 @@ function ActionBar({
|
|
|
10962
11169
|
if (!dateStr) return "Never";
|
|
10963
11170
|
return new Date(dateStr).toLocaleString();
|
|
10964
11171
|
};
|
|
10965
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10966
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex
|
|
10967
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-
|
|
11172
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
11173
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "md:hidden flex flex-col gap-3 py-3 px-4 bg-[var(--kyro-bg)] border-t border-[var(--kyro-border)]", children: [
|
|
11174
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
11175
|
+
onBack && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11176
|
+
"button",
|
|
11177
|
+
{
|
|
11178
|
+
type: "button",
|
|
11179
|
+
onClick: onBack,
|
|
11180
|
+
className: "p-2 rounded-lg hover:bg-[var(--kyro-surface-accent)] text-[var(--kyro-text-secondary)] transition-all",
|
|
11181
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-4 h-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M19 12H5M12 19l-7-7 7-7" }) })
|
|
11182
|
+
}
|
|
11183
|
+
),
|
|
11184
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 ml-auto", children: [
|
|
11185
|
+
onPreview && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11186
|
+
"button",
|
|
11187
|
+
{
|
|
11188
|
+
type: "button",
|
|
11189
|
+
onClick: onPreview,
|
|
11190
|
+
className: "p-2 rounded-lg hover:bg-[var(--kyro-surface-accent)] text-[var(--kyro-text-secondary)] transition-all",
|
|
11191
|
+
title: "Preview",
|
|
11192
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, { className: "w-4 h-4" })
|
|
11193
|
+
}
|
|
11194
|
+
),
|
|
11195
|
+
onViewHistory && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11196
|
+
"button",
|
|
11197
|
+
{
|
|
11198
|
+
type: "button",
|
|
11199
|
+
onClick: onViewHistory,
|
|
11200
|
+
className: "p-2 rounded-lg hover:bg-[var(--kyro-surface-accent)] text-[var(--kyro-text-secondary)] transition-all",
|
|
11201
|
+
title: "View History",
|
|
11202
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, { className: "w-4 h-4" })
|
|
11203
|
+
}
|
|
11204
|
+
),
|
|
11205
|
+
onDuplicate && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11206
|
+
"button",
|
|
11207
|
+
{
|
|
11208
|
+
type: "button",
|
|
11209
|
+
onClick: onDuplicate,
|
|
11210
|
+
className: "p-2 rounded-lg hover:bg-[var(--kyro-surface-accent)] text-[var(--kyro-text-secondary)] transition-all",
|
|
11211
|
+
title: "Duplicate",
|
|
11212
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "w-4 h-4" })
|
|
11213
|
+
}
|
|
11214
|
+
),
|
|
11215
|
+
onDelete && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11216
|
+
"button",
|
|
11217
|
+
{
|
|
11218
|
+
type: "button",
|
|
11219
|
+
onClick: onDelete,
|
|
11220
|
+
className: "p-2 rounded-lg hover:bg-[var(--kyro-danger-bg)] text-[var(--kyro-error)] transition-all",
|
|
11221
|
+
title: "Delete",
|
|
11222
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "w-4 h-4" })
|
|
11223
|
+
}
|
|
11224
|
+
),
|
|
11225
|
+
onToggleSidebar && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11226
|
+
"button",
|
|
11227
|
+
{
|
|
11228
|
+
type: "button",
|
|
11229
|
+
onClick: onToggleSidebar,
|
|
11230
|
+
className: "p-2 rounded-lg hover:bg-[var(--kyro-surface-accent)] text-[var(--kyro-text-secondary)] transition-all",
|
|
11231
|
+
title: "Toggle Sidebar",
|
|
11232
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
11233
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }),
|
|
11234
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: "9", y1: "3", x2: "9", y2: "21" })
|
|
11235
|
+
] })
|
|
11236
|
+
}
|
|
11237
|
+
)
|
|
11238
|
+
] })
|
|
11239
|
+
] }),
|
|
11240
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1 bg-[var(--kyro-bg-secondary)] p-0.5 rounded-lg border border-[var(--kyro-border)] self-start", children: ["edit", "version", "api"].map((v) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
11241
|
+
"button",
|
|
11242
|
+
{
|
|
11243
|
+
type: "button",
|
|
11244
|
+
onClick: () => setView(v),
|
|
11245
|
+
className: `px-4 py-1.5 text-xs font-bold rounded-md transition-all ${view === v ? "bg-[var(--kyro-surface)] shadow-sm border border-[var(--kyro-border)] text-[var(--kyro-text-primary)]" : "text-[var(--kyro-text-secondary)] opacity-50 hover:opacity-100"}`,
|
|
11246
|
+
children: v === "edit" ? "Edit" : v === "version" ? "Version" : "API"
|
|
11247
|
+
},
|
|
11248
|
+
v
|
|
11249
|
+
)) }),
|
|
11250
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [
|
|
10968
11251
|
getStatusBadge(),
|
|
10969
11252
|
getSaveStatusText() && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10970
11253
|
"span",
|
|
10971
11254
|
{
|
|
10972
|
-
className: `text-
|
|
11255
|
+
className: `text-xs ${saveStatus === "error" ? "text-[var(--kyro-error)]" : "text-[var(--kyro-text-muted)]"}`,
|
|
10973
11256
|
children: [
|
|
10974
11257
|
saveStatus === "saving" ? /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: "sm", className: "inline mr-1" }) : null,
|
|
10975
11258
|
getSaveStatusText()
|
|
10976
11259
|
]
|
|
10977
11260
|
}
|
|
10978
|
-
)
|
|
11261
|
+
),
|
|
11262
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[10px] text-[var(--kyro-text-muted)] ml-auto", children: [
|
|
11263
|
+
updatedAt && `Updated ${formatDate2(updatedAt)}`,
|
|
11264
|
+
publishedAt && status === "published" && ` \xB7 Published ${formatDate2(publishedAt)}`
|
|
11265
|
+
] })
|
|
10979
11266
|
] }),
|
|
10980
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
10981
|
-
|
|
10982
|
-
"
|
|
10983
|
-
|
|
11267
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
11268
|
+
status === "draft" && onPublish && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11269
|
+
"button",
|
|
11270
|
+
{
|
|
11271
|
+
type: "button",
|
|
11272
|
+
onClick: onPublish,
|
|
11273
|
+
disabled: saveStatus === "saving",
|
|
11274
|
+
className: "kyro-btn kyro-btn-primary kyro-btn-md flex items-center gap-2 flex-1 justify-center",
|
|
11275
|
+
children: [
|
|
11276
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, { className: "w-4 h-4" }),
|
|
11277
|
+
"Publish"
|
|
11278
|
+
]
|
|
11279
|
+
}
|
|
11280
|
+
),
|
|
11281
|
+
status === "published" && onUnpublish && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11282
|
+
"button",
|
|
11283
|
+
{
|
|
11284
|
+
type: "button",
|
|
11285
|
+
onClick: onUnpublish,
|
|
11286
|
+
disabled: saveStatus === "saving",
|
|
11287
|
+
className: "kyro-btn kyro-btn-secondary kyro-btn-md flex items-center gap-2 flex-1 justify-center",
|
|
11288
|
+
children: [
|
|
11289
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Undo, { className: "w-4 h-4" }),
|
|
11290
|
+
"Unpublish"
|
|
11291
|
+
]
|
|
11292
|
+
}
|
|
11293
|
+
),
|
|
11294
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11295
|
+
SplitButton,
|
|
11296
|
+
{
|
|
11297
|
+
status,
|
|
11298
|
+
saveStatus,
|
|
11299
|
+
hasChanges,
|
|
11300
|
+
onPublish: onSave,
|
|
11301
|
+
children: [
|
|
11302
|
+
onDuplicate && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11303
|
+
DropdownItem,
|
|
11304
|
+
{
|
|
11305
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "w-4 h-4" }),
|
|
11306
|
+
children: "Duplicate"
|
|
11307
|
+
}
|
|
11308
|
+
),
|
|
11309
|
+
onViewHistory && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11310
|
+
DropdownItem,
|
|
11311
|
+
{
|
|
11312
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, { className: "w-4 h-4" }),
|
|
11313
|
+
children: "View History"
|
|
11314
|
+
}
|
|
11315
|
+
),
|
|
11316
|
+
onPreview && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11317
|
+
DropdownItem,
|
|
11318
|
+
{
|
|
11319
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, { className: "w-4 h-4" }),
|
|
11320
|
+
children: "Preview"
|
|
11321
|
+
}
|
|
11322
|
+
),
|
|
11323
|
+
(onDuplicate || onViewHistory || onPreview) && /* @__PURE__ */ jsxRuntime.jsx(DropdownSeparator, {}),
|
|
11324
|
+
onDelete && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11325
|
+
DropdownItem,
|
|
11326
|
+
{
|
|
11327
|
+
onClick: onDelete,
|
|
11328
|
+
danger: true,
|
|
11329
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "w-4 h-4" }),
|
|
11330
|
+
children: "Delete"
|
|
11331
|
+
}
|
|
11332
|
+
)
|
|
11333
|
+
]
|
|
11334
|
+
}
|
|
11335
|
+
) })
|
|
11336
|
+
] })
|
|
11337
|
+
] }),
|
|
11338
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "hidden md:flex flex-row items-center justify-between gap-4 py-3 px-6 bg-transparent border-0 static z-40", children: [
|
|
11339
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-row items-center gap-4", children: [
|
|
11340
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
11341
|
+
getStatusBadge(),
|
|
11342
|
+
getSaveStatusText() && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11343
|
+
"span",
|
|
11344
|
+
{
|
|
11345
|
+
className: `text-sm ${saveStatus === "error" ? "text-[var(--kyro-error)]" : "text-[var(--kyro-text-muted)]"}`,
|
|
11346
|
+
children: [
|
|
11347
|
+
saveStatus === "saving" ? /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: "sm", className: "inline mr-1" }) : null,
|
|
11348
|
+
getSaveStatusText()
|
|
11349
|
+
]
|
|
11350
|
+
}
|
|
11351
|
+
)
|
|
10984
11352
|
] }),
|
|
10985
|
-
|
|
10986
|
-
"
|
|
10987
|
-
|
|
11353
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-xs space-y-0.5", children: [
|
|
11354
|
+
updatedAt && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-[var(--kyro-text-muted)]", children: [
|
|
11355
|
+
"Updated: ",
|
|
11356
|
+
formatDate2(updatedAt)
|
|
11357
|
+
] }),
|
|
11358
|
+
publishedAt && status === "published" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-[var(--kyro-primary)] font-medium", children: [
|
|
11359
|
+
"Published: ",
|
|
11360
|
+
formatDate2(publishedAt)
|
|
11361
|
+
] })
|
|
10988
11362
|
] })
|
|
11363
|
+
] }),
|
|
11364
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [
|
|
11365
|
+
status === "draft" && onPublish && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11366
|
+
"button",
|
|
11367
|
+
{
|
|
11368
|
+
type: "button",
|
|
11369
|
+
onClick: onPublish,
|
|
11370
|
+
disabled: saveStatus === "saving",
|
|
11371
|
+
className: "kyro-btn kyro-btn-primary kyro-btn-md flex items-center gap-2",
|
|
11372
|
+
children: [
|
|
11373
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, { className: "w-4 h-4" }),
|
|
11374
|
+
"Publish"
|
|
11375
|
+
]
|
|
11376
|
+
}
|
|
11377
|
+
),
|
|
11378
|
+
status === "published" && onUnpublish && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11379
|
+
"button",
|
|
11380
|
+
{
|
|
11381
|
+
type: "button",
|
|
11382
|
+
onClick: onUnpublish,
|
|
11383
|
+
disabled: saveStatus === "saving",
|
|
11384
|
+
className: "kyro-btn kyro-btn-secondary kyro-btn-md flex items-center gap-2",
|
|
11385
|
+
children: [
|
|
11386
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Undo, { className: "w-4 h-4" }),
|
|
11387
|
+
"Unpublish"
|
|
11388
|
+
]
|
|
11389
|
+
}
|
|
11390
|
+
),
|
|
11391
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
11392
|
+
SplitButton,
|
|
11393
|
+
{
|
|
11394
|
+
status,
|
|
11395
|
+
saveStatus,
|
|
11396
|
+
hasChanges,
|
|
11397
|
+
onPublish: onSave,
|
|
11398
|
+
children: [
|
|
11399
|
+
onDuplicate && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11400
|
+
DropdownItem,
|
|
11401
|
+
{
|
|
11402
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "w-4 h-4" }),
|
|
11403
|
+
children: "Duplicate"
|
|
11404
|
+
}
|
|
11405
|
+
),
|
|
11406
|
+
onViewHistory && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11407
|
+
DropdownItem,
|
|
11408
|
+
{
|
|
11409
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, { className: "w-4 h-4" }),
|
|
11410
|
+
children: "View History"
|
|
11411
|
+
}
|
|
11412
|
+
),
|
|
11413
|
+
onPreview && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11414
|
+
DropdownItem,
|
|
11415
|
+
{
|
|
11416
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, { className: "w-4 h-4" }),
|
|
11417
|
+
children: "Preview"
|
|
11418
|
+
}
|
|
11419
|
+
),
|
|
11420
|
+
(onDuplicate || onViewHistory || onPreview) && /* @__PURE__ */ jsxRuntime.jsx(DropdownSeparator, {}),
|
|
11421
|
+
onDelete && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11422
|
+
DropdownItem,
|
|
11423
|
+
{
|
|
11424
|
+
onClick: onDelete,
|
|
11425
|
+
danger: true,
|
|
11426
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "w-4 h-4" }),
|
|
11427
|
+
children: "Delete"
|
|
11428
|
+
}
|
|
11429
|
+
)
|
|
11430
|
+
]
|
|
11431
|
+
}
|
|
11432
|
+
)
|
|
10989
11433
|
] })
|
|
10990
|
-
] }),
|
|
10991
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
10992
|
-
status === "draft" && onPublish && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10993
|
-
"button",
|
|
10994
|
-
{
|
|
10995
|
-
type: "button",
|
|
10996
|
-
onClick: onPublish,
|
|
10997
|
-
disabled: saveStatus === "saving",
|
|
10998
|
-
className: "kyro-btn kyro-btn-primary kyro-btn-md flex items-center gap-2",
|
|
10999
|
-
children: [
|
|
11000
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, { className: "w-4 h-4" }),
|
|
11001
|
-
"Publish"
|
|
11002
|
-
]
|
|
11003
|
-
}
|
|
11004
|
-
),
|
|
11005
|
-
status === "published" && onUnpublish && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11006
|
-
"button",
|
|
11007
|
-
{
|
|
11008
|
-
type: "button",
|
|
11009
|
-
onClick: onUnpublish,
|
|
11010
|
-
disabled: saveStatus === "saving",
|
|
11011
|
-
className: "kyro-btn kyro-btn-secondary kyro-btn-md flex items-center gap-2",
|
|
11012
|
-
children: [
|
|
11013
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Undo, { className: "w-4 h-4" }),
|
|
11014
|
-
"Unpublish"
|
|
11015
|
-
]
|
|
11016
|
-
}
|
|
11017
|
-
),
|
|
11018
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
11019
|
-
SplitButton,
|
|
11020
|
-
{
|
|
11021
|
-
status,
|
|
11022
|
-
saveStatus,
|
|
11023
|
-
hasChanges,
|
|
11024
|
-
onPublish: onSave,
|
|
11025
|
-
children: [
|
|
11026
|
-
onDuplicate && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11027
|
-
DropdownItem,
|
|
11028
|
-
{
|
|
11029
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "w-4 h-4" }),
|
|
11030
|
-
children: "Duplicate"
|
|
11031
|
-
}
|
|
11032
|
-
),
|
|
11033
|
-
onViewHistory && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11034
|
-
DropdownItem,
|
|
11035
|
-
{
|
|
11036
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, { className: "w-4 h-4" }),
|
|
11037
|
-
children: "View History"
|
|
11038
|
-
}
|
|
11039
|
-
),
|
|
11040
|
-
onPreview && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11041
|
-
DropdownItem,
|
|
11042
|
-
{
|
|
11043
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, { className: "w-4 h-4" }),
|
|
11044
|
-
children: "Preview"
|
|
11045
|
-
}
|
|
11046
|
-
),
|
|
11047
|
-
(onDuplicate || onViewHistory || onPreview) && /* @__PURE__ */ jsxRuntime.jsx(DropdownSeparator, {}),
|
|
11048
|
-
onDelete && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11049
|
-
DropdownItem,
|
|
11050
|
-
{
|
|
11051
|
-
onClick: onDelete,
|
|
11052
|
-
danger: true,
|
|
11053
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "w-4 h-4" }),
|
|
11054
|
-
children: "Delete"
|
|
11055
|
-
}
|
|
11056
|
-
)
|
|
11057
|
-
]
|
|
11058
|
-
}
|
|
11059
|
-
)
|
|
11060
11434
|
] })
|
|
11061
11435
|
] });
|
|
11062
11436
|
}
|
|
@@ -11072,32 +11446,32 @@ function DetailView({
|
|
|
11072
11446
|
mode = "collection"
|
|
11073
11447
|
}) {
|
|
11074
11448
|
const { confirm, alert } = useUIStore();
|
|
11075
|
-
const [data, setData] =
|
|
11076
|
-
const [originalData, setOriginalData] =
|
|
11077
|
-
const [loading, setLoading] =
|
|
11078
|
-
const [saving, setSaving] =
|
|
11079
|
-
const [saveStatus, setSaveStatus] =
|
|
11080
|
-
const [deleting, setDeleting] =
|
|
11081
|
-
const [status, setStatus] =
|
|
11082
|
-
const [createdAt, setCreatedAt] =
|
|
11083
|
-
const [updatedAt, setUpdatedAt] =
|
|
11084
|
-
const [publishedAt, setPublishedAt] =
|
|
11085
|
-
const [justSaved, setJustSaved] =
|
|
11449
|
+
const [data, setData] = React.useState({});
|
|
11450
|
+
const [originalData, setOriginalData] = React.useState({});
|
|
11451
|
+
const [loading, setLoading] = React.useState(true);
|
|
11452
|
+
const [saving, setSaving] = React.useState(false);
|
|
11453
|
+
const [saveStatus, setSaveStatus] = React.useState("idle");
|
|
11454
|
+
const [deleting, setDeleting] = React.useState(false);
|
|
11455
|
+
const [status, setStatus] = React.useState("draft");
|
|
11456
|
+
const [createdAt, setCreatedAt] = React.useState(null);
|
|
11457
|
+
const [updatedAt, setUpdatedAt] = React.useState(null);
|
|
11458
|
+
const [publishedAt, setPublishedAt] = React.useState(null);
|
|
11459
|
+
const [justSaved, setJustSaved] = React.useState(false);
|
|
11086
11460
|
const fields2 = global?.fields || collection?.fields || [];
|
|
11087
11461
|
const label = global?.label || collection?.label || "Document";
|
|
11088
11462
|
const slug = global?.slug || collection?.slug || "";
|
|
11089
11463
|
const hasChanges = JSON.stringify(data) !== JSON.stringify(originalData);
|
|
11090
|
-
|
|
11464
|
+
React.useEffect(() => {
|
|
11091
11465
|
if (hasChanges && status === "published") {
|
|
11092
11466
|
setStatus("draft");
|
|
11093
11467
|
}
|
|
11094
11468
|
}, [hasChanges, status]);
|
|
11095
|
-
|
|
11469
|
+
React.useEffect(() => {
|
|
11096
11470
|
if (hasChanges && saveStatus === "saved") {
|
|
11097
11471
|
setSaveStatus("idle");
|
|
11098
11472
|
}
|
|
11099
11473
|
}, [hasChanges, saveStatus]);
|
|
11100
|
-
|
|
11474
|
+
React.useEffect(() => {
|
|
11101
11475
|
if (mode === "global") {
|
|
11102
11476
|
loadGlobal();
|
|
11103
11477
|
} else if (documentId) {
|
|
@@ -11136,7 +11510,7 @@ function DetailView({
|
|
|
11136
11510
|
setLoading(false);
|
|
11137
11511
|
}
|
|
11138
11512
|
};
|
|
11139
|
-
const handleSave =
|
|
11513
|
+
const handleSave = React.useCallback(
|
|
11140
11514
|
async (isAutosave = false) => {
|
|
11141
11515
|
try {
|
|
11142
11516
|
setSaveStatus("saving");
|
|
@@ -11280,7 +11654,27 @@ function DetailView({
|
|
|
11280
11654
|
]
|
|
11281
11655
|
}
|
|
11282
11656
|
),
|
|
11283
|
-
|
|
11657
|
+
isSingleLayout ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "md:hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
11658
|
+
ActionBar,
|
|
11659
|
+
{
|
|
11660
|
+
status,
|
|
11661
|
+
saveStatus,
|
|
11662
|
+
hasChanges,
|
|
11663
|
+
onSave: () => handleSave(false),
|
|
11664
|
+
onPublish: handlePublish,
|
|
11665
|
+
onUnpublish: status === "published" ? handleUnpublish : void 0,
|
|
11666
|
+
onDuplicate: handleDuplicate,
|
|
11667
|
+
onViewHistory: () => {
|
|
11668
|
+
window.dispatchEvent(new CustomEvent("kyro:show-version-history"));
|
|
11669
|
+
},
|
|
11670
|
+
onPreview: () => window.open(`/preview/${slug}/${documentId}`, "_blank"),
|
|
11671
|
+
onDelete: handleDeleteTrigger,
|
|
11672
|
+
onBack,
|
|
11673
|
+
onToggleSidebar: () => window.dispatchEvent(new CustomEvent("toggle-sidebar")),
|
|
11674
|
+
publishedAt,
|
|
11675
|
+
updatedAt
|
|
11676
|
+
}
|
|
11677
|
+
) }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
11284
11678
|
ActionBar,
|
|
11285
11679
|
{
|
|
11286
11680
|
status,
|
|
@@ -11295,6 +11689,8 @@ function DetailView({
|
|
|
11295
11689
|
},
|
|
11296
11690
|
onPreview: () => window.open(`/preview/${slug}/${documentId}`, "_blank"),
|
|
11297
11691
|
onDelete: handleDeleteTrigger,
|
|
11692
|
+
onBack,
|
|
11693
|
+
onToggleSidebar: () => window.dispatchEvent(new CustomEvent("toggle-sidebar")),
|
|
11298
11694
|
publishedAt,
|
|
11299
11695
|
updatedAt
|
|
11300
11696
|
}
|
|
@@ -11302,9 +11698,9 @@ function DetailView({
|
|
|
11302
11698
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
11303
11699
|
"div",
|
|
11304
11700
|
{
|
|
11305
|
-
className: isSingleLayout ? "w-full pb-32 pt-8" : "w-full mx-auto grid grid-cols-1 lg:grid-cols-[1fr_360px] gap-8 pb-32",
|
|
11701
|
+
className: isSingleLayout ? "w-full pb-32 pt-4 md:pt-8" : "w-full mx-auto grid grid-cols-1 lg:grid-cols-[1fr_360px] gap-4 md:gap-8 pt-4 md:pt-0 pb-32",
|
|
11306
11702
|
children: [
|
|
11307
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-8 min-w-0", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "surface-tile p-8", children: [
|
|
11703
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-4 md:space-y-8 min-w-0", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "surface-tile p-4 md:p-8", children: [
|
|
11308
11704
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-8 px-1", children: [
|
|
11309
11705
|
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-[10px] font-bold tracking-[0.2em] opacity-40", children: "Core Configuration" }),
|
|
11310
11706
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-px flex-1 bg-[var(--kyro-border)] ml-6 opacity-30" })
|
|
@@ -11346,10 +11742,10 @@ function DetailView({
|
|
|
11346
11742
|
)
|
|
11347
11743
|
] })
|
|
11348
11744
|
] }) }),
|
|
11349
|
-
!isSingleLayout && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6 animate-in fade-in slide-in-from-right-4 duration-500", children: [
|
|
11350
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "surface-tile p-8", children: [
|
|
11351
|
-
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-[10px] font-bold tracking-[0.2em] opacity-40 mb-6", children: "Metadata" }),
|
|
11352
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
|
|
11745
|
+
!isSingleLayout && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4 md:space-y-6 animate-in fade-in slide-in-from-right-4 duration-500", children: [
|
|
11746
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "surface-tile p-4 md:p-8", children: [
|
|
11747
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-[10px] font-bold tracking-[0.2em] opacity-40 mb-4 md:mb-6", children: "Metadata" }),
|
|
11748
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4 md:space-y-6", children: [
|
|
11353
11749
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
11354
11750
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-bold tracking-widest opacity-40", children: "Dynamic Status" }),
|
|
11355
11751
|
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -11383,9 +11779,9 @@ function DetailView({
|
|
|
11383
11779
|
] })
|
|
11384
11780
|
] })
|
|
11385
11781
|
] }),
|
|
11386
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "surface-tile p-8 bg-[var(--kyro-bg-secondary)]", children: [
|
|
11387
|
-
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-[10px] font-bold tracking-[0.2em] opacity-40 mb-4", children: "Quick Links" }),
|
|
11388
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
|
|
11782
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "surface-tile p-4 md:p-8 bg-[var(--kyro-bg-secondary)]", children: [
|
|
11783
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-[10px] font-bold tracking-[0.2em] opacity-40 mb-3 md:mb-4", children: "Quick Links" }),
|
|
11784
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2 md:space-y-3", children: [
|
|
11389
11785
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11390
11786
|
"button",
|
|
11391
11787
|
{
|
|
@@ -11428,8 +11824,8 @@ function CreateView({
|
|
|
11428
11824
|
onSuccess,
|
|
11429
11825
|
onError
|
|
11430
11826
|
}) {
|
|
11431
|
-
const [data, setData] =
|
|
11432
|
-
const [saving, setSaving] =
|
|
11827
|
+
const [data, setData] = React.useState({});
|
|
11828
|
+
const [saving, setSaving] = React.useState(false);
|
|
11433
11829
|
const fields2 = collection.fields || [];
|
|
11434
11830
|
const label = collection.label || collection.slug;
|
|
11435
11831
|
const handleSubmit = async (e) => {
|
|
@@ -11472,8 +11868,8 @@ function CreateView({
|
|
|
11472
11868
|
] });
|
|
11473
11869
|
}
|
|
11474
11870
|
function Toast({ type, message, onClose }) {
|
|
11475
|
-
const [isPaused, setIsPaused] =
|
|
11476
|
-
const timerRef =
|
|
11871
|
+
const [isPaused, setIsPaused] = React__default.default.useState(false);
|
|
11872
|
+
const timerRef = React__default.default.useRef(null);
|
|
11477
11873
|
const startTimer = () => {
|
|
11478
11874
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
11479
11875
|
timerRef.current = setTimeout(onClose, 5e3);
|
|
@@ -11481,7 +11877,7 @@ function Toast({ type, message, onClose }) {
|
|
|
11481
11877
|
const clearTimer = () => {
|
|
11482
11878
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
11483
11879
|
};
|
|
11484
|
-
|
|
11880
|
+
React__default.default.useEffect(() => {
|
|
11485
11881
|
if (!isPaused) {
|
|
11486
11882
|
startTimer();
|
|
11487
11883
|
} else {
|
|
@@ -11502,14 +11898,13 @@ function Toast({ type, message, onClose }) {
|
|
|
11502
11898
|
onMouseEnter: () => setIsPaused(true),
|
|
11503
11899
|
onMouseLeave: () => setIsPaused(false),
|
|
11504
11900
|
children: [
|
|
11505
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "kyro-toast-accent" }),
|
|
11506
11901
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "kyro-toast-icon-container", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "w-4 h-4" }) }),
|
|
11507
11902
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "kyro-toast-content", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "kyro-toast-message", children: message }) }),
|
|
11508
11903
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
11509
11904
|
"button",
|
|
11510
11905
|
{
|
|
11511
11906
|
type: "button",
|
|
11512
|
-
className: "kyro-toast-close
|
|
11907
|
+
className: "kyro-toast-close",
|
|
11513
11908
|
onClick: onClose,
|
|
11514
11909
|
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-3.5 h-3.5" })
|
|
11515
11910
|
}
|
|
@@ -11527,15 +11922,20 @@ function useToast() {
|
|
|
11527
11922
|
const toasts = useToastStore((state) => state.toasts);
|
|
11528
11923
|
return { toasts, addToast, removeToast };
|
|
11529
11924
|
}
|
|
11925
|
+
function Toaster() {
|
|
11926
|
+
const toasts = useToastStore((state) => state.toasts);
|
|
11927
|
+
const removeToast = useToastStore((state) => state.removeToast);
|
|
11928
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "kyro-toasts-container", style: { position: "fixed", bottom: "24px", right: "24px", display: "flex", flexDirection: "column", gap: "12px", zIndex: 9999, pointerEvents: "none" }, children: toasts.map((t) => /* @__PURE__ */ jsxRuntime.jsx("div", { style: { pointerEvents: "auto" }, children: /* @__PURE__ */ jsxRuntime.jsx(Toast, { type: t.type, message: t.message, onClose: () => removeToast(t.id) }) }, t.id)) });
|
|
11929
|
+
}
|
|
11530
11930
|
function LoginPage({ onAuth, theme = "light" }) {
|
|
11531
|
-
const [mode, setMode] =
|
|
11532
|
-
const [email, setEmail] =
|
|
11533
|
-
const [password, setPassword] =
|
|
11534
|
-
const [confirmPassword, setConfirmPassword] =
|
|
11535
|
-
const [loading, setLoading] =
|
|
11536
|
-
const [
|
|
11537
|
-
const
|
|
11538
|
-
|
|
11931
|
+
const [mode, setMode] = React.useState("login");
|
|
11932
|
+
const [email, setEmail] = React.useState("");
|
|
11933
|
+
const [password, setPassword] = React.useState("");
|
|
11934
|
+
const [confirmPassword, setConfirmPassword] = React.useState("");
|
|
11935
|
+
const [loading, setLoading] = React.useState(false);
|
|
11936
|
+
const [isFirstUser, setIsFirstUser] = React.useState(false);
|
|
11937
|
+
const addToast = useToastStore((state) => state.addToast);
|
|
11938
|
+
React.useEffect(() => {
|
|
11539
11939
|
checkIfFirstUser();
|
|
11540
11940
|
}, []);
|
|
11541
11941
|
const checkIfFirstUser = async () => {
|
|
@@ -11546,13 +11946,6 @@ function LoginPage({ onAuth, theme = "light" }) {
|
|
|
11546
11946
|
setMode("register");
|
|
11547
11947
|
}
|
|
11548
11948
|
};
|
|
11549
|
-
const addToast = (type, message) => {
|
|
11550
|
-
const id = Math.random().toString(36).substring(7);
|
|
11551
|
-
setToasts((prev) => [...prev, { id, type, message }]);
|
|
11552
|
-
setTimeout(() => {
|
|
11553
|
-
setToasts((prev) => prev.filter((t) => t.id !== id));
|
|
11554
|
-
}, 5e3);
|
|
11555
|
-
};
|
|
11556
11949
|
const handleSubmit = async (e) => {
|
|
11557
11950
|
e.preventDefault();
|
|
11558
11951
|
setLoading(true);
|
|
@@ -11578,7 +11971,7 @@ function LoginPage({ onAuth, theme = "light" }) {
|
|
|
11578
11971
|
setLoading(false);
|
|
11579
11972
|
}
|
|
11580
11973
|
};
|
|
11581
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ThemeProvider, { defaultMode: theme, children: /* @__PURE__ */ jsxRuntime.
|
|
11974
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ThemeProvider, { defaultMode: theme, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "kyro-login-page", children: [
|
|
11582
11975
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "kyro-login-container", children: [
|
|
11583
11976
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "kyro-login-header", children: [
|
|
11584
11977
|
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "kyro-login-title", children: isFirstUser ? "Create Admin Account" : mode === "login" ? "Sign In" : "Create Account" }),
|
|
@@ -11668,27 +12061,19 @@ function LoginPage({ onAuth, theme = "light" }) {
|
|
|
11668
12061
|
)
|
|
11669
12062
|
] }) }) })
|
|
11670
12063
|
] }),
|
|
11671
|
-
|
|
11672
|
-
|
|
11673
|
-
{
|
|
11674
|
-
type: toast2.type,
|
|
11675
|
-
message: toast2.message,
|
|
11676
|
-
onClose: () => setToasts((prev) => prev.filter((t) => t.id !== toast2.id))
|
|
11677
|
-
},
|
|
11678
|
-
toast2.id
|
|
11679
|
-
))
|
|
11680
|
-
] }) }) });
|
|
12064
|
+
/* @__PURE__ */ jsxRuntime.jsx(Toaster, {})
|
|
12065
|
+
] }) });
|
|
11681
12066
|
}
|
|
11682
12067
|
function Dashboard({ collections: collections2, onNavigate, user }) {
|
|
11683
12068
|
const { permissions } = useAuthStore();
|
|
11684
|
-
const [stats, setStats] =
|
|
12069
|
+
const [stats, setStats] = React.useState({
|
|
11685
12070
|
totalDocs: 0,
|
|
11686
12071
|
totalMedia: 0,
|
|
11687
12072
|
totalUsers: 0,
|
|
11688
12073
|
recentActivity: []
|
|
11689
12074
|
});
|
|
11690
|
-
const [loading, setLoading] =
|
|
11691
|
-
|
|
12075
|
+
const [loading, setLoading] = React.useState(true);
|
|
12076
|
+
React.useEffect(() => {
|
|
11692
12077
|
const timer = setTimeout(() => {
|
|
11693
12078
|
setStats({
|
|
11694
12079
|
totalDocs: 124,
|
|
@@ -12009,15 +12394,15 @@ function Dashboard({ collections: collections2, onNavigate, user }) {
|
|
|
12009
12394
|
] });
|
|
12010
12395
|
}
|
|
12011
12396
|
function UserManagement() {
|
|
12012
|
-
const [users, setUsers] =
|
|
12013
|
-
const [loading, setLoading] =
|
|
12014
|
-
const [searchQuery, setSearchQuery] =
|
|
12015
|
-
const [showCreateModal, setShowCreateModal] =
|
|
12016
|
-
const [createForm, setCreateForm] =
|
|
12017
|
-
const [createError, setCreateError] =
|
|
12018
|
-
const [creating, setCreating] =
|
|
12397
|
+
const [users, setUsers] = React.useState([]);
|
|
12398
|
+
const [loading, setLoading] = React.useState(true);
|
|
12399
|
+
const [searchQuery, setSearchQuery] = React.useState("");
|
|
12400
|
+
const [showCreateModal, setShowCreateModal] = React.useState(false);
|
|
12401
|
+
const [createForm, setCreateForm] = React.useState({ name: "", email: "", password: "", role: "customer" });
|
|
12402
|
+
const [createError, setCreateError] = React.useState("");
|
|
12403
|
+
const [creating, setCreating] = React.useState(false);
|
|
12019
12404
|
const { confirm, alert } = useUIStore();
|
|
12020
|
-
|
|
12405
|
+
React.useEffect(() => {
|
|
12021
12406
|
loadUsers();
|
|
12022
12407
|
}, []);
|
|
12023
12408
|
const loadUsers = async () => {
|
|
@@ -12099,7 +12484,7 @@ function UserManagement() {
|
|
|
12099
12484
|
const filteredUsers = users.filter(
|
|
12100
12485
|
(u) => u.email.toLowerCase().includes(searchQuery.toLowerCase()) || u.name?.toLowerCase().includes(searchQuery.toLowerCase())
|
|
12101
12486
|
);
|
|
12102
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full space-y-6 animate-in fade-in slide-in-from-bottom-4 duration-700 px-8 pb-12", children: [
|
|
12487
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full space-y-6 animate-in fade-in slide-in-from-bottom-4 duration-700 px-4 md:px-8 pb-12", children: [
|
|
12103
12488
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
12104
12489
|
PageHeader,
|
|
12105
12490
|
{
|
|
@@ -12137,8 +12522,8 @@ function UserManagement() {
|
|
|
12137
12522
|
/* @__PURE__ */ jsxRuntime.jsx("button", { className: "px-4 py-1.5 text-[10px] font-bold tracking-widest opacity-40 hover:opacity-100 transition-all", children: "LOCKED" })
|
|
12138
12523
|
] })
|
|
12139
12524
|
] }),
|
|
12140
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "surface-tile overflow-
|
|
12141
|
-
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "text-[var(--kyro-text-secondary)] font-bold text-[9px] tracking-[0.2em] uppercase border-b border-[var(--kyro-border)]", children: [
|
|
12525
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "surface-tile overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full text-left", children: [
|
|
12526
|
+
/* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "text-[var(--kyro-text-secondary)] font-bold text-[9px] tracking-[0.2em] uppercase border-b border-[var(--kyro-border)] whitespace-nowrap", children: [
|
|
12142
12527
|
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-6 py-4 w-64", children: "Member Identity" }),
|
|
12143
12528
|
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-6 py-4", children: "Administrative Role" }),
|
|
12144
12529
|
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-6 py-4", children: "Security Status" }),
|
|
@@ -12282,8 +12667,8 @@ function UserManagement() {
|
|
|
12282
12667
|
] });
|
|
12283
12668
|
}
|
|
12284
12669
|
function AvatarCell({ user }) {
|
|
12285
|
-
const [url, setUrl] =
|
|
12286
|
-
|
|
12670
|
+
const [url, setUrl] = React.useState(null);
|
|
12671
|
+
React.useEffect(() => {
|
|
12287
12672
|
const avatar = user.avatar;
|
|
12288
12673
|
if (typeof avatar === "string" && /^[0-9a-f-]+$/i.test(avatar)) {
|
|
12289
12674
|
apiGet(`/api/media/${avatar}`).then((media) => setUrl(media?.thumbnailUrl || media?.url || null)).catch(() => setUrl(null));
|
|
@@ -12295,15 +12680,15 @@ function AvatarCell({ user }) {
|
|
|
12295
12680
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-8 h-8 rounded-lg bg-[var(--kyro-surface-accent)] border border-[var(--kyro-border)] flex items-center justify-center text-xs font-bold text-[var(--kyro-primary)] flex-shrink-0", children: user.name ? user.name[0] : user.email[0].toUpperCase() });
|
|
12296
12681
|
}
|
|
12297
12682
|
function BrandingHub() {
|
|
12298
|
-
const [siteName, setSiteName] =
|
|
12299
|
-
const [adminTitle, setAdminTitle] =
|
|
12300
|
-
const [primaryColor, setPrimaryColor] =
|
|
12301
|
-
const [dashboardGreeting, setDashboardGreeting] =
|
|
12683
|
+
const [siteName, setSiteName] = React.useState("Kyro CMS");
|
|
12684
|
+
const [adminTitle, setAdminTitle] = React.useState("Command Center");
|
|
12685
|
+
const [primaryColor, setPrimaryColor] = React.useState("#6366f1");
|
|
12686
|
+
const [dashboardGreeting, setDashboardGreeting] = React.useState(
|
|
12302
12687
|
"Welcome back to your Command Center."
|
|
12303
12688
|
);
|
|
12304
|
-
const [saving, setSaving] =
|
|
12305
|
-
const [saved, setSaved] =
|
|
12306
|
-
|
|
12689
|
+
const [saving, setSaving] = React.useState(false);
|
|
12690
|
+
const [saved, setSaved] = React.useState(false);
|
|
12691
|
+
React.useEffect(() => {
|
|
12307
12692
|
const fetchBranding = async () => {
|
|
12308
12693
|
try {
|
|
12309
12694
|
const result = await apiGet("/api/globals/site-settings");
|
|
@@ -12499,15 +12884,15 @@ function BrandingHub() {
|
|
|
12499
12884
|
}
|
|
12500
12885
|
var API_BASE2 = typeof __KYRO_API_PATH__ !== "undefined" ? __KYRO_API_PATH__ : "/api";
|
|
12501
12886
|
function DeveloperCenter({ collections: collections2 }) {
|
|
12502
|
-
const [keys, setKeys] =
|
|
12503
|
-
const [loading, setLoading] =
|
|
12504
|
-
const [showKey, setShowKey] =
|
|
12505
|
-
const [testEndpoint, setTestEndpoint] =
|
|
12506
|
-
const [playgroundResult, setPlaygroundResult] =
|
|
12507
|
-
const [exploring, setExploring] =
|
|
12887
|
+
const [keys, setKeys] = React.useState([]);
|
|
12888
|
+
const [loading, setLoading] = React.useState(false);
|
|
12889
|
+
const [showKey, setShowKey] = React.useState(null);
|
|
12890
|
+
const [testEndpoint, setTestEndpoint] = React.useState("");
|
|
12891
|
+
const [playgroundResult, setPlaygroundResult] = React.useState(null);
|
|
12892
|
+
const [exploring, setExploring] = React.useState(false);
|
|
12508
12893
|
const { confirm, alert } = useUIStore();
|
|
12509
|
-
const [showCreateModal, setShowCreateModal] =
|
|
12510
|
-
const [newKeyName, setNewKeyName] =
|
|
12894
|
+
const [showCreateModal, setShowCreateModal] = React.useState(false);
|
|
12895
|
+
const [newKeyName, setNewKeyName] = React.useState("");
|
|
12511
12896
|
const loadKeys = async () => {
|
|
12512
12897
|
try {
|
|
12513
12898
|
const data = await apiGet("/api/keys");
|
|
@@ -12516,7 +12901,7 @@ function DeveloperCenter({ collections: collections2 }) {
|
|
|
12516
12901
|
console.error(e);
|
|
12517
12902
|
}
|
|
12518
12903
|
};
|
|
12519
|
-
|
|
12904
|
+
React.useEffect(() => {
|
|
12520
12905
|
loadKeys();
|
|
12521
12906
|
}, []);
|
|
12522
12907
|
const handleGenerateKey = async () => {
|
|
@@ -12834,12 +13219,12 @@ function DeveloperCenter({ collections: collections2 }) {
|
|
|
12834
13219
|
] });
|
|
12835
13220
|
}
|
|
12836
13221
|
function useResourceManager(options) {
|
|
12837
|
-
const [items, setItems] =
|
|
12838
|
-
const [loading, setLoading] =
|
|
12839
|
-
const [error, setError] =
|
|
12840
|
-
const [isCreateModalOpen, setIsCreateModalOpen] =
|
|
13222
|
+
const [items, setItems] = React.useState([]);
|
|
13223
|
+
const [loading, setLoading] = React.useState(false);
|
|
13224
|
+
const [error, setError] = React.useState(null);
|
|
13225
|
+
const [isCreateModalOpen, setIsCreateModalOpen] = React.useState(false);
|
|
12841
13226
|
const { confirm } = useUIStore();
|
|
12842
|
-
const load =
|
|
13227
|
+
const load = React.useCallback(async () => {
|
|
12843
13228
|
setLoading(true);
|
|
12844
13229
|
setError(null);
|
|
12845
13230
|
try {
|
|
@@ -12856,10 +13241,10 @@ function useResourceManager(options) {
|
|
|
12856
13241
|
setLoading(false);
|
|
12857
13242
|
}
|
|
12858
13243
|
}, [options.endpoint, options.transformLoad]);
|
|
12859
|
-
|
|
13244
|
+
React.useEffect(() => {
|
|
12860
13245
|
load();
|
|
12861
13246
|
}, [load]);
|
|
12862
|
-
const remove =
|
|
13247
|
+
const remove = React.useCallback((id, resourceName = "item") => {
|
|
12863
13248
|
confirm({
|
|
12864
13249
|
title: `Delete ${resourceName}`,
|
|
12865
13250
|
message: `Are you sure you want to delete this ${resourceName.toLowerCase()}? This action cannot be undone.`,
|
|
@@ -12869,6 +13254,7 @@ function useResourceManager(options) {
|
|
|
12869
13254
|
await apiDelete(`${options.endpoint}/${id}`);
|
|
12870
13255
|
setItems((prev) => prev.filter((item) => item.id !== id));
|
|
12871
13256
|
options.onSuccess?.("delete", id);
|
|
13257
|
+
toast.success(`${resourceName} deleted`);
|
|
12872
13258
|
} catch (e) {
|
|
12873
13259
|
const message = e instanceof Error ? e.message : `Failed to delete ${resourceName}`;
|
|
12874
13260
|
toast.error(message);
|
|
@@ -12877,7 +13263,7 @@ function useResourceManager(options) {
|
|
|
12877
13263
|
}
|
|
12878
13264
|
});
|
|
12879
13265
|
}, [options.endpoint, confirm]);
|
|
12880
|
-
const create3 =
|
|
13266
|
+
const create3 = React.useCallback(async (data) => {
|
|
12881
13267
|
setError(null);
|
|
12882
13268
|
try {
|
|
12883
13269
|
const created = await apiPost(options.endpoint, data);
|
|
@@ -12892,7 +13278,7 @@ function useResourceManager(options) {
|
|
|
12892
13278
|
throw e;
|
|
12893
13279
|
}
|
|
12894
13280
|
}, [options.endpoint]);
|
|
12895
|
-
const update =
|
|
13281
|
+
const update = React.useCallback(async (id, data) => {
|
|
12896
13282
|
setError(null);
|
|
12897
13283
|
try {
|
|
12898
13284
|
const updated = await apiPatch(`${options.endpoint}/${id}`, data);
|
|
@@ -12932,17 +13318,17 @@ function WebhookManager() {
|
|
|
12932
13318
|
endpoint: "/api/webhooks"
|
|
12933
13319
|
});
|
|
12934
13320
|
const { confirm } = useUIStore();
|
|
12935
|
-
const [showTestModal, setShowTestModal] =
|
|
12936
|
-
const [showHelpModal, setShowHelpModal] =
|
|
12937
|
-
const [testResult, setTestResult] =
|
|
12938
|
-
const [testId, setTestId] =
|
|
12939
|
-
const [formData, setFormData] =
|
|
13321
|
+
const [showTestModal, setShowTestModal] = React.useState(false);
|
|
13322
|
+
const [showHelpModal, setShowHelpModal] = React.useState(false);
|
|
13323
|
+
const [testResult, setTestResult] = React.useState(null);
|
|
13324
|
+
const [testId, setTestId] = React.useState(null);
|
|
13325
|
+
const [formData, setFormData] = React.useState({
|
|
12940
13326
|
name: "",
|
|
12941
13327
|
url: "",
|
|
12942
13328
|
events: [],
|
|
12943
13329
|
secret: ""
|
|
12944
13330
|
});
|
|
12945
|
-
const [createError, setCreateError] =
|
|
13331
|
+
const [createError, setCreateError] = React.useState("");
|
|
12946
13332
|
const handleCreate = async () => {
|
|
12947
13333
|
if (!formData.name.trim() || !formData.url.trim()) {
|
|
12948
13334
|
setCreateError("Name and URL are required");
|
|
@@ -13097,12 +13483,12 @@ function WebhookManager() {
|
|
|
13097
13483
|
] })
|
|
13098
13484
|
] })
|
|
13099
13485
|
] }),
|
|
13100
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid sm:grid-cols-3 gap-6 pt-2", children: [
|
|
13486
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-3 gap-6 pt-2", children: [
|
|
13101
13487
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
|
|
13102
13488
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[9px] font-bold uppercase tracking-widest opacity-30", children: "Destination" }),
|
|
13103
13489
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-mono text-xs opacity-60 truncate max-w-[200px]", title: webhook.url, children: webhook.url })
|
|
13104
13490
|
] }),
|
|
13105
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1 border-l border-[var(--kyro-border)] pl-6", children: [
|
|
13491
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1 sm:border-l border-t sm:border-t-0 border-[var(--kyro-border)] pt-4 sm:pt-0 sm:pl-6 mt-4 sm:mt-0", children: [
|
|
13106
13492
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[9px] font-bold uppercase tracking-widest opacity-30", children: "Events" }),
|
|
13107
13493
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-1", children: [
|
|
13108
13494
|
webhook.events.slice(0, 2).map((event) => /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "outline", className: "text-[8px] font-bold px-1.5 opacity-60", children: event }, event)),
|
|
@@ -13113,7 +13499,7 @@ function WebhookManager() {
|
|
|
13113
13499
|
] })
|
|
13114
13500
|
] })
|
|
13115
13501
|
] }),
|
|
13116
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1 border-l border-[var(--kyro-border)] pl-6", children: [
|
|
13502
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1 sm:border-l border-t sm:border-t-0 border-[var(--kyro-border)] pt-4 sm:pt-0 sm:pl-6 mt-4 sm:mt-0", children: [
|
|
13117
13503
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[9px] font-bold uppercase tracking-widest opacity-30", children: "Activity" }),
|
|
13118
13504
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-[10px] font-bold opacity-60 flex items-center gap-1.5", children: [
|
|
13119
13505
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, { className: "w-3 h-3" }),
|
|
@@ -13216,7 +13602,7 @@ function WebhookManager() {
|
|
|
13216
13602
|
] }),
|
|
13217
13603
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
|
|
13218
13604
|
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-xs font-bold mb-1.5 text-[var(--kyro-text-secondary)] uppercase tracking-wider", children: "Subscribed Events" }),
|
|
13219
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-4", children: eventOptions.map((opt) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
13605
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-4", children: eventOptions.map((opt) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
13220
13606
|
"button",
|
|
13221
13607
|
{
|
|
13222
13608
|
type: "button",
|
|
@@ -13394,13 +13780,13 @@ function CommandPalette({
|
|
|
13394
13780
|
onNavigate
|
|
13395
13781
|
}) {
|
|
13396
13782
|
const { user, permissions } = useAuthStore();
|
|
13397
|
-
const [query, setQuery] =
|
|
13398
|
-
const [selectedIndex, setSelectedIndex] =
|
|
13399
|
-
const [loading, setLoading] =
|
|
13400
|
-
const [searchResults, setSearchResults] =
|
|
13401
|
-
const inputRef =
|
|
13402
|
-
const debounceRef =
|
|
13403
|
-
|
|
13783
|
+
const [query, setQuery] = React.useState("");
|
|
13784
|
+
const [selectedIndex, setSelectedIndex] = React.useState(0);
|
|
13785
|
+
const [loading, setLoading] = React.useState(false);
|
|
13786
|
+
const [searchResults, setSearchResults] = React.useState([]);
|
|
13787
|
+
const inputRef = React.useRef(null);
|
|
13788
|
+
const debounceRef = React.useRef(null);
|
|
13789
|
+
React.useEffect(() => {
|
|
13404
13790
|
if (isOpen) {
|
|
13405
13791
|
setQuery("");
|
|
13406
13792
|
setSelectedIndex(0);
|
|
@@ -13409,7 +13795,7 @@ function CommandPalette({
|
|
|
13409
13795
|
setTimeout(() => inputRef.current?.focus(), 100);
|
|
13410
13796
|
}
|
|
13411
13797
|
}, [isOpen]);
|
|
13412
|
-
const performSearch =
|
|
13798
|
+
const performSearch = React.useCallback(async (searchQuery) => {
|
|
13413
13799
|
if (!searchQuery || searchQuery.length < 2) {
|
|
13414
13800
|
setSearchResults([]);
|
|
13415
13801
|
return;
|
|
@@ -13430,7 +13816,7 @@ function CommandPalette({
|
|
|
13430
13816
|
setLoading(false);
|
|
13431
13817
|
}
|
|
13432
13818
|
}, []);
|
|
13433
|
-
|
|
13819
|
+
React.useEffect(() => {
|
|
13434
13820
|
if (debounceRef.current) {
|
|
13435
13821
|
clearTimeout(debounceRef.current);
|
|
13436
13822
|
}
|
|
@@ -13677,7 +14063,7 @@ function CommandPalette({
|
|
|
13677
14063
|
}
|
|
13678
14064
|
function GlobalModal() {
|
|
13679
14065
|
const { modal, closeModal } = useUIStore();
|
|
13680
|
-
const [loading, setLoading] =
|
|
14066
|
+
const [loading, setLoading] = React.useState(false);
|
|
13681
14067
|
if (!modal.open || !modal.config) return null;
|
|
13682
14068
|
const { config } = modal;
|
|
13683
14069
|
const handleConfirm = async () => {
|
|
@@ -13717,24 +14103,22 @@ function GlobalModal() {
|
|
|
13717
14103
|
);
|
|
13718
14104
|
}
|
|
13719
14105
|
function Admin({ config, theme = "light", onThemeChange }) {
|
|
13720
|
-
const [authenticated, setAuthenticated] =
|
|
13721
|
-
const [currentUser, setCurrentUser] =
|
|
13722
|
-
const collections2 =
|
|
14106
|
+
const [authenticated, setAuthenticated] = React.useState(false);
|
|
14107
|
+
const [currentUser, setCurrentUser] = React.useState(null);
|
|
14108
|
+
const collections2 = React.useMemo(
|
|
13723
14109
|
() => toCollectionMap(toArray(config.collections)),
|
|
13724
14110
|
[config.collections]
|
|
13725
14111
|
);
|
|
13726
|
-
const globals2 =
|
|
14112
|
+
const globals2 = React.useMemo(
|
|
13727
14113
|
() => toGlobalMap(toArray(config.globals)),
|
|
13728
14114
|
[config.globals]
|
|
13729
14115
|
);
|
|
13730
|
-
const [activeCollection, setActiveCollection] =
|
|
13731
|
-
const [activeGlobal, setActiveGlobal] =
|
|
13732
|
-
const [currentView, setCurrentView] =
|
|
13733
|
-
const [activeDocumentId, setActiveDocumentId] =
|
|
13734
|
-
const [isCommandPaletteOpen, setIsCommandPaletteOpen] =
|
|
13735
|
-
|
|
13736
|
-
const removeToast = useToastStore((state) => state.removeToast);
|
|
13737
|
-
React56.useEffect(() => {
|
|
14116
|
+
const [activeCollection, setActiveCollection] = React.useState(null);
|
|
14117
|
+
const [activeGlobal, setActiveGlobal] = React.useState(null);
|
|
14118
|
+
const [currentView, setCurrentView] = React.useState("list");
|
|
14119
|
+
const [activeDocumentId, setActiveDocumentId] = React.useState(null);
|
|
14120
|
+
const [isCommandPaletteOpen, setIsCommandPaletteOpen] = React.useState(false);
|
|
14121
|
+
React.useEffect(() => {
|
|
13738
14122
|
const checkAuth = async () => {
|
|
13739
14123
|
try {
|
|
13740
14124
|
const response = await fetch("/api/users/me");
|
|
@@ -13749,7 +14133,7 @@ function Admin({ config, theme = "light", onThemeChange }) {
|
|
|
13749
14133
|
};
|
|
13750
14134
|
checkAuth();
|
|
13751
14135
|
}, []);
|
|
13752
|
-
|
|
14136
|
+
React.useEffect(() => {
|
|
13753
14137
|
if (authenticated && !activeCollection) {
|
|
13754
14138
|
const firstCol = Object.keys(collections2)[0];
|
|
13755
14139
|
if (firstCol) setActiveCollection(firstCol);
|
|
@@ -13761,7 +14145,7 @@ function Admin({ config, theme = "light", onThemeChange }) {
|
|
|
13761
14145
|
if (id) setActiveDocumentId(id);
|
|
13762
14146
|
setIsCommandPaletteOpen(false);
|
|
13763
14147
|
};
|
|
13764
|
-
|
|
14148
|
+
React.useEffect(() => {
|
|
13765
14149
|
const handleKeyDown = (e) => {
|
|
13766
14150
|
if ((e.metaKey || e.ctrlKey) && e.key === "k") {
|
|
13767
14151
|
e.preventDefault();
|
|
@@ -13855,15 +14239,7 @@ function Admin({ config, theme = "light", onThemeChange }) {
|
|
|
13855
14239
|
renderContent()
|
|
13856
14240
|
] }) }) }),
|
|
13857
14241
|
/* @__PURE__ */ jsxRuntime.jsx(GlobalModal, {}),
|
|
13858
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
13859
|
-
Toast,
|
|
13860
|
-
{
|
|
13861
|
-
type: t.type,
|
|
13862
|
-
message: t.message,
|
|
13863
|
-
onClose: () => removeToast(t.id)
|
|
13864
|
-
},
|
|
13865
|
-
t.id
|
|
13866
|
-
)) })
|
|
14242
|
+
/* @__PURE__ */ jsxRuntime.jsx(Toaster, {})
|
|
13867
14243
|
] }) });
|
|
13868
14244
|
}
|
|
13869
14245
|
function BulkActionsBar({
|
|
@@ -14161,10 +14537,10 @@ function getApiUrl(path2) {
|
|
|
14161
14537
|
return `${base}${path2}`;
|
|
14162
14538
|
}
|
|
14163
14539
|
function useKyroQuery(slug, options = {}) {
|
|
14164
|
-
const [data, setData] =
|
|
14165
|
-
const [loading, setLoading] =
|
|
14166
|
-
const [error, setError] =
|
|
14167
|
-
const fetchData =
|
|
14540
|
+
const [data, setData] = React.useState(null);
|
|
14541
|
+
const [loading, setLoading] = React.useState(true);
|
|
14542
|
+
const [error, setError] = React.useState(null);
|
|
14543
|
+
const fetchData = React.useCallback(async () => {
|
|
14168
14544
|
setLoading(true);
|
|
14169
14545
|
setError(null);
|
|
14170
14546
|
try {
|
|
@@ -14186,15 +14562,15 @@ function useKyroQuery(slug, options = {}) {
|
|
|
14186
14562
|
setLoading(false);
|
|
14187
14563
|
}
|
|
14188
14564
|
}, [slug, options.page, options.limit, options.sort, options.order]);
|
|
14189
|
-
|
|
14565
|
+
React.useEffect(() => {
|
|
14190
14566
|
fetchData();
|
|
14191
14567
|
}, [fetchData]);
|
|
14192
14568
|
return { data, loading, error, refetch: fetchData };
|
|
14193
14569
|
}
|
|
14194
14570
|
function useKyroMutation(slug, method = "POST") {
|
|
14195
|
-
const [loading, setLoading] =
|
|
14196
|
-
const [error, setError] =
|
|
14197
|
-
const mutate =
|
|
14571
|
+
const [loading, setLoading] = React.useState(false);
|
|
14572
|
+
const [error, setError] = React.useState(null);
|
|
14573
|
+
const mutate = React.useCallback(
|
|
14198
14574
|
async (data) => {
|
|
14199
14575
|
setLoading(true);
|
|
14200
14576
|
setError(null);
|