gavaengine 2.3.0 → 2.4.1

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.
@@ -3,7 +3,10 @@ import {
3
3
  useGavaActions,
4
4
  useGavaConfig,
5
5
  useSplash
6
- } from "./chunk-PHT76VW6.js";
6
+ } from "./chunk-MANXBV2D.js";
7
+ import {
8
+ useGavaAuth
9
+ } from "./chunk-IU2SMMVV.js";
7
10
 
8
11
  // src/components/editor/ArticleEditor.tsx
9
12
  import { useState as useState6, useEffect as useEffect4, useCallback as useCallback4, useRef as useRef3 } from "react";
@@ -596,7 +599,7 @@ function MediaPickerModal({
596
599
 
597
600
  // src/components/editor/EditorToolbar.tsx
598
601
  import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
599
- var TEXT_COLORS = [
602
+ var DEFAULT_TEXT_COLORS = [
600
603
  { label: "Black", value: "#171717" },
601
604
  { label: "Red", value: "#dc2626" },
602
605
  { label: "Orange", value: "#ea580c" },
@@ -605,7 +608,7 @@ var TEXT_COLORS = [
605
608
  { label: "Purple", value: "#9333ea" },
606
609
  { label: "Gray", value: "#6b7280" }
607
610
  ];
608
- var HIGHLIGHT_COLORS = [
611
+ var DEFAULT_HIGHLIGHT_COLORS = [
609
612
  { label: "Yellow", value: "#fef08a" },
610
613
  { label: "Green", value: "#bbf7d0" },
611
614
  { label: "Blue", value: "#bfdbfe" },
@@ -615,6 +618,7 @@ var HIGHLIGHT_COLORS = [
615
618
  ];
616
619
  function EditorToolbar({ editor }) {
617
620
  const actions = useGavaActions();
621
+ const { strings, editorToolbar } = useGavaConfig();
618
622
  const [showColorPicker, setShowColorPicker] = useState3(false);
619
623
  const [showHighlightPicker, setShowHighlightPicker] = useState3(false);
620
624
  const [showTableMenu, setShowTableMenu] = useState3(false);
@@ -622,6 +626,8 @@ function EditorToolbar({ editor }) {
622
626
  const colorRef = useRef2(null);
623
627
  const highlightRef = useRef2(null);
624
628
  const tableRef = useRef2(null);
629
+ const textColors = editorToolbar?.textColors ?? DEFAULT_TEXT_COLORS;
630
+ const highlightColors = editorToolbar?.highlightColors ?? DEFAULT_HIGHLIGHT_COLORS;
625
631
  useEffect2(() => {
626
632
  const handleClick = (e) => {
627
633
  if (colorRef.current && !colorRef.current.contains(e.target))
@@ -645,20 +651,20 @@ function EditorToolbar({ editor }) {
645
651
  const addLink = useCallback3(() => {
646
652
  if (!editor) return;
647
653
  const previousUrl = editor.getAttributes("link").href;
648
- const url = window.prompt("URL:", previousUrl);
654
+ const url = window.prompt(strings.linkPrompt, previousUrl);
649
655
  if (url === null) return;
650
656
  if (url === "") {
651
657
  editor.chain().focus().extendMarkRange("link").unsetLink().run();
652
658
  return;
653
659
  }
654
660
  editor.chain().focus().extendMarkRange("link").setLink({ href: url }).run();
655
- }, [editor]);
661
+ }, [editor, strings.linkPrompt]);
656
662
  const addYoutube = useCallback3(() => {
657
663
  if (!editor) return;
658
- const url = window.prompt("YouTube URL:");
664
+ const url = window.prompt(strings.youtubePrompt);
659
665
  if (!url) return;
660
666
  editor.commands.setYoutubeVideo({ src: url, width: 640, height: 360 });
661
- }, [editor]);
667
+ }, [editor, strings.youtubePrompt]);
662
668
  const addVideo = useCallback3(() => {
663
669
  if (!editor) return;
664
670
  const input = document.createElement("input");
@@ -717,7 +723,7 @@ function EditorToolbar({ editor }) {
717
723
  {
718
724
  onClick: () => editor.chain().focus().toggleBold().run(),
719
725
  active: editor.isActive("bold"),
720
- title: "Bold",
726
+ title: strings.bold,
721
727
  children: /* @__PURE__ */ jsx5(Bold, { className: "w-4 h-4" })
722
728
  }
723
729
  ),
@@ -726,7 +732,7 @@ function EditorToolbar({ editor }) {
726
732
  {
727
733
  onClick: () => editor.chain().focus().toggleItalic().run(),
728
734
  active: editor.isActive("italic"),
729
- title: "Italic",
735
+ title: strings.italic,
730
736
  children: /* @__PURE__ */ jsx5(Italic, { className: "w-4 h-4" })
731
737
  }
732
738
  ),
@@ -735,7 +741,7 @@ function EditorToolbar({ editor }) {
735
741
  {
736
742
  onClick: () => editor.chain().focus().toggleUnderline().run(),
737
743
  active: editor.isActive("underline"),
738
- title: "Underline",
744
+ title: strings.underline,
739
745
  children: /* @__PURE__ */ jsx5(Underline, { className: "w-4 h-4" })
740
746
  }
741
747
  ),
@@ -744,7 +750,7 @@ function EditorToolbar({ editor }) {
744
750
  {
745
751
  onClick: () => editor.chain().focus().toggleStrike().run(),
746
752
  active: editor.isActive("strike"),
747
- title: "Strikethrough",
753
+ title: strings.strikethrough,
748
754
  children: /* @__PURE__ */ jsx5(Strikethrough, { className: "w-4 h-4" })
749
755
  }
750
756
  ),
@@ -753,7 +759,7 @@ function EditorToolbar({ editor }) {
753
759
  {
754
760
  onClick: () => editor.chain().focus().toggleSuperscript().run(),
755
761
  active: editor.isActive("superscript"),
756
- title: "Superscript",
762
+ title: strings.superscript,
757
763
  children: /* @__PURE__ */ jsx5(Superscript, { className: "w-4 h-4" })
758
764
  }
759
765
  ),
@@ -762,7 +768,7 @@ function EditorToolbar({ editor }) {
762
768
  {
763
769
  onClick: () => editor.chain().focus().toggleSubscript().run(),
764
770
  active: editor.isActive("subscript"),
765
- title: "Subscript",
771
+ title: strings.subscript,
766
772
  children: /* @__PURE__ */ jsx5(Subscript, { className: "w-4 h-4" })
767
773
  }
768
774
  ),
@@ -777,7 +783,7 @@ function EditorToolbar({ editor }) {
777
783
  setShowTableMenu(false);
778
784
  },
779
785
  active: showColorPicker,
780
- title: "Text color",
786
+ title: strings.textColor,
781
787
  children: /* @__PURE__ */ jsxs3("div", { className: "flex flex-col items-center gap-0.5", children: [
782
788
  /* @__PURE__ */ jsx5(Palette, { className: "w-4 h-4" }),
783
789
  /* @__PURE__ */ jsx5(
@@ -801,11 +807,11 @@ function EditorToolbar({ editor }) {
801
807
  setShowColorPicker(false);
802
808
  },
803
809
  className: "w-7 h-7 rounded-md border border-card-border hover:scale-110 transition-transform flex items-center justify-center bg-background",
804
- title: "Default",
810
+ title: strings.defaultColor,
805
811
  children: /* @__PURE__ */ jsx5(X2, { className: "w-3 h-3 text-muted" })
806
812
  }
807
813
  ),
808
- TEXT_COLORS.map((c) => /* @__PURE__ */ jsx5(
814
+ textColors.map((c) => /* @__PURE__ */ jsx5(
809
815
  "button",
810
816
  {
811
817
  onClick: () => {
@@ -830,7 +836,7 @@ function EditorToolbar({ editor }) {
830
836
  setShowTableMenu(false);
831
837
  },
832
838
  active: editor.isActive("highlight"),
833
- title: "Highlight",
839
+ title: strings.highlight,
834
840
  children: /* @__PURE__ */ jsx5(Highlighter, { className: "w-4 h-4" })
835
841
  }
836
842
  ),
@@ -843,11 +849,11 @@ function EditorToolbar({ editor }) {
843
849
  setShowHighlightPicker(false);
844
850
  },
845
851
  className: "w-7 h-7 rounded-md border border-card-border hover:scale-110 transition-transform flex items-center justify-center bg-background",
846
- title: "Remove",
852
+ title: strings.removeHighlight,
847
853
  children: /* @__PURE__ */ jsx5(X2, { className: "w-3 h-3 text-muted" })
848
854
  }
849
855
  ),
850
- HIGHLIGHT_COLORS.map((c) => /* @__PURE__ */ jsx5(
856
+ highlightColors.map((c) => /* @__PURE__ */ jsx5(
851
857
  "button",
852
858
  {
853
859
  onClick: () => {
@@ -868,7 +874,7 @@ function EditorToolbar({ editor }) {
868
874
  {
869
875
  onClick: () => editor.chain().focus().toggleHeading({ level: 2 }).run(),
870
876
  active: editor.isActive("heading", { level: 2 }),
871
- title: "H2",
877
+ title: strings.heading2,
872
878
  children: /* @__PURE__ */ jsx5(Heading2, { className: "w-4 h-4" })
873
879
  }
874
880
  ),
@@ -877,7 +883,7 @@ function EditorToolbar({ editor }) {
877
883
  {
878
884
  onClick: () => editor.chain().focus().toggleHeading({ level: 3 }).run(),
879
885
  active: editor.isActive("heading", { level: 3 }),
880
- title: "H3",
886
+ title: strings.heading3,
881
887
  children: /* @__PURE__ */ jsx5(Heading3, { className: "w-4 h-4" })
882
888
  }
883
889
  ),
@@ -887,7 +893,7 @@ function EditorToolbar({ editor }) {
887
893
  {
888
894
  onClick: () => editor.chain().focus().toggleBulletList().run(),
889
895
  active: editor.isActive("bulletList"),
890
- title: "Bullet list",
896
+ title: strings.bulletList,
891
897
  children: /* @__PURE__ */ jsx5(List, { className: "w-4 h-4" })
892
898
  }
893
899
  ),
@@ -896,7 +902,7 @@ function EditorToolbar({ editor }) {
896
902
  {
897
903
  onClick: () => editor.chain().focus().toggleOrderedList().run(),
898
904
  active: editor.isActive("orderedList"),
899
- title: "Numbered list",
905
+ title: strings.numberedList,
900
906
  children: /* @__PURE__ */ jsx5(ListOrdered, { className: "w-4 h-4" })
901
907
  }
902
908
  ),
@@ -905,7 +911,7 @@ function EditorToolbar({ editor }) {
905
911
  {
906
912
  onClick: () => editor.chain().focus().toggleBlockquote().run(),
907
913
  active: editor.isActive("blockquote"),
908
- title: "Quote",
914
+ title: strings.quote,
909
915
  children: /* @__PURE__ */ jsx5(Quote, { className: "w-4 h-4" })
910
916
  }
911
917
  ),
@@ -914,7 +920,7 @@ function EditorToolbar({ editor }) {
914
920
  {
915
921
  onClick: () => editor.chain().focus().toggleCodeBlock().run(),
916
922
  active: editor.isActive("codeBlock"),
917
- title: "Code block",
923
+ title: strings.codeBlock,
918
924
  children: /* @__PURE__ */ jsx5(Code, { className: "w-4 h-4" })
919
925
  }
920
926
  ),
@@ -922,7 +928,7 @@ function EditorToolbar({ editor }) {
922
928
  ToolButton,
923
929
  {
924
930
  onClick: () => editor.chain().focus().setHorizontalRule().run(),
925
- title: "Divider",
931
+ title: strings.divider,
926
932
  children: /* @__PURE__ */ jsx5(Minus, { className: "w-4 h-4" })
927
933
  }
928
934
  ),
@@ -932,7 +938,7 @@ function EditorToolbar({ editor }) {
932
938
  {
933
939
  onClick: () => editor.chain().focus().setTextAlign("left").run(),
934
940
  active: editor.isActive({ textAlign: "left" }),
935
- title: "Align left",
941
+ title: strings.alignLeft,
936
942
  children: /* @__PURE__ */ jsx5(AlignLeft2, { className: "w-4 h-4" })
937
943
  }
938
944
  ),
@@ -941,7 +947,7 @@ function EditorToolbar({ editor }) {
941
947
  {
942
948
  onClick: () => editor.chain().focus().setTextAlign("center").run(),
943
949
  active: editor.isActive({ textAlign: "center" }),
944
- title: "Align center",
950
+ title: strings.alignCenter,
945
951
  children: /* @__PURE__ */ jsx5(AlignCenter2, { className: "w-4 h-4" })
946
952
  }
947
953
  ),
@@ -950,7 +956,7 @@ function EditorToolbar({ editor }) {
950
956
  {
951
957
  onClick: () => editor.chain().focus().setTextAlign("right").run(),
952
958
  active: editor.isActive({ textAlign: "right" }),
953
- title: "Align right",
959
+ title: strings.alignRight,
954
960
  children: /* @__PURE__ */ jsx5(AlignRight2, { className: "w-4 h-4" })
955
961
  }
956
962
  ),
@@ -965,7 +971,7 @@ function EditorToolbar({ editor }) {
965
971
  setShowHighlightPicker(false);
966
972
  },
967
973
  active: editor.isActive("table"),
968
- title: "Table",
974
+ title: strings.table,
969
975
  children: /* @__PURE__ */ jsx5(Table, { className: "w-4 h-4" })
970
976
  }
971
977
  ),
@@ -978,7 +984,7 @@ function EditorToolbar({ editor }) {
978
984
  },
979
985
  children: /* @__PURE__ */ jsxs3("span", { className: "flex items-center gap-2", children: [
980
986
  /* @__PURE__ */ jsx5(Plus, { className: "w-3.5 h-3.5" }),
981
- "Insert 3x3 table"
987
+ strings.insertTable
982
988
  ] })
983
989
  }
984
990
  ) : /* @__PURE__ */ jsxs3(Fragment3, { children: [
@@ -989,7 +995,7 @@ function EditorToolbar({ editor }) {
989
995
  editor.chain().focus().addRowBefore().run();
990
996
  setShowTableMenu(false);
991
997
  },
992
- children: "Add row above"
998
+ children: strings.addRowAbove
993
999
  }
994
1000
  ),
995
1001
  /* @__PURE__ */ jsx5(
@@ -999,7 +1005,7 @@ function EditorToolbar({ editor }) {
999
1005
  editor.chain().focus().addRowAfter().run();
1000
1006
  setShowTableMenu(false);
1001
1007
  },
1002
- children: "Add row below"
1008
+ children: strings.addRowBelow
1003
1009
  }
1004
1010
  ),
1005
1011
  /* @__PURE__ */ jsx5(
@@ -1009,7 +1015,7 @@ function EditorToolbar({ editor }) {
1009
1015
  editor.chain().focus().addColumnBefore().run();
1010
1016
  setShowTableMenu(false);
1011
1017
  },
1012
- children: "Add column left"
1018
+ children: strings.addColumnLeft
1013
1019
  }
1014
1020
  ),
1015
1021
  /* @__PURE__ */ jsx5(
@@ -1019,7 +1025,7 @@ function EditorToolbar({ editor }) {
1019
1025
  editor.chain().focus().addColumnAfter().run();
1020
1026
  setShowTableMenu(false);
1021
1027
  },
1022
- children: "Add column right"
1028
+ children: strings.addColumnRight
1023
1029
  }
1024
1030
  ),
1025
1031
  /* @__PURE__ */ jsx5("div", { className: "border-t border-card-border my-1" }),
@@ -1031,7 +1037,7 @@ function EditorToolbar({ editor }) {
1031
1037
  editor.chain().focus().deleteRow().run();
1032
1038
  setShowTableMenu(false);
1033
1039
  },
1034
- children: "Delete row"
1040
+ children: strings.deleteRow
1035
1041
  }
1036
1042
  ),
1037
1043
  /* @__PURE__ */ jsx5(
@@ -1042,7 +1048,7 @@ function EditorToolbar({ editor }) {
1042
1048
  editor.chain().focus().deleteColumn().run();
1043
1049
  setShowTableMenu(false);
1044
1050
  },
1045
- children: "Delete column"
1051
+ children: strings.deleteColumn
1046
1052
  }
1047
1053
  ),
1048
1054
  /* @__PURE__ */ jsx5(
@@ -1053,22 +1059,22 @@ function EditorToolbar({ editor }) {
1053
1059
  editor.chain().focus().deleteTable().run();
1054
1060
  setShowTableMenu(false);
1055
1061
  },
1056
- children: "Delete table"
1062
+ children: strings.deleteTable
1057
1063
  }
1058
1064
  )
1059
1065
  ] }) })
1060
1066
  ] }),
1061
1067
  /* @__PURE__ */ jsx5(Divider, {}),
1062
- /* @__PURE__ */ jsx5(ToolButton, { onClick: addLink, active: editor.isActive("link"), title: "Link", children: /* @__PURE__ */ jsx5(Link, { className: "w-4 h-4" }) }),
1063
- /* @__PURE__ */ jsx5(ToolButton, { onClick: () => setMediaPickerOpen(true), title: "Image", children: /* @__PURE__ */ jsx5(Image2, { className: "w-4 h-4" }) }),
1064
- /* @__PURE__ */ jsx5(ToolButton, { onClick: addYoutube, title: "YouTube", children: /* @__PURE__ */ jsx5(Youtube2, { className: "w-4 h-4" }) }),
1065
- /* @__PURE__ */ jsx5(ToolButton, { onClick: addVideo, title: "Video", children: /* @__PURE__ */ jsx5(Video, { className: "w-4 h-4" }) }),
1068
+ /* @__PURE__ */ jsx5(ToolButton, { onClick: addLink, active: editor.isActive("link"), title: strings.link, children: /* @__PURE__ */ jsx5(Link, { className: "w-4 h-4" }) }),
1069
+ /* @__PURE__ */ jsx5(ToolButton, { onClick: () => setMediaPickerOpen(true), title: strings.image, children: /* @__PURE__ */ jsx5(Image2, { className: "w-4 h-4" }) }),
1070
+ /* @__PURE__ */ jsx5(ToolButton, { onClick: addYoutube, title: strings.youtube, children: /* @__PURE__ */ jsx5(Youtube2, { className: "w-4 h-4" }) }),
1071
+ /* @__PURE__ */ jsx5(ToolButton, { onClick: addVideo, title: strings.video, children: /* @__PURE__ */ jsx5(Video, { className: "w-4 h-4" }) }),
1066
1072
  /* @__PURE__ */ jsx5(Divider, {}),
1067
1073
  /* @__PURE__ */ jsx5(
1068
1074
  ToolButton,
1069
1075
  {
1070
1076
  onClick: () => editor.chain().focus().undo().run(),
1071
- title: "Undo",
1077
+ title: strings.undo,
1072
1078
  children: /* @__PURE__ */ jsx5(Undo2, { className: "w-4 h-4" })
1073
1079
  }
1074
1080
  ),
@@ -1076,7 +1082,7 @@ function EditorToolbar({ editor }) {
1076
1082
  ToolButton,
1077
1083
  {
1078
1084
  onClick: () => editor.chain().focus().redo().run(),
1079
- title: "Redo",
1085
+ title: strings.redo,
1080
1086
  children: /* @__PURE__ */ jsx5(Redo2, { className: "w-4 h-4" })
1081
1087
  }
1082
1088
  ),
@@ -1282,7 +1288,7 @@ function ArticleEditor({ article, canPublish: canPub }) {
1282
1288
  const router = useRouter();
1283
1289
  const actions = useGavaActions();
1284
1290
  const config = useGavaConfig();
1285
- const { strings, routes, categories, editor: editorConfig } = config;
1291
+ const { strings, routes, categories, editor: editorConfig, statuses } = config;
1286
1292
  const [title, setTitle] = useState6(article.title);
1287
1293
  const [slug, setSlug] = useState6(article.slug);
1288
1294
  const [excerpt, setExcerpt] = useState6(article.excerpt);
@@ -1425,7 +1431,7 @@ function ArticleEditor({ article, canPublish: canPub }) {
1425
1431
  await doSave();
1426
1432
  try {
1427
1433
  await actions.publishArticle(article.id);
1428
- setStatus("pubblicato");
1434
+ setStatus(statuses.published);
1429
1435
  router.refresh();
1430
1436
  } catch (err) {
1431
1437
  alert(err instanceof Error ? err.message : "Error publishing");
@@ -1434,7 +1440,7 @@ function ArticleEditor({ article, canPublish: canPub }) {
1434
1440
  const handleUnpublish = async () => {
1435
1441
  try {
1436
1442
  await actions.unpublishArticle(article.id);
1437
- setStatus("bozza");
1443
+ setStatus(statuses.draft);
1438
1444
  router.refresh();
1439
1445
  } catch (err) {
1440
1446
  alert(err instanceof Error ? err.message : "Error");
@@ -1509,11 +1515,11 @@ function ArticleEditor({ article, canPublish: canPub }) {
1509
1515
  "button",
1510
1516
  {
1511
1517
  onClick: () => window.open(
1512
- status === "pubblicato" && slug ? routes.articleView(slug) : routes.articlePreview(article.id),
1518
+ status === statuses.published && slug ? routes.articleView(slug) : routes.articlePreview(article.id),
1513
1519
  "_blank"
1514
1520
  ),
1515
1521
  className: "p-2 rounded-full text-muted hover:text-foreground hover:bg-card-border/50 transition-colors",
1516
- title: status === "pubblicato" ? strings.viewArticle : strings.preview,
1522
+ title: status === statuses.published ? strings.viewArticle : strings.preview,
1517
1523
  children: /* @__PURE__ */ jsx8(Eye, { className: "w-4 h-4" })
1518
1524
  }
1519
1525
  ),
@@ -1549,7 +1555,7 @@ function ArticleEditor({ article, canPublish: canPub }) {
1549
1555
  children: strings.saveDraft
1550
1556
  }
1551
1557
  ),
1552
- canPub && status === "bozza" && /* @__PURE__ */ jsxs6(
1558
+ canPub && status === statuses.draft && /* @__PURE__ */ jsxs6(
1553
1559
  "button",
1554
1560
  {
1555
1561
  onClick: handlePublish,
@@ -1560,7 +1566,7 @@ function ArticleEditor({ article, canPublish: canPub }) {
1560
1566
  ]
1561
1567
  }
1562
1568
  ),
1563
- canPub && status === "pubblicato" && /* @__PURE__ */ jsx8(
1569
+ canPub && status === statuses.published && /* @__PURE__ */ jsx8(
1564
1570
  "button",
1565
1571
  {
1566
1572
  onClick: handleUnpublish,
@@ -1579,7 +1585,7 @@ function ArticleEditor({ article, canPublish: canPub }) {
1579
1585
  /* @__PURE__ */ jsxs6("div", { className: "flex-1 flex min-h-0", children: [
1580
1586
  /* @__PURE__ */ jsxs6("div", { className: "flex-1 overflow-y-auto", ref: scrollRef, children: [
1581
1587
  /* @__PURE__ */ jsxs6("div", { className: "article-content-wrapper py-8", children: [
1582
- /* @__PURE__ */ jsx8("div", { className: "flex items-center gap-2 mb-6", children: status === "pubblicato" ? /* @__PURE__ */ jsxs6("span", { className: "inline-flex items-center gap-1.5 text-xs font-medium text-green-600 bg-green-50 px-2.5 py-1 rounded-full", children: [
1588
+ /* @__PURE__ */ jsx8("div", { className: "flex items-center gap-2 mb-6", children: status === statuses.published ? /* @__PURE__ */ jsxs6("span", { className: "inline-flex items-center gap-1.5 text-xs font-medium text-green-600 bg-green-50 px-2.5 py-1 rounded-full", children: [
1583
1589
  /* @__PURE__ */ jsx8(Globe, { className: "w-3 h-3" }),
1584
1590
  strings.published
1585
1591
  ] }) : /* @__PURE__ */ jsxs6("span", { className: "inline-flex items-center gap-1.5 text-xs font-medium text-amber-600 bg-amber-50 px-2.5 py-1 rounded-full", children: [
@@ -1684,7 +1690,7 @@ function ArticleEditor({ article, canPublish: canPub }) {
1684
1690
  }
1685
1691
  )
1686
1692
  ] }) }),
1687
- status === "pubblicato" && slug && /* @__PURE__ */ jsx8("div", { children: /* @__PURE__ */ jsxs6(
1693
+ status === statuses.published && slug && /* @__PURE__ */ jsx8("div", { children: /* @__PURE__ */ jsxs6(
1688
1694
  "a",
1689
1695
  {
1690
1696
  href: routes.articleView(slug),
@@ -1961,26 +1967,28 @@ function ArticleList({
1961
1967
  }) {
1962
1968
  const router = useRouter2();
1963
1969
  const actions = useGavaActions();
1964
- const { strings, routes } = useGavaConfig();
1970
+ const config = useGavaConfig();
1971
+ const { strings, routes, statuses, locale } = config;
1965
1972
  const filterLabels = {
1966
- tutti: strings.all,
1967
- bozza: strings.drafts,
1968
- pubblicato: strings.published
1973
+ all: strings.all,
1974
+ draft: strings.drafts,
1975
+ published: strings.published
1969
1976
  };
1970
- const [filter, setFilter] = useState8("tutti");
1977
+ const [filter, setFilter] = useState8("all");
1971
1978
  const [search, setSearch] = useState8("");
1972
1979
  const filterRefs = useRef4({});
1973
1980
  const [indicator, setIndicator] = useState8({ left: 0, width: 0 });
1974
1981
  const filtered = articles.filter((a) => {
1975
- if (filter !== "tutti" && a.status !== filter) return false;
1982
+ if (filter === "draft" && a.status !== statuses.draft) return false;
1983
+ if (filter === "published" && a.status !== statuses.published) return false;
1976
1984
  if (search && !a.title.toLowerCase().includes(search.toLowerCase()))
1977
1985
  return false;
1978
1986
  return true;
1979
1987
  });
1980
1988
  const counts = {
1981
- tutti: articles.length,
1982
- bozza: articles.filter((a) => a.status === "bozza").length,
1983
- pubblicato: articles.filter((a) => a.status === "pubblicato").length
1989
+ all: articles.length,
1990
+ draft: articles.filter((a) => a.status === statuses.draft).length,
1991
+ published: articles.filter((a) => a.status === statuses.published).length
1984
1992
  };
1985
1993
  const updateIndicator = useCallback6(() => {
1986
1994
  const el = filterRefs.current[filter];
@@ -2033,7 +2041,7 @@ function ArticleList({
2033
2041
  style: { left: indicator.left, width: indicator.width }
2034
2042
  }
2035
2043
  ),
2036
- ["tutti", "bozza", "pubblicato"].map((f) => /* @__PURE__ */ jsxs8(
2044
+ ["all", "draft", "published"].map((f) => /* @__PURE__ */ jsxs8(
2037
2045
  "button",
2038
2046
  {
2039
2047
  ref: (el) => {
@@ -2104,20 +2112,20 @@ function ArticleList({
2104
2112
  ] }) }),
2105
2113
  /* @__PURE__ */ jsx10("td", { className: "px-4 py-3 text-muted hidden md:table-cell", children: article.authorName || "\u2014" }),
2106
2114
  /* @__PURE__ */ jsx10("td", { className: "px-4 py-3 text-muted hidden lg:table-cell", children: article.category || "\u2014" }),
2107
- /* @__PURE__ */ jsx10("td", { className: "px-4 py-3", children: article.status === "pubblicato" ? /* @__PURE__ */ jsxs8("span", { className: "inline-flex items-center gap-1 text-xs font-medium text-green-600 bg-green-50 px-2 py-0.5 rounded-full", children: [
2115
+ /* @__PURE__ */ jsx10("td", { className: "px-4 py-3", children: article.status === statuses.published ? /* @__PURE__ */ jsxs8("span", { className: "inline-flex items-center gap-1 text-xs font-medium text-green-600 bg-green-50 px-2 py-0.5 rounded-full", children: [
2108
2116
  /* @__PURE__ */ jsx10(Globe2, { className: "w-3 h-3" }),
2109
2117
  strings.published
2110
2118
  ] }) : /* @__PURE__ */ jsxs8("span", { className: "inline-flex items-center gap-1 text-xs font-medium text-amber-600 bg-amber-50 px-2 py-0.5 rounded-full", children: [
2111
2119
  /* @__PURE__ */ jsx10(FileText2, { className: "w-3 h-3" }),
2112
2120
  strings.draft
2113
2121
  ] }) }),
2114
- /* @__PURE__ */ jsx10("td", { className: "px-4 py-3 text-muted text-sm hidden sm:table-cell", children: new Date(article.updatedAt).toLocaleDateString("it-IT", {
2122
+ /* @__PURE__ */ jsx10("td", { className: "px-4 py-3 text-muted text-sm hidden sm:table-cell", children: new Date(article.updatedAt).toLocaleDateString(locale, {
2115
2123
  day: "numeric",
2116
2124
  month: "short",
2117
2125
  year: "numeric"
2118
2126
  }) }),
2119
2127
  canEdit && /* @__PURE__ */ jsx10("td", { className: "px-4 py-3 text-right", children: /* @__PURE__ */ jsxs8("div", { className: "flex items-center justify-end gap-1", children: [
2120
- canPub && article.status === "pubblicato" && /* @__PURE__ */ jsx10(
2128
+ canPub && article.status === statuses.published && /* @__PURE__ */ jsx10(
2121
2129
  "button",
2122
2130
  {
2123
2131
  onClick: () => handleUnpublish(article.id, article.title),
@@ -2162,7 +2170,7 @@ function UserTable({
2162
2170
  currentUserId
2163
2171
  }) {
2164
2172
  const actions = useGavaActions();
2165
- const { strings, roles, routes } = useGavaConfig();
2173
+ const { strings, roles, routes, locale } = useGavaConfig();
2166
2174
  async function handleDelete(id, name) {
2167
2175
  if (!confirm(strings.deleteUserConfirm(name))) return;
2168
2176
  const result = await actions.deleteUser(id);
@@ -2186,7 +2194,7 @@ function UserTable({
2186
2194
  /* @__PURE__ */ jsx11("td", { className: "py-3 px-4 text-foreground", children: user.name }),
2187
2195
  /* @__PURE__ */ jsx11("td", { className: "py-3 px-4 text-muted", children: user.email }),
2188
2196
  /* @__PURE__ */ jsx11("td", { className: "py-3 px-4", children: /* @__PURE__ */ jsx11("span", { className: "inline-block px-2 py-0.5 bg-accent/10 text-accent text-xs font-medium rounded-full", children: roles.labels[user.role] || user.role }) }),
2189
- /* @__PURE__ */ jsx11("td", { className: "py-3 px-4 text-muted", children: new Date(user.createdAt).toLocaleDateString("it-IT") }),
2197
+ /* @__PURE__ */ jsx11("td", { className: "py-3 px-4 text-muted", children: new Date(user.createdAt).toLocaleDateString(locale) }),
2190
2198
  /* @__PURE__ */ jsx11("td", { className: "py-3 px-4 text-right", children: /* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-end gap-2", children: [
2191
2199
  /* @__PURE__ */ jsx11(
2192
2200
  Link3,
@@ -2984,30 +2992,70 @@ import Link4 from "next/link";
2984
2992
  import { usePathname } from "next/navigation";
2985
2993
  import { useSession, signOut } from "next-auth/react";
2986
2994
  import { FileText as FileText3, Users, LogOut, BarChart3, ImageIcon as ImageIcon3 } from "lucide-react";
2987
- import { useState as useState15 } from "react";
2988
- import { jsx as jsx25, jsxs as jsxs23 } from "react/jsx-runtime";
2989
- function DashboardNavbar() {
2990
- const pathname = usePathname();
2991
- const { data: session } = useSession();
2992
- const [mobileOpen, setMobileOpen] = useState15(false);
2993
- const { branding, roles, strings, routes } = useGavaConfig();
2994
- const role = session?.user?.role;
2995
- const navigation = [
2995
+ import { useState as useState15, useMemo } from "react";
2996
+ import { Fragment as Fragment7, jsx as jsx25, jsxs as jsxs23 } from "react/jsx-runtime";
2997
+ function useDefaultNavigation() {
2998
+ const config = useGavaConfig();
2999
+ return useMemo(
3000
+ () => buildDefaultNavigation(config),
3001
+ [config]
3002
+ );
3003
+ }
3004
+ function buildDefaultNavigation(config) {
3005
+ const { strings, routes } = config;
3006
+ return [
2996
3007
  { name: strings.articles, href: routes.articles, icon: FileText3 },
2997
- ...roles.canEdit(role || "") ? [{ name: strings.media, href: routes.media, icon: ImageIcon3 }] : [],
2998
- ...roles.canPublish(role || "") ? [
2999
- {
3000
- name: strings.statistics,
3001
- href: routes.dashboard + "/statistiche",
3002
- icon: BarChart3
3003
- }
3004
- ] : [],
3005
- ...role === roles.adminRole ? [{ name: strings.users, href: routes.users, icon: Users }] : []
3008
+ {
3009
+ name: strings.media,
3010
+ href: routes.media,
3011
+ icon: ImageIcon3,
3012
+ visible: (role) => config.roles.canEdit(role)
3013
+ },
3014
+ {
3015
+ name: strings.statistics,
3016
+ href: routes.statistics,
3017
+ icon: BarChart3,
3018
+ visible: (role) => config.roles.canPublish(role)
3019
+ },
3020
+ {
3021
+ name: strings.users,
3022
+ href: routes.users,
3023
+ icon: Users,
3024
+ visible: (role) => role === config.roles.adminRole
3025
+ }
3006
3026
  ];
3027
+ }
3028
+ function DashboardNavbar({
3029
+ navigation: navProp,
3030
+ className,
3031
+ renderLogo,
3032
+ renderUser
3033
+ } = {}) {
3034
+ const pathname = usePathname();
3035
+ const config = useGavaConfig();
3036
+ const { branding, roles, strings, routes } = config;
3037
+ const [mobileOpen, setMobileOpen] = useState15(false);
3038
+ const gavaAuth = useGavaAuth();
3039
+ const { data: nextAuthSession } = useSession();
3040
+ const session = gavaAuth.session ?? nextAuthSession ?? null;
3041
+ const role = session?.user?.role ?? "";
3042
+ const handleSignOut = () => {
3043
+ if (gavaAuth.signOut) {
3044
+ gavaAuth.signOut();
3045
+ } else {
3046
+ signOut({ callbackUrl: routes.login });
3047
+ }
3048
+ };
3049
+ const defaultNav = useMemo(() => buildDefaultNavigation(config), [config]);
3050
+ const rawNavigation = navProp ?? config.navigation ?? defaultNav;
3051
+ const navigation = useMemo(
3052
+ () => rawNavigation.filter((item) => !item.visible || item.visible(role)),
3053
+ [rawNavigation, role]
3054
+ );
3007
3055
  const isActive = (href) => pathname.startsWith(href);
3008
- return /* @__PURE__ */ jsx25("header", { className: "sticky top-0 z-50 px-4 pb-4", children: /* @__PURE__ */ jsx25("div", { className: "mx-auto max-w-7xl", children: /* @__PURE__ */ jsxs23("nav", { className: "bg-background/95 backdrop-blur-sm border border-t-transparent border-card-border rounded-b-xl", children: [
3056
+ return /* @__PURE__ */ jsx25("header", { className: `sticky top-0 z-50 px-4 pb-4${className ? ` ${className}` : ""}`, children: /* @__PURE__ */ jsx25("div", { className: "mx-auto max-w-7xl", children: /* @__PURE__ */ jsxs23("nav", { className: "bg-background/95 backdrop-blur-sm border border-t-transparent border-card-border rounded-b-xl", children: [
3009
3057
  /* @__PURE__ */ jsxs23("div", { className: "flex h-14 items-center justify-between px-6", children: [
3010
- /* @__PURE__ */ jsxs23(Link4, { href: routes.home, className: "flex items-center gap-3", children: [
3058
+ renderLogo ? renderLogo() : /* @__PURE__ */ jsxs23(Link4, { href: routes.home, className: "flex items-center gap-3", children: [
3011
3059
  branding.logo && /* @__PURE__ */ jsx25("span", { className: "relative z-[9999] -my-[100px] py-[100px] bg-white rounded-b-lg px-1.5 pb-1.5", children: /* @__PURE__ */ jsx25(
3012
3060
  "img",
3013
3061
  {
@@ -3031,21 +3079,21 @@ function DashboardNavbar() {
3031
3079
  },
3032
3080
  item.name
3033
3081
  )) }),
3034
- /* @__PURE__ */ jsxs23("div", { className: "hidden md:flex md:items-center md:gap-3", children: [
3082
+ /* @__PURE__ */ jsx25("div", { className: "hidden md:flex md:items-center md:gap-3", children: renderUser ? renderUser({ name: session?.user?.name, role }) : /* @__PURE__ */ jsxs23(Fragment7, { children: [
3035
3083
  /* @__PURE__ */ jsxs23("div", { className: "text-right", children: [
3036
3084
  /* @__PURE__ */ jsx25("p", { className: "text-sm font-medium text-foreground leading-tight", children: session?.user?.name }),
3037
- /* @__PURE__ */ jsx25("p", { className: "text-xs text-muted leading-tight", children: roles.labels[role || ""] || role })
3085
+ /* @__PURE__ */ jsx25("p", { className: "text-xs text-muted leading-tight", children: roles.labels[role] || role })
3038
3086
  ] }),
3039
3087
  /* @__PURE__ */ jsx25(
3040
3088
  "button",
3041
3089
  {
3042
- onClick: () => signOut({ callbackUrl: routes.login }),
3090
+ onClick: handleSignOut,
3043
3091
  className: "p-2 rounded-full text-muted hover:text-foreground hover:bg-card transition-colors",
3044
3092
  title: strings.logout,
3045
3093
  children: /* @__PURE__ */ jsx25(LogOut, { className: "w-4 h-4" })
3046
3094
  }
3047
3095
  )
3048
- ] }),
3096
+ ] }) }),
3049
3097
  /* @__PURE__ */ jsxs23(
3050
3098
  "button",
3051
3099
  {
@@ -3097,12 +3145,12 @@ function DashboardNavbar() {
3097
3145
  /* @__PURE__ */ jsxs23("div", { className: "pt-3 mt-2 border-t border-card-border", children: [
3098
3146
  /* @__PURE__ */ jsxs23("div", { className: "px-3 mb-2", children: [
3099
3147
  /* @__PURE__ */ jsx25("p", { className: "text-sm font-medium text-foreground", children: session?.user?.name }),
3100
- /* @__PURE__ */ jsx25("p", { className: "text-xs text-muted", children: roles.labels[role || ""] || role })
3148
+ /* @__PURE__ */ jsx25("p", { className: "text-xs text-muted", children: roles.labels[role] || role })
3101
3149
  ] }),
3102
3150
  /* @__PURE__ */ jsxs23(
3103
3151
  "button",
3104
3152
  {
3105
- onClick: () => signOut({ callbackUrl: routes.login }),
3153
+ onClick: handleSignOut,
3106
3154
  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",
3107
3155
  children: [
3108
3156
  /* @__PURE__ */ jsx25(LogOut, { className: "w-4 h-4" }),
@@ -3139,6 +3187,21 @@ var accentStyles = {
3139
3187
  border: "border-l-amber-500",
3140
3188
  bg: "bg-amber-500/10",
3141
3189
  text: "text-amber-600"
3190
+ },
3191
+ red: {
3192
+ border: "border-l-red-500",
3193
+ bg: "bg-red-500/10",
3194
+ text: "text-red-600"
3195
+ },
3196
+ pink: {
3197
+ border: "border-l-pink-500",
3198
+ bg: "bg-pink-500/10",
3199
+ text: "text-pink-600"
3200
+ },
3201
+ teal: {
3202
+ border: "border-l-teal-500",
3203
+ bg: "bg-teal-500/10",
3204
+ text: "text-teal-600"
3142
3205
  }
3143
3206
  };
3144
3207
  function StatCard({
@@ -3147,7 +3210,7 @@ function StatCard({
3147
3210
  icon: Icon,
3148
3211
  accent = "blue"
3149
3212
  }) {
3150
- const s = accentStyles[accent];
3213
+ const s = typeof accent === "string" ? accentStyles[accent] : accent;
3151
3214
  return /* @__PURE__ */ jsx26(
3152
3215
  "div",
3153
3216
  {
@@ -3165,14 +3228,21 @@ function StatCard({
3165
3228
 
3166
3229
  // src/components/splash/SplashScreen.tsx
3167
3230
  import { jsx as jsx27, jsxs as jsxs25 } from "react/jsx-runtime";
3168
- var SPLASH_WORDS = ["Powerful", "Flexible", "Modular", "Secure", "Customizable"];
3169
- function pickRandom3() {
3170
- const shuffled = [...SPLASH_WORDS].sort(() => Math.random() - 0.5);
3231
+ var DEFAULT_WORDS = ["Powerful", "Flexible", "Modular", "Secure", "Customizable"];
3232
+ var DEFAULT_TOP_TEXT = "GAVA";
3233
+ var DEFAULT_BOTTOM_TEXT = "ENGINE";
3234
+ function pickRandom3(source) {
3235
+ const shuffled = [...source].sort(() => Math.random() - 0.5);
3171
3236
  return shuffled.slice(0, 3);
3172
3237
  }
3173
- var words = pickRandom3();
3174
3238
  function SplashScreen() {
3175
3239
  const { phase } = useSplash();
3240
+ const config = useGavaConfig();
3241
+ const splashConfig = config.splash;
3242
+ const wordSource = splashConfig?.words ?? DEFAULT_WORDS;
3243
+ const topText = splashConfig?.topText ?? DEFAULT_TOP_TEXT;
3244
+ const bottomText = splashConfig?.bottomText ?? DEFAULT_BOTTOM_TEXT;
3245
+ const words = pickRandom3(wordSource);
3176
3246
  if (phase === "idle") return null;
3177
3247
  const topClass = phase === "closing" ? "splash-enter-down" : phase === "opening" ? "splash-exit-up" : "";
3178
3248
  const bottomClass = phase === "closing" ? "splash-enter-up" : phase === "opening" ? "splash-exit-down" : "";
@@ -3181,7 +3251,7 @@ function SplashScreen() {
3181
3251
  "div",
3182
3252
  {
3183
3253
  className: `splash-half splash-half-top absolute inset-x-0 top-0 h-1/2 bg-background overflow-hidden ${topClass}`,
3184
- children: /* @__PURE__ */ jsx27("div", { className: "absolute inset-0 flex flex-col items-center justify-end pb-2", children: /* @__PURE__ */ jsx27("span", { className: "splash-title", children: "GAVA" }) })
3254
+ children: /* @__PURE__ */ jsx27("div", { className: "absolute inset-0 flex flex-col items-center justify-end pb-2", children: /* @__PURE__ */ jsx27("span", { className: "splash-title", children: topText }) })
3185
3255
  }
3186
3256
  ),
3187
3257
  /* @__PURE__ */ jsx27(
@@ -3189,7 +3259,7 @@ function SplashScreen() {
3189
3259
  {
3190
3260
  className: `splash-half splash-half-bottom absolute inset-x-0 bottom-0 h-1/2 bg-background overflow-hidden ${bottomClass}`,
3191
3261
  children: /* @__PURE__ */ jsxs25("div", { className: "absolute inset-0 flex flex-col items-center justify-start pt-2", children: [
3192
- /* @__PURE__ */ jsx27("span", { className: "splash-title", children: "ENGINE" }),
3262
+ /* @__PURE__ */ jsx27("span", { className: "splash-title", children: bottomText }),
3193
3263
  /* @__PURE__ */ jsx27("div", { className: "flex items-center gap-3 mt-6", children: words.map((word, i) => /* @__PURE__ */ jsxs25(
3194
3264
  "span",
3195
3265
  {
@@ -3253,9 +3323,10 @@ export {
3253
3323
  ContentEditor,
3254
3324
  ContentList,
3255
3325
  CategoryManager,
3326
+ useDefaultNavigation,
3256
3327
  DashboardNavbar,
3257
3328
  StatCard,
3258
3329
  SplashScreen,
3259
3330
  DashboardSplashTrigger
3260
3331
  };
3261
- //# sourceMappingURL=chunk-XUWBLDOW.js.map
3332
+ //# sourceMappingURL=chunk-WPVUAMRJ.js.map