react-text-forge 1.2.12 → 1.3.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.
@@ -386,6 +386,7 @@ const deserialize = (html) => {
386
386
  return null;
387
387
  }
388
388
  const children = Array.from(node.childNodes).map(deserializeNode).flat().filter(Boolean);
389
+ const validChildren = children.length > 0 ? children : [{ text: "" }];
389
390
  const styles = {
390
391
  bold: node.querySelector("strong") !== null,
391
392
  italic: node.querySelector("em") !== null,
@@ -403,33 +404,33 @@ const deserialize = (html) => {
403
404
  };
404
405
  switch (node.nodeName) {
405
406
  case "P":
406
- return jsx("element", { type: "paragraph" }, children);
407
+ return jsx("element", { type: "paragraph" }, validChildren);
407
408
  case "PRE":
408
- return jsx("element", { type: "code" }, children);
409
+ return jsx("element", { type: "code" }, validChildren);
409
410
  case "UL":
410
- return jsx("element", { type: "bullet-list" }, children);
411
+ return jsx("element", { type: "bullet-list" }, validChildren);
411
412
  case "OL":
412
- return jsx("element", { type: "numbered-list" }, children);
413
+ return jsx("element", { type: "numbered-list" }, validChildren);
413
414
  case "LI":
414
- return jsx("element", { type: "list-item" }, children);
415
+ return jsx("element", { type: "list-item" }, validChildren);
415
416
  case "H1":
416
- return jsx("element", { type: "h1" }, children);
417
+ return jsx("element", { type: "h1" }, validChildren);
417
418
  case "H2":
418
- return jsx("element", { type: "h2" }, children);
419
+ return jsx("element", { type: "h2" }, validChildren);
419
420
  case "BLOCKQUOTE":
420
- return jsx("element", { type: "blockquote" }, children);
421
+ return jsx("element", { type: "blockquote" }, validChildren);
421
422
  case "IMG":
422
423
  return jsx("element", { type: "image", url: node.getAttribute("src") });
423
424
  case "TABLE":
424
- return jsx("element", { type: "table" }, children);
425
+ return jsx("element", { type: "table" }, validChildren);
425
426
  case "TR":
426
- return jsx("element", { type: "table-row" }, children);
427
+ return jsx("element", { type: "table-row" }, validChildren);
427
428
  case "TD":
428
- return jsx("element", { type: "table-cell" }, children);
429
+ return jsx("element", { type: "table-cell" }, validChildren);
429
430
  case "A":
430
- return jsx("element", { type: "link", url: node.getAttribute("href") }, children);
431
+ return jsx("element", { type: "link", url: node.getAttribute("href") }, validChildren);
431
432
  default:
432
- return children.map((child) => {
433
+ return validChildren.map((child) => {
433
434
  if (typeof child === "string") {
434
435
  return jsx("text", styles, child);
435
436
  }
@@ -879,7 +880,7 @@ const CodeElement = ({ attributes, children, element }) => {
879
880
  const CustomEditor = {
880
881
  /**
881
882
  * Permet de définir si le format défini est actif
882
- * @param {object} editor - éditeur de texte
883
+ * @param {ReactEditor} editor - éditeur de texte
883
884
  * @param {string} format - format défini (ex: gras, italique, etc...)
884
885
  * @returns {boolean}
885
886
  */
@@ -889,7 +890,7 @@ const CustomEditor = {
889
890
  },
890
891
  /**
891
892
  * Permet de gérer l'application et la désapplication du format défini
892
- * @param {object} editor - éditeur de texte
893
+ * @param {ReactEditor} editor - éditeur de texte
893
894
  * @param {string} format - format défini (ex: gras, italique, etc...)
894
895
  * @returns {void}
895
896
  */
@@ -908,7 +909,7 @@ const CustomEditor = {
908
909
  },
909
910
  /**
910
911
  * Permet de définir si le bloc défini est actif
911
- * @param {object} editor - éditeur de texte
912
+ * @param {ReactEditor} editor - éditeur de texte
912
913
  * @param {string} blockType - élément défini (ex: p, h1, h2...)
913
914
  * @returns {boolean}
914
915
  */
@@ -920,7 +921,7 @@ const CustomEditor = {
920
921
  },
921
922
  /**
922
923
  * Permet de définir si le bloc défini est dans une liste à puces (non-ordonnée ou numérotée)
923
- * @param {object} editor - éditeur de texte
924
+ * @param {ReactEditor} editor - éditeur de texte
924
925
  * @returns {boolean}
925
926
  */
926
927
  isSelectionInList(editor) {
@@ -931,7 +932,7 @@ const CustomEditor = {
931
932
  },
932
933
  /**
933
934
  * Permet de définir la puce utilisée dans une liste à puces (non-ordonnée ou numérotée)
934
- * @param {object} editor - éditeur de texte
935
+ * @param {ReactEditor} editor - éditeur de texte
935
936
  * @returns {string}
936
937
  */
937
938
  getListStyleType(editor) {
@@ -940,9 +941,31 @@ const CustomEditor = {
940
941
  });
941
942
  return match[0].listStyleType;
942
943
  },
944
+ /**
945
+ * Permet de récupérer le type de bloc utilisé
946
+ * @param {Editor} editor
947
+ * @param {Range | Point | null} selection
948
+ */
949
+ getCurrentBlock(editor, selection) {
950
+ if (!selection) {
951
+ return null;
952
+ }
953
+ const [currentNodeEntry] = Editor.nodes(editor, {
954
+ match: (node) => {
955
+ return Element$1.isElement(node);
956
+ },
957
+ // Limiter la recherche au chemin de la sélection
958
+ at: selection
959
+ });
960
+ if (currentNodeEntry) {
961
+ const [node] = currentNodeEntry;
962
+ return node.type;
963
+ }
964
+ return null;
965
+ },
943
966
  /**
944
967
  * Permet de gérer l'application et la désapplication du bloc défini
945
- * @param {object} editor - éditeur de texte
968
+ * @param {ReactEditor} editor - éditeur de texte
946
969
  * @param {string} blockType - format défini (ex: gras, italique, etc...)
947
970
  * @param {string} bulletType - puces définies dans
948
971
  * @returns {void}
@@ -989,7 +1012,7 @@ const CustomEditor = {
989
1012
  },
990
1013
  /**
991
1014
  * Permet de définir si le bloc défini possède un alignement
992
- * @param {object} editor - éditeur de texte
1015
+ * @param {ReactEditor} editor - éditeur de texte
993
1016
  * @param {string} align - alignement défini (ex: left, right ou center.)
994
1017
  * @returns {boolean}
995
1018
  */
@@ -1001,7 +1024,7 @@ const CustomEditor = {
1001
1024
  },
1002
1025
  /**
1003
1026
  * Permet de gérer l'alignement du bloc sélectionné
1004
- * @param {object} editor - éditeur de texte
1027
+ * @param {ReactEditor} editor - éditeur de texte
1005
1028
  * @param {string} alignement - alignement défini (ex: left, right ou center)
1006
1029
  * @returns {void}
1007
1030
  */
@@ -1016,7 +1039,7 @@ const CustomEditor = {
1016
1039
  },
1017
1040
  /**
1018
1041
  * Permet de définir si le bloc sélectionné peut être indenté
1019
- * @param {object} editor - éditeur de texte
1042
+ * @param {ReactEditor} editor - éditeur de texte
1020
1043
  * @param {string} mark - indentation sélectionné
1021
1044
  * @returns {boolean}
1022
1045
  */
@@ -1041,7 +1064,7 @@ const CustomEditor = {
1041
1064
  },
1042
1065
  /**
1043
1066
  * Permet de gérer l'indentation du bloc sélectionné
1044
- * @param {object} editor - éditeur de texte
1067
+ * @param {ReactEditor} editor - éditeur de texte
1045
1068
  * @returns {void}
1046
1069
  */
1047
1070
  handleIndent(editor) {
@@ -1074,7 +1097,7 @@ const CustomEditor = {
1074
1097
  },
1075
1098
  /**
1076
1099
  * Permet de gérer l'désindentation du bloc sélectionné
1077
- * @param {object} editor - éditeur de texte
1100
+ * @param {ReactEditor} editor - éditeur de texte
1078
1101
  * @returns {void}
1079
1102
  */
1080
1103
  handleOutdent(editor) {
@@ -1106,7 +1129,7 @@ const CustomEditor = {
1106
1129
  },
1107
1130
  /**
1108
1131
  * Permet de définir si le bloc sélectionné est un lien
1109
- * @param {object} editor - éditeur de texte
1132
+ * @param {ReactEditor} editor - éditeur de texte
1110
1133
  * @returns {boolean}
1111
1134
  */
1112
1135
  isLinkActive(editor) {
@@ -1119,7 +1142,7 @@ const CustomEditor = {
1119
1142
  },
1120
1143
  /**
1121
1144
  * Permet de ajouter ou mettre à jour un lien
1122
- * @param {object} editor - éditeur de texte
1145
+ * @param {ReactEditor} editor - éditeur de texte
1123
1146
  * @param {string} url - url défini
1124
1147
  * @param {string} openInNewTab - attribut pour définir si le lien ouvre dans un nouvel onglet
1125
1148
  * @returns {void}
@@ -1159,7 +1182,7 @@ const CustomEditor = {
1159
1182
  },
1160
1183
  /**
1161
1184
  * Permet de supprimer le lien
1162
- * @param {object} editor - éditeur de texte
1185
+ * @param {ReactEditor} editor - éditeur de texte
1163
1186
  * @returns {void}
1164
1187
  */
1165
1188
  removeLink(editor) {
@@ -1185,7 +1208,7 @@ const CustomEditor = {
1185
1208
  },
1186
1209
  /**
1187
1210
  * Permet de gérer la couleur de fond du bloc sélectionné
1188
- * @param {object} editor - éditeur de texte
1211
+ * @param {ReactEditor} editor - éditeur de texte
1189
1212
  * @param {string} coulor - couleur définie
1190
1213
  * @returns {void}
1191
1214
  */
@@ -1197,7 +1220,7 @@ const CustomEditor = {
1197
1220
  },
1198
1221
  /**
1199
1222
  * Permet de gérer la couleur de texte du bloc sélectionné
1200
- * @param {object} editor - éditeur de texte
1223
+ * @param {ReactEditor} editor - éditeur de texte
1201
1224
  * @param {string} coulor - couleur définie
1202
1225
  * @returns {void}
1203
1226
  */
@@ -1209,7 +1232,7 @@ const CustomEditor = {
1209
1232
  },
1210
1233
  /**
1211
1234
  * Permet de gérer la taille de police bloc sélectionné
1212
- * @param {object} editor - éditeur de texte
1235
+ * @param {ReactEditor} editor - éditeur de texte
1213
1236
  * @param {string} size - taille définie
1214
1237
  * @returns {void}
1215
1238
  */
@@ -1221,7 +1244,7 @@ const CustomEditor = {
1221
1244
  },
1222
1245
  /**
1223
1246
  * Permet de gérer la police d'écriture bloc sélectionné
1224
- * @param {object} editor - éditeur de texte
1247
+ * @param {ReactEditor} editor - éditeur de texte
1225
1248
  * @param {string} fontFamily - police définie
1226
1249
  * @returns {void}
1227
1250
  */
@@ -1234,7 +1257,7 @@ const CustomEditor = {
1234
1257
  /**
1235
1258
  * Permet de vérifier si la sélection se situe dans un code
1236
1259
  *
1237
- * @param {object} editor - éditeur de texte
1260
+ * @param {ReactEditor} editor - éditeur de texte
1238
1261
  * @returns {boolean}
1239
1262
  */
1240
1263
  isSelectionInCode(editor) {
@@ -1246,7 +1269,7 @@ const CustomEditor = {
1246
1269
  /**
1247
1270
  * Permet de récupérer le langage actuel
1248
1271
  *
1249
- * @param {object} editor - éditeur de texte
1272
+ * @param {ReactEditor} editor - éditeur de texte
1250
1273
  * @returns {boolean}
1251
1274
  */
1252
1275
  getCurrentCodeLanguage(editor) {
@@ -1257,7 +1280,7 @@ const CustomEditor = {
1257
1280
  },
1258
1281
  /**
1259
1282
  * Gère l'ajout, l'édition et la suppression d'un bloc de code
1260
- * @param {object} editor - éditeur de texte
1283
+ * @param {ReactEditor} editor - éditeur de texte
1261
1284
  * @param {string} language - langage défini (ex: cpp(C++), php, etc...)
1262
1285
  * @returns {void}
1263
1286
  */
@@ -1329,7 +1352,7 @@ const CustomEditor = {
1329
1352
  /**
1330
1353
  * Insère un bloc de code
1331
1354
  *
1332
- * @param {object} editor
1355
+ * @param {ReactEditor} editor
1333
1356
  * @param {string} text
1334
1357
  * @return {void}
1335
1358
  */
@@ -1352,7 +1375,7 @@ const CustomEditor = {
1352
1375
  },
1353
1376
  /**
1354
1377
  * Permet de gérer les images
1355
- * @param {object} editor - éditeur de texte
1378
+ * @param {ReactEditor} editor - éditeur de texte
1356
1379
  * @param {string} url - url définie
1357
1380
  * @returns {void}
1358
1381
  */
@@ -1372,7 +1395,7 @@ const CustomEditor = {
1372
1395
  /**
1373
1396
  * Permet de gérer l'upload d'un fichier
1374
1397
  * @param {Event} event
1375
- * @param {object} editor - éditeur de texte
1398
+ * @param {ReactEditor} editor - éditeur de texte
1376
1399
  * @returns {void}
1377
1400
  */
1378
1401
  handleFileChange(event, editor) {
@@ -1426,7 +1449,7 @@ const CustomEditor = {
1426
1449
  },
1427
1450
  /**
1428
1451
  * Permet de créer un tableau
1429
- * @param {object} editor - éditeur de texte
1452
+ * @param {ReactEditor} editor - éditeur de texte
1430
1453
  * @param {number} rows - nombre de lignes
1431
1454
  * @param {number} columns - nombre de colonnes
1432
1455
  * @returns {void}
@@ -1446,7 +1469,7 @@ const CustomEditor = {
1446
1469
  },
1447
1470
  /**
1448
1471
  * Permet de définir si l'élément sélectionné est dans un tableau
1449
- * @param {object} editor - éditeur de texte
1472
+ * @param {ReactEditor} editor - éditeur de texte
1450
1473
  * @returns {boolean}
1451
1474
  */
1452
1475
  isSelectionInTable(editor) {
@@ -1457,7 +1480,7 @@ const CustomEditor = {
1457
1480
  },
1458
1481
  /**
1459
1482
  * Permet d'obtenir le tableau sélectionné
1460
- * @param {object} editor - éditeur de texte
1483
+ * @param {ReactEditor} editor - éditeur de texte
1461
1484
  * @returns {void}
1462
1485
  */
1463
1486
  getTableFromSelection(editor) {
@@ -1468,7 +1491,7 @@ const CustomEditor = {
1468
1491
  },
1469
1492
  /**
1470
1493
  * Permet d'ajouter une ligne au tableau sélectionné
1471
- * @param {object} editor - éditeur de texte
1494
+ * @param {ReactEditor} editor - éditeur de texte
1472
1495
  * @returns {void}
1473
1496
  */
1474
1497
  addRow(editor) {
@@ -1493,7 +1516,7 @@ const CustomEditor = {
1493
1516
  },
1494
1517
  /**
1495
1518
  * Permet d'ajouter une colonne au tableau sélectionné
1496
- * @param {object} editor - éditeur de texte
1519
+ * @param {ReactEditor} editor - éditeur de texte
1497
1520
  * @returns {void}
1498
1521
  */
1499
1522
  addColumn(editor) {
@@ -1530,7 +1553,7 @@ const CustomEditor = {
1530
1553
  },
1531
1554
  /**
1532
1555
  * Permet de supprimer une ligne du tableau sélectionné
1533
- * @param {object} editor - éditeur de texte
1556
+ * @param {ReactEditor} editor - éditeur de texte
1534
1557
  * @returns {void}
1535
1558
  */
1536
1559
  deleteRow(editor) {
@@ -1552,7 +1575,7 @@ const CustomEditor = {
1552
1575
  },
1553
1576
  /**
1554
1577
  * Permet de supprimer une colonne du tableau sélectionné
1555
- * @param {object} editor - éditeur de texte
1578
+ * @param {ReactEditor} editor - éditeur de texte
1556
1579
  * @returns {void}
1557
1580
  */
1558
1581
  deleteColumn(editor) {
@@ -1588,7 +1611,7 @@ const CustomEditor = {
1588
1611
  },
1589
1612
  /**
1590
1613
  * Permet de supprimer le tableau sélectionné
1591
- * @param {object} editor - éditeur de texte
1614
+ * @param {ReactEditor} editor - éditeur de texte
1592
1615
  * @returns {void}
1593
1616
  */
1594
1617
  deleteTable(editor) {
@@ -1734,6 +1757,7 @@ const ListElement = ({ attributes, children, element }) => {
1734
1757
  textAlign: element.align || "left",
1735
1758
  listStyleType: element.listStyleType || "disc"
1736
1759
  };
1760
+ console.log(element.type);
1737
1761
  switch (element.type) {
1738
1762
  case "bullet-list":
1739
1763
  return /* @__PURE__ */ jsxRuntimeExports.jsx("ul", { className: "rtf", style, ...attributes, children });
@@ -1841,6 +1865,7 @@ const ThemeProvider = ({ showTheme, backgroundDarkColor, borderDarkColor, imageD
1841
1865
  const useTheme = () => useContext(ThemeContext);
1842
1866
  const ReactTextForgeContext = createContext();
1843
1867
  const ReactTextForgeProvider = ({ backgroundColor, borderColor, imageColor, editor, children }) => {
1868
+ const [dropdownActive, setDropdownActive] = useState(null);
1844
1869
  const { showTheme, isDarkTheme, backgroundDarkColor, borderDarkColor, imageDarkColor } = useTheme();
1845
1870
  const resolvedBackgroundColor = showTheme && isDarkTheme ? backgroundDarkColor : backgroundColor;
1846
1871
  const resolvedBorderColor = showTheme && isDarkTheme ? borderDarkColor : borderColor;
@@ -1850,12 +1875,20 @@ const ReactTextForgeProvider = ({ backgroundColor, borderColor, imageColor, edit
1850
1875
  document.documentElement.style.setProperty("--border-color", resolvedBorderColor);
1851
1876
  document.documentElement.style.setProperty("--image-color", resolvedImageColor);
1852
1877
  }, [resolvedBackgroundColor, resolvedBorderColor, resolvedImageColor]);
1853
- return /* @__PURE__ */ jsxRuntimeExports.jsx(ReactTextForgeContext.Provider, { value: { backgroundColor: resolvedBackgroundColor, borderColor: resolvedBorderColor, editor, imageColor: resolvedImageColor }, children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "rtf react-text-forge", style: { backgroundColor: resolvedBackgroundColor, borderColor: resolvedBorderColor }, children }) });
1878
+ const value = {
1879
+ backgroundColor: resolvedBackgroundColor,
1880
+ borderColor: resolvedBorderColor,
1881
+ editor,
1882
+ imageColor: resolvedImageColor,
1883
+ dropdownActive,
1884
+ setDropdownActive
1885
+ };
1886
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(ReactTextForgeContext.Provider, { value, children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "rtf react-text-forge", style: { backgroundColor: resolvedBackgroundColor, borderColor: resolvedBorderColor }, children }) });
1854
1887
  };
1855
1888
  const useReactTextForgeContext = () => {
1856
1889
  return useContext(ReactTextForgeContext);
1857
1890
  };
1858
- const BulletTypeSelector = ({ onChange, selectStyle, toggleForm }) => {
1891
+ const BulletTypeSelector = ({ onChange, selectStyle, onClose }) => {
1859
1892
  const bulletTypes = [
1860
1893
  { value: "disc", label: "Disque" },
1861
1894
  { value: "circle", label: "Cercle" },
@@ -1866,7 +1899,7 @@ const BulletTypeSelector = ({ onChange, selectStyle, toggleForm }) => {
1866
1899
  { value: "'➔'", label: "Flèche épaisse" }
1867
1900
  ];
1868
1901
  const { editor } = useReactTextForgeContext();
1869
- return /* @__PURE__ */ jsxRuntimeExports.jsx("ul", { onMouseLeave: () => toggleForm(false), style: selectStyle, className: "rtf dropdown-menu", children: bulletTypes.map((type) => /* @__PURE__ */ jsxRuntimeExports.jsx(
1902
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("ul", { onMouseLeave: onClose, style: selectStyle, className: "rtf dropdown-menu", children: bulletTypes.map((type) => /* @__PURE__ */ jsxRuntimeExports.jsx(
1870
1903
  "li",
1871
1904
  {
1872
1905
  value: type.value,
@@ -1877,7 +1910,7 @@ const BulletTypeSelector = ({ onChange, selectStyle, toggleForm }) => {
1877
1910
  type.value
1878
1911
  )) });
1879
1912
  };
1880
- const NumeredTypeSelector = ({ onChange, selectStyle, toggleForm }) => {
1913
+ const NumeredTypeSelector = ({ onChange, selectStyle, onClose }) => {
1881
1914
  const numeredTypes = [
1882
1915
  { value: "decimal", label: "Décimal" },
1883
1916
  { value: "upper-roman", label: "Lettres Romaines majuscules" },
@@ -1886,7 +1919,7 @@ const NumeredTypeSelector = ({ onChange, selectStyle, toggleForm }) => {
1886
1919
  { value: "lower-greek", label: "Lettres Grecques minuscules" }
1887
1920
  ];
1888
1921
  const { editor } = useReactTextForgeContext();
1889
- return /* @__PURE__ */ jsxRuntimeExports.jsx("ul", { onMouseLeave: () => toggleForm(false), style: selectStyle, className: "rtf dropdown-menu", children: numeredTypes.map((type) => /* @__PURE__ */ jsxRuntimeExports.jsx(
1922
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("ul", { onMouseLeave: onClose, style: selectStyle, className: "rtf dropdown-menu", children: numeredTypes.map((type) => /* @__PURE__ */ jsxRuntimeExports.jsx(
1890
1923
  "li",
1891
1924
  {
1892
1925
  value: type.value,
@@ -2003,15 +2036,21 @@ function Images({ format, imageColor }) {
2003
2036
  return returnImage();
2004
2037
  }
2005
2038
  const BlockListDropdown = ({ format, isActive, onMouseDown }) => {
2006
- const { backgroundColor, editor, imageColor } = useReactTextForgeContext();
2007
- const [showBulletOptions, setShowBulletOptions] = useState(false);
2039
+ const { backgroundColor, editor, imageColor, dropdownActive, setDropdownActive } = useReactTextForgeContext();
2008
2040
  const selectStyle = {
2009
2041
  backgroundColor,
2010
2042
  color: imageColor
2011
2043
  };
2012
2044
  const handleBulletTypeChange = (bulletType) => {
2013
2045
  CustomEditor.toggleBlock(editor, format === "bulletList" ? "bullet-list" : "numbered-list", bulletType);
2014
- setShowBulletOptions(false);
2046
+ setDropdownActive(null);
2047
+ };
2048
+ const toggleDropDown = () => {
2049
+ if (dropdownActive !== format) {
2050
+ setDropdownActive(format);
2051
+ } else {
2052
+ setDropdownActive(null);
2053
+ }
2015
2054
  };
2016
2055
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
2017
2056
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
@@ -2028,42 +2067,47 @@ const BlockListDropdown = ({ format, isActive, onMouseDown }) => {
2028
2067
  {
2029
2068
  className: "rtf tool tool--arrow",
2030
2069
  style: { color: selectStyle.color },
2031
- onClick: () => setShowBulletOptions(!showBulletOptions),
2032
- children: showBulletOptions ? "↑" : "↓"
2070
+ onClick: toggleDropDown,
2071
+ children: dropdownActive === format ? "↑" : "↓"
2033
2072
  }
2034
2073
  )
2035
2074
  ]
2036
2075
  }
2037
2076
  ),
2038
- showBulletOptions && (format === "bulletList" ? /* @__PURE__ */ jsxRuntimeExports.jsx(
2077
+ dropdownActive === "bulletList" && format === "bulletList" && /* @__PURE__ */ jsxRuntimeExports.jsx(
2039
2078
  BulletTypeSelector,
2040
2079
  {
2041
2080
  selectStyle,
2042
2081
  onChange: handleBulletTypeChange,
2043
- toggleForm: setShowBulletOptions
2082
+ onClose: () => setDropdownActive(null)
2044
2083
  }
2045
- ) : /* @__PURE__ */ jsxRuntimeExports.jsx(
2084
+ ),
2085
+ dropdownActive === "numberedList" && format === "numberedList" && /* @__PURE__ */ jsxRuntimeExports.jsx(
2046
2086
  NumeredTypeSelector,
2047
2087
  {
2048
2088
  selectStyle,
2049
2089
  onChange: handleBulletTypeChange,
2050
- toggleForm: setShowBulletOptions
2090
+ onClose: () => setDropdownActive(null)
2051
2091
  }
2052
- ))
2092
+ )
2053
2093
  ] });
2054
2094
  };
2055
- function ContainerDropdown({ disabled = false, elements, elementSelected, format, isOpen, setIsOpen, onClick }) {
2056
- const { backgroundColor, imageColor } = useReactTextForgeContext();
2095
+ function ContainerDropdown({ disabled = false, elements, elementSelected, format, onClick }) {
2096
+ const { backgroundColor, imageColor, dropdownActive, setDropdownActive } = useReactTextForgeContext();
2057
2097
  const toggleForm = () => {
2058
- setIsOpen(!isOpen);
2098
+ if (dropdownActive !== null && dropdownActive === format) {
2099
+ setDropdownActive(null);
2100
+ } else {
2101
+ setDropdownActive(format);
2102
+ }
2059
2103
  };
2060
2104
  const selectElement = (element) => {
2061
2105
  onClick(element);
2062
- setIsOpen(false);
2106
+ setDropdownActive(null);
2063
2107
  };
2064
2108
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rtf dropdown tool", children: [
2065
2109
  /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: toggleForm, className: "rtf dropdown-toggle", disabled, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Images, { format, imageColor }) }),
2066
- isOpen && /* @__PURE__ */ jsxRuntimeExports.jsx("ul", { style: { backgroundColor, color: imageColor }, className: "rtf dropdown-menu", onMouseLeave: toggleForm, children: elements.map((element, index) => /* @__PURE__ */ jsxRuntimeExports.jsx(
2110
+ dropdownActive === format && /* @__PURE__ */ jsxRuntimeExports.jsx("ul", { style: { backgroundColor, color: imageColor }, className: "rtf dropdown-menu", onMouseLeave: toggleForm, children: elements.map((element, index) => /* @__PURE__ */ jsxRuntimeExports.jsx(
2067
2111
  "li",
2068
2112
  {
2069
2113
  style: { backgroundColor: `${elementSelected && element === elementSelected ? `color-mix(in srgb, ${backgroundColor} 80%, ${isDarkColor(backgroundColor) ? "white" : "black"})` : backgroundColor}` },
@@ -2075,7 +2119,6 @@ function ContainerDropdown({ disabled = false, elements, elementSelected, format
2075
2119
  ] });
2076
2120
  }
2077
2121
  const FontSizeDropdown = ({ disabled, sizeSelected, onSelectSize }) => {
2078
- const [isOpen, setIsOpen] = useState(false);
2079
2122
  const fontSizes = ["10px", "12px", "14px", "16px", "18px", "20px", "24px", "28px", "36px"];
2080
2123
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
2081
2124
  ContainerDropdown,
@@ -2084,14 +2127,11 @@ const FontSizeDropdown = ({ disabled, sizeSelected, onSelectSize }) => {
2084
2127
  elements: fontSizes,
2085
2128
  elementSelected: sizeSelected,
2086
2129
  format: "size",
2087
- isOpen,
2088
- setIsOpen,
2089
2130
  onClick: onSelectSize
2090
2131
  }
2091
2132
  );
2092
2133
  };
2093
2134
  const FontFamilyDropdown = ({ fontFamilySelected, onSelectFontFamily }) => {
2094
- const [isOpen, setIsOpen] = useState(false);
2095
2135
  const fontFamilies = ["Arial", "Arial Black", "Bookman", "Comic Sans MS", "Courier", "Courier New", "Garamond", "Georgia", "Helvetica", "Impact", "Palatino", "Times", "Times New Roman", "Trebuchet MS", "Verdana"];
2096
2136
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
2097
2137
  ContainerDropdown,
@@ -2099,8 +2139,6 @@ const FontFamilyDropdown = ({ fontFamilySelected, onSelectFontFamily }) => {
2099
2139
  elements: fontFamilies,
2100
2140
  elementSelected: fontFamilySelected,
2101
2141
  format: "fontFamily",
2102
- isOpen,
2103
- setIsOpen,
2104
2142
  onClick: onSelectFontFamily
2105
2143
  }
2106
2144
  );
@@ -2207,29 +2245,21 @@ const LinkForm = ({ onClose, initialUrl = "", isOpenInNewTab }) => {
2207
2245
  *
2208
2246
  * For any questions or suggestions, please contact: administrateur@nhumeria.fr
2209
2247
  */
2210
- function useToolbar(editor) {
2248
+ function useToolbar(editor, setDropdownActive) {
2211
2249
  const [selectedLink, setSelectedLink] = useState("");
2212
2250
  const [colorMode, setColorMode] = useState("");
2213
2251
  const [openInNewTab, setOpenInNewTab] = useState(false);
2214
2252
  const [selectedColor, setSelectedColor] = useState("");
2215
2253
  const [selectedBackgroundColor, setSelectedBackgroundColor] = useState("");
2216
2254
  const [activeBlock, setActiveBlock] = useState("paragraph");
2217
- const [showColorPicker, setShowColorPicker] = useState(false);
2218
2255
  const [selectedLanguage, setSelectedLanguage] = useState("");
2219
- const [showLinkForm, setShowLinkForm] = useState(false);
2220
- const toggleLinkForm = () => {
2221
- setShowLinkForm(!showLinkForm);
2222
- };
2223
- const toggleColorPicker = () => {
2224
- setShowColorPicker(!showColorPicker);
2225
- };
2226
2256
  const handleColorChange = (color) => {
2227
2257
  CustomEditor.applyTextColor(editor, color);
2228
- toggleColorPicker();
2258
+ setDropdownActive(null);
2229
2259
  };
2230
2260
  const handleBackgroundColorChange = (color) => {
2231
2261
  CustomEditor.applyBackgroundTextColor(editor, color);
2232
- toggleColorPicker();
2262
+ setDropdownActive(null);
2233
2263
  };
2234
2264
  const handleBlockTypeChange = (blockType) => {
2235
2265
  CustomEditor.toggleBlock(editor, blockType);
@@ -2250,6 +2280,7 @@ function useToolbar(editor) {
2250
2280
  };
2251
2281
  return {
2252
2282
  activeBlock,
2283
+ setActiveBlock,
2253
2284
  colorMode,
2254
2285
  setColorMode,
2255
2286
  openInNewTab,
@@ -2262,13 +2293,8 @@ function useToolbar(editor) {
2262
2293
  setSelectedLanguage,
2263
2294
  selectedLink,
2264
2295
  setSelectedLink,
2265
- showColorPicker,
2266
- showLinkForm,
2267
- setShowLinkForm,
2268
2296
  // Fonctions utiles
2269
2297
  detectCurrentLanguage,
2270
- toggleLinkForm,
2271
- toggleColorPicker,
2272
2298
  handleColorChange,
2273
2299
  handleBackgroundColorChange,
2274
2300
  handleBlockTypeChange
@@ -2276,6 +2302,7 @@ function useToolbar(editor) {
2276
2302
  }
2277
2303
  function ColorPickerPopup({ selectedColor, onSelectColor, onClose }) {
2278
2304
  const [color, setColor] = useState("#ffffff");
2305
+ const { theme } = useTheme();
2279
2306
  const { editor, backgroundColor, borderColor, imageColor } = useReactTextForgeContext();
2280
2307
  const style = {
2281
2308
  backgroundColor,
@@ -2318,8 +2345,18 @@ function ColorPickerPopup({ selectedColor, onSelectColor, onClose }) {
2318
2345
  setColor(selectedColor);
2319
2346
  }
2320
2347
  }, [selectedColor]);
2348
+ useEffect(() => {
2349
+ const inputs = document.querySelectorAll(".sketch-picker input");
2350
+ const labels = document.querySelectorAll(".sketch-picker label");
2351
+ inputs.forEach((input, index) => {
2352
+ input.style.border = "2px solid " + borderColor;
2353
+ input.style.background = backgroundColor;
2354
+ input.style.color = imageColor;
2355
+ labels[index].style.color = imageColor;
2356
+ });
2357
+ }, [theme]);
2321
2358
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { onMouseLeave: onClose, className: "rtf color-picker-popup", children: [
2322
- /* @__PURE__ */ jsxRuntimeExports.jsx(SketchPicker, { styles: pickerStyles, color, onChangeComplete: handleChangeComplete }),
2359
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SketchPicker, { className: "rtf sketch-picker", styles: pickerStyles, color, onChangeComplete: handleChangeComplete }),
2323
2360
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style, className: "rtf link-form-actions", children: [
2324
2361
  /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "rtf", style: confirmStyle, onClick: handleApplyColor, disabled: !color, children: "Appliquer" }),
2325
2362
  /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "rtf", style: cancelStyle, onClick: handleCancel, children: "Annuler" })
@@ -2327,13 +2364,14 @@ function ColorPickerPopup({ selectedColor, onSelectColor, onClose }) {
2327
2364
  ] });
2328
2365
  }
2329
2366
  const BlockquoteButton = () => {
2330
- const { editor, backgroundColor, imageColor } = useReactTextForgeContext();
2367
+ const { editor, backgroundColor, imageColor, setDropdownActive } = useReactTextForgeContext();
2331
2368
  const isActive = CustomEditor.isBlockquoteActive(editor);
2332
2369
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
2333
2370
  "button",
2334
2371
  {
2335
2372
  onMouseDown: (event) => {
2336
2373
  event.preventDefault();
2374
+ setDropdownActive(null);
2337
2375
  CustomEditor.toggleBlockquote(editor);
2338
2376
  },
2339
2377
  style: { backgroundColor: isActive ? `color-mix(in srgb, ${backgroundColor} 80%, ${isDarkColor(backgroundColor) ? "white" : "black"})` : "" },
@@ -2375,7 +2413,7 @@ const Tooltip = ({ text, children, position = "top" }) => {
2375
2413
  };
2376
2414
  const FormatButton = ({ activeMarks, format, isActive, tooltip }) => {
2377
2415
  const [selectedFontFamily, setSelectedFontFamily] = useState("");
2378
- const { backgroundColor, editor, imageColor } = useReactTextForgeContext();
2416
+ const { backgroundColor, editor, imageColor, dropdownActive, setDropdownActive } = useReactTextForgeContext();
2379
2417
  const {
2380
2418
  activeBlock,
2381
2419
  colorMode,
@@ -2390,13 +2428,8 @@ const FormatButton = ({ activeMarks, format, isActive, tooltip }) => {
2390
2428
  selectedColor,
2391
2429
  setSelectedColor,
2392
2430
  selectedLink,
2393
- setSelectedLink,
2394
- showColorPicker,
2395
- showLinkForm,
2396
- setShowLinkForm,
2397
- toggleColorPicker,
2398
- toggleLinkForm
2399
- } = useToolbar(editor);
2431
+ setSelectedLink
2432
+ } = useToolbar(editor, setDropdownActive);
2400
2433
  const isHeading = activeBlock === "h1" || activeBlock === "h2";
2401
2434
  const alignList = ["left", "center", "right"];
2402
2435
  const handleFontSizeChange = (size) => {
@@ -2430,7 +2463,10 @@ const FormatButton = ({ activeMarks, format, isActive, tooltip }) => {
2430
2463
  {
2431
2464
  title: tooltip,
2432
2465
  className: "rtf tool",
2433
- onClick: () => format === "indent" ? CustomEditor.handleIndent(editor) : CustomEditor.handleOutdent(editor),
2466
+ onClick: () => {
2467
+ setDropdownActive(null);
2468
+ format === "indent" ? CustomEditor.handleIndent(editor) : CustomEditor.handleOutdent(editor);
2469
+ },
2434
2470
  disabled: !isActive,
2435
2471
  children: /* @__PURE__ */ jsxRuntimeExports.jsx(Images, { format, imageColor: isActive ? imageColor : `color-mix(in srgb, ${imageColor} 40%, black)` })
2436
2472
  }
@@ -2450,18 +2486,18 @@ const FormatButton = ({ activeMarks, format, isActive, tooltip }) => {
2450
2486
  {
2451
2487
  onMouseDown: (event) => {
2452
2488
  event.preventDefault();
2489
+ setDropdownActive("href");
2453
2490
  handleMouseDown();
2454
- toggleLinkForm();
2455
2491
  },
2456
2492
  title: tooltip,
2457
2493
  className: `rtf tool tool--${isActive ? "active" : "inactive"}`,
2458
2494
  children: /* @__PURE__ */ jsxRuntimeExports.jsx(Images, { format, imageColor })
2459
2495
  }
2460
2496
  ),
2461
- showLinkForm && /* @__PURE__ */ jsxRuntimeExports.jsx(
2497
+ dropdownActive === "href" && /* @__PURE__ */ jsxRuntimeExports.jsx(
2462
2498
  LinkForm,
2463
2499
  {
2464
- onClose: () => setShowLinkForm(false),
2500
+ onClose: () => setDropdownActive(null),
2465
2501
  initialUrl: selectedLink,
2466
2502
  isOpenInNewTab: openInNewTab
2467
2503
  }
@@ -2475,25 +2511,25 @@ const FormatButton = ({ activeMarks, format, isActive, tooltip }) => {
2475
2511
  event.preventDefault();
2476
2512
  handleMouseDown();
2477
2513
  if (format === "color") {
2514
+ setDropdownActive("color");
2478
2515
  setSelectedColor(activeMarks[format]);
2479
2516
  setColorMode("color");
2480
- toggleColorPicker();
2481
2517
  } else {
2518
+ setDropdownActive("bgColor");
2482
2519
  setSelectedBackgroundColor(activeMarks[format]);
2483
2520
  setColorMode("bgColor");
2484
- toggleColorPicker();
2485
2521
  }
2486
2522
  },
2487
2523
  className: `rtf tool tool--${isActive ? "active" : "inactive"}`,
2488
2524
  children: /* @__PURE__ */ jsxRuntimeExports.jsx(Images, { format, imageColor })
2489
2525
  }
2490
2526
  ),
2491
- showColorPicker && /* @__PURE__ */ jsxRuntimeExports.jsx(
2527
+ dropdownActive === format && /* @__PURE__ */ jsxRuntimeExports.jsx(
2492
2528
  ColorPickerPopup,
2493
2529
  {
2494
2530
  selectedColor: colorMode === "color" ? selectedColor : selectedBackgroundColor,
2495
2531
  onSelectColor: colorMode === "color" ? handleColorChange : handleBackgroundColorChange,
2496
- onClose: colorMode === "color" ? toggleColorPicker : toggleColorPicker
2532
+ onClose: () => setDropdownActive(null)
2497
2533
  }
2498
2534
  )
2499
2535
  ] }) : format === "blockquote" ? /* @__PURE__ */ jsxRuntimeExports.jsx(BlockquoteButton, { tooltip }) : /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -2501,6 +2537,7 @@ const FormatButton = ({ activeMarks, format, isActive, tooltip }) => {
2501
2537
  {
2502
2538
  onMouseDown: (event) => {
2503
2539
  event.preventDefault();
2540
+ setDropdownActive(null);
2504
2541
  if (alignList.includes(format)) {
2505
2542
  CustomEditor.toggleAlign(editor, format);
2506
2543
  } else {
@@ -2519,8 +2556,12 @@ const BlockTypeDropdown = forwardRef(({ tooltip }, ref) => {
2519
2556
  const { editor } = useReactTextForgeContext();
2520
2557
  const {
2521
2558
  activeBlock,
2559
+ setActiveBlock,
2522
2560
  handleBlockTypeChange
2523
2561
  } = useToolbar(editor);
2562
+ useEffect(() => {
2563
+ setActiveBlock(CustomEditor.getCurrentBlock(editor, editor.selection));
2564
+ }, [editor.selection]);
2524
2565
  const blockTypes = [
2525
2566
  {
2526
2567
  type: "paragraph",
@@ -2547,7 +2588,7 @@ const BlockTypeDropdown = forwardRef(({ tooltip }, ref) => {
2547
2588
  });
2548
2589
  const LanguageDropdown = forwardRef((props, ref) => {
2549
2590
  const [isOpen, setIsOpen] = useState(false);
2550
- const { backgroundColor, editor, imageColor } = useReactTextForgeContext();
2591
+ const { backgroundColor, editor, imageColor, dropdownActive, setDropdownActive } = useReactTextForgeContext();
2551
2592
  const {
2552
2593
  selectedLanguage,
2553
2594
  setSelectedLanguage
@@ -2573,6 +2614,11 @@ const LanguageDropdown = forwardRef((props, ref) => {
2573
2614
  };
2574
2615
  const toggleForm = () => {
2575
2616
  setIsOpen(!isOpen);
2617
+ if (!isOpen === true) {
2618
+ setDropdownActive("code");
2619
+ return;
2620
+ }
2621
+ setDropdownActive(null);
2576
2622
  };
2577
2623
  const handleLanguageChange = (language) => {
2578
2624
  setSelectedLanguage(language);
@@ -2581,7 +2627,7 @@ const LanguageDropdown = forwardRef((props, ref) => {
2581
2627
  };
2582
2628
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { ref, className: `rtf dropdown tool ${selectedLanguage && selectedLanguage !== "init" && selectedLanguage !== "" ? "tool--active" : ""}`, children: [
2583
2629
  /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "rtf dropdown-toggle", onClick: toggleForm, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Images, { format: "blockCode", imageColor }) }),
2584
- isOpen && /* @__PURE__ */ jsxRuntimeExports.jsxs("ul", { style: dropdownStyle, onMouseLeave: toggleForm, className: "rtf dropdown-menu", children: [
2630
+ isOpen && dropdownActive === "code" && /* @__PURE__ */ jsxRuntimeExports.jsxs("ul", { style: dropdownStyle, onMouseLeave: toggleForm, className: "rtf dropdown-menu", children: [
2585
2631
  selectedLanguage && /* @__PURE__ */ jsxRuntimeExports.jsx("li", { onClick: () => handleLanguageChange("init"), children: "Réinitialiser" }),
2586
2632
  Object.keys(languages).map((lang) => /* @__PURE__ */ jsxRuntimeExports.jsx(
2587
2633
  "li",
@@ -2600,7 +2646,7 @@ const LanguageDropdown = forwardRef((props, ref) => {
2600
2646
  ] });
2601
2647
  });
2602
2648
  const ImageForm = forwardRef((props, ref) => {
2603
- const { editor, imageColor } = useReactTextForgeContext();
2649
+ const { editor, imageColor, setDropdownActive } = useReactTextForgeContext();
2604
2650
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rtf tool image-upload-container", ref, children: [
2605
2651
  /* @__PURE__ */ jsxRuntimeExports.jsx(
2606
2652
  "input",
@@ -2612,7 +2658,7 @@ const ImageForm = forwardRef((props, ref) => {
2612
2658
  className: "rtf hidden-file-input"
2613
2659
  }
2614
2660
  ),
2615
- /* @__PURE__ */ jsxRuntimeExports.jsx("label", { htmlFor: "file-input", className: "rtf image-upload-label", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Images, { format: "image", imageColor }) })
2661
+ /* @__PURE__ */ jsxRuntimeExports.jsx("label", { htmlFor: "file-input", className: "rtf image-upload-label", onClick: () => setDropdownActive(null), children: /* @__PURE__ */ jsxRuntimeExports.jsx(Images, { format: "image", imageColor }) })
2616
2662
  ] });
2617
2663
  });
2618
2664
  const TableForm = ({ onClose }) => {
@@ -2662,8 +2708,8 @@ const TableForm = ({ onClose }) => {
2662
2708
  ] })
2663
2709
  ] });
2664
2710
  };
2665
- const TableDropdown = forwardRef(({ allButtons, hiddenButtons }, ref) => {
2666
- const { editor, imageColor } = useReactTextForgeContext();
2711
+ const TableButtons = forwardRef(({ allButtons, hiddenButtons }, ref) => {
2712
+ const { editor, imageColor, setDropdownActive } = useReactTextForgeContext();
2667
2713
  const isTableSelected = CustomEditor.isSelectionInTable(editor);
2668
2714
  const buttons = [
2669
2715
  { name: "deleteTable", alt: "Supprimer le tableau", onClick: CustomEditor.deleteTable },
@@ -2672,6 +2718,10 @@ const TableDropdown = forwardRef(({ allButtons, hiddenButtons }, ref) => {
2672
2718
  { name: "deleteRow", alt: "Supprimer une ligne", onClick: CustomEditor.deleteRow },
2673
2719
  { name: "deleteColumn", alt: "Supprimer une colonne", onClick: CustomEditor.deleteColumn }
2674
2720
  ];
2721
+ const handleClick = (button) => {
2722
+ setDropdownActive(null);
2723
+ button.onClick(editor);
2724
+ };
2675
2725
  return /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: buttons.map((button, index) => {
2676
2726
  var _a, _b;
2677
2727
  return /* @__PURE__ */ jsxRuntimeExports.jsx(Tooltip, { text: allButtons.find((action) => action.format === button.name).tooltip, position: "bottom", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -2680,7 +2730,7 @@ const TableDropdown = forwardRef(({ allButtons, hiddenButtons }, ref) => {
2680
2730
  ref: (el) => ref.current[button.name] = el,
2681
2731
  className: "rtf tool",
2682
2732
  style: { display: hiddenButtons.includes(button.name) ? "none" : "inline-block" },
2683
- onClick: () => button.onClick(editor),
2733
+ onClick: () => handleClick(button),
2684
2734
  disabled: !isTableSelected,
2685
2735
  children: /* @__PURE__ */ jsxRuntimeExports.jsx(
2686
2736
  Images,
@@ -2698,7 +2748,8 @@ const Toolbar = ({ activeMarks }) => {
2698
2748
  const [hiddenButtons, setHiddenButtons] = useState([]);
2699
2749
  const toolbarRef = useRef(null);
2700
2750
  const buttonsRef = useRef({});
2701
- const { editor, imageColor, backgroundColor } = useReactTextForgeContext();
2751
+ const modalRef = useRef(null);
2752
+ const { editor, imageColor, backgroundColor, dropdownActive, setDropdownActive } = useReactTextForgeContext();
2702
2753
  const allButtons = [
2703
2754
  { format: "blockType", tooltip: "Insérer un bloc de texte" },
2704
2755
  { format: "bold", tooltip: "Gras (Ctrl+B)" },
@@ -2732,26 +2783,40 @@ const Toolbar = ({ activeMarks }) => {
2732
2783
  { format: "redo", tooltip: "Rétablir (Ctrl+Y)" }
2733
2784
  ];
2734
2785
  const [showTableForm, setShowTableForm] = useState(false);
2786
+ const [toolbarGap, setToolbarGap] = useState(0);
2735
2787
  const tablesActions = ["deleteTable", "addRow", "addColumn", "deleteRow", "deleteColumn"];
2736
2788
  const toggleTableForm = () => {
2737
2789
  setShowTableForm(!showTableForm);
2790
+ if (!showTableForm === true) {
2791
+ setDropdownActive("table");
2792
+ return;
2793
+ }
2794
+ setDropdownActive(null);
2738
2795
  };
2739
2796
  const handleBlur = () => {
2740
2797
  document.querySelector(".rtf.toolbar").blur();
2741
2798
  };
2742
- const toggleModal = () => setShowModal((prev) => !prev);
2799
+ const toggleModal = () => {
2800
+ setShowModal((prev) => !prev);
2801
+ };
2743
2802
  const handleResize = () => {
2744
2803
  if (toolbarRef.current) {
2745
2804
  const toolbar = toolbarRef.current;
2746
2805
  const toolbarWidth = toolbar.clientWidth - 15;
2747
- const totalWidth = 978;
2806
+ let totalWidth = 0;
2807
+ allButtons.forEach((button, index) => {
2808
+ const buttonElement = buttonsRef.current[button.format];
2809
+ if (buttonElement) {
2810
+ totalWidth += (index === 0 ? buttonElement.clientWidth : buttonsRef.current[allButtons[1].format].clientWidth) + 5;
2811
+ }
2812
+ });
2748
2813
  if (totalWidth > toolbarWidth) {
2749
2814
  let currentWidth = 0;
2750
2815
  const visibleButtons = [];
2751
- allButtons.forEach((button) => {
2816
+ allButtons.forEach((button, index) => {
2752
2817
  const buttonElement = buttonsRef.current[button.format];
2753
2818
  if (buttonElement) {
2754
- currentWidth += (button.format === "blockType" ? buttonElement.clientWidth : 25) + 5;
2819
+ currentWidth += (index === 0 ? buttonElement.clientWidth : buttonsRef.current[allButtons[1].format].clientWidth) + 5;
2755
2820
  if (currentWidth <= toolbarWidth) {
2756
2821
  visibleButtons.push(button.format);
2757
2822
  }
@@ -2774,7 +2839,14 @@ const Toolbar = ({ activeMarks }) => {
2774
2839
  resizeObserver.disconnect();
2775
2840
  };
2776
2841
  }, []);
2777
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rtf toolbar-container", children: [
2842
+ useEffect(() => {
2843
+ if (modalRef.current) {
2844
+ setToolbarGap(modalRef.current.clientHeight);
2845
+ } else {
2846
+ setToolbarGap(0);
2847
+ }
2848
+ }, [showModal]);
2849
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rtf toolbar-container", style: { marginBottom: toolbarGap }, children: [
2778
2850
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rtf toolbar", onClick: handleBlur, ref: toolbarRef, children: [
2779
2851
  /* @__PURE__ */ jsxRuntimeExports.jsx(BlockTypeDropdown, { ref: (el) => buttonsRef.current["blockType"] = el, tooltip: allButtons.find((button) => button.format === "blockType").tooltip }),
2780
2852
  Object.keys(activeMarks).map((format, index) => /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -2797,7 +2869,7 @@ const Toolbar = ({ activeMarks }) => {
2797
2869
  )),
2798
2870
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rtf dropdown tool", style: { display: hiddenButtons.includes("table") ? "none" : "flex", padding: hiddenButtons.includes("table") ? 0 : 5 }, children: [
2799
2871
  /* @__PURE__ */ jsxRuntimeExports.jsx(Tooltip, { text: allButtons.find((action) => action.format === "table").tooltip, position: "bottom", children: /* @__PURE__ */ jsxRuntimeExports.jsx("button", { ref: (el) => buttonsRef.current["table"] = el, onClick: toggleTableForm, className: "rtf dropdown-toggle", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Images, { format: "table", imageColor }) }) }),
2800
- showTableForm && !hiddenButtons.includes("table") && /* @__PURE__ */ jsxRuntimeExports.jsx(
2872
+ showTableForm && !hiddenButtons.includes("table") && dropdownActive === "table" && /* @__PURE__ */ jsxRuntimeExports.jsx(
2801
2873
  TableForm,
2802
2874
  {
2803
2875
  onClose: toggleTableForm
@@ -2805,16 +2877,16 @@ const Toolbar = ({ activeMarks }) => {
2805
2877
  )
2806
2878
  ] }),
2807
2879
  /* @__PURE__ */ jsxRuntimeExports.jsx(
2808
- TableDropdown,
2880
+ TableButtons,
2809
2881
  {
2810
2882
  allButtons,
2811
2883
  hiddenButtons,
2812
2884
  ref: buttonsRef
2813
2885
  }
2814
2886
  ),
2815
- !hiddenButtons.includes("image") && /* @__PURE__ */ jsxRuntimeExports.jsx(Tooltip, { text: allButtons.find((button) => button.format === "image").tooltip, position: "bottom", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ImageForm, { ref: (el) => buttonsRef.current["image"] = el }) }),
2816
- !hiddenButtons.includes("code") && /* @__PURE__ */ jsxRuntimeExports.jsx(Tooltip, { text: allButtons.find((button) => button.format === "code").tooltip, position: "bottom", children: /* @__PURE__ */ jsxRuntimeExports.jsx(LanguageDropdown, { ref: (el) => buttonsRef.current["code"] = el }) }),
2817
- ["undo", "redo"].map((historyAction) => !hiddenButtons.includes(historyAction) && /* @__PURE__ */ jsxRuntimeExports.jsx(Tooltip, { text: allButtons.find((button) => button.format === historyAction).tooltip, position: "bottom", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
2887
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "rtf dropdown tool", style: { display: hiddenButtons.includes("image") ? "none" : "flex", padding: 0 }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Tooltip, { text: allButtons.find((button) => button.format === "image").tooltip, position: "bottom", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ImageForm, { ref: (el) => buttonsRef.current["image"] = el }) }) }),
2888
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "rtf dropdown tool", style: { display: hiddenButtons.includes("code") ? "none" : "flex", padding: 0 }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Tooltip, { text: allButtons.find((button) => button.format === "code").tooltip, position: "bottom", children: /* @__PURE__ */ jsxRuntimeExports.jsx(LanguageDropdown, { ref: (el) => buttonsRef.current["code"] = el }) }) }),
2889
+ ["undo", "redo"].map((historyAction) => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "rtf dropdown tool", style: { display: hiddenButtons.includes(historyAction) ? "none" : "flex", padding: 0 }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Tooltip, { text: allButtons.find((button) => button.format === historyAction).tooltip, position: "bottom", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
2818
2890
  "button",
2819
2891
  {
2820
2892
  ref: (el) => buttonsRef.current[historyAction] = el,
@@ -2833,21 +2905,29 @@ const Toolbar = ({ activeMarks }) => {
2833
2905
  children: /* @__PURE__ */ jsxRuntimeExports.jsx(Images, { format: historyAction, imageColor: editor.history[historyAction + "s"].length === 0 ? `color-mix(in srgb, ${imageColor} 40%, ${isDarkColor(imageColor) ? "white" : "black"})` : imageColor })
2834
2906
  },
2835
2907
  historyAction
2836
- ) }, historyAction)),
2908
+ ) }) }, historyAction)),
2837
2909
  hiddenButtons.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(Tooltip, { text: "Voir plus", position: "bottom", children: /* @__PURE__ */ jsxRuntimeExports.jsx("button", { className: "rtf tool toolbar-more-button", onClick: toggleModal, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Images, { format: "more", imageColor }) }) })
2838
2910
  ] }),
2839
- showModal && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "rtf toolbar-modal", style: { backgroundColor }, onMouseLeave: () => setShowModal(false), children: hiddenButtons.map((format) => {
2911
+ showModal && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "rtf toolbar-modal", ref: modalRef, style: { backgroundColor }, onMouseLeave: () => setShowModal(false), children: hiddenButtons.map((format) => {
2840
2912
  if (format === "image" || format === "code" || format === "table" || format === "deleteTable" || format === "addRow" || format === "addColumn" || format === "deleteRow" || format === "deleteColumn") {
2841
- return format === "image" ? /* @__PURE__ */ jsxRuntimeExports.jsx(ImageForm, { ref: (el) => buttonsRef.current["image"] = el }, format) : format === "code" ? /* @__PURE__ */ jsxRuntimeExports.jsx(LanguageDropdown, { ref: (el) => buttonsRef.current["code"] = el }, format) : format === "table" ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "rtf dropdown tool", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Tooltip, { text: allButtons.find((action) => action.format === format).tooltip, position: "bottom", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
2842
- "button",
2843
- {
2844
- className: "rtf dropdown-toggle",
2845
- ref: (el) => buttonsRef.current[format] = el,
2846
- onClick: toggleTableForm,
2847
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(Images, { format, imageColor })
2848
- }
2849
- ) }, format) }) : tablesActions.includes(format) ? /* @__PURE__ */ jsxRuntimeExports.jsx(
2850
- TableDropdown,
2913
+ return format === "image" ? /* @__PURE__ */ jsxRuntimeExports.jsx(ImageForm, { ref: (el) => buttonsRef.current["image"] = el }, format) : format === "code" ? /* @__PURE__ */ jsxRuntimeExports.jsx(LanguageDropdown, { ref: (el) => buttonsRef.current["code"] = el }, format) : format === "table" ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rtf dropdown tool", children: [
2914
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Tooltip, { text: allButtons.find((action) => action.format === format).tooltip, position: "bottom", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
2915
+ "button",
2916
+ {
2917
+ className: "rtf dropdown-toggle",
2918
+ ref: (el) => buttonsRef.current[format] = el,
2919
+ onClick: toggleTableForm,
2920
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(Images, { format, imageColor })
2921
+ }
2922
+ ) }),
2923
+ showTableForm && dropdownActive === "table" && /* @__PURE__ */ jsxRuntimeExports.jsx(
2924
+ TableForm,
2925
+ {
2926
+ onClose: toggleTableForm
2927
+ }
2928
+ )
2929
+ ] }, format) : tablesActions.includes(format) ? /* @__PURE__ */ jsxRuntimeExports.jsx(
2930
+ TableButtons,
2851
2931
  {
2852
2932
  allButtons,
2853
2933
  hiddenButtons: tablesActions.filter((tablesAction) => tablesAction !== format),