gavaengine 0.1.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/DashboardSplashTrigger-CRpueuUi.d.ts +154 -0
- package/dist/auth/index.d.ts +42 -0
- package/dist/auth/index.js +12 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/{chunk-D5PTZWTT.js → chunk-4LM22T36.js} +2 -2
- package/dist/chunk-MC3FBYWV.js +534 -0
- package/dist/chunk-MC3FBYWV.js.map +1 -0
- package/dist/chunk-QO42DDRU.js +113 -0
- package/dist/chunk-QO42DDRU.js.map +1 -0
- package/dist/{chunk-3C3AAR3S.js → chunk-YSVQQBBU.js} +474 -50
- package/dist/chunk-YSVQQBBU.js.map +1 -0
- package/dist/components/index.d.ts +64 -132
- package/dist/components/index.js +22 -2
- package/dist/content/index.d.ts +45 -0
- package/dist/content/index.js +38 -0
- package/dist/content/index.js.map +1 -0
- package/dist/handlers/index.d.ts +60 -3
- package/dist/handlers/index.js +477 -126
- package/dist/handlers/index.js.map +1 -1
- package/dist/i18n/index.d.ts +114 -0
- package/dist/i18n/index.js +249 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/{index-B1ZYC5TP.d.ts → index-CCsSC4nF.d.ts} +119 -2
- package/dist/index.d.ts +45 -7
- package/dist/index.js +226 -39
- package/dist/index.js.map +1 -1
- package/dist/providers/index.d.ts +3 -2
- package/dist/providers/index.js +2 -2
- package/dist/types-X07o_zKf.d.ts +198 -0
- package/dist/types-d8-k_4dN.d.ts +19 -0
- package/package.json +16 -1
- package/dist/chunk-3C3AAR3S.js.map +0 -1
- package/dist/chunk-BVLJYZ6T.js +0 -252
- package/dist/chunk-BVLJYZ6T.js.map +0 -1
- package/dist/types-BZgSeTU8.d.ts +0 -101
- /package/dist/{chunk-D5PTZWTT.js.map → chunk-4LM22T36.js.map} +0 -0
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
useGavaActions,
|
|
4
4
|
useGavaConfig,
|
|
5
5
|
useSplash
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-MC3FBYWV.js";
|
|
7
7
|
|
|
8
8
|
// src/components/editor/ArticleEditor.tsx
|
|
9
9
|
import { useState as useState6, useEffect as useEffect4, useCallback as useCallback4, useRef as useRef3 } from "react";
|
|
@@ -2444,17 +2444,431 @@ function MediaGrid({ media }) {
|
|
|
2444
2444
|
] });
|
|
2445
2445
|
}
|
|
2446
2446
|
|
|
2447
|
+
// src/components/content/ContentEditor.tsx
|
|
2448
|
+
import { useState as useState12, useCallback as useCallback8 } from "react";
|
|
2449
|
+
|
|
2450
|
+
// src/components/content/field-renderers/TextRenderer.tsx
|
|
2451
|
+
import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2452
|
+
function TextRenderer({ field, value, onChange }) {
|
|
2453
|
+
return /* @__PURE__ */ jsxs12("div", { className: "ge-field ge-field-text", children: [
|
|
2454
|
+
/* @__PURE__ */ jsx14("label", { className: "ge-field-label", children: field.label }),
|
|
2455
|
+
/* @__PURE__ */ jsx14(
|
|
2456
|
+
"input",
|
|
2457
|
+
{
|
|
2458
|
+
type: "text",
|
|
2459
|
+
value: value || "",
|
|
2460
|
+
onChange: (e) => onChange(e.target.value),
|
|
2461
|
+
placeholder: field.placeholder,
|
|
2462
|
+
className: "ge-field-input"
|
|
2463
|
+
}
|
|
2464
|
+
)
|
|
2465
|
+
] });
|
|
2466
|
+
}
|
|
2467
|
+
|
|
2468
|
+
// src/components/content/field-renderers/NumberRenderer.tsx
|
|
2469
|
+
import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2470
|
+
function NumberRenderer({ field, value, onChange }) {
|
|
2471
|
+
return /* @__PURE__ */ jsxs13("div", { className: "ge-field ge-field-number", children: [
|
|
2472
|
+
/* @__PURE__ */ jsx15("label", { className: "ge-field-label", children: field.label }),
|
|
2473
|
+
/* @__PURE__ */ jsx15(
|
|
2474
|
+
"input",
|
|
2475
|
+
{
|
|
2476
|
+
type: "number",
|
|
2477
|
+
value: value ?? "",
|
|
2478
|
+
onChange: (e) => onChange(Number(e.target.value)),
|
|
2479
|
+
placeholder: field.placeholder,
|
|
2480
|
+
className: "ge-field-input"
|
|
2481
|
+
}
|
|
2482
|
+
)
|
|
2483
|
+
] });
|
|
2484
|
+
}
|
|
2485
|
+
|
|
2486
|
+
// src/components/content/field-renderers/BooleanRenderer.tsx
|
|
2487
|
+
import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
2488
|
+
function BooleanRenderer({ field, value, onChange }) {
|
|
2489
|
+
return /* @__PURE__ */ jsx16("div", { className: "ge-field ge-field-boolean", children: /* @__PURE__ */ jsxs14("label", { className: "ge-field-label", children: [
|
|
2490
|
+
/* @__PURE__ */ jsx16(
|
|
2491
|
+
"input",
|
|
2492
|
+
{
|
|
2493
|
+
type: "checkbox",
|
|
2494
|
+
checked: value ?? false,
|
|
2495
|
+
onChange: (e) => onChange(e.target.checked),
|
|
2496
|
+
className: "ge-field-checkbox"
|
|
2497
|
+
}
|
|
2498
|
+
),
|
|
2499
|
+
/* @__PURE__ */ jsx16("span", { children: field.label })
|
|
2500
|
+
] }) });
|
|
2501
|
+
}
|
|
2502
|
+
|
|
2503
|
+
// src/components/content/field-renderers/DateRenderer.tsx
|
|
2504
|
+
import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2505
|
+
function DateRenderer({ field, value, onChange }) {
|
|
2506
|
+
return /* @__PURE__ */ jsxs15("div", { className: "ge-field ge-field-date", children: [
|
|
2507
|
+
/* @__PURE__ */ jsx17("label", { className: "ge-field-label", children: field.label }),
|
|
2508
|
+
/* @__PURE__ */ jsx17(
|
|
2509
|
+
"input",
|
|
2510
|
+
{
|
|
2511
|
+
type: "date",
|
|
2512
|
+
value: value || "",
|
|
2513
|
+
onChange: (e) => onChange(e.target.value),
|
|
2514
|
+
className: "ge-field-input"
|
|
2515
|
+
}
|
|
2516
|
+
)
|
|
2517
|
+
] });
|
|
2518
|
+
}
|
|
2519
|
+
|
|
2520
|
+
// src/components/content/field-renderers/SelectRenderer.tsx
|
|
2521
|
+
import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2522
|
+
function SelectRenderer({ field, value, onChange, options }) {
|
|
2523
|
+
const selectOptions = options ?? field.options ?? [];
|
|
2524
|
+
return /* @__PURE__ */ jsxs16("div", { className: "ge-field ge-field-select", children: [
|
|
2525
|
+
/* @__PURE__ */ jsx18("label", { className: "ge-field-label", children: field.label }),
|
|
2526
|
+
/* @__PURE__ */ jsxs16(
|
|
2527
|
+
"select",
|
|
2528
|
+
{
|
|
2529
|
+
value: value || "",
|
|
2530
|
+
onChange: (e) => onChange(e.target.value),
|
|
2531
|
+
className: "ge-field-input",
|
|
2532
|
+
children: [
|
|
2533
|
+
/* @__PURE__ */ jsx18("option", { value: "", children: field.placeholder ?? `Select ${field.label.toLowerCase()}` }),
|
|
2534
|
+
selectOptions.map((opt) => /* @__PURE__ */ jsx18("option", { value: opt, children: opt }, opt))
|
|
2535
|
+
]
|
|
2536
|
+
}
|
|
2537
|
+
)
|
|
2538
|
+
] });
|
|
2539
|
+
}
|
|
2540
|
+
|
|
2541
|
+
// src/components/content/field-renderers/SlugRenderer.tsx
|
|
2542
|
+
import { useCallback as useCallback7 } from "react";
|
|
2543
|
+
import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
2544
|
+
function generateSlug(text) {
|
|
2545
|
+
return text.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
2546
|
+
}
|
|
2547
|
+
function SlugRenderer({ field, value, onChange, sourceValue }) {
|
|
2548
|
+
const handleGenerate = useCallback7(() => {
|
|
2549
|
+
if (sourceValue) {
|
|
2550
|
+
onChange(generateSlug(sourceValue));
|
|
2551
|
+
}
|
|
2552
|
+
}, [sourceValue, onChange]);
|
|
2553
|
+
return /* @__PURE__ */ jsxs17("div", { className: "ge-field ge-field-slug", children: [
|
|
2554
|
+
/* @__PURE__ */ jsx19("label", { className: "ge-field-label", children: field.label }),
|
|
2555
|
+
/* @__PURE__ */ jsxs17("div", { style: { display: "flex", gap: "0.5rem" }, children: [
|
|
2556
|
+
/* @__PURE__ */ jsx19(
|
|
2557
|
+
"input",
|
|
2558
|
+
{
|
|
2559
|
+
type: "text",
|
|
2560
|
+
value: value || "",
|
|
2561
|
+
onChange: (e) => onChange(e.target.value),
|
|
2562
|
+
placeholder: field.placeholder,
|
|
2563
|
+
className: "ge-field-input",
|
|
2564
|
+
style: { flex: 1 }
|
|
2565
|
+
}
|
|
2566
|
+
),
|
|
2567
|
+
field.generateFrom && sourceValue && /* @__PURE__ */ jsx19(
|
|
2568
|
+
"button",
|
|
2569
|
+
{
|
|
2570
|
+
type: "button",
|
|
2571
|
+
onClick: handleGenerate,
|
|
2572
|
+
className: "ge-field-slug-generate",
|
|
2573
|
+
title: "Generate from title",
|
|
2574
|
+
children: "\u21BB"
|
|
2575
|
+
}
|
|
2576
|
+
)
|
|
2577
|
+
] })
|
|
2578
|
+
] });
|
|
2579
|
+
}
|
|
2580
|
+
|
|
2581
|
+
// src/components/content/field-renderers/ImageRenderer.tsx
|
|
2582
|
+
import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
2583
|
+
function ImageRenderer({ field, value, onChange }) {
|
|
2584
|
+
return /* @__PURE__ */ jsxs18("div", { className: "ge-field ge-field-image", children: [
|
|
2585
|
+
/* @__PURE__ */ jsx20("label", { className: "ge-field-label", children: field.label }),
|
|
2586
|
+
value && /* @__PURE__ */ jsx20("div", { className: "ge-field-image-preview", children: /* @__PURE__ */ jsx20("img", { src: value, alt: field.label, style: { maxWidth: "100%", maxHeight: 200, objectFit: "cover", borderRadius: 8 } }) }),
|
|
2587
|
+
/* @__PURE__ */ jsx20(
|
|
2588
|
+
"input",
|
|
2589
|
+
{
|
|
2590
|
+
type: "text",
|
|
2591
|
+
value: value || "",
|
|
2592
|
+
onChange: (e) => onChange(e.target.value),
|
|
2593
|
+
placeholder: field.placeholder ?? "Image URL",
|
|
2594
|
+
className: "ge-field-input"
|
|
2595
|
+
}
|
|
2596
|
+
)
|
|
2597
|
+
] });
|
|
2598
|
+
}
|
|
2599
|
+
|
|
2600
|
+
// src/components/content/field-renderers/JsonRenderer.tsx
|
|
2601
|
+
import { useState as useState11 } from "react";
|
|
2602
|
+
import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
2603
|
+
function JsonRenderer({ field, value, onChange }) {
|
|
2604
|
+
const [raw, setRaw] = useState11(
|
|
2605
|
+
() => typeof value === "string" ? value : JSON.stringify(value ?? {}, null, 2)
|
|
2606
|
+
);
|
|
2607
|
+
const [error, setError] = useState11(null);
|
|
2608
|
+
const handleChange = (text) => {
|
|
2609
|
+
setRaw(text);
|
|
2610
|
+
try {
|
|
2611
|
+
const parsed = JSON.parse(text);
|
|
2612
|
+
setError(null);
|
|
2613
|
+
onChange(parsed);
|
|
2614
|
+
} catch {
|
|
2615
|
+
setError("Invalid JSON");
|
|
2616
|
+
}
|
|
2617
|
+
};
|
|
2618
|
+
return /* @__PURE__ */ jsxs19("div", { className: "ge-field ge-field-json", children: [
|
|
2619
|
+
/* @__PURE__ */ jsx21("label", { className: "ge-field-label", children: field.label }),
|
|
2620
|
+
/* @__PURE__ */ jsx21(
|
|
2621
|
+
"textarea",
|
|
2622
|
+
{
|
|
2623
|
+
value: raw,
|
|
2624
|
+
onChange: (e) => handleChange(e.target.value),
|
|
2625
|
+
className: "ge-field-input ge-field-json-textarea",
|
|
2626
|
+
rows: 6,
|
|
2627
|
+
style: { fontFamily: "monospace", fontSize: "0.85rem" }
|
|
2628
|
+
}
|
|
2629
|
+
),
|
|
2630
|
+
error && /* @__PURE__ */ jsx21("span", { className: "ge-field-error", children: error })
|
|
2631
|
+
] });
|
|
2632
|
+
}
|
|
2633
|
+
|
|
2634
|
+
// src/components/content/ContentEditor.tsx
|
|
2635
|
+
import { jsx as jsx22, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
2636
|
+
function ContentEditor({
|
|
2637
|
+
contentType,
|
|
2638
|
+
actions,
|
|
2639
|
+
initialData,
|
|
2640
|
+
id,
|
|
2641
|
+
categories,
|
|
2642
|
+
onSave,
|
|
2643
|
+
onPublish
|
|
2644
|
+
}) {
|
|
2645
|
+
const [data, setData] = useState12(initialData ?? {});
|
|
2646
|
+
const [saving, setSaving] = useState12(false);
|
|
2647
|
+
const [saved, setSaved] = useState12(false);
|
|
2648
|
+
const handleFieldChange = useCallback8((fieldName, value) => {
|
|
2649
|
+
setData((prev) => ({ ...prev, [fieldName]: value }));
|
|
2650
|
+
setSaved(false);
|
|
2651
|
+
}, []);
|
|
2652
|
+
const handleSave = useCallback8(async () => {
|
|
2653
|
+
if (!id) return;
|
|
2654
|
+
setSaving(true);
|
|
2655
|
+
try {
|
|
2656
|
+
await actions.update(id, data);
|
|
2657
|
+
setSaved(true);
|
|
2658
|
+
onSave?.();
|
|
2659
|
+
} finally {
|
|
2660
|
+
setSaving(false);
|
|
2661
|
+
}
|
|
2662
|
+
}, [id, data, actions, onSave]);
|
|
2663
|
+
const handlePublish = useCallback8(async () => {
|
|
2664
|
+
if (!id || !actions.publish) return;
|
|
2665
|
+
await actions.publish(id);
|
|
2666
|
+
onPublish?.();
|
|
2667
|
+
}, [id, actions, onPublish]);
|
|
2668
|
+
const mainFields = contentType.fields.filter(
|
|
2669
|
+
(f) => !f.hidden && f.admin?.position !== "sidebar" && f.type !== "richtext"
|
|
2670
|
+
);
|
|
2671
|
+
const sidebarFields = contentType.fields.filter(
|
|
2672
|
+
(f) => !f.hidden && f.admin?.position === "sidebar"
|
|
2673
|
+
);
|
|
2674
|
+
const richtextField = contentType.fields.find((f) => f.type === "richtext");
|
|
2675
|
+
const renderField = (field) => {
|
|
2676
|
+
const value = data[field.name];
|
|
2677
|
+
const onChange = (v) => handleFieldChange(field.name, v);
|
|
2678
|
+
switch (field.type) {
|
|
2679
|
+
case "text":
|
|
2680
|
+
return /* @__PURE__ */ jsx22(TextRenderer, { field, value, onChange }, field.name);
|
|
2681
|
+
case "number":
|
|
2682
|
+
return /* @__PURE__ */ jsx22(NumberRenderer, { field, value, onChange }, field.name);
|
|
2683
|
+
case "boolean":
|
|
2684
|
+
return /* @__PURE__ */ jsx22(BooleanRenderer, { field, value, onChange }, field.name);
|
|
2685
|
+
case "date":
|
|
2686
|
+
return /* @__PURE__ */ jsx22(DateRenderer, { field, value, onChange }, field.name);
|
|
2687
|
+
case "select":
|
|
2688
|
+
return /* @__PURE__ */ jsx22(
|
|
2689
|
+
SelectRenderer,
|
|
2690
|
+
{
|
|
2691
|
+
field,
|
|
2692
|
+
value,
|
|
2693
|
+
onChange,
|
|
2694
|
+
options: field.name === "category" ? categories : field.options
|
|
2695
|
+
},
|
|
2696
|
+
field.name
|
|
2697
|
+
);
|
|
2698
|
+
case "slug":
|
|
2699
|
+
return /* @__PURE__ */ jsx22(
|
|
2700
|
+
SlugRenderer,
|
|
2701
|
+
{
|
|
2702
|
+
field,
|
|
2703
|
+
value,
|
|
2704
|
+
onChange,
|
|
2705
|
+
sourceValue: field.generateFrom ? data[field.generateFrom] : void 0
|
|
2706
|
+
},
|
|
2707
|
+
field.name
|
|
2708
|
+
);
|
|
2709
|
+
case "image":
|
|
2710
|
+
return /* @__PURE__ */ jsx22(ImageRenderer, { field, value, onChange }, field.name);
|
|
2711
|
+
case "json":
|
|
2712
|
+
return /* @__PURE__ */ jsx22(JsonRenderer, { field, value, onChange }, field.name);
|
|
2713
|
+
case "richtext":
|
|
2714
|
+
return /* @__PURE__ */ jsxs20("div", { className: "ge-field ge-field-richtext", children: [
|
|
2715
|
+
/* @__PURE__ */ jsx22("label", { className: "ge-field-label", children: field.label }),
|
|
2716
|
+
/* @__PURE__ */ jsx22(
|
|
2717
|
+
"textarea",
|
|
2718
|
+
{
|
|
2719
|
+
value: value || "",
|
|
2720
|
+
onChange: (e) => onChange(e.target.value),
|
|
2721
|
+
className: "ge-field-input ge-field-richtext-textarea",
|
|
2722
|
+
rows: 12,
|
|
2723
|
+
placeholder: field.placeholder
|
|
2724
|
+
}
|
|
2725
|
+
)
|
|
2726
|
+
] }, field.name);
|
|
2727
|
+
default:
|
|
2728
|
+
return /* @__PURE__ */ jsx22(TextRenderer, { field, value, onChange }, field.name);
|
|
2729
|
+
}
|
|
2730
|
+
};
|
|
2731
|
+
return /* @__PURE__ */ jsxs20("div", { className: "ge-content-editor", children: [
|
|
2732
|
+
/* @__PURE__ */ jsxs20("div", { className: "ge-content-editor-header", children: [
|
|
2733
|
+
/* @__PURE__ */ jsx22("h1", { children: id ? `Edit ${contentType.labels.singular}` : `New ${contentType.labels.singular}` }),
|
|
2734
|
+
/* @__PURE__ */ jsxs20("div", { className: "ge-content-editor-actions", children: [
|
|
2735
|
+
/* @__PURE__ */ jsx22("span", { className: "ge-content-editor-status", children: saving ? "Saving..." : saved ? "Saved" : "" }),
|
|
2736
|
+
/* @__PURE__ */ jsx22("button", { onClick: handleSave, disabled: saving, className: "ge-btn ge-btn-secondary", children: "Save" }),
|
|
2737
|
+
actions.publish && /* @__PURE__ */ jsx22("button", { onClick: handlePublish, className: "ge-btn ge-btn-primary", children: "Publish" })
|
|
2738
|
+
] })
|
|
2739
|
+
] }),
|
|
2740
|
+
/* @__PURE__ */ jsxs20("div", { className: "ge-content-editor-body", children: [
|
|
2741
|
+
/* @__PURE__ */ jsxs20("div", { className: "ge-content-editor-main", children: [
|
|
2742
|
+
mainFields.map(renderField),
|
|
2743
|
+
richtextField && renderField(richtextField)
|
|
2744
|
+
] }),
|
|
2745
|
+
sidebarFields.length > 0 && /* @__PURE__ */ jsx22("div", { className: "ge-content-editor-sidebar", children: sidebarFields.map(renderField) })
|
|
2746
|
+
] })
|
|
2747
|
+
] });
|
|
2748
|
+
}
|
|
2749
|
+
|
|
2750
|
+
// src/components/content/ContentList.tsx
|
|
2751
|
+
import { useState as useState13, useEffect as useEffect6, useCallback as useCallback9 } from "react";
|
|
2752
|
+
import { jsx as jsx23, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
2753
|
+
function ContentList({
|
|
2754
|
+
contentType,
|
|
2755
|
+
actions,
|
|
2756
|
+
onEdit,
|
|
2757
|
+
onCreate
|
|
2758
|
+
}) {
|
|
2759
|
+
const [items, setItems] = useState13([]);
|
|
2760
|
+
const [search, setSearch] = useState13("");
|
|
2761
|
+
const [statusFilter, setStatusFilter] = useState13("");
|
|
2762
|
+
const [loading, setLoading] = useState13(true);
|
|
2763
|
+
const loadItems = useCallback9(async () => {
|
|
2764
|
+
setLoading(true);
|
|
2765
|
+
try {
|
|
2766
|
+
const result = await actions.getAll({
|
|
2767
|
+
search: search || void 0,
|
|
2768
|
+
status: statusFilter || void 0
|
|
2769
|
+
});
|
|
2770
|
+
setItems(result);
|
|
2771
|
+
} finally {
|
|
2772
|
+
setLoading(false);
|
|
2773
|
+
}
|
|
2774
|
+
}, [actions, search, statusFilter]);
|
|
2775
|
+
useEffect6(() => {
|
|
2776
|
+
loadItems();
|
|
2777
|
+
}, [loadItems]);
|
|
2778
|
+
const handleDelete = useCallback9(
|
|
2779
|
+
async (id, title) => {
|
|
2780
|
+
if (!confirm(`Delete "${title || "Untitled"}"?`)) return;
|
|
2781
|
+
await actions.delete(id);
|
|
2782
|
+
loadItems();
|
|
2783
|
+
},
|
|
2784
|
+
[actions, loadItems]
|
|
2785
|
+
);
|
|
2786
|
+
const handleCreate = useCallback9(async () => {
|
|
2787
|
+
if (onCreate) {
|
|
2788
|
+
onCreate();
|
|
2789
|
+
} else {
|
|
2790
|
+
const id = await actions.create();
|
|
2791
|
+
onEdit?.(id);
|
|
2792
|
+
}
|
|
2793
|
+
}, [actions, onCreate, onEdit]);
|
|
2794
|
+
const columns = contentType.admin?.listColumns ?? ["title", "status", "updatedAt"];
|
|
2795
|
+
return /* @__PURE__ */ jsxs21("div", { className: "ge-content-list", children: [
|
|
2796
|
+
/* @__PURE__ */ jsxs21("div", { className: "ge-content-list-header", children: [
|
|
2797
|
+
/* @__PURE__ */ jsx23("h1", { children: contentType.labels.plural }),
|
|
2798
|
+
/* @__PURE__ */ jsxs21("button", { onClick: handleCreate, className: "ge-btn ge-btn-primary", children: [
|
|
2799
|
+
"New ",
|
|
2800
|
+
contentType.labels.singular
|
|
2801
|
+
] })
|
|
2802
|
+
] }),
|
|
2803
|
+
/* @__PURE__ */ jsxs21("div", { className: "ge-content-list-filters", children: [
|
|
2804
|
+
/* @__PURE__ */ jsx23(
|
|
2805
|
+
"input",
|
|
2806
|
+
{
|
|
2807
|
+
type: "text",
|
|
2808
|
+
value: search,
|
|
2809
|
+
onChange: (e) => setSearch(e.target.value),
|
|
2810
|
+
placeholder: `Search ${contentType.labels.plural.toLowerCase()}...`,
|
|
2811
|
+
className: "ge-field-input"
|
|
2812
|
+
}
|
|
2813
|
+
),
|
|
2814
|
+
contentType.statuses && contentType.statuses.length > 0 && /* @__PURE__ */ jsxs21(
|
|
2815
|
+
"select",
|
|
2816
|
+
{
|
|
2817
|
+
value: statusFilter,
|
|
2818
|
+
onChange: (e) => setStatusFilter(e.target.value),
|
|
2819
|
+
className: "ge-field-input",
|
|
2820
|
+
children: [
|
|
2821
|
+
/* @__PURE__ */ jsx23("option", { value: "", children: "All" }),
|
|
2822
|
+
contentType.statuses.map((s) => /* @__PURE__ */ jsx23("option", { value: s, children: s.charAt(0).toUpperCase() + s.slice(1) }, s))
|
|
2823
|
+
]
|
|
2824
|
+
}
|
|
2825
|
+
)
|
|
2826
|
+
] }),
|
|
2827
|
+
loading ? /* @__PURE__ */ jsx23("p", { children: "Loading..." }) : items.length === 0 ? /* @__PURE__ */ jsxs21("p", { children: [
|
|
2828
|
+
"No ",
|
|
2829
|
+
contentType.labels.plural.toLowerCase(),
|
|
2830
|
+
" found."
|
|
2831
|
+
] }) : /* @__PURE__ */ jsxs21("table", { className: "ge-content-list-table", children: [
|
|
2832
|
+
/* @__PURE__ */ jsx23("thead", { children: /* @__PURE__ */ jsxs21("tr", { children: [
|
|
2833
|
+
columns.map((col) => /* @__PURE__ */ jsx23("th", { children: col.charAt(0).toUpperCase() + col.slice(1) }, col)),
|
|
2834
|
+
/* @__PURE__ */ jsx23("th", { children: "Actions" })
|
|
2835
|
+
] }) }),
|
|
2836
|
+
/* @__PURE__ */ jsx23("tbody", { children: items.map((item) => /* @__PURE__ */ jsxs21("tr", { children: [
|
|
2837
|
+
columns.map((col) => /* @__PURE__ */ jsx23("td", { children: col === "updatedAt" || col === "createdAt" ? new Date(item[col]).toLocaleDateString() : String(item[col] ?? "") }, col)),
|
|
2838
|
+
/* @__PURE__ */ jsxs21("td", { children: [
|
|
2839
|
+
/* @__PURE__ */ jsx23(
|
|
2840
|
+
"button",
|
|
2841
|
+
{
|
|
2842
|
+
onClick: () => onEdit?.(item.id),
|
|
2843
|
+
className: "ge-btn ge-btn-small",
|
|
2844
|
+
children: "Edit"
|
|
2845
|
+
}
|
|
2846
|
+
),
|
|
2847
|
+
/* @__PURE__ */ jsx23(
|
|
2848
|
+
"button",
|
|
2849
|
+
{
|
|
2850
|
+
onClick: () => handleDelete(item.id, item.title || item.name || ""),
|
|
2851
|
+
className: "ge-btn ge-btn-small ge-btn-danger",
|
|
2852
|
+
children: "Delete"
|
|
2853
|
+
}
|
|
2854
|
+
)
|
|
2855
|
+
] })
|
|
2856
|
+
] }, item.id)) })
|
|
2857
|
+
] })
|
|
2858
|
+
] });
|
|
2859
|
+
}
|
|
2860
|
+
|
|
2447
2861
|
// src/components/dashboard/DashboardNavbar.tsx
|
|
2448
2862
|
import Link4 from "next/link";
|
|
2449
2863
|
import { usePathname } from "next/navigation";
|
|
2450
2864
|
import { useSession, signOut } from "next-auth/react";
|
|
2451
2865
|
import { FileText as FileText3, Users, LogOut, BarChart3, ImageIcon as ImageIcon3 } from "lucide-react";
|
|
2452
|
-
import { useState as
|
|
2453
|
-
import { jsx as
|
|
2866
|
+
import { useState as useState14 } from "react";
|
|
2867
|
+
import { jsx as jsx24, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
2454
2868
|
function DashboardNavbar() {
|
|
2455
2869
|
const pathname = usePathname();
|
|
2456
2870
|
const { data: session } = useSession();
|
|
2457
|
-
const [mobileOpen, setMobileOpen] =
|
|
2871
|
+
const [mobileOpen, setMobileOpen] = useState14(false);
|
|
2458
2872
|
const { branding, roles, strings, routes } = useGavaConfig();
|
|
2459
2873
|
const role = session?.user?.role;
|
|
2460
2874
|
const navigation = [
|
|
@@ -2470,10 +2884,10 @@ function DashboardNavbar() {
|
|
|
2470
2884
|
...role === roles.adminRole ? [{ name: strings.users, href: routes.users, icon: Users }] : []
|
|
2471
2885
|
];
|
|
2472
2886
|
const isActive = (href) => pathname.startsWith(href);
|
|
2473
|
-
return /* @__PURE__ */
|
|
2474
|
-
/* @__PURE__ */
|
|
2475
|
-
/* @__PURE__ */
|
|
2476
|
-
branding.logo && /* @__PURE__ */
|
|
2887
|
+
return /* @__PURE__ */ jsx24("header", { className: "sticky top-0 z-50 px-4 pb-4", children: /* @__PURE__ */ jsx24("div", { className: "mx-auto max-w-7xl", children: /* @__PURE__ */ jsxs22("nav", { className: "bg-background/95 backdrop-blur-sm border border-t-transparent border-card-border rounded-b-xl", children: [
|
|
2888
|
+
/* @__PURE__ */ jsxs22("div", { className: "flex h-14 items-center justify-between px-6", children: [
|
|
2889
|
+
/* @__PURE__ */ jsxs22(Link4, { href: routes.home, className: "flex items-center gap-3", children: [
|
|
2890
|
+
branding.logo && /* @__PURE__ */ jsx24("span", { className: "relative z-[9999] -my-[100px] py-[100px] bg-white rounded-b-lg px-1.5 pb-1.5", children: /* @__PURE__ */ jsx24(
|
|
2477
2891
|
"img",
|
|
2478
2892
|
{
|
|
2479
2893
|
src: branding.logo,
|
|
@@ -2482,36 +2896,36 @@ function DashboardNavbar() {
|
|
|
2482
2896
|
height: 44
|
|
2483
2897
|
}
|
|
2484
2898
|
) }),
|
|
2485
|
-
/* @__PURE__ */
|
|
2899
|
+
/* @__PURE__ */ jsx24("span", { className: "font-bold text-lg text-foreground", children: branding.name })
|
|
2486
2900
|
] }),
|
|
2487
|
-
/* @__PURE__ */
|
|
2901
|
+
/* @__PURE__ */ jsx24("div", { className: "hidden md:flex md:items-center md:gap-6", children: navigation.map((item) => /* @__PURE__ */ jsxs22(
|
|
2488
2902
|
Link4,
|
|
2489
2903
|
{
|
|
2490
2904
|
href: item.href,
|
|
2491
2905
|
className: `flex items-center gap-2 text-sm font-medium transition-colors ${isActive(item.href) ? "text-accent" : "text-muted hover:text-foreground"}`,
|
|
2492
2906
|
children: [
|
|
2493
|
-
/* @__PURE__ */
|
|
2907
|
+
/* @__PURE__ */ jsx24(item.icon, { className: "w-4 h-4" }),
|
|
2494
2908
|
item.name
|
|
2495
2909
|
]
|
|
2496
2910
|
},
|
|
2497
2911
|
item.name
|
|
2498
2912
|
)) }),
|
|
2499
|
-
/* @__PURE__ */
|
|
2500
|
-
/* @__PURE__ */
|
|
2501
|
-
/* @__PURE__ */
|
|
2502
|
-
/* @__PURE__ */
|
|
2913
|
+
/* @__PURE__ */ jsxs22("div", { className: "hidden md:flex md:items-center md:gap-3", children: [
|
|
2914
|
+
/* @__PURE__ */ jsxs22("div", { className: "text-right", children: [
|
|
2915
|
+
/* @__PURE__ */ jsx24("p", { className: "text-sm font-medium text-foreground leading-tight", children: session?.user?.name }),
|
|
2916
|
+
/* @__PURE__ */ jsx24("p", { className: "text-xs text-muted leading-tight", children: roles.labels[role || ""] || role })
|
|
2503
2917
|
] }),
|
|
2504
|
-
/* @__PURE__ */
|
|
2918
|
+
/* @__PURE__ */ jsx24(
|
|
2505
2919
|
"button",
|
|
2506
2920
|
{
|
|
2507
2921
|
onClick: () => signOut({ callbackUrl: routes.login }),
|
|
2508
2922
|
className: "p-2 rounded-full text-muted hover:text-foreground hover:bg-card transition-colors",
|
|
2509
2923
|
title: strings.logout,
|
|
2510
|
-
children: /* @__PURE__ */
|
|
2924
|
+
children: /* @__PURE__ */ jsx24(LogOut, { className: "w-4 h-4" })
|
|
2511
2925
|
}
|
|
2512
2926
|
)
|
|
2513
2927
|
] }),
|
|
2514
|
-
/* @__PURE__ */
|
|
2928
|
+
/* @__PURE__ */ jsxs22(
|
|
2515
2929
|
"button",
|
|
2516
2930
|
{
|
|
2517
2931
|
type: "button",
|
|
@@ -2519,19 +2933,19 @@ function DashboardNavbar() {
|
|
|
2519
2933
|
className: "md:hidden p-2 rounded-full text-foreground flex flex-col justify-center items-center w-10 h-10 gap-1.5",
|
|
2520
2934
|
"aria-label": "Menu",
|
|
2521
2935
|
children: [
|
|
2522
|
-
/* @__PURE__ */
|
|
2936
|
+
/* @__PURE__ */ jsx24(
|
|
2523
2937
|
"span",
|
|
2524
2938
|
{
|
|
2525
2939
|
className: `block h-0.5 w-5 bg-foreground rounded-full transition-all duration-300 ease-in-out ${mobileOpen ? "rotate-45 translate-y-2" : ""}`
|
|
2526
2940
|
}
|
|
2527
2941
|
),
|
|
2528
|
-
/* @__PURE__ */
|
|
2942
|
+
/* @__PURE__ */ jsx24(
|
|
2529
2943
|
"span",
|
|
2530
2944
|
{
|
|
2531
2945
|
className: `block h-0.5 w-5 bg-foreground rounded-full transition-all duration-300 ease-in-out ${mobileOpen ? "opacity-0 scale-0" : ""}`
|
|
2532
2946
|
}
|
|
2533
2947
|
),
|
|
2534
|
-
/* @__PURE__ */
|
|
2948
|
+
/* @__PURE__ */ jsx24(
|
|
2535
2949
|
"span",
|
|
2536
2950
|
{
|
|
2537
2951
|
className: `block h-0.5 w-5 bg-foreground rounded-full transition-all duration-300 ease-in-out ${mobileOpen ? "-rotate-45 -translate-y-2" : ""}`
|
|
@@ -2541,36 +2955,36 @@ function DashboardNavbar() {
|
|
|
2541
2955
|
}
|
|
2542
2956
|
)
|
|
2543
2957
|
] }),
|
|
2544
|
-
/* @__PURE__ */
|
|
2958
|
+
/* @__PURE__ */ jsx24(
|
|
2545
2959
|
"div",
|
|
2546
2960
|
{
|
|
2547
2961
|
className: `md:hidden overflow-hidden transition-all duration-300 ease-in-out ${mobileOpen ? "max-h-80 opacity-100" : "max-h-0 opacity-0"}`,
|
|
2548
|
-
children: /* @__PURE__ */
|
|
2549
|
-
navigation.map((item) => /* @__PURE__ */
|
|
2962
|
+
children: /* @__PURE__ */ jsxs22("div", { className: "py-4 border-t border-card-border mx-6 space-y-1", children: [
|
|
2963
|
+
navigation.map((item) => /* @__PURE__ */ jsxs22(
|
|
2550
2964
|
Link4,
|
|
2551
2965
|
{
|
|
2552
2966
|
href: item.href,
|
|
2553
2967
|
onClick: () => setMobileOpen(false),
|
|
2554
2968
|
className: `flex items-center gap-3 px-3 py-2 rounded-full text-sm font-medium transition-colors ${isActive(item.href) ? "text-accent" : "text-muted hover:text-foreground"}`,
|
|
2555
2969
|
children: [
|
|
2556
|
-
/* @__PURE__ */
|
|
2970
|
+
/* @__PURE__ */ jsx24(item.icon, { className: "w-4 h-4" }),
|
|
2557
2971
|
item.name
|
|
2558
2972
|
]
|
|
2559
2973
|
},
|
|
2560
2974
|
item.name
|
|
2561
2975
|
)),
|
|
2562
|
-
/* @__PURE__ */
|
|
2563
|
-
/* @__PURE__ */
|
|
2564
|
-
/* @__PURE__ */
|
|
2565
|
-
/* @__PURE__ */
|
|
2976
|
+
/* @__PURE__ */ jsxs22("div", { className: "pt-3 mt-2 border-t border-card-border", children: [
|
|
2977
|
+
/* @__PURE__ */ jsxs22("div", { className: "px-3 mb-2", children: [
|
|
2978
|
+
/* @__PURE__ */ jsx24("p", { className: "text-sm font-medium text-foreground", children: session?.user?.name }),
|
|
2979
|
+
/* @__PURE__ */ jsx24("p", { className: "text-xs text-muted", children: roles.labels[role || ""] || role })
|
|
2566
2980
|
] }),
|
|
2567
|
-
/* @__PURE__ */
|
|
2981
|
+
/* @__PURE__ */ jsxs22(
|
|
2568
2982
|
"button",
|
|
2569
2983
|
{
|
|
2570
2984
|
onClick: () => signOut({ callbackUrl: routes.login }),
|
|
2571
2985
|
className: "flex items-center gap-3 px-3 py-2 text-sm text-muted hover:text-foreground transition-colors w-full rounded-full hover:bg-card",
|
|
2572
2986
|
children: [
|
|
2573
|
-
/* @__PURE__ */
|
|
2987
|
+
/* @__PURE__ */ jsx24(LogOut, { className: "w-4 h-4" }),
|
|
2574
2988
|
strings.logout
|
|
2575
2989
|
]
|
|
2576
2990
|
}
|
|
@@ -2583,7 +2997,7 @@ function DashboardNavbar() {
|
|
|
2583
2997
|
}
|
|
2584
2998
|
|
|
2585
2999
|
// src/components/dashboard/StatCard.tsx
|
|
2586
|
-
import { jsx as
|
|
3000
|
+
import { jsx as jsx25, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
2587
3001
|
var accentStyles = {
|
|
2588
3002
|
blue: {
|
|
2589
3003
|
border: "border-l-blue-500",
|
|
@@ -2613,23 +3027,23 @@ function StatCard({
|
|
|
2613
3027
|
accent = "blue"
|
|
2614
3028
|
}) {
|
|
2615
3029
|
const s = accentStyles[accent];
|
|
2616
|
-
return /* @__PURE__ */
|
|
3030
|
+
return /* @__PURE__ */ jsx25(
|
|
2617
3031
|
"div",
|
|
2618
3032
|
{
|
|
2619
3033
|
className: `bg-card border border-card-border rounded-xl p-5 border-l-[3px] ${s.border} transition-all duration-200 hover:shadow-sm`,
|
|
2620
|
-
children: /* @__PURE__ */
|
|
2621
|
-
/* @__PURE__ */
|
|
2622
|
-
/* @__PURE__ */
|
|
2623
|
-
/* @__PURE__ */
|
|
3034
|
+
children: /* @__PURE__ */ jsxs23("div", { className: "flex items-start justify-between", children: [
|
|
3035
|
+
/* @__PURE__ */ jsxs23("div", { children: [
|
|
3036
|
+
/* @__PURE__ */ jsx25("p", { className: "text-xs font-medium text-muted uppercase tracking-wide mb-2", children: label }),
|
|
3037
|
+
/* @__PURE__ */ jsx25("p", { className: "text-3xl font-bold text-foreground tabular-nums", children: value })
|
|
2624
3038
|
] }),
|
|
2625
|
-
/* @__PURE__ */
|
|
3039
|
+
/* @__PURE__ */ jsx25("div", { className: `p-2 rounded-lg ${s.bg}`, children: /* @__PURE__ */ jsx25(Icon, { className: `w-5 h-5 ${s.text}` }) })
|
|
2626
3040
|
] })
|
|
2627
3041
|
}
|
|
2628
3042
|
);
|
|
2629
3043
|
}
|
|
2630
3044
|
|
|
2631
3045
|
// src/components/splash/SplashScreen.tsx
|
|
2632
|
-
import { jsx as
|
|
3046
|
+
import { jsx as jsx26, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
2633
3047
|
var SPLASH_WORDS = ["Powerful", "Flexible", "Modular", "Secure", "Customizable"];
|
|
2634
3048
|
function pickRandom3() {
|
|
2635
3049
|
const shuffled = [...SPLASH_WORDS].sort(() => Math.random() - 0.5);
|
|
@@ -2641,28 +3055,28 @@ function SplashScreen() {
|
|
|
2641
3055
|
if (phase === "idle") return null;
|
|
2642
3056
|
const topClass = phase === "closing" ? "splash-enter-down" : phase === "opening" ? "splash-exit-up" : "";
|
|
2643
3057
|
const bottomClass = phase === "closing" ? "splash-enter-up" : phase === "opening" ? "splash-exit-down" : "";
|
|
2644
|
-
return /* @__PURE__ */
|
|
2645
|
-
/* @__PURE__ */
|
|
3058
|
+
return /* @__PURE__ */ jsxs24("div", { className: "fixed inset-0 z-[9999] pointer-events-none", children: [
|
|
3059
|
+
/* @__PURE__ */ jsx26(
|
|
2646
3060
|
"div",
|
|
2647
3061
|
{
|
|
2648
3062
|
className: `splash-half splash-half-top absolute inset-x-0 top-0 h-1/2 bg-background overflow-hidden ${topClass}`,
|
|
2649
|
-
children: /* @__PURE__ */
|
|
3063
|
+
children: /* @__PURE__ */ jsx26("div", { className: "absolute inset-0 flex flex-col items-center justify-end pb-2", children: /* @__PURE__ */ jsx26("span", { className: "splash-title", children: "GAVA" }) })
|
|
2650
3064
|
}
|
|
2651
3065
|
),
|
|
2652
|
-
/* @__PURE__ */
|
|
3066
|
+
/* @__PURE__ */ jsx26(
|
|
2653
3067
|
"div",
|
|
2654
3068
|
{
|
|
2655
3069
|
className: `splash-half splash-half-bottom absolute inset-x-0 bottom-0 h-1/2 bg-background overflow-hidden ${bottomClass}`,
|
|
2656
|
-
children: /* @__PURE__ */
|
|
2657
|
-
/* @__PURE__ */
|
|
2658
|
-
/* @__PURE__ */
|
|
3070
|
+
children: /* @__PURE__ */ jsxs24("div", { className: "absolute inset-0 flex flex-col items-center justify-start pt-2", children: [
|
|
3071
|
+
/* @__PURE__ */ jsx26("span", { className: "splash-title", children: "ENGINE" }),
|
|
3072
|
+
/* @__PURE__ */ jsx26("div", { className: "flex items-center gap-3 mt-6", children: words.map((word, i) => /* @__PURE__ */ jsxs24(
|
|
2659
3073
|
"span",
|
|
2660
3074
|
{
|
|
2661
3075
|
className: "splash-word text-xs sm:text-sm font-medium tracking-widest uppercase",
|
|
2662
3076
|
style: { animationDelay: `${0.2 + i * 0.1}s` },
|
|
2663
3077
|
children: [
|
|
2664
3078
|
word,
|
|
2665
|
-
i < 2 && /* @__PURE__ */
|
|
3079
|
+
i < 2 && /* @__PURE__ */ jsx26("span", { className: "ml-3 text-muted-foreground", children: "\xB7" })
|
|
2666
3080
|
]
|
|
2667
3081
|
},
|
|
2668
3082
|
word
|
|
@@ -2674,10 +3088,10 @@ function SplashScreen() {
|
|
|
2674
3088
|
}
|
|
2675
3089
|
|
|
2676
3090
|
// src/components/splash/DashboardSplashTrigger.tsx
|
|
2677
|
-
import { useEffect as
|
|
3091
|
+
import { useEffect as useEffect7 } from "react";
|
|
2678
3092
|
function DashboardSplashTrigger() {
|
|
2679
3093
|
const { openSplash } = useSplash();
|
|
2680
|
-
|
|
3094
|
+
useEffect7(() => {
|
|
2681
3095
|
if (typeof window.requestIdleCallback === "function") {
|
|
2682
3096
|
const id = window.requestIdleCallback(() => openSplash());
|
|
2683
3097
|
return () => window.cancelIdleCallback(id);
|
|
@@ -2707,9 +3121,19 @@ export {
|
|
|
2707
3121
|
UserTable,
|
|
2708
3122
|
UserForm,
|
|
2709
3123
|
MediaGrid,
|
|
3124
|
+
TextRenderer,
|
|
3125
|
+
NumberRenderer,
|
|
3126
|
+
BooleanRenderer,
|
|
3127
|
+
DateRenderer,
|
|
3128
|
+
SelectRenderer,
|
|
3129
|
+
SlugRenderer,
|
|
3130
|
+
ImageRenderer,
|
|
3131
|
+
JsonRenderer,
|
|
3132
|
+
ContentEditor,
|
|
3133
|
+
ContentList,
|
|
2710
3134
|
DashboardNavbar,
|
|
2711
3135
|
StatCard,
|
|
2712
3136
|
SplashScreen,
|
|
2713
3137
|
DashboardSplashTrigger
|
|
2714
3138
|
};
|
|
2715
|
-
//# sourceMappingURL=chunk-
|
|
3139
|
+
//# sourceMappingURL=chunk-YSVQQBBU.js.map
|