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.
- package/dist/react-text-forge.css +1 -1
- package/dist/react-text-forge.js +215 -135
- package/dist/react-text-forge.umd.cjs +9 -9
- package/dist/src/components/useToolbar.d.ts +2 -1
- package/dist/src/components/utils/CustomEditor.d.ts +140 -128
- package/dist/src/components/utils/dropdown/ContainerDropdown.d.ts +1 -5
- package/dist/src/components/utils/dropdown/{TableDropdown.d.ts → TableButtons.d.ts} +2 -2
- package/dist/src/components/utils/form/BulletTypeSelector.d.ts +3 -3
- package/dist/src/components/utils/form/NumeredTypeSelector.d.ts +3 -3
- package/package.json +1 -1
package/dist/react-text-forge.js
CHANGED
|
@@ -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" },
|
|
407
|
+
return jsx("element", { type: "paragraph" }, validChildren);
|
|
407
408
|
case "PRE":
|
|
408
|
-
return jsx("element", { type: "code" },
|
|
409
|
+
return jsx("element", { type: "code" }, validChildren);
|
|
409
410
|
case "UL":
|
|
410
|
-
return jsx("element", { type: "bullet-list" },
|
|
411
|
+
return jsx("element", { type: "bullet-list" }, validChildren);
|
|
411
412
|
case "OL":
|
|
412
|
-
return jsx("element", { type: "numbered-list" },
|
|
413
|
+
return jsx("element", { type: "numbered-list" }, validChildren);
|
|
413
414
|
case "LI":
|
|
414
|
-
return jsx("element", { type: "list-item" },
|
|
415
|
+
return jsx("element", { type: "list-item" }, validChildren);
|
|
415
416
|
case "H1":
|
|
416
|
-
return jsx("element", { type: "h1" },
|
|
417
|
+
return jsx("element", { type: "h1" }, validChildren);
|
|
417
418
|
case "H2":
|
|
418
|
-
return jsx("element", { type: "h2" },
|
|
419
|
+
return jsx("element", { type: "h2" }, validChildren);
|
|
419
420
|
case "BLOCKQUOTE":
|
|
420
|
-
return jsx("element", { type: "blockquote" },
|
|
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" },
|
|
425
|
+
return jsx("element", { type: "table" }, validChildren);
|
|
425
426
|
case "TR":
|
|
426
|
-
return jsx("element", { type: "table-row" },
|
|
427
|
+
return jsx("element", { type: "table-row" }, validChildren);
|
|
427
428
|
case "TD":
|
|
428
|
-
return jsx("element", { type: "table-cell" },
|
|
429
|
+
return jsx("element", { type: "table-cell" }, validChildren);
|
|
429
430
|
case "A":
|
|
430
|
-
return jsx("element", { type: "link", url: node.getAttribute("href") },
|
|
431
|
+
return jsx("element", { type: "link", url: node.getAttribute("href") }, validChildren);
|
|
431
432
|
default:
|
|
432
|
-
return
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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
|
-
|
|
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,
|
|
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:
|
|
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,
|
|
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:
|
|
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
|
-
|
|
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:
|
|
2032
|
-
children:
|
|
2070
|
+
onClick: toggleDropDown,
|
|
2071
|
+
children: dropdownActive === format ? "↑" : "↓"
|
|
2033
2072
|
}
|
|
2034
2073
|
)
|
|
2035
2074
|
]
|
|
2036
2075
|
}
|
|
2037
2076
|
),
|
|
2038
|
-
|
|
2077
|
+
dropdownActive === "bulletList" && format === "bulletList" && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2039
2078
|
BulletTypeSelector,
|
|
2040
2079
|
{
|
|
2041
2080
|
selectStyle,
|
|
2042
2081
|
onChange: handleBulletTypeChange,
|
|
2043
|
-
|
|
2082
|
+
onClose: () => setDropdownActive(null)
|
|
2044
2083
|
}
|
|
2045
|
-
)
|
|
2084
|
+
),
|
|
2085
|
+
dropdownActive === "numberedList" && format === "numberedList" && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2046
2086
|
NumeredTypeSelector,
|
|
2047
2087
|
{
|
|
2048
2088
|
selectStyle,
|
|
2049
2089
|
onChange: handleBulletTypeChange,
|
|
2050
|
-
|
|
2090
|
+
onClose: () => setDropdownActive(null)
|
|
2051
2091
|
}
|
|
2052
|
-
)
|
|
2092
|
+
)
|
|
2053
2093
|
] });
|
|
2054
2094
|
};
|
|
2055
|
-
function ContainerDropdown({ disabled = false, elements, elementSelected, format,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2258
|
+
setDropdownActive(null);
|
|
2229
2259
|
};
|
|
2230
2260
|
const handleBackgroundColorChange = (color) => {
|
|
2231
2261
|
CustomEditor.applyBackgroundTextColor(editor, color);
|
|
2232
|
-
|
|
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
|
-
|
|
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: () =>
|
|
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
|
-
|
|
2497
|
+
dropdownActive === "href" && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
2462
2498
|
LinkForm,
|
|
2463
2499
|
{
|
|
2464
|
-
onClose: () =>
|
|
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
|
-
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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 = () =>
|
|
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
|
-
|
|
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 += (
|
|
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
|
-
|
|
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
|
-
|
|
2880
|
+
TableButtons,
|
|
2809
2881
|
{
|
|
2810
2882
|
allButtons,
|
|
2811
2883
|
hiddenButtons,
|
|
2812
2884
|
ref: buttonsRef
|
|
2813
2885
|
}
|
|
2814
2886
|
),
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
["undo", "redo"].map((historyAction) =>
|
|
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.
|
|
2842
|
-
"
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
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),
|