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.
Files changed (36) hide show
  1. package/dist/DashboardSplashTrigger-CRpueuUi.d.ts +154 -0
  2. package/dist/auth/index.d.ts +42 -0
  3. package/dist/auth/index.js +12 -0
  4. package/dist/auth/index.js.map +1 -0
  5. package/dist/{chunk-D5PTZWTT.js → chunk-4LM22T36.js} +2 -2
  6. package/dist/chunk-MC3FBYWV.js +534 -0
  7. package/dist/chunk-MC3FBYWV.js.map +1 -0
  8. package/dist/chunk-QO42DDRU.js +113 -0
  9. package/dist/chunk-QO42DDRU.js.map +1 -0
  10. package/dist/{chunk-3C3AAR3S.js → chunk-YSVQQBBU.js} +474 -50
  11. package/dist/chunk-YSVQQBBU.js.map +1 -0
  12. package/dist/components/index.d.ts +64 -132
  13. package/dist/components/index.js +22 -2
  14. package/dist/content/index.d.ts +45 -0
  15. package/dist/content/index.js +38 -0
  16. package/dist/content/index.js.map +1 -0
  17. package/dist/handlers/index.d.ts +60 -3
  18. package/dist/handlers/index.js +477 -126
  19. package/dist/handlers/index.js.map +1 -1
  20. package/dist/i18n/index.d.ts +114 -0
  21. package/dist/i18n/index.js +249 -0
  22. package/dist/i18n/index.js.map +1 -0
  23. package/dist/{index-B1ZYC5TP.d.ts → index-CCsSC4nF.d.ts} +119 -2
  24. package/dist/index.d.ts +45 -7
  25. package/dist/index.js +226 -39
  26. package/dist/index.js.map +1 -1
  27. package/dist/providers/index.d.ts +3 -2
  28. package/dist/providers/index.js +2 -2
  29. package/dist/types-X07o_zKf.d.ts +198 -0
  30. package/dist/types-d8-k_4dN.d.ts +19 -0
  31. package/package.json +16 -1
  32. package/dist/chunk-3C3AAR3S.js.map +0 -1
  33. package/dist/chunk-BVLJYZ6T.js +0 -252
  34. package/dist/chunk-BVLJYZ6T.js.map +0 -1
  35. package/dist/types-BZgSeTU8.d.ts +0 -101
  36. /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-BVLJYZ6T.js";
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 useState11 } from "react";
2453
- import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
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] = useState11(false);
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__ */ jsx14("header", { className: "sticky top-0 z-50 px-4 pb-4", children: /* @__PURE__ */ jsx14("div", { className: "mx-auto max-w-7xl", children: /* @__PURE__ */ jsxs12("nav", { className: "bg-background/95 backdrop-blur-sm border border-t-transparent border-card-border rounded-b-xl", children: [
2474
- /* @__PURE__ */ jsxs12("div", { className: "flex h-14 items-center justify-between px-6", children: [
2475
- /* @__PURE__ */ jsxs12(Link4, { href: routes.home, className: "flex items-center gap-3", children: [
2476
- branding.logo && /* @__PURE__ */ jsx14("span", { className: "relative z-[9999] -my-[100px] py-[100px] bg-white rounded-b-lg px-1.5 pb-1.5", children: /* @__PURE__ */ jsx14(
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__ */ jsx14("span", { className: "font-bold text-lg text-foreground", children: branding.name })
2899
+ /* @__PURE__ */ jsx24("span", { className: "font-bold text-lg text-foreground", children: branding.name })
2486
2900
  ] }),
2487
- /* @__PURE__ */ jsx14("div", { className: "hidden md:flex md:items-center md:gap-6", children: navigation.map((item) => /* @__PURE__ */ jsxs12(
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__ */ jsx14(item.icon, { className: "w-4 h-4" }),
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__ */ jsxs12("div", { className: "hidden md:flex md:items-center md:gap-3", children: [
2500
- /* @__PURE__ */ jsxs12("div", { className: "text-right", children: [
2501
- /* @__PURE__ */ jsx14("p", { className: "text-sm font-medium text-foreground leading-tight", children: session?.user?.name }),
2502
- /* @__PURE__ */ jsx14("p", { className: "text-xs text-muted leading-tight", children: roles.labels[role || ""] || role })
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__ */ jsx14(
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__ */ jsx14(LogOut, { className: "w-4 h-4" })
2924
+ children: /* @__PURE__ */ jsx24(LogOut, { className: "w-4 h-4" })
2511
2925
  }
2512
2926
  )
2513
2927
  ] }),
2514
- /* @__PURE__ */ jsxs12(
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__ */ jsx14(
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__ */ jsx14(
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__ */ jsx14(
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__ */ jsx14(
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__ */ jsxs12("div", { className: "py-4 border-t border-card-border mx-6 space-y-1", children: [
2549
- navigation.map((item) => /* @__PURE__ */ jsxs12(
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__ */ jsx14(item.icon, { className: "w-4 h-4" }),
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__ */ jsxs12("div", { className: "pt-3 mt-2 border-t border-card-border", children: [
2563
- /* @__PURE__ */ jsxs12("div", { className: "px-3 mb-2", children: [
2564
- /* @__PURE__ */ jsx14("p", { className: "text-sm font-medium text-foreground", children: session?.user?.name }),
2565
- /* @__PURE__ */ jsx14("p", { className: "text-xs text-muted", children: roles.labels[role || ""] || role })
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__ */ jsxs12(
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__ */ jsx14(LogOut, { className: "w-4 h-4" }),
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 jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
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__ */ jsx15(
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__ */ jsxs13("div", { className: "flex items-start justify-between", children: [
2621
- /* @__PURE__ */ jsxs13("div", { children: [
2622
- /* @__PURE__ */ jsx15("p", { className: "text-xs font-medium text-muted uppercase tracking-wide mb-2", children: label }),
2623
- /* @__PURE__ */ jsx15("p", { className: "text-3xl font-bold text-foreground tabular-nums", children: value })
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__ */ jsx15("div", { className: `p-2 rounded-lg ${s.bg}`, children: /* @__PURE__ */ jsx15(Icon, { className: `w-5 h-5 ${s.text}` }) })
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 jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
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__ */ jsxs14("div", { className: "fixed inset-0 z-[9999] pointer-events-none", children: [
2645
- /* @__PURE__ */ jsx16(
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__ */ jsx16("div", { className: "absolute inset-0 flex flex-col items-center justify-end pb-2", children: /* @__PURE__ */ jsx16("span", { className: "splash-title", children: "GAVA" }) })
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__ */ jsx16(
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__ */ jsxs14("div", { className: "absolute inset-0 flex flex-col items-center justify-start pt-2", children: [
2657
- /* @__PURE__ */ jsx16("span", { className: "splash-title", children: "ENGINE" }),
2658
- /* @__PURE__ */ jsx16("div", { className: "flex items-center gap-3 mt-6", children: words.map((word, i) => /* @__PURE__ */ jsxs14(
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__ */ jsx16("span", { className: "ml-3 text-muted-foreground", children: "\xB7" })
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 useEffect6 } from "react";
3091
+ import { useEffect as useEffect7 } from "react";
2678
3092
  function DashboardSplashTrigger() {
2679
3093
  const { openSplash } = useSplash();
2680
- useEffect6(() => {
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-3C3AAR3S.js.map
3139
+ //# sourceMappingURL=chunk-YSVQQBBU.js.map