@cgi-learning-hub/ui 1.15.0-dev.1788516152 → 1.15.0-dev.1788530642
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/tiptap/index.cjs.js +182 -16
- package/dist/tiptap/index.es.js +182 -16
- package/package.json +1 -1
package/dist/tiptap/index.cjs.js
CHANGED
|
@@ -609,7 +609,7 @@ var CODE_BLOCK_SHORTCUT_KEY = "mod+alt+c";
|
|
|
609
609
|
/**
|
|
610
610
|
* Checks if code block can be toggled in the current editor state
|
|
611
611
|
*/
|
|
612
|
-
function canToggle$
|
|
612
|
+
function canToggle$2(editor, turnInto = true) {
|
|
613
613
|
if (!editor || !editor.isEditable) return false;
|
|
614
614
|
if (!isNodeInSchema("codeBlock", editor) || isNodeTypeSelected(editor, ["image"])) return false;
|
|
615
615
|
if (!turnInto) return editor.can().toggleNode("codeBlock", "paragraph");
|
|
@@ -629,7 +629,7 @@ function canToggle$1(editor, turnInto = true) {
|
|
|
629
629
|
*/
|
|
630
630
|
function toggleCodeBlock(editor) {
|
|
631
631
|
if (!editor || !editor.isEditable) return false;
|
|
632
|
-
if (!canToggle$
|
|
632
|
+
if (!canToggle$2(editor)) return false;
|
|
633
633
|
try {
|
|
634
634
|
const view = editor.view;
|
|
635
635
|
let state = view.state;
|
|
@@ -681,7 +681,7 @@ function shouldShowButton$4(props) {
|
|
|
681
681
|
if (!hideWhenUnavailable) return true;
|
|
682
682
|
if (!editor.isEditable) return false;
|
|
683
683
|
if (!isNodeInSchema("codeBlock", editor)) return false;
|
|
684
|
-
if (!editor.isActive("code")) return canToggle$
|
|
684
|
+
if (!editor.isActive("code")) return canToggle$2(editor);
|
|
685
685
|
return true;
|
|
686
686
|
}
|
|
687
687
|
/**
|
|
@@ -731,7 +731,7 @@ function useCodeBlock(config) {
|
|
|
731
731
|
const { editor: providedEditor, hideWhenUnavailable = false, onToggled } = config || {};
|
|
732
732
|
const { editor } = useTiptapEditor(providedEditor);
|
|
733
733
|
const [isVisible, setIsVisible] = (0, react.useState)(true);
|
|
734
|
-
const canToggleState = canToggle$
|
|
734
|
+
const canToggleState = canToggle$2(editor);
|
|
735
735
|
const isActive = editor?.isActive("codeBlock") || false;
|
|
736
736
|
(0, react.useEffect)(() => {
|
|
737
737
|
if (!editor) return;
|
|
@@ -897,7 +897,7 @@ var HEADING_SHORTCUT_KEYS = {
|
|
|
897
897
|
/**
|
|
898
898
|
* Checks if heading can be toggled in the current editor state
|
|
899
899
|
*/
|
|
900
|
-
function canToggle(editor, level, turnInto = true) {
|
|
900
|
+
function canToggle$1(editor, level, turnInto = true) {
|
|
901
901
|
if (!editor || !editor.isEditable) return false;
|
|
902
902
|
if (!isNodeInSchema("heading", editor) || isNodeTypeSelected(editor, ["image"])) return false;
|
|
903
903
|
if (!turnInto) return level ? editor.can().setNode("heading", { level }) : editor.can().setNode("heading");
|
|
@@ -926,7 +926,7 @@ function isHeadingActive(editor, level) {
|
|
|
926
926
|
function toggleHeading(editor, level) {
|
|
927
927
|
if (!editor || !editor.isEditable) return false;
|
|
928
928
|
const levels = Array.isArray(level) ? level : [level];
|
|
929
|
-
const toggleLevel = levels.find((l) => canToggle(editor, l));
|
|
929
|
+
const toggleLevel = levels.find((l) => canToggle$1(editor, l));
|
|
930
930
|
if (!toggleLevel) return false;
|
|
931
931
|
try {
|
|
932
932
|
const view = editor.view;
|
|
@@ -973,15 +973,15 @@ function toggleHeading(editor, level) {
|
|
|
973
973
|
/**
|
|
974
974
|
* Determines if the heading menu item should be shown
|
|
975
975
|
*/
|
|
976
|
-
function shouldShowItem(props) {
|
|
976
|
+
function shouldShowItem$1(props) {
|
|
977
977
|
const { editor, level, hideWhenUnavailable } = props;
|
|
978
978
|
if (!editor) return false;
|
|
979
979
|
if (!hideWhenUnavailable) return true;
|
|
980
980
|
if (!editor.isEditable) return false;
|
|
981
981
|
if (!isNodeInSchema("heading", editor)) return false;
|
|
982
982
|
if (!editor.isActive("code")) {
|
|
983
|
-
if (Array.isArray(level)) return level.some((l) => canToggle(editor, l));
|
|
984
|
-
return canToggle(editor, level);
|
|
983
|
+
if (Array.isArray(level)) return level.some((l) => canToggle$1(editor, l));
|
|
984
|
+
return canToggle$1(editor, level);
|
|
985
985
|
}
|
|
986
986
|
return true;
|
|
987
987
|
}
|
|
@@ -1035,12 +1035,12 @@ function useHeading(config) {
|
|
|
1035
1035
|
const { editor: providedEditor, level, hideWhenUnavailable = false, onToggled } = config;
|
|
1036
1036
|
const { editor } = useTiptapEditor(providedEditor);
|
|
1037
1037
|
const [isVisible, setIsVisible] = (0, react.useState)(true);
|
|
1038
|
-
const canToggleState = canToggle(editor, level);
|
|
1038
|
+
const canToggleState = canToggle$1(editor, level);
|
|
1039
1039
|
const isActive = isHeadingActive(editor, level);
|
|
1040
1040
|
(0, react.useEffect)(() => {
|
|
1041
1041
|
if (!editor) return;
|
|
1042
1042
|
const handleSelectionUpdate = () => {
|
|
1043
|
-
setIsVisible(shouldShowItem({
|
|
1043
|
+
setIsVisible(shouldShowItem$1({
|
|
1044
1044
|
editor,
|
|
1045
1045
|
level,
|
|
1046
1046
|
hideWhenUnavailable
|
|
@@ -1129,6 +1129,169 @@ var HeadingMenuItem = (0, react.forwardRef)(({ editor: providedEditor, level, te
|
|
|
1129
1129
|
});
|
|
1130
1130
|
HeadingMenuItem.displayName = "HeadingMenuItem";
|
|
1131
1131
|
//#endregion
|
|
1132
|
+
//#region src/tiptap/components/ui/paragraph-menu-item/use-paragraph.ts
|
|
1133
|
+
/**
|
|
1134
|
+
* Checks if paragraph can be toggled in the current editor state
|
|
1135
|
+
*/
|
|
1136
|
+
function canToggle(editor, turnInto = true) {
|
|
1137
|
+
if (!editor || !editor.isEditable) return false;
|
|
1138
|
+
if (!isNodeInSchema("paragraph", editor) || isNodeTypeSelected(editor, ["image"])) return false;
|
|
1139
|
+
if (!turnInto) return editor.can().setNode("paragraph");
|
|
1140
|
+
if (!selectionWithinConvertibleTypes(editor, [
|
|
1141
|
+
"paragraph",
|
|
1142
|
+
"heading",
|
|
1143
|
+
"bulletList",
|
|
1144
|
+
"orderedList",
|
|
1145
|
+
"taskList",
|
|
1146
|
+
"blockquote",
|
|
1147
|
+
"codeBlock"
|
|
1148
|
+
])) return false;
|
|
1149
|
+
return editor.can().setNode("paragraph") || editor.can().clearNodes();
|
|
1150
|
+
}
|
|
1151
|
+
/**
|
|
1152
|
+
* Checks if paragraph is currently active
|
|
1153
|
+
*/
|
|
1154
|
+
function isParagraphActive(editor) {
|
|
1155
|
+
if (!editor || !editor.isEditable) return false;
|
|
1156
|
+
return editor.isActive("paragraph");
|
|
1157
|
+
}
|
|
1158
|
+
/**
|
|
1159
|
+
* Toggles paragraph in the editor
|
|
1160
|
+
*/
|
|
1161
|
+
function toggleParagraph(editor) {
|
|
1162
|
+
if (!editor || !editor.isEditable || !canToggle(editor)) return false;
|
|
1163
|
+
try {
|
|
1164
|
+
const view = editor.view;
|
|
1165
|
+
let state = view.state;
|
|
1166
|
+
let tr = state.tr;
|
|
1167
|
+
const blocks = getSelectedBlockNodes(editor);
|
|
1168
|
+
const isPossibleToTurnInto = selectionWithinConvertibleTypes(editor, [
|
|
1169
|
+
"paragraph",
|
|
1170
|
+
"heading",
|
|
1171
|
+
"bulletList",
|
|
1172
|
+
"orderedList",
|
|
1173
|
+
"taskList",
|
|
1174
|
+
"blockquote",
|
|
1175
|
+
"codeBlock"
|
|
1176
|
+
]) && blocks.length === 1;
|
|
1177
|
+
if ((state.selection.empty || state.selection instanceof _tiptap_pm_state.TextSelection) && isPossibleToTurnInto) {
|
|
1178
|
+
const pos = findNodePosition({
|
|
1179
|
+
editor,
|
|
1180
|
+
node: state.selection.$anchor.node(1)
|
|
1181
|
+
})?.pos;
|
|
1182
|
+
if (!isValidPosition(pos)) return false;
|
|
1183
|
+
tr = tr.setSelection(_tiptap_pm_state.NodeSelection.create(state.doc, pos));
|
|
1184
|
+
view.dispatch(tr);
|
|
1185
|
+
state = view.state;
|
|
1186
|
+
}
|
|
1187
|
+
const selection = state.selection;
|
|
1188
|
+
let chain = editor.chain().focus();
|
|
1189
|
+
if (selection instanceof _tiptap_pm_state.NodeSelection) {
|
|
1190
|
+
const firstChild = selection.node.firstChild?.firstChild;
|
|
1191
|
+
const lastChild = selection.node.lastChild?.lastChild;
|
|
1192
|
+
const from = firstChild ? selection.from + firstChild.nodeSize : selection.from + 1;
|
|
1193
|
+
const to = lastChild ? selection.to - lastChild.nodeSize : selection.to - 1;
|
|
1194
|
+
const resolvedFrom = state.doc.resolve(from);
|
|
1195
|
+
const resolvedTo = state.doc.resolve(to);
|
|
1196
|
+
chain = chain.setTextSelection(_tiptap_pm_state.TextSelection.between(resolvedFrom, resolvedTo)).clearNodes();
|
|
1197
|
+
}
|
|
1198
|
+
chain.setNode("paragraph").run();
|
|
1199
|
+
editor.chain().focus().selectTextblockEnd().run();
|
|
1200
|
+
return true;
|
|
1201
|
+
} catch {
|
|
1202
|
+
return false;
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
/**
|
|
1206
|
+
* Determines if the paragraph menu item should be shown
|
|
1207
|
+
*/
|
|
1208
|
+
function shouldShowItem(props) {
|
|
1209
|
+
const { editor, hideWhenUnavailable } = props;
|
|
1210
|
+
if (!editor) return false;
|
|
1211
|
+
if (!hideWhenUnavailable) return true;
|
|
1212
|
+
if (!editor.isEditable) return false;
|
|
1213
|
+
if (!isNodeInSchema("paragraph", editor)) return false;
|
|
1214
|
+
if (!editor.isActive("code")) return canToggle(editor);
|
|
1215
|
+
return true;
|
|
1216
|
+
}
|
|
1217
|
+
/**
|
|
1218
|
+
* Custom hook that provides paragraph functionality for Tiptap editor
|
|
1219
|
+
*/
|
|
1220
|
+
function useParagraph(config) {
|
|
1221
|
+
const { editor: providedEditor, hideWhenUnavailable = false, onToggled } = config;
|
|
1222
|
+
const { editor } = useTiptapEditor(providedEditor);
|
|
1223
|
+
const [isVisible, setIsVisible] = (0, react.useState)(true);
|
|
1224
|
+
const canToggleState = canToggle(editor);
|
|
1225
|
+
const isActive = isParagraphActive(editor);
|
|
1226
|
+
(0, react.useEffect)(() => {
|
|
1227
|
+
if (!editor) return;
|
|
1228
|
+
const handleSelectionUpdate = () => {
|
|
1229
|
+
setIsVisible(shouldShowItem({
|
|
1230
|
+
editor,
|
|
1231
|
+
hideWhenUnavailable
|
|
1232
|
+
}));
|
|
1233
|
+
};
|
|
1234
|
+
handleSelectionUpdate();
|
|
1235
|
+
editor.on("selectionUpdate", handleSelectionUpdate);
|
|
1236
|
+
return () => {
|
|
1237
|
+
editor.off("selectionUpdate", handleSelectionUpdate);
|
|
1238
|
+
};
|
|
1239
|
+
}, [editor, hideWhenUnavailable]);
|
|
1240
|
+
return {
|
|
1241
|
+
isVisible,
|
|
1242
|
+
isActive,
|
|
1243
|
+
handleToggle: (0, react.useCallback)(() => {
|
|
1244
|
+
if (!editor) return false;
|
|
1245
|
+
const success = toggleParagraph(editor);
|
|
1246
|
+
if (success) onToggled?.();
|
|
1247
|
+
return success;
|
|
1248
|
+
}, [editor, onToggled]),
|
|
1249
|
+
canToggle: canToggleState,
|
|
1250
|
+
label: "Paragraphe"
|
|
1251
|
+
};
|
|
1252
|
+
}
|
|
1253
|
+
//#endregion
|
|
1254
|
+
//#region src/tiptap/components/ui/paragraph-menu-item/paragraph-menu-item.tsx
|
|
1255
|
+
/**
|
|
1256
|
+
* Menu item component for toggling paragraph in a Tiptap editor.
|
|
1257
|
+
*
|
|
1258
|
+
* For custom menu item implementations, use the `useParagraph` hook instead.
|
|
1259
|
+
*/
|
|
1260
|
+
var ParagraphMenuItem = (0, react.forwardRef)(({ editor: providedEditor, text, hideWhenUnavailable = false, onToggled, showShortcut = false, onClick, children, ...menuItemProps }, ref) => {
|
|
1261
|
+
const { editor } = useTiptapEditor(providedEditor);
|
|
1262
|
+
const { isVisible, canToggle, isActive, handleToggle, label } = useParagraph({
|
|
1263
|
+
editor,
|
|
1264
|
+
hideWhenUnavailable,
|
|
1265
|
+
onToggled
|
|
1266
|
+
});
|
|
1267
|
+
const handleClick = (0, react.useCallback)((event) => {
|
|
1268
|
+
onClick?.(event);
|
|
1269
|
+
if (event.defaultPrevented) return;
|
|
1270
|
+
handleToggle();
|
|
1271
|
+
}, [handleToggle, onClick]);
|
|
1272
|
+
if (!isVisible) return null;
|
|
1273
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_mui_material_MenuItem.default, {
|
|
1274
|
+
component: "li",
|
|
1275
|
+
role: "button",
|
|
1276
|
+
tabIndex: -1,
|
|
1277
|
+
disabled: !canToggle,
|
|
1278
|
+
"data-disabled": !canToggle,
|
|
1279
|
+
"aria-label": label,
|
|
1280
|
+
"aria-pressed": isActive,
|
|
1281
|
+
tooltip: label,
|
|
1282
|
+
selected: isActive,
|
|
1283
|
+
onClick: handleClick,
|
|
1284
|
+
...menuItemProps,
|
|
1285
|
+
ref,
|
|
1286
|
+
children: children ?? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [label && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_mui_material_Typography.default, {
|
|
1287
|
+
component: "span",
|
|
1288
|
+
variant: "body2",
|
|
1289
|
+
children: label
|
|
1290
|
+
}), showShortcut && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_mui_material_Badge.default, { children: parseShortcutKeys({ shortcutKeys: "ctrl+alt+p" }) })] })
|
|
1291
|
+
});
|
|
1292
|
+
});
|
|
1293
|
+
ParagraphMenuItem.displayName = "ParagraphMenuItem";
|
|
1294
|
+
//#endregion
|
|
1132
1295
|
//#region src/tiptap/components/icons/heading-icon.tsx
|
|
1133
1296
|
var HeadingIcon = (0, _mui_material_utils.createSvgIcon)(/* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1134
1297
|
d: "M6 3C6.55228 3 7 3.44772 7 4V11H17V4C17 3.44772 17.4477 3 18 3C18.5523 3 19 3.44772 19 4V20C19 20.5523 18.5523 21 18 21C17.4477 21 17 20.5523 17 20V13H7V20C7 20.5523 6.55228 21 6 21C5.44772 21 5 20.5523 5 20V4C5 3.44772 5.44772 3 6 3Z",
|
|
@@ -1202,11 +1365,11 @@ function useHeadingMenu(config) {
|
|
|
1202
1365
|
const [isVisible, setIsVisible] = (0, react.useState)(true);
|
|
1203
1366
|
const activeLevel = getActiveHeadingLevel(editor, levels);
|
|
1204
1367
|
const isActive = isHeadingActive(editor);
|
|
1205
|
-
const canToggleState = canToggle(editor);
|
|
1368
|
+
const canToggleState = canToggle$1(editor);
|
|
1206
1369
|
(0, react.useEffect)(() => {
|
|
1207
1370
|
if (!editor) return;
|
|
1208
1371
|
const handleSelectionUpdate = () => {
|
|
1209
|
-
setIsVisible(shouldShowItem({
|
|
1372
|
+
setIsVisible(shouldShowItem$1({
|
|
1210
1373
|
editor,
|
|
1211
1374
|
hideWhenUnavailable,
|
|
1212
1375
|
level: levels
|
|
@@ -1286,7 +1449,7 @@ var HeadingMenu = (0, react.forwardRef)(({ editor: providedEditor, levels = [
|
|
|
1286
1449
|
...buttonProps,
|
|
1287
1450
|
ref,
|
|
1288
1451
|
children: children ? children : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { fontSize: "small" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExpandMoreRounded_default, { sx: { fontSize: "0.75rem" } })] })
|
|
1289
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.
|
|
1452
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_mui_material_Menu.default, {
|
|
1290
1453
|
id: "heading-menu",
|
|
1291
1454
|
anchorEl,
|
|
1292
1455
|
open,
|
|
@@ -1295,12 +1458,15 @@ var HeadingMenu = (0, react.forwardRef)(({ editor: providedEditor, levels = [
|
|
|
1295
1458
|
"aria-labelledby": "heading-button",
|
|
1296
1459
|
role: "listbox"
|
|
1297
1460
|
} },
|
|
1298
|
-
children:
|
|
1461
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ParagraphMenuItem, {
|
|
1462
|
+
editor,
|
|
1463
|
+
onClick: handleClose
|
|
1464
|
+
}), levels.map((level) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HeadingMenuItem, {
|
|
1299
1465
|
editor,
|
|
1300
1466
|
level,
|
|
1301
1467
|
text: `Heading ${level}`,
|
|
1302
1468
|
onClick: handleClose
|
|
1303
|
-
}, `heading-${level}`))
|
|
1469
|
+
}, `heading-${level}`))]
|
|
1304
1470
|
})] });
|
|
1305
1471
|
});
|
|
1306
1472
|
HeadingMenu.displayName = "HeadingMenu";
|
package/dist/tiptap/index.es.js
CHANGED
|
@@ -585,7 +585,7 @@ var CODE_BLOCK_SHORTCUT_KEY = "mod+alt+c";
|
|
|
585
585
|
/**
|
|
586
586
|
* Checks if code block can be toggled in the current editor state
|
|
587
587
|
*/
|
|
588
|
-
function canToggle$
|
|
588
|
+
function canToggle$2(editor, turnInto = true) {
|
|
589
589
|
if (!editor || !editor.isEditable) return false;
|
|
590
590
|
if (!isNodeInSchema("codeBlock", editor) || isNodeTypeSelected(editor, ["image"])) return false;
|
|
591
591
|
if (!turnInto) return editor.can().toggleNode("codeBlock", "paragraph");
|
|
@@ -605,7 +605,7 @@ function canToggle$1(editor, turnInto = true) {
|
|
|
605
605
|
*/
|
|
606
606
|
function toggleCodeBlock(editor) {
|
|
607
607
|
if (!editor || !editor.isEditable) return false;
|
|
608
|
-
if (!canToggle$
|
|
608
|
+
if (!canToggle$2(editor)) return false;
|
|
609
609
|
try {
|
|
610
610
|
const view = editor.view;
|
|
611
611
|
let state = view.state;
|
|
@@ -657,7 +657,7 @@ function shouldShowButton$4(props) {
|
|
|
657
657
|
if (!hideWhenUnavailable) return true;
|
|
658
658
|
if (!editor.isEditable) return false;
|
|
659
659
|
if (!isNodeInSchema("codeBlock", editor)) return false;
|
|
660
|
-
if (!editor.isActive("code")) return canToggle$
|
|
660
|
+
if (!editor.isActive("code")) return canToggle$2(editor);
|
|
661
661
|
return true;
|
|
662
662
|
}
|
|
663
663
|
/**
|
|
@@ -707,7 +707,7 @@ function useCodeBlock(config) {
|
|
|
707
707
|
const { editor: providedEditor, hideWhenUnavailable = false, onToggled } = config || {};
|
|
708
708
|
const { editor } = useTiptapEditor(providedEditor);
|
|
709
709
|
const [isVisible, setIsVisible] = useState(true);
|
|
710
|
-
const canToggleState = canToggle$
|
|
710
|
+
const canToggleState = canToggle$2(editor);
|
|
711
711
|
const isActive = editor?.isActive("codeBlock") || false;
|
|
712
712
|
useEffect(() => {
|
|
713
713
|
if (!editor) return;
|
|
@@ -873,7 +873,7 @@ var HEADING_SHORTCUT_KEYS = {
|
|
|
873
873
|
/**
|
|
874
874
|
* Checks if heading can be toggled in the current editor state
|
|
875
875
|
*/
|
|
876
|
-
function canToggle(editor, level, turnInto = true) {
|
|
876
|
+
function canToggle$1(editor, level, turnInto = true) {
|
|
877
877
|
if (!editor || !editor.isEditable) return false;
|
|
878
878
|
if (!isNodeInSchema("heading", editor) || isNodeTypeSelected(editor, ["image"])) return false;
|
|
879
879
|
if (!turnInto) return level ? editor.can().setNode("heading", { level }) : editor.can().setNode("heading");
|
|
@@ -902,7 +902,7 @@ function isHeadingActive(editor, level) {
|
|
|
902
902
|
function toggleHeading(editor, level) {
|
|
903
903
|
if (!editor || !editor.isEditable) return false;
|
|
904
904
|
const levels = Array.isArray(level) ? level : [level];
|
|
905
|
-
const toggleLevel = levels.find((l) => canToggle(editor, l));
|
|
905
|
+
const toggleLevel = levels.find((l) => canToggle$1(editor, l));
|
|
906
906
|
if (!toggleLevel) return false;
|
|
907
907
|
try {
|
|
908
908
|
const view = editor.view;
|
|
@@ -949,15 +949,15 @@ function toggleHeading(editor, level) {
|
|
|
949
949
|
/**
|
|
950
950
|
* Determines if the heading menu item should be shown
|
|
951
951
|
*/
|
|
952
|
-
function shouldShowItem(props) {
|
|
952
|
+
function shouldShowItem$1(props) {
|
|
953
953
|
const { editor, level, hideWhenUnavailable } = props;
|
|
954
954
|
if (!editor) return false;
|
|
955
955
|
if (!hideWhenUnavailable) return true;
|
|
956
956
|
if (!editor.isEditable) return false;
|
|
957
957
|
if (!isNodeInSchema("heading", editor)) return false;
|
|
958
958
|
if (!editor.isActive("code")) {
|
|
959
|
-
if (Array.isArray(level)) return level.some((l) => canToggle(editor, l));
|
|
960
|
-
return canToggle(editor, level);
|
|
959
|
+
if (Array.isArray(level)) return level.some((l) => canToggle$1(editor, l));
|
|
960
|
+
return canToggle$1(editor, level);
|
|
961
961
|
}
|
|
962
962
|
return true;
|
|
963
963
|
}
|
|
@@ -1011,12 +1011,12 @@ function useHeading(config) {
|
|
|
1011
1011
|
const { editor: providedEditor, level, hideWhenUnavailable = false, onToggled } = config;
|
|
1012
1012
|
const { editor } = useTiptapEditor(providedEditor);
|
|
1013
1013
|
const [isVisible, setIsVisible] = useState(true);
|
|
1014
|
-
const canToggleState = canToggle(editor, level);
|
|
1014
|
+
const canToggleState = canToggle$1(editor, level);
|
|
1015
1015
|
const isActive = isHeadingActive(editor, level);
|
|
1016
1016
|
useEffect(() => {
|
|
1017
1017
|
if (!editor) return;
|
|
1018
1018
|
const handleSelectionUpdate = () => {
|
|
1019
|
-
setIsVisible(shouldShowItem({
|
|
1019
|
+
setIsVisible(shouldShowItem$1({
|
|
1020
1020
|
editor,
|
|
1021
1021
|
level,
|
|
1022
1022
|
hideWhenUnavailable
|
|
@@ -1105,6 +1105,169 @@ var HeadingMenuItem = forwardRef(({ editor: providedEditor, level, text, hideWhe
|
|
|
1105
1105
|
});
|
|
1106
1106
|
HeadingMenuItem.displayName = "HeadingMenuItem";
|
|
1107
1107
|
//#endregion
|
|
1108
|
+
//#region src/tiptap/components/ui/paragraph-menu-item/use-paragraph.ts
|
|
1109
|
+
/**
|
|
1110
|
+
* Checks if paragraph can be toggled in the current editor state
|
|
1111
|
+
*/
|
|
1112
|
+
function canToggle(editor, turnInto = true) {
|
|
1113
|
+
if (!editor || !editor.isEditable) return false;
|
|
1114
|
+
if (!isNodeInSchema("paragraph", editor) || isNodeTypeSelected(editor, ["image"])) return false;
|
|
1115
|
+
if (!turnInto) return editor.can().setNode("paragraph");
|
|
1116
|
+
if (!selectionWithinConvertibleTypes(editor, [
|
|
1117
|
+
"paragraph",
|
|
1118
|
+
"heading",
|
|
1119
|
+
"bulletList",
|
|
1120
|
+
"orderedList",
|
|
1121
|
+
"taskList",
|
|
1122
|
+
"blockquote",
|
|
1123
|
+
"codeBlock"
|
|
1124
|
+
])) return false;
|
|
1125
|
+
return editor.can().setNode("paragraph") || editor.can().clearNodes();
|
|
1126
|
+
}
|
|
1127
|
+
/**
|
|
1128
|
+
* Checks if paragraph is currently active
|
|
1129
|
+
*/
|
|
1130
|
+
function isParagraphActive(editor) {
|
|
1131
|
+
if (!editor || !editor.isEditable) return false;
|
|
1132
|
+
return editor.isActive("paragraph");
|
|
1133
|
+
}
|
|
1134
|
+
/**
|
|
1135
|
+
* Toggles paragraph in the editor
|
|
1136
|
+
*/
|
|
1137
|
+
function toggleParagraph(editor) {
|
|
1138
|
+
if (!editor || !editor.isEditable || !canToggle(editor)) return false;
|
|
1139
|
+
try {
|
|
1140
|
+
const view = editor.view;
|
|
1141
|
+
let state = view.state;
|
|
1142
|
+
let tr = state.tr;
|
|
1143
|
+
const blocks = getSelectedBlockNodes(editor);
|
|
1144
|
+
const isPossibleToTurnInto = selectionWithinConvertibleTypes(editor, [
|
|
1145
|
+
"paragraph",
|
|
1146
|
+
"heading",
|
|
1147
|
+
"bulletList",
|
|
1148
|
+
"orderedList",
|
|
1149
|
+
"taskList",
|
|
1150
|
+
"blockquote",
|
|
1151
|
+
"codeBlock"
|
|
1152
|
+
]) && blocks.length === 1;
|
|
1153
|
+
if ((state.selection.empty || state.selection instanceof TextSelection) && isPossibleToTurnInto) {
|
|
1154
|
+
const pos = findNodePosition({
|
|
1155
|
+
editor,
|
|
1156
|
+
node: state.selection.$anchor.node(1)
|
|
1157
|
+
})?.pos;
|
|
1158
|
+
if (!isValidPosition(pos)) return false;
|
|
1159
|
+
tr = tr.setSelection(NodeSelection.create(state.doc, pos));
|
|
1160
|
+
view.dispatch(tr);
|
|
1161
|
+
state = view.state;
|
|
1162
|
+
}
|
|
1163
|
+
const selection = state.selection;
|
|
1164
|
+
let chain = editor.chain().focus();
|
|
1165
|
+
if (selection instanceof NodeSelection) {
|
|
1166
|
+
const firstChild = selection.node.firstChild?.firstChild;
|
|
1167
|
+
const lastChild = selection.node.lastChild?.lastChild;
|
|
1168
|
+
const from = firstChild ? selection.from + firstChild.nodeSize : selection.from + 1;
|
|
1169
|
+
const to = lastChild ? selection.to - lastChild.nodeSize : selection.to - 1;
|
|
1170
|
+
const resolvedFrom = state.doc.resolve(from);
|
|
1171
|
+
const resolvedTo = state.doc.resolve(to);
|
|
1172
|
+
chain = chain.setTextSelection(TextSelection.between(resolvedFrom, resolvedTo)).clearNodes();
|
|
1173
|
+
}
|
|
1174
|
+
chain.setNode("paragraph").run();
|
|
1175
|
+
editor.chain().focus().selectTextblockEnd().run();
|
|
1176
|
+
return true;
|
|
1177
|
+
} catch {
|
|
1178
|
+
return false;
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
/**
|
|
1182
|
+
* Determines if the paragraph menu item should be shown
|
|
1183
|
+
*/
|
|
1184
|
+
function shouldShowItem(props) {
|
|
1185
|
+
const { editor, hideWhenUnavailable } = props;
|
|
1186
|
+
if (!editor) return false;
|
|
1187
|
+
if (!hideWhenUnavailable) return true;
|
|
1188
|
+
if (!editor.isEditable) return false;
|
|
1189
|
+
if (!isNodeInSchema("paragraph", editor)) return false;
|
|
1190
|
+
if (!editor.isActive("code")) return canToggle(editor);
|
|
1191
|
+
return true;
|
|
1192
|
+
}
|
|
1193
|
+
/**
|
|
1194
|
+
* Custom hook that provides paragraph functionality for Tiptap editor
|
|
1195
|
+
*/
|
|
1196
|
+
function useParagraph(config) {
|
|
1197
|
+
const { editor: providedEditor, hideWhenUnavailable = false, onToggled } = config;
|
|
1198
|
+
const { editor } = useTiptapEditor(providedEditor);
|
|
1199
|
+
const [isVisible, setIsVisible] = useState(true);
|
|
1200
|
+
const canToggleState = canToggle(editor);
|
|
1201
|
+
const isActive = isParagraphActive(editor);
|
|
1202
|
+
useEffect(() => {
|
|
1203
|
+
if (!editor) return;
|
|
1204
|
+
const handleSelectionUpdate = () => {
|
|
1205
|
+
setIsVisible(shouldShowItem({
|
|
1206
|
+
editor,
|
|
1207
|
+
hideWhenUnavailable
|
|
1208
|
+
}));
|
|
1209
|
+
};
|
|
1210
|
+
handleSelectionUpdate();
|
|
1211
|
+
editor.on("selectionUpdate", handleSelectionUpdate);
|
|
1212
|
+
return () => {
|
|
1213
|
+
editor.off("selectionUpdate", handleSelectionUpdate);
|
|
1214
|
+
};
|
|
1215
|
+
}, [editor, hideWhenUnavailable]);
|
|
1216
|
+
return {
|
|
1217
|
+
isVisible,
|
|
1218
|
+
isActive,
|
|
1219
|
+
handleToggle: useCallback(() => {
|
|
1220
|
+
if (!editor) return false;
|
|
1221
|
+
const success = toggleParagraph(editor);
|
|
1222
|
+
if (success) onToggled?.();
|
|
1223
|
+
return success;
|
|
1224
|
+
}, [editor, onToggled]),
|
|
1225
|
+
canToggle: canToggleState,
|
|
1226
|
+
label: "Paragraphe"
|
|
1227
|
+
};
|
|
1228
|
+
}
|
|
1229
|
+
//#endregion
|
|
1230
|
+
//#region src/tiptap/components/ui/paragraph-menu-item/paragraph-menu-item.tsx
|
|
1231
|
+
/**
|
|
1232
|
+
* Menu item component for toggling paragraph in a Tiptap editor.
|
|
1233
|
+
*
|
|
1234
|
+
* For custom menu item implementations, use the `useParagraph` hook instead.
|
|
1235
|
+
*/
|
|
1236
|
+
var ParagraphMenuItem = forwardRef(({ editor: providedEditor, text, hideWhenUnavailable = false, onToggled, showShortcut = false, onClick, children, ...menuItemProps }, ref) => {
|
|
1237
|
+
const { editor } = useTiptapEditor(providedEditor);
|
|
1238
|
+
const { isVisible, canToggle, isActive, handleToggle, label } = useParagraph({
|
|
1239
|
+
editor,
|
|
1240
|
+
hideWhenUnavailable,
|
|
1241
|
+
onToggled
|
|
1242
|
+
});
|
|
1243
|
+
const handleClick = useCallback((event) => {
|
|
1244
|
+
onClick?.(event);
|
|
1245
|
+
if (event.defaultPrevented) return;
|
|
1246
|
+
handleToggle();
|
|
1247
|
+
}, [handleToggle, onClick]);
|
|
1248
|
+
if (!isVisible) return null;
|
|
1249
|
+
return /* @__PURE__ */ jsx(MenuItem, {
|
|
1250
|
+
component: "li",
|
|
1251
|
+
role: "button",
|
|
1252
|
+
tabIndex: -1,
|
|
1253
|
+
disabled: !canToggle,
|
|
1254
|
+
"data-disabled": !canToggle,
|
|
1255
|
+
"aria-label": label,
|
|
1256
|
+
"aria-pressed": isActive,
|
|
1257
|
+
tooltip: label,
|
|
1258
|
+
selected: isActive,
|
|
1259
|
+
onClick: handleClick,
|
|
1260
|
+
...menuItemProps,
|
|
1261
|
+
ref,
|
|
1262
|
+
children: children ?? /* @__PURE__ */ jsxs(Fragment$1, { children: [label && /* @__PURE__ */ jsx(Typography, {
|
|
1263
|
+
component: "span",
|
|
1264
|
+
variant: "body2",
|
|
1265
|
+
children: label
|
|
1266
|
+
}), showShortcut && /* @__PURE__ */ jsx(Badge, { children: parseShortcutKeys({ shortcutKeys: "ctrl+alt+p" }) })] })
|
|
1267
|
+
});
|
|
1268
|
+
});
|
|
1269
|
+
ParagraphMenuItem.displayName = "ParagraphMenuItem";
|
|
1270
|
+
//#endregion
|
|
1108
1271
|
//#region src/tiptap/components/icons/heading-icon.tsx
|
|
1109
1272
|
var HeadingIcon = createSvgIcon(/* @__PURE__ */ jsx("path", {
|
|
1110
1273
|
d: "M6 3C6.55228 3 7 3.44772 7 4V11H17V4C17 3.44772 17.4477 3 18 3C18.5523 3 19 3.44772 19 4V20C19 20.5523 18.5523 21 18 21C17.4477 21 17 20.5523 17 20V13H7V20C7 20.5523 6.55228 21 6 21C5.44772 21 5 20.5523 5 20V4C5 3.44772 5.44772 3 6 3Z",
|
|
@@ -1178,11 +1341,11 @@ function useHeadingMenu(config) {
|
|
|
1178
1341
|
const [isVisible, setIsVisible] = useState(true);
|
|
1179
1342
|
const activeLevel = getActiveHeadingLevel(editor, levels);
|
|
1180
1343
|
const isActive = isHeadingActive(editor);
|
|
1181
|
-
const canToggleState = canToggle(editor);
|
|
1344
|
+
const canToggleState = canToggle$1(editor);
|
|
1182
1345
|
useEffect(() => {
|
|
1183
1346
|
if (!editor) return;
|
|
1184
1347
|
const handleSelectionUpdate = () => {
|
|
1185
|
-
setIsVisible(shouldShowItem({
|
|
1348
|
+
setIsVisible(shouldShowItem$1({
|
|
1186
1349
|
editor,
|
|
1187
1350
|
hideWhenUnavailable,
|
|
1188
1351
|
level: levels
|
|
@@ -1262,7 +1425,7 @@ var HeadingMenu = forwardRef(({ editor: providedEditor, levels = [
|
|
|
1262
1425
|
...buttonProps,
|
|
1263
1426
|
ref,
|
|
1264
1427
|
children: children ? children : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Icon, { fontSize: "small" }), /* @__PURE__ */ jsx(ExpandMoreRounded_default, { sx: { fontSize: "0.75rem" } })] })
|
|
1265
|
-
}), /* @__PURE__ */
|
|
1428
|
+
}), /* @__PURE__ */ jsxs(Menu, {
|
|
1266
1429
|
id: "heading-menu",
|
|
1267
1430
|
anchorEl,
|
|
1268
1431
|
open,
|
|
@@ -1271,12 +1434,15 @@ var HeadingMenu = forwardRef(({ editor: providedEditor, levels = [
|
|
|
1271
1434
|
"aria-labelledby": "heading-button",
|
|
1272
1435
|
role: "listbox"
|
|
1273
1436
|
} },
|
|
1274
|
-
children:
|
|
1437
|
+
children: [/* @__PURE__ */ jsx(ParagraphMenuItem, {
|
|
1438
|
+
editor,
|
|
1439
|
+
onClick: handleClose
|
|
1440
|
+
}), levels.map((level) => /* @__PURE__ */ jsx(HeadingMenuItem, {
|
|
1275
1441
|
editor,
|
|
1276
1442
|
level,
|
|
1277
1443
|
text: `Heading ${level}`,
|
|
1278
1444
|
onClick: handleClose
|
|
1279
|
-
}, `heading-${level}`))
|
|
1445
|
+
}, `heading-${level}`))]
|
|
1280
1446
|
})] });
|
|
1281
1447
|
});
|
|
1282
1448
|
HeadingMenu.displayName = "HeadingMenu";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cgi-learning-hub/ui",
|
|
3
|
-
"version": "1.15.0-dev.
|
|
3
|
+
"version": "1.15.0-dev.1788530642",
|
|
4
4
|
"description": "React component library for Hub's design system, built on Material UI with custom and extended components.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cgi-learning-hub",
|