smartrte-react 0.2.7 → 0.2.10
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/components/ClassicEditor.js +452 -15
- package/dist/theme.d.ts +1 -1
- package/dist/theme.js +15 -0
- package/package.json +1 -1
|
@@ -55,10 +55,12 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
|
|
|
55
55
|
const [showSpecialChars, setShowSpecialChars] = useState(false);
|
|
56
56
|
const [colorPickerType, setColorPickerType] = useState('text');
|
|
57
57
|
const savedRangeRef = useRef(null);
|
|
58
|
+
const inlineScriptCaretOverrideRef = useRef(null);
|
|
58
59
|
const historyRef = useRef({
|
|
59
60
|
undo: [],
|
|
60
61
|
redo: [],
|
|
61
62
|
});
|
|
63
|
+
const inputHistoryGroupRef = useRef(null);
|
|
62
64
|
const [currentFontSize, setCurrentFontSize] = useState("");
|
|
63
65
|
const [currentFont, setCurrentFont] = useState("");
|
|
64
66
|
const [currentBlockType, setCurrentBlockType] = useState("p");
|
|
@@ -114,14 +116,28 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
|
|
|
114
116
|
const element = node instanceof HTMLElement ? node : null;
|
|
115
117
|
const block = element?.closest("p,h1,h2,h3,h4,h5,h6,li,blockquote,pre,div");
|
|
116
118
|
const tag = block?.tagName.toLowerCase();
|
|
119
|
+
const scriptOverride = inlineScriptCaretOverrideRef.current;
|
|
120
|
+
const overrideApplies = Boolean(scriptOverride &&
|
|
121
|
+
range.collapsed &&
|
|
122
|
+
range.startContainer === scriptOverride.container &&
|
|
123
|
+
range.startOffset === scriptOverride.offset);
|
|
124
|
+
if (scriptOverride && !overrideApplies) {
|
|
125
|
+
inlineScriptCaretOverrideRef.current = null;
|
|
126
|
+
}
|
|
127
|
+
const subscriptActive = document.queryCommandState("subscript") || Boolean(element?.closest("sub"));
|
|
128
|
+
const superscriptActive = document.queryCommandState("superscript") || Boolean(element?.closest("sup"));
|
|
117
129
|
setCurrentBlockType(tag === "h1" || tag === "h2" || tag === "h3" ? tag : "p");
|
|
118
130
|
setActiveState({
|
|
119
131
|
bold: document.queryCommandState("bold"),
|
|
120
132
|
italic: document.queryCommandState("italic"),
|
|
121
133
|
underline: document.queryCommandState("underline"),
|
|
122
134
|
strikeThrough: document.queryCommandState("strikeThrough"),
|
|
123
|
-
subscript:
|
|
124
|
-
|
|
135
|
+
subscript: overrideApplies && scriptOverride?.command === "subscript"
|
|
136
|
+
? false
|
|
137
|
+
: subscriptActive,
|
|
138
|
+
superscript: overrideApplies && scriptOverride?.command === "superscript"
|
|
139
|
+
? false
|
|
140
|
+
: superscriptActive,
|
|
125
141
|
unorderedList: Boolean(element?.closest("ul")),
|
|
126
142
|
orderedList: Boolean(element?.closest("ol")),
|
|
127
143
|
blockquote: Boolean(element?.closest("blockquote")),
|
|
@@ -165,6 +181,7 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
|
|
|
165
181
|
toggleList("ol");
|
|
166
182
|
return;
|
|
167
183
|
}
|
|
184
|
+
pushEditorHistory();
|
|
168
185
|
const beforeHtml = editableRef.current?.innerHTML || "";
|
|
169
186
|
const ok = document.execCommand(command, false, valueArg);
|
|
170
187
|
const afterHtml = editableRef.current?.innerHTML || "";
|
|
@@ -178,6 +195,74 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
|
|
|
178
195
|
}
|
|
179
196
|
catch { }
|
|
180
197
|
};
|
|
198
|
+
const getScriptAncestor = (node, tagName) => {
|
|
199
|
+
const editor = editableRef.current;
|
|
200
|
+
let element = node instanceof HTMLElement ? node : node?.parentElement || null;
|
|
201
|
+
while (element && element !== editor) {
|
|
202
|
+
if (element.tagName.toLowerCase() === tagName)
|
|
203
|
+
return element;
|
|
204
|
+
element = element.parentElement;
|
|
205
|
+
}
|
|
206
|
+
return null;
|
|
207
|
+
};
|
|
208
|
+
const toggleInlineScript = (command) => {
|
|
209
|
+
try {
|
|
210
|
+
if (!restoreSavedSelection()) {
|
|
211
|
+
safeSelectRange(getSelectionRangeInEditor());
|
|
212
|
+
}
|
|
213
|
+
const editor = editableRef.current;
|
|
214
|
+
const range = getSelectionRangeInEditor();
|
|
215
|
+
if (!editor || !range)
|
|
216
|
+
return;
|
|
217
|
+
const tagName = command === "subscript" ? "sub" : "sup";
|
|
218
|
+
const script = range.collapsed
|
|
219
|
+
? getScriptAncestor(range.startContainer, tagName)
|
|
220
|
+
: null;
|
|
221
|
+
if (range.collapsed && document.queryCommandState(command)) {
|
|
222
|
+
document.execCommand(command, false);
|
|
223
|
+
const currentRange = getSelectionRangeInEditor();
|
|
224
|
+
savedRangeRef.current = currentRange?.cloneRange() || null;
|
|
225
|
+
inlineScriptCaretOverrideRef.current = currentRange?.collapsed
|
|
226
|
+
? {
|
|
227
|
+
command,
|
|
228
|
+
container: currentRange.startContainer,
|
|
229
|
+
offset: currentRange.startOffset,
|
|
230
|
+
}
|
|
231
|
+
: null;
|
|
232
|
+
setActiveState((current) => ({
|
|
233
|
+
...current,
|
|
234
|
+
subscript: command === "subscript" ? false : current.subscript,
|
|
235
|
+
superscript: command === "superscript" ? false : current.superscript,
|
|
236
|
+
}));
|
|
237
|
+
handleInput();
|
|
238
|
+
requestAnimationFrame(updateActiveState);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
if (script) {
|
|
242
|
+
const nextRange = document.createRange();
|
|
243
|
+
nextRange.setStartAfter(script);
|
|
244
|
+
nextRange.collapse(true);
|
|
245
|
+
safeSelectRange(nextRange);
|
|
246
|
+
savedRangeRef.current = nextRange.cloneRange();
|
|
247
|
+
inlineScriptCaretOverrideRef.current = {
|
|
248
|
+
command,
|
|
249
|
+
container: nextRange.startContainer,
|
|
250
|
+
offset: nextRange.startOffset,
|
|
251
|
+
};
|
|
252
|
+
setActiveState((current) => ({
|
|
253
|
+
...current,
|
|
254
|
+
subscript: command === "subscript" ? false : current.subscript,
|
|
255
|
+
superscript: command === "superscript" ? false : current.superscript,
|
|
256
|
+
}));
|
|
257
|
+
requestAnimationFrame(updateActiveState);
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
inlineScriptCaretOverrideRef.current = null;
|
|
261
|
+
exec(command);
|
|
262
|
+
requestAnimationFrame(updateActiveState);
|
|
263
|
+
}
|
|
264
|
+
catch { }
|
|
265
|
+
};
|
|
181
266
|
const applyFormatBlock = (blockName) => {
|
|
182
267
|
try {
|
|
183
268
|
if (!restoreSavedSelection()) {
|
|
@@ -206,10 +291,12 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
|
|
|
206
291
|
onChange(html);
|
|
207
292
|
}
|
|
208
293
|
};
|
|
209
|
-
const pushEditorHistory = () => {
|
|
294
|
+
const pushEditorHistory = (preserveInputGroup = false) => {
|
|
210
295
|
const editor = editableRef.current;
|
|
211
296
|
if (!editor)
|
|
212
297
|
return;
|
|
298
|
+
if (!preserveInputGroup)
|
|
299
|
+
inputHistoryGroupRef.current = null;
|
|
213
300
|
const selectionCells = selectionRef.current
|
|
214
301
|
? getCellsInGridRect(selectionRef.current.tbody, selectionRef.current.sr, selectionRef.current.sc, selectionRef.current.er, selectionRef.current.ec)
|
|
215
302
|
: [];
|
|
@@ -247,22 +334,47 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
|
|
|
247
334
|
const history = historyRef.current;
|
|
248
335
|
const from = dir === "undo" ? history.undo : history.redo;
|
|
249
336
|
const to = dir === "undo" ? history.redo : history.undo;
|
|
250
|
-
const
|
|
337
|
+
const currentHtml = editor.innerHTML;
|
|
338
|
+
let html;
|
|
339
|
+
while (from.length > 0) {
|
|
340
|
+
const candidate = from.pop();
|
|
341
|
+
if (candidate !== currentHtml) {
|
|
342
|
+
html = candidate;
|
|
343
|
+
break;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
251
346
|
if (html == null)
|
|
252
347
|
return false;
|
|
253
|
-
to.
|
|
348
|
+
if (to[to.length - 1] !== currentHtml)
|
|
349
|
+
to.push(currentHtml);
|
|
254
350
|
editor.innerHTML = html;
|
|
255
351
|
fixNegativeMargins(editor);
|
|
256
352
|
ensureTableWrappers(editor);
|
|
257
353
|
addTableResizeHandles();
|
|
258
354
|
clearSelectionDecor();
|
|
259
355
|
setTableMenu(null);
|
|
356
|
+
inputHistoryGroupRef.current = null;
|
|
357
|
+
focusElementEnd(editor);
|
|
358
|
+
requestAnimationFrame(updateActiveState);
|
|
260
359
|
if (html !== lastEmittedRef.current) {
|
|
261
360
|
lastEmittedRef.current = html;
|
|
262
361
|
onChange?.(html);
|
|
263
362
|
}
|
|
264
363
|
return true;
|
|
265
364
|
};
|
|
365
|
+
const captureInputHistory = (inputType) => {
|
|
366
|
+
const now = Date.now();
|
|
367
|
+
const previous = inputHistoryGroupRef.current;
|
|
368
|
+
const groupable = inputType === "insertText" ||
|
|
369
|
+
inputType === "deleteContentBackward" ||
|
|
370
|
+
inputType === "deleteContentForward";
|
|
371
|
+
const continuesGroup = groupable &&
|
|
372
|
+
previous?.inputType === inputType &&
|
|
373
|
+
now - previous.timestamp < 1000;
|
|
374
|
+
if (!continuesGroup)
|
|
375
|
+
pushEditorHistory(true);
|
|
376
|
+
inputHistoryGroupRef.current = { inputType, timestamp: now };
|
|
377
|
+
};
|
|
266
378
|
const restoreSavedSelection = () => {
|
|
267
379
|
const editor = editableRef.current;
|
|
268
380
|
if (!editor)
|
|
@@ -292,6 +404,21 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
|
|
|
292
404
|
return;
|
|
293
405
|
exec("createLink", url);
|
|
294
406
|
};
|
|
407
|
+
const openEditorLink = (anchor) => {
|
|
408
|
+
const rawHref = anchor.getAttribute("href")?.trim();
|
|
409
|
+
if (!rawHref)
|
|
410
|
+
return;
|
|
411
|
+
try {
|
|
412
|
+
const url = new URL(rawHref, window.location.href);
|
|
413
|
+
if (!["http:", "https:", "mailto:", "tel:"].includes(url.protocol))
|
|
414
|
+
return;
|
|
415
|
+
const target = anchor.getAttribute("target") || "_blank";
|
|
416
|
+
const opened = window.open(url.href, target, target === "_blank" ? "noopener,noreferrer" : undefined);
|
|
417
|
+
if (opened && target === "_blank")
|
|
418
|
+
opened.opener = null;
|
|
419
|
+
}
|
|
420
|
+
catch { }
|
|
421
|
+
};
|
|
295
422
|
const getSelectionRangeInEditor = () => {
|
|
296
423
|
const editor = editableRef.current;
|
|
297
424
|
if (!editor)
|
|
@@ -568,6 +695,89 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
|
|
|
568
695
|
}
|
|
569
696
|
return changed;
|
|
570
697
|
};
|
|
698
|
+
const nestListSelection = () => {
|
|
699
|
+
const editor = editableRef.current;
|
|
700
|
+
if (!editor)
|
|
701
|
+
return;
|
|
702
|
+
if (!restoreSavedSelection())
|
|
703
|
+
safeSelectRange(getSelectionRangeInEditor());
|
|
704
|
+
const range = getSelectionRangeInEditor();
|
|
705
|
+
if (!range || range.collapsed)
|
|
706
|
+
return;
|
|
707
|
+
const items = sortInDocumentOrder(getSelectedListItems(getSelectedBlocks(range)));
|
|
708
|
+
const firstList = items[0]?.parentElement;
|
|
709
|
+
if (items.length === 0 ||
|
|
710
|
+
!firstList ||
|
|
711
|
+
!["ul", "ol"].includes(firstList.tagName.toLowerCase())) {
|
|
712
|
+
return;
|
|
713
|
+
}
|
|
714
|
+
const listTag = firstList.tagName.toLowerCase();
|
|
715
|
+
const directItems = items.filter((item) => item.parentElement === firstList);
|
|
716
|
+
if (directItems.length === 0 || !directItems[0].previousElementSibling)
|
|
717
|
+
return;
|
|
718
|
+
pushEditorHistory();
|
|
719
|
+
if (nestSelectedListItems(directItems, listTag)) {
|
|
720
|
+
handleInput();
|
|
721
|
+
requestAnimationFrame(updateActiveState);
|
|
722
|
+
}
|
|
723
|
+
};
|
|
724
|
+
const applyListStyle = (value) => {
|
|
725
|
+
const listTag = value.startsWith("ordered:") ? "ol" : "ul";
|
|
726
|
+
const styleType = value.replace(/^(ordered|bullet):/, "");
|
|
727
|
+
if (!restoreSavedSelection())
|
|
728
|
+
safeSelectRange(getSelectionRangeInEditor());
|
|
729
|
+
const range = getSelectionRangeInEditor();
|
|
730
|
+
if (!range)
|
|
731
|
+
return;
|
|
732
|
+
const lists = new Set();
|
|
733
|
+
getSelectedListItems(getSelectedBlocks(range)).forEach((item) => {
|
|
734
|
+
const list = item.parentElement;
|
|
735
|
+
if (list &&
|
|
736
|
+
["ul", "ol"].includes(list.tagName.toLowerCase())) {
|
|
737
|
+
lists.add(list);
|
|
738
|
+
}
|
|
739
|
+
});
|
|
740
|
+
[range.startContainer, range.endContainer].forEach((node) => {
|
|
741
|
+
const element = node instanceof HTMLElement ? node : node.parentElement;
|
|
742
|
+
const list = element?.closest("ul,ol");
|
|
743
|
+
if (list && editableRef.current?.contains(list))
|
|
744
|
+
lists.add(list);
|
|
745
|
+
});
|
|
746
|
+
if (lists.size === 0) {
|
|
747
|
+
const block = getCurrentBlock();
|
|
748
|
+
if (!block?.closest("ul,ol")) {
|
|
749
|
+
toggleList(listTag);
|
|
750
|
+
const currentList = getCurrentBlock()?.closest(listTag);
|
|
751
|
+
if (currentList)
|
|
752
|
+
currentList.style.listStyleType = styleType;
|
|
753
|
+
handleInput();
|
|
754
|
+
return;
|
|
755
|
+
}
|
|
756
|
+
const currentList = block.closest("ul,ol");
|
|
757
|
+
if (currentList)
|
|
758
|
+
lists.add(currentList);
|
|
759
|
+
}
|
|
760
|
+
if (lists.size === 0)
|
|
761
|
+
return;
|
|
762
|
+
pushEditorHistory();
|
|
763
|
+
let lastList = null;
|
|
764
|
+
lists.forEach((list) => {
|
|
765
|
+
const target = list.tagName.toLowerCase() === listTag
|
|
766
|
+
? list
|
|
767
|
+
: cloneListShell(list, listTag);
|
|
768
|
+
if (target !== list) {
|
|
769
|
+
target.innerHTML = list.innerHTML;
|
|
770
|
+
list.parentElement?.replaceChild(target, list);
|
|
771
|
+
}
|
|
772
|
+
target.style.listStyleType = styleType;
|
|
773
|
+
lastList = target;
|
|
774
|
+
});
|
|
775
|
+
const lastItem = lastList?.lastElementChild;
|
|
776
|
+
if (lastItem)
|
|
777
|
+
focusElementEnd(lastItem);
|
|
778
|
+
handleInput();
|
|
779
|
+
requestAnimationFrame(updateActiveState);
|
|
780
|
+
};
|
|
571
781
|
const convertSelectedBlocksToList = (blocks, listTag) => {
|
|
572
782
|
const editor = editableRef.current;
|
|
573
783
|
if (!editor || blocks.length === 0)
|
|
@@ -612,19 +822,99 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
|
|
|
612
822
|
focusElementEnd(lastLi);
|
|
613
823
|
return true;
|
|
614
824
|
};
|
|
825
|
+
const transformSelectedListItems = (items, listTag) => {
|
|
826
|
+
const editor = editableRef.current;
|
|
827
|
+
if (!editor || items.length === 0)
|
|
828
|
+
return false;
|
|
829
|
+
const selected = new Set(items.filter((item) => {
|
|
830
|
+
const parentItem = item.parentElement?.closest("li");
|
|
831
|
+
return !parentItem || !items.includes(parentItem);
|
|
832
|
+
}));
|
|
833
|
+
const lists = new Set();
|
|
834
|
+
selected.forEach((item) => {
|
|
835
|
+
const list = item.parentElement;
|
|
836
|
+
if (list &&
|
|
837
|
+
(list.tagName.toLowerCase() === "ul" || list.tagName.toLowerCase() === "ol")) {
|
|
838
|
+
lists.add(list);
|
|
839
|
+
}
|
|
840
|
+
});
|
|
841
|
+
let changed = false;
|
|
842
|
+
let lastTarget = null;
|
|
843
|
+
lists.forEach((list) => {
|
|
844
|
+
const parent = list.parentElement;
|
|
845
|
+
if (!parent || !editor.contains(list))
|
|
846
|
+
return;
|
|
847
|
+
const toggleOff = list.tagName.toLowerCase() === listTag;
|
|
848
|
+
let pendingList = null;
|
|
849
|
+
const flushPendingList = () => {
|
|
850
|
+
if (!pendingList?.childNodes.length)
|
|
851
|
+
return;
|
|
852
|
+
parent.insertBefore(pendingList, list);
|
|
853
|
+
pendingList = null;
|
|
854
|
+
};
|
|
855
|
+
Array.from(list.children).forEach((child) => {
|
|
856
|
+
if (!(child instanceof HTMLElement) || child.tagName.toLowerCase() !== "li")
|
|
857
|
+
return;
|
|
858
|
+
const isSelected = selected.has(child);
|
|
859
|
+
if (isSelected && toggleOff) {
|
|
860
|
+
flushPendingList();
|
|
861
|
+
const paragraph = document.createElement("p");
|
|
862
|
+
paragraph.innerHTML = child.innerHTML || "<br>";
|
|
863
|
+
parent.insertBefore(paragraph, list);
|
|
864
|
+
lastTarget = paragraph;
|
|
865
|
+
child.remove();
|
|
866
|
+
changed = true;
|
|
867
|
+
return;
|
|
868
|
+
}
|
|
869
|
+
const outputTag = isSelected ? listTag : list.tagName.toLowerCase();
|
|
870
|
+
if (!pendingList || pendingList.tagName.toLowerCase() !== outputTag) {
|
|
871
|
+
flushPendingList();
|
|
872
|
+
pendingList = cloneListShell(list, outputTag);
|
|
873
|
+
}
|
|
874
|
+
pendingList.appendChild(child);
|
|
875
|
+
if (isSelected) {
|
|
876
|
+
lastTarget = child;
|
|
877
|
+
changed = true;
|
|
878
|
+
}
|
|
879
|
+
});
|
|
880
|
+
flushPendingList();
|
|
881
|
+
list.remove();
|
|
882
|
+
});
|
|
883
|
+
if (changed && lastTarget)
|
|
884
|
+
focusElementEnd(lastTarget);
|
|
885
|
+
return changed;
|
|
886
|
+
};
|
|
615
887
|
const toggleList = (listTag) => {
|
|
616
888
|
const editor = editableRef.current;
|
|
617
889
|
if (!editor)
|
|
618
890
|
return;
|
|
619
891
|
if (!restoreSavedSelection())
|
|
620
892
|
safeSelectRange(getSelectionRangeInEditor());
|
|
893
|
+
const setListActiveState = (active) => {
|
|
894
|
+
setActiveState((current) => ({
|
|
895
|
+
...current,
|
|
896
|
+
unorderedList: listTag === "ul" ? active : false,
|
|
897
|
+
orderedList: listTag === "ol" ? active : false,
|
|
898
|
+
}));
|
|
899
|
+
};
|
|
621
900
|
const range = getSelectionRangeInEditor();
|
|
622
901
|
if (range && !range.collapsed) {
|
|
623
902
|
const blocks = getSelectedBlocks(range);
|
|
624
903
|
const selectedListItems = getSelectedListItems(blocks);
|
|
904
|
+
if (selectedListItems.length > 0) {
|
|
905
|
+
pushEditorHistory();
|
|
906
|
+
if (transformSelectedListItems(selectedListItems, listTag)) {
|
|
907
|
+
const active = Boolean(getCurrentBlock()?.closest(listTag));
|
|
908
|
+
setListActiveState(active);
|
|
909
|
+
handleInput();
|
|
910
|
+
requestAnimationFrame(updateActiveState);
|
|
911
|
+
return;
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
pushEditorHistory();
|
|
625
915
|
const convertedBlocks = convertSelectedBlocksToList(blocks, listTag);
|
|
626
|
-
|
|
627
|
-
|
|
916
|
+
if (convertedBlocks) {
|
|
917
|
+
setListActiveState(true);
|
|
628
918
|
handleInput();
|
|
629
919
|
requestAnimationFrame(updateActiveState);
|
|
630
920
|
return;
|
|
@@ -632,31 +922,39 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
|
|
|
632
922
|
}
|
|
633
923
|
const block = getCurrentBlock();
|
|
634
924
|
if (!block) {
|
|
925
|
+
pushEditorHistory();
|
|
635
926
|
insertEmptyListAtSelection(listTag);
|
|
927
|
+
setListActiveState(true);
|
|
636
928
|
handleInput();
|
|
637
929
|
requestAnimationFrame(updateActiveState);
|
|
638
930
|
return;
|
|
639
931
|
}
|
|
640
932
|
const currentList = block.closest("ul,ol");
|
|
641
933
|
if (currentList && editor.contains(currentList)) {
|
|
934
|
+
pushEditorHistory();
|
|
642
935
|
if (currentList.tagName.toLowerCase() === listTag) {
|
|
643
936
|
const li = block.closest("li");
|
|
644
|
-
if (li)
|
|
937
|
+
if (li) {
|
|
645
938
|
unwrapListItem(li, currentList);
|
|
939
|
+
setListActiveState(false);
|
|
940
|
+
}
|
|
646
941
|
}
|
|
647
942
|
else {
|
|
648
943
|
convertListTag(currentList, listTag);
|
|
944
|
+
setListActiveState(true);
|
|
649
945
|
}
|
|
650
946
|
handleInput();
|
|
651
947
|
requestAnimationFrame(updateActiveState);
|
|
652
948
|
return;
|
|
653
949
|
}
|
|
950
|
+
pushEditorHistory();
|
|
654
951
|
const list = document.createElement(listTag);
|
|
655
952
|
const li = document.createElement("li");
|
|
656
953
|
li.innerHTML = block.innerHTML || "<br>";
|
|
657
954
|
list.appendChild(li);
|
|
658
955
|
block.parentElement?.replaceChild(list, block);
|
|
659
956
|
focusElementEnd(li);
|
|
957
|
+
setListActiveState(true);
|
|
660
958
|
handleInput();
|
|
661
959
|
requestAnimationFrame(updateActiveState);
|
|
662
960
|
};
|
|
@@ -3327,6 +3625,50 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
|
|
|
3327
3625
|
return null;
|
|
3328
3626
|
return getMovableElementFromNode(element);
|
|
3329
3627
|
};
|
|
3628
|
+
const getMoveTarget = () => {
|
|
3629
|
+
const editor = editableRef.current;
|
|
3630
|
+
if (!editor)
|
|
3631
|
+
return null;
|
|
3632
|
+
const imageTarget = selectedImage?.parentElement?.tagName === "A"
|
|
3633
|
+
? selectedImage.parentElement
|
|
3634
|
+
: selectedImage;
|
|
3635
|
+
if (imageTarget && editor.contains(imageTarget))
|
|
3636
|
+
return imageTarget;
|
|
3637
|
+
const range = getSelectionRangeInEditor();
|
|
3638
|
+
let node = range?.commonAncestorContainer || null;
|
|
3639
|
+
if (node?.nodeType === Node.TEXT_NODE)
|
|
3640
|
+
node = node.parentNode;
|
|
3641
|
+
const element = node instanceof HTMLElement ? node : null;
|
|
3642
|
+
if (!element)
|
|
3643
|
+
return null;
|
|
3644
|
+
const listItem = element.closest("li");
|
|
3645
|
+
if (listItem && editor.contains(listItem))
|
|
3646
|
+
return listItem;
|
|
3647
|
+
const cell = getClosestCell(element);
|
|
3648
|
+
if (cell) {
|
|
3649
|
+
const block = element.closest("p,h1,h2,h3,h4,h5,h6,blockquote,pre,div");
|
|
3650
|
+
if (block && block !== cell && cell.contains(block))
|
|
3651
|
+
return block;
|
|
3652
|
+
return cell;
|
|
3653
|
+
}
|
|
3654
|
+
return getTopLevelMovableElement();
|
|
3655
|
+
};
|
|
3656
|
+
const outdentListItem = (item) => {
|
|
3657
|
+
const list = item.parentElement;
|
|
3658
|
+
const parentItem = list?.parentElement;
|
|
3659
|
+
const outerList = parentItem?.parentElement;
|
|
3660
|
+
if (!list ||
|
|
3661
|
+
!parentItem ||
|
|
3662
|
+
parentItem.tagName.toLowerCase() !== "li" ||
|
|
3663
|
+
!outerList ||
|
|
3664
|
+
!["ul", "ol"].includes(outerList.tagName.toLowerCase())) {
|
|
3665
|
+
return false;
|
|
3666
|
+
}
|
|
3667
|
+
outerList.insertBefore(item, parentItem.nextSibling);
|
|
3668
|
+
if (!list.querySelector("li"))
|
|
3669
|
+
list.remove();
|
|
3670
|
+
return true;
|
|
3671
|
+
};
|
|
3330
3672
|
const elementSibling = (element, direction) => {
|
|
3331
3673
|
let sibling = direction === "previous" ? element.previousSibling : element.nextSibling;
|
|
3332
3674
|
while (sibling && sibling.nodeType === Node.TEXT_NODE && !sibling.textContent?.trim()) {
|
|
@@ -3336,11 +3678,40 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
|
|
|
3336
3678
|
};
|
|
3337
3679
|
const moveCurrentElement = (direction) => {
|
|
3338
3680
|
const editor = editableRef.current;
|
|
3339
|
-
|
|
3681
|
+
let target = getMoveTarget();
|
|
3340
3682
|
if (!editor || !target)
|
|
3341
3683
|
return;
|
|
3342
3684
|
pushEditorHistory();
|
|
3343
|
-
if (
|
|
3685
|
+
if (target.tagName === "TD" || target.tagName === "TH") {
|
|
3686
|
+
const cell = target;
|
|
3687
|
+
const paragraph = document.createElement("p");
|
|
3688
|
+
while (cell.firstChild)
|
|
3689
|
+
paragraph.appendChild(cell.firstChild);
|
|
3690
|
+
cell.appendChild(paragraph);
|
|
3691
|
+
target = paragraph;
|
|
3692
|
+
}
|
|
3693
|
+
if (target.tagName.toLowerCase() === "li") {
|
|
3694
|
+
const list = target.parentElement;
|
|
3695
|
+
if (!list)
|
|
3696
|
+
return;
|
|
3697
|
+
if (direction === "up") {
|
|
3698
|
+
const previous = elementSibling(target, "previous");
|
|
3699
|
+
if (previous?.nodeName === "LI")
|
|
3700
|
+
list.insertBefore(target, previous);
|
|
3701
|
+
}
|
|
3702
|
+
else if (direction === "down") {
|
|
3703
|
+
const next = elementSibling(target, "next");
|
|
3704
|
+
if (next?.nodeName === "LI")
|
|
3705
|
+
list.insertBefore(next, target);
|
|
3706
|
+
}
|
|
3707
|
+
else if (direction === "right") {
|
|
3708
|
+
nestSelectedListItems([target], list.tagName.toLowerCase());
|
|
3709
|
+
}
|
|
3710
|
+
else {
|
|
3711
|
+
outdentListItem(target);
|
|
3712
|
+
}
|
|
3713
|
+
}
|
|
3714
|
+
else if (direction === "up") {
|
|
3344
3715
|
const previous = elementSibling(target, "previous");
|
|
3345
3716
|
if (previous)
|
|
3346
3717
|
target.parentElement?.insertBefore(target, previous);
|
|
@@ -3419,7 +3790,24 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
|
|
|
3419
3790
|
background: "var(--srte-bg)",
|
|
3420
3791
|
color: "var(--srte-text)",
|
|
3421
3792
|
boxSizing: "border-box"
|
|
3422
|
-
}, children: [_jsxs("div", {
|
|
3793
|
+
}, children: [_jsxs("div", { "aria-disabled": readOnly, onMouseDown: (event) => {
|
|
3794
|
+
if (readOnly) {
|
|
3795
|
+
event.preventDefault();
|
|
3796
|
+
event.stopPropagation();
|
|
3797
|
+
return;
|
|
3798
|
+
}
|
|
3799
|
+
preserveToolbarMouseDown(event);
|
|
3800
|
+
}, onClick: (event) => {
|
|
3801
|
+
if (!readOnly)
|
|
3802
|
+
return;
|
|
3803
|
+
event.preventDefault();
|
|
3804
|
+
event.stopPropagation();
|
|
3805
|
+
}, onKeyDown: (event) => {
|
|
3806
|
+
if (!readOnly)
|
|
3807
|
+
return;
|
|
3808
|
+
event.preventDefault();
|
|
3809
|
+
event.stopPropagation();
|
|
3810
|
+
}, style: {
|
|
3423
3811
|
display: "flex",
|
|
3424
3812
|
flexWrap: "wrap",
|
|
3425
3813
|
maxWidth: "100%",
|
|
@@ -3430,6 +3818,9 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
|
|
|
3430
3818
|
position: "sticky",
|
|
3431
3819
|
top: 0,
|
|
3432
3820
|
zIndex: 1,
|
|
3821
|
+
opacity: readOnly ? 0.55 : 1,
|
|
3822
|
+
pointerEvents: readOnly ? "none" : "auto",
|
|
3823
|
+
userSelect: readOnly ? "none" : undefined,
|
|
3433
3824
|
}, children: [media && (_jsx("input", { ref: fileInputRef, type: "file", accept: "image/*", multiple: true, style: { display: "none" }, onChange: (e) => {
|
|
3434
3825
|
const list = e.currentTarget.files;
|
|
3435
3826
|
if (list && list.length) {
|
|
@@ -3542,7 +3933,20 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
|
|
|
3542
3933
|
borderRadius: 6,
|
|
3543
3934
|
background: "var(--srte-input-bg)",
|
|
3544
3935
|
color: "var(--srte-input-text)",
|
|
3545
|
-
}, children: _jsx("span", { style: { fontWeight: 700, padding: "1px 4px", background: "var(--srte-accent-bg)", borderRadius: 3 }, children: "A" }) }), _jsxs("button", { title: "Subscript", onClick: () =>
|
|
3936
|
+
}, children: _jsx("span", { style: { fontWeight: 700, padding: "1px 4px", background: "var(--srte-accent-bg)", borderRadius: 3 }, children: "A" }) }), _jsxs("button", { title: "Subscript", onClick: () => toggleInlineScript("subscript"), "aria-pressed": activeState.subscript, style: activeButtonStyle(activeState.subscript), children: ["X", _jsx("sub", { children: "2" })] }), _jsxs("button", { title: "Superscript", onClick: () => toggleInlineScript("superscript"), "aria-pressed": activeState.superscript, style: activeButtonStyle(activeState.superscript), children: ["X", _jsx("sup", { children: "2" })] }), _jsx("button", { title: "Bulleted list", onClick: () => exec("insertUnorderedList"), "aria-pressed": activeState.unorderedList, style: activeButtonStyle(activeState.unorderedList, { padding: "0 10px" }), children: "\u2022 List" }), _jsx("button", { title: "Numbered list", onClick: () => exec("insertOrderedList"), "aria-pressed": activeState.orderedList, style: activeButtonStyle(activeState.orderedList, { padding: "0 10px" }), children: "1. List" }), _jsxs("select", { defaultValue: "", onMouseDown: preserveEditorSelection, onChange: (e) => {
|
|
3937
|
+
const value = e.target.value;
|
|
3938
|
+
if (value)
|
|
3939
|
+
applyListStyle(value);
|
|
3940
|
+
e.currentTarget.value = "";
|
|
3941
|
+
}, title: "List style", "aria-label": "List style", style: {
|
|
3942
|
+
height: 32,
|
|
3943
|
+
maxWidth: 112,
|
|
3944
|
+
padding: "0 6px",
|
|
3945
|
+
border: "1px solid var(--srte-input-border)",
|
|
3946
|
+
borderRadius: 6,
|
|
3947
|
+
background: "var(--srte-input-bg)",
|
|
3948
|
+
color: "var(--srte-input-text)",
|
|
3949
|
+
}, children: [_jsx("option", { value: "", disabled: true, children: "List style" }), _jsxs("optgroup", { label: "Bullets", children: [_jsx("option", { value: "bullet:disc", children: "Disc" }), _jsx("option", { value: "bullet:circle", children: "Circle" }), _jsx("option", { value: "bullet:square", children: "Square" })] }), _jsxs("optgroup", { label: "Numbered", children: [_jsx("option", { value: "ordered:decimal", children: "1, 2, 3" }), _jsx("option", { value: "ordered:lower-alpha", children: "a, b, c" }), _jsx("option", { value: "ordered:upper-alpha", children: "A, B, C" }), _jsx("option", { value: "ordered:lower-roman", children: "i, ii, iii" }), _jsx("option", { value: "ordered:upper-roman", children: "I, II, III" })] })] }), _jsx("button", { title: "Blockquote", onClick: toggleBlockquote, "aria-pressed": activeState.blockquote, style: activeButtonStyle(activeState.blockquote), children: "\u275D" }), _jsx("button", { title: "Special characters", onClick: () => setShowSpecialChars(true), style: {
|
|
3546
3950
|
height: 32,
|
|
3547
3951
|
minWidth: 32,
|
|
3548
3952
|
padding: "0 8px",
|
|
@@ -4064,7 +4468,16 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
|
|
|
4064
4468
|
boxSizing: "border-box",
|
|
4065
4469
|
position: "relative",
|
|
4066
4470
|
scrollPaddingBottom: 24,
|
|
4067
|
-
}, children: [_jsx("div", { ref: editableRef, contentEditable: !readOnly, suppressContentEditableWarning: true,
|
|
4471
|
+
}, children: [_jsx("div", { ref: editableRef, contentEditable: !readOnly, suppressContentEditableWarning: true, onBeforeInput: (e) => {
|
|
4472
|
+
const inputType = e.nativeEvent.inputType || "input";
|
|
4473
|
+
if (inputType === "historyUndo" || inputType === "historyRedo") {
|
|
4474
|
+
if (restoreEditorHistory(inputType === "historyUndo" ? "undo" : "redo")) {
|
|
4475
|
+
e.preventDefault();
|
|
4476
|
+
}
|
|
4477
|
+
return;
|
|
4478
|
+
}
|
|
4479
|
+
captureInputHistory(inputType);
|
|
4480
|
+
}, onInput: handleInput, onKeyUp: updateActiveState, onMouseUp: updateActiveState, onCompositionStart: () => (isComposingRef.current = true), onCompositionEnd: () => {
|
|
4068
4481
|
isComposingRef.current = false;
|
|
4069
4482
|
handleInput();
|
|
4070
4483
|
}, onMouseMove: (e) => {
|
|
@@ -4084,6 +4497,7 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
|
|
|
4084
4497
|
return;
|
|
4085
4498
|
}
|
|
4086
4499
|
}
|
|
4500
|
+
pushEditorHistory();
|
|
4087
4501
|
const html = e.clipboardData?.getData("text/html");
|
|
4088
4502
|
if (html) {
|
|
4089
4503
|
e.preventDefault();
|
|
@@ -4166,6 +4580,13 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
|
|
|
4166
4580
|
}
|
|
4167
4581
|
}, onClick: (e) => {
|
|
4168
4582
|
const t = e.target;
|
|
4583
|
+
const anchor = t?.closest("a");
|
|
4584
|
+
if (anchor && editableRef.current?.contains(anchor)) {
|
|
4585
|
+
e.preventDefault();
|
|
4586
|
+
e.stopPropagation();
|
|
4587
|
+
openEditorLink(anchor);
|
|
4588
|
+
return;
|
|
4589
|
+
}
|
|
4169
4590
|
if (t && t.tagName === "IMG") {
|
|
4170
4591
|
setSelectedImage(t);
|
|
4171
4592
|
scheduleImageOverlay();
|
|
@@ -4241,13 +4662,29 @@ export function ClassicEditor({ value, onChange, placeholder = "Type here…", m
|
|
|
4241
4662
|
// Keep Tab for indentation in lists; otherwise insert 2 spaces
|
|
4242
4663
|
if (e.key === "Tab") {
|
|
4243
4664
|
e.preventDefault();
|
|
4244
|
-
|
|
4245
|
-
|
|
4665
|
+
const selection = getSelectionRangeInEditor();
|
|
4666
|
+
const selectedListItems = selection && !selection.collapsed
|
|
4667
|
+
? getSelectedListItems(getSelectedBlocks(selection))
|
|
4668
|
+
: [];
|
|
4669
|
+
if (selectedListItems.length > 0) {
|
|
4670
|
+
if (!e.shiftKey) {
|
|
4671
|
+
nestListSelection();
|
|
4672
|
+
return;
|
|
4673
|
+
}
|
|
4674
|
+
pushEditorHistory();
|
|
4675
|
+
exec("outdent");
|
|
4676
|
+
return;
|
|
4677
|
+
}
|
|
4678
|
+
const currentBlock = getCurrentBlock();
|
|
4679
|
+
if (currentBlock?.closest("li")) {
|
|
4680
|
+
pushEditorHistory();
|
|
4246
4681
|
exec(e.shiftKey ? "outdent" : "indent");
|
|
4247
4682
|
}
|
|
4248
4683
|
else {
|
|
4684
|
+
captureInputHistory("insertText");
|
|
4249
4685
|
document.execCommand("insertText", false, " ");
|
|
4250
4686
|
}
|
|
4687
|
+
return;
|
|
4251
4688
|
}
|
|
4252
4689
|
// Table navigation with arrows inside cells
|
|
4253
4690
|
if (["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"].includes(e.key)) {
|
package/dist/theme.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export type SrteTheme = 'light' | 'dark';
|
|
2
|
-
export declare const SRTE_DEFAULT_CSS = "\n.srte-editor {\n --srte-bg: #ffffff;\n --srte-text: #111111;\n --srte-text-muted: #4b5563;\n --srte-border: #dddddd;\n --srte-border-light: #eeeeee;\n --srte-toolbar-bg: #ffffff;\n --srte-input-bg: #ffffff;\n --srte-input-text: #111111;\n --srte-input-border: #e5e7eb;\n --srte-modal-backdrop: rgba(0, 0, 0, 0.35);\n --srte-modal-backdrop-filter: blur(2px);\n --srte-modal-bg: #ffffff;\n --srte-modal-text: #000000;\n --srte-menu-bg: #ffffff;\n --srte-menu-text: #111111;\n --srte-menu-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);\n --srte-accent: #1e90ff;\n --srte-accent-bg: rgba(30, 144, 255, 0.15);\n --srte-danger: #dc2626;\n --srte-primary: #2563eb;\n --srte-surface-subtle: #f3f4f6;\n --srte-on-primary: #ffffff;\n --srte-cancel-bg: #f3f4f6;\n}\n.srte-editor.srte-dark {\n --srte-bg: #1e1e1e;\n --srte-text: #e0e0e0;\n --srte-text-muted: #9ca3af;\n --srte-border: #3a3a3a;\n --srte-border-light: #2e2e2e;\n --srte-toolbar-bg: #252525;\n --srte-input-bg: #2a2a2a;\n --srte-input-text: #e0e0e0;\n --srte-input-border: #444444;\n --srte-modal-backdrop: rgba(0, 0, 0, 0.22);\n --srte-modal-backdrop-filter: blur(10px) saturate(0.9);\n --srte-modal-bg: #1e293b;\n --srte-modal-text: #e0e0e0;\n --srte-menu-bg: #1e293b;\n --srte-menu-text: #e0e0e0;\n --srte-menu-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);\n --srte-accent: #3b9eff;\n --srte-accent-bg: rgba(59, 158, 255, 0.2);\n --srte-danger: #ef4444;\n --srte-primary: #3b82f6;\n --srte-surface-subtle: #333333;\n --srte-on-primary: #ffffff;\n --srte-cancel-bg: #333333;\n}\n.srte-editor [contenteditable] blockquote {\n border-left: 4px solid var(--srte-accent);\n margin: 0.75em 0;\n padding: 0.5em 1em;\n background: var(--srte-surface-subtle);\n color: var(--srte-text);\n}\n.srte-editor [contenteditable] p,\n.srte-editor [contenteditable] h1,\n.srte-editor [contenteditable] h2,\n.srte-editor [contenteditable] h3 {\n color: inherit;\n}\n.srte-editor [contenteditable] p {\n display: block;\n margin: 0 0 0.75em;\n font-size: 1em;\n font-weight: 400;\n line-height: 1.6;\n}\n.srte-editor [contenteditable] h1,\n.srte-editor [contenteditable] h2,\n.srte-editor [contenteditable] h3 {\n display: block;\n margin: 0.75em 0 0.4em;\n font-weight: 700;\n line-height: 1.25;\n}\n.srte-editor [contenteditable] h1 {\n font-size: 2em;\n}\n.srte-editor [contenteditable] h2 {\n font-size: 1.5em;\n}\n.srte-editor [contenteditable] h3 {\n font-size: 1.25em;\n}\n.srte-editor [contenteditable] > :first-child {\n margin-top: 0;\n}\n.srte-editor [contenteditable] ul {\n list-style-type: disc;\n list-style-position: outside;\n margin: 0.75em 0;\n padding-left: 1.75em;\n}\n.srte-editor [contenteditable] ol {\n list-style-type: decimal;\n list-style-position: outside;\n margin: 0.75em 0;\n padding-left: 1.75em;\n}\n.srte-editor [contenteditable] li {\n display: list-item;\n margin: 0.25em 0;\n padding-left: 0.25em;\n}\n.srte-editor [contenteditable] li::marker {\n color: currentColor;\n}\n.srte-editor.srte-dark [contenteditable] [style*=\"color\"]:not(td):not(th):not(.srte-preserve-colors):not(.srte-preserve-colors *),\n.srte-editor.srte-dark [contenteditable] [style*=\"background\"]:not(td):not(th):not(.srte-preserve-colors):not(.srte-preserve-colors *) {\n color: var(--srte-text) !important;\n background: transparent !important;\n background-color: transparent !important;\n}\n.srte-editor [contenteditable] sub,\n.srte-editor [contenteditable] sup {\n line-height: 0;\n}\n";
|
|
2
|
+
export declare const SRTE_DEFAULT_CSS = "\n.srte-editor {\n --srte-bg: #ffffff;\n --srte-text: #111111;\n --srte-text-muted: #4b5563;\n --srte-border: #dddddd;\n --srte-border-light: #eeeeee;\n --srte-toolbar-bg: #ffffff;\n --srte-input-bg: #ffffff;\n --srte-input-text: #111111;\n --srte-input-border: #e5e7eb;\n --srte-modal-backdrop: rgba(0, 0, 0, 0.35);\n --srte-modal-backdrop-filter: blur(2px);\n --srte-modal-bg: #ffffff;\n --srte-modal-text: #000000;\n --srte-menu-bg: #ffffff;\n --srte-menu-text: #111111;\n --srte-menu-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);\n --srte-accent: #1e90ff;\n --srte-accent-bg: rgba(30, 144, 255, 0.15);\n --srte-danger: #dc2626;\n --srte-primary: #2563eb;\n --srte-surface-subtle: #f3f4f6;\n --srte-on-primary: #ffffff;\n --srte-cancel-bg: #f3f4f6;\n}\n.srte-editor.srte-dark {\n --srte-bg: #1e1e1e;\n --srte-text: #e0e0e0;\n --srte-text-muted: #9ca3af;\n --srte-border: #3a3a3a;\n --srte-border-light: #2e2e2e;\n --srte-toolbar-bg: #252525;\n --srte-input-bg: #2a2a2a;\n --srte-input-text: #e0e0e0;\n --srte-input-border: #444444;\n --srte-modal-backdrop: rgba(0, 0, 0, 0.22);\n --srte-modal-backdrop-filter: blur(10px) saturate(0.9);\n --srte-modal-bg: #1e293b;\n --srte-modal-text: #e0e0e0;\n --srte-menu-bg: #1e293b;\n --srte-menu-text: #e0e0e0;\n --srte-menu-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);\n --srte-accent: #3b9eff;\n --srte-accent-bg: rgba(59, 158, 255, 0.2);\n --srte-danger: #ef4444;\n --srte-primary: #3b82f6;\n --srte-surface-subtle: #333333;\n --srte-on-primary: #ffffff;\n --srte-cancel-bg: #333333;\n}\n.srte-editor [contenteditable] blockquote {\n border-left: 4px solid var(--srte-accent);\n margin: 0.75em 0;\n padding: 0.5em 1em;\n background: var(--srte-surface-subtle);\n color: var(--srte-text);\n}\n.srte-editor [contenteditable] p,\n.srte-editor [contenteditable] h1,\n.srte-editor [contenteditable] h2,\n.srte-editor [contenteditable] h3 {\n color: inherit;\n}\n.srte-editor [contenteditable] p {\n display: block;\n margin: 0 0 0.75em;\n font-size: 1em;\n font-weight: 400;\n line-height: 1.6;\n}\n.srte-editor [contenteditable] h1,\n.srte-editor [contenteditable] h2,\n.srte-editor [contenteditable] h3 {\n display: block;\n margin: 0.75em 0 0.4em;\n font-weight: 700;\n line-height: 1.25;\n}\n.srte-editor [contenteditable] h1 {\n font-size: 2em;\n}\n.srte-editor [contenteditable] h2 {\n font-size: 1.5em;\n}\n.srte-editor [contenteditable] h3 {\n font-size: 1.25em;\n}\n.srte-editor [contenteditable] > :first-child {\n margin-top: 0;\n}\n.srte-editor [contenteditable] ul {\n list-style-type: disc;\n list-style-position: outside;\n margin: 0.75em 0;\n padding-left: 1.75em;\n}\n.srte-editor [contenteditable] ol {\n list-style-type: decimal;\n list-style-position: outside;\n margin: 0.75em 0;\n padding-left: 1.75em;\n}\n.srte-editor [contenteditable] li {\n display: list-item;\n margin: 0.25em 0;\n padding-left: 0.25em;\n}\n.srte-editor [contenteditable] li::marker {\n color: currentColor;\n}\n.srte-editor [contenteditable] a,\n.srte-editor [contenteditable] a:visited {\n color: var(--srte-primary) !important;\n text-decoration: underline !important;\n text-decoration-thickness: 1px !important;\n text-underline-offset: 2px !important;\n cursor: pointer;\n}\n.srte-editor [contenteditable] a:hover {\n color: var(--srte-accent) !important;\n}\n.srte-editor [contenteditable] a:focus-visible {\n outline: 2px solid var(--srte-accent);\n outline-offset: 2px;\n}\n.srte-editor.srte-dark [contenteditable] [style*=\"color\"]:not(td):not(th):not(.srte-preserve-colors):not(.srte-preserve-colors *),\n.srte-editor.srte-dark [contenteditable] [style*=\"background\"]:not(td):not(th):not(.srte-preserve-colors):not(.srte-preserve-colors *) {\n color: var(--srte-text) !important;\n background: transparent !important;\n background-color: transparent !important;\n}\n.srte-editor [contenteditable] sub,\n.srte-editor [contenteditable] sup {\n line-height: 0;\n}\n";
|
|
3
3
|
export declare function ensureStyleSheet(): void;
|
package/dist/theme.js
CHANGED
|
@@ -109,6 +109,21 @@ export const SRTE_DEFAULT_CSS = `
|
|
|
109
109
|
.srte-editor [contenteditable] li::marker {
|
|
110
110
|
color: currentColor;
|
|
111
111
|
}
|
|
112
|
+
.srte-editor [contenteditable] a,
|
|
113
|
+
.srte-editor [contenteditable] a:visited {
|
|
114
|
+
color: var(--srte-primary) !important;
|
|
115
|
+
text-decoration: underline !important;
|
|
116
|
+
text-decoration-thickness: 1px !important;
|
|
117
|
+
text-underline-offset: 2px !important;
|
|
118
|
+
cursor: pointer;
|
|
119
|
+
}
|
|
120
|
+
.srte-editor [contenteditable] a:hover {
|
|
121
|
+
color: var(--srte-accent) !important;
|
|
122
|
+
}
|
|
123
|
+
.srte-editor [contenteditable] a:focus-visible {
|
|
124
|
+
outline: 2px solid var(--srte-accent);
|
|
125
|
+
outline-offset: 2px;
|
|
126
|
+
}
|
|
112
127
|
.srte-editor.srte-dark [contenteditable] [style*="color"]:not(td):not(th):not(.srte-preserve-colors):not(.srte-preserve-colors *),
|
|
113
128
|
.srte-editor.srte-dark [contenteditable] [style*="background"]:not(td):not(th):not(.srte-preserve-colors):not(.srte-preserve-colors *) {
|
|
114
129
|
color: var(--srte-text) !important;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "smartrte-react",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.10",
|
|
4
4
|
"description": "A powerful, feature-rich Rich Text Editor for React with support for tables, mathematical formulas (LaTeX/KaTeX), and media management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|