@skalfa/skalfa-component 1.0.34 → 1.0.35
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.
|
@@ -458,6 +458,68 @@ function InputContentComponent({ label, tip, className = "", value, invalid, val
|
|
|
458
458
|
}
|
|
459
459
|
}
|
|
460
460
|
}, [handleBold, handleItalic, handleUnderline, handleStrikethrough, handleLink, handleEditorChange, updateActiveStates]);
|
|
461
|
+
const handlePaste = (0, react_1.useCallback)((e) => {
|
|
462
|
+
const pastedText = e.clipboardData.getData("text/plain");
|
|
463
|
+
if (!pastedText)
|
|
464
|
+
return;
|
|
465
|
+
const urlRegex = /(\b(?:https?:\/\/|www\.)[^\s()<>]+(?:\([\w\d]+\)|[^.,?;:"')\s]))/gi;
|
|
466
|
+
if (urlRegex.test(pastedText)) {
|
|
467
|
+
e.preventDefault();
|
|
468
|
+
const escapeHtml = (text) => {
|
|
469
|
+
return text
|
|
470
|
+
.replace(/&/g, "&")
|
|
471
|
+
.replace(/</g, "<")
|
|
472
|
+
.replace(/>/g, ">")
|
|
473
|
+
.replace(/"/g, """)
|
|
474
|
+
.replace(/'/g, "'");
|
|
475
|
+
};
|
|
476
|
+
const tokens = [];
|
|
477
|
+
let lastIndex = 0;
|
|
478
|
+
let match;
|
|
479
|
+
urlRegex.lastIndex = 0;
|
|
480
|
+
while ((match = urlRegex.exec(pastedText)) !== null) {
|
|
481
|
+
if (match.index > lastIndex) {
|
|
482
|
+
tokens.push(escapeHtml(pastedText.substring(lastIndex, match.index)));
|
|
483
|
+
}
|
|
484
|
+
const url = match[0];
|
|
485
|
+
let href = url;
|
|
486
|
+
if (url.toLowerCase().startsWith("www.")) {
|
|
487
|
+
href = "https://" + url;
|
|
488
|
+
}
|
|
489
|
+
const escapedHref = escapeHtml(href);
|
|
490
|
+
const escapedUrl = escapeHtml(url);
|
|
491
|
+
tokens.push(`<a href="${escapedHref}" class="text-primary underline" data-link="${escapedHref}" target="_blank" rel="noopener">${escapedUrl}</a>`);
|
|
492
|
+
lastIndex = urlRegex.lastIndex;
|
|
493
|
+
}
|
|
494
|
+
if (lastIndex < pastedText.length) {
|
|
495
|
+
tokens.push(escapeHtml(pastedText.substring(lastIndex)));
|
|
496
|
+
}
|
|
497
|
+
const htmlContent = tokens.join("").replace(/\n/g, "<br>");
|
|
498
|
+
const sel = window.getSelection();
|
|
499
|
+
if (!sel || sel.rangeCount === 0)
|
|
500
|
+
return;
|
|
501
|
+
const range = sel.getRangeAt(0);
|
|
502
|
+
range.deleteContents();
|
|
503
|
+
const tempDiv = document.createElement("div");
|
|
504
|
+
tempDiv.innerHTML = htmlContent;
|
|
505
|
+
const fragment = document.createDocumentFragment();
|
|
506
|
+
let child;
|
|
507
|
+
while ((child = tempDiv.firstChild)) {
|
|
508
|
+
fragment.appendChild(child);
|
|
509
|
+
}
|
|
510
|
+
const lastNode = fragment.lastChild;
|
|
511
|
+
range.insertNode(fragment);
|
|
512
|
+
if (lastNode) {
|
|
513
|
+
const newRange = document.createRange();
|
|
514
|
+
newRange.setStartAfter(lastNode);
|
|
515
|
+
newRange.collapse(true);
|
|
516
|
+
sel.removeAllRanges();
|
|
517
|
+
sel.addRange(newRange);
|
|
518
|
+
}
|
|
519
|
+
saveSelection();
|
|
520
|
+
handleEditorChange();
|
|
521
|
+
}
|
|
522
|
+
}, [saveSelection, handleEditorChange]);
|
|
461
523
|
const renderControlItem = (0, react_1.useCallback)((item, index) => {
|
|
462
524
|
if (typeof item !== "string") {
|
|
463
525
|
return (0, jsx_runtime_1.jsx)("div", { children: item }, index);
|
|
@@ -555,7 +617,7 @@ function InputContentComponent({ label, tip, className = "", value, invalid, val
|
|
|
555
617
|
saveSelection();
|
|
556
618
|
handleEditorChange();
|
|
557
619
|
updateActiveStates();
|
|
558
|
-
}, onKeyDown: handleKeyDown, onMouseUp: () => {
|
|
620
|
+
}, onKeyDown: handleKeyDown, onPaste: handlePaste, onMouseUp: () => {
|
|
559
621
|
saveSelection();
|
|
560
622
|
updateActiveStates();
|
|
561
623
|
}, onKeyUp: () => {
|
|
@@ -58,7 +58,7 @@ export type TableSupervisionProps = {
|
|
|
58
58
|
description: string;
|
|
59
59
|
};
|
|
60
60
|
on?: (item: Record<string, any>) => boolean;
|
|
61
|
-
} | ((row:
|
|
61
|
+
} | ((row: Record<string, any>, setModal?: (type: "EDIT" | "DELETE") => void, setDataSelected?: () => void, reset?: () => void, size?: string) => ReactNode))[];
|
|
62
62
|
block?: boolean;
|
|
63
63
|
noIndex?: boolean;
|
|
64
64
|
actionBulkingControl?: TableProps["actionBulking"];
|
package/package.json
CHANGED
|
@@ -574,6 +574,83 @@ export function InputContentComponent({
|
|
|
574
574
|
}
|
|
575
575
|
}, [handleBold, handleItalic, handleUnderline, handleStrikethrough, handleLink, handleEditorChange, updateActiveStates]);
|
|
576
576
|
|
|
577
|
+
const handlePaste = useCallback((e: React.ClipboardEvent<HTMLDivElement>) => {
|
|
578
|
+
const pastedText = e.clipboardData.getData("text/plain");
|
|
579
|
+
if (!pastedText) return;
|
|
580
|
+
|
|
581
|
+
const urlRegex = /(\b(?:https?:\/\/|www\.)[^\s()<>]+(?:\([\w\d]+\)|[^.,?;:"')\s]))/gi;
|
|
582
|
+
|
|
583
|
+
if (urlRegex.test(pastedText)) {
|
|
584
|
+
e.preventDefault();
|
|
585
|
+
|
|
586
|
+
const escapeHtml = (text: string) => {
|
|
587
|
+
return text
|
|
588
|
+
.replace(/&/g, "&")
|
|
589
|
+
.replace(/</g, "<")
|
|
590
|
+
.replace(/>/g, ">")
|
|
591
|
+
.replace(/"/g, """)
|
|
592
|
+
.replace(/'/g, "'");
|
|
593
|
+
};
|
|
594
|
+
|
|
595
|
+
const tokens: string[] = [];
|
|
596
|
+
let lastIndex = 0;
|
|
597
|
+
let match;
|
|
598
|
+
urlRegex.lastIndex = 0;
|
|
599
|
+
|
|
600
|
+
while ((match = urlRegex.exec(pastedText)) !== null) {
|
|
601
|
+
if (match.index > lastIndex) {
|
|
602
|
+
tokens.push(escapeHtml(pastedText.substring(lastIndex, match.index)));
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
const url = match[0];
|
|
606
|
+
let href = url;
|
|
607
|
+
if (url.toLowerCase().startsWith("www.")) {
|
|
608
|
+
href = "https://" + url;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
const escapedHref = escapeHtml(href);
|
|
612
|
+
const escapedUrl = escapeHtml(url);
|
|
613
|
+
tokens.push(`<a href="${escapedHref}" class="text-primary underline" data-link="${escapedHref}" target="_blank" rel="noopener">${escapedUrl}</a>`);
|
|
614
|
+
|
|
615
|
+
lastIndex = urlRegex.lastIndex;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
if (lastIndex < pastedText.length) {
|
|
619
|
+
tokens.push(escapeHtml(pastedText.substring(lastIndex)));
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
const htmlContent = tokens.join("").replace(/\n/g, "<br>");
|
|
623
|
+
|
|
624
|
+
const sel = window.getSelection();
|
|
625
|
+
if (!sel || sel.rangeCount === 0) return;
|
|
626
|
+
const range = sel.getRangeAt(0);
|
|
627
|
+
range.deleteContents();
|
|
628
|
+
|
|
629
|
+
const tempDiv = document.createElement("div");
|
|
630
|
+
tempDiv.innerHTML = htmlContent;
|
|
631
|
+
|
|
632
|
+
const fragment = document.createDocumentFragment();
|
|
633
|
+
let child: Node | null;
|
|
634
|
+
while ((child = tempDiv.firstChild)) {
|
|
635
|
+
fragment.appendChild(child);
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
const lastNode = fragment.lastChild;
|
|
639
|
+
range.insertNode(fragment);
|
|
640
|
+
|
|
641
|
+
if (lastNode) {
|
|
642
|
+
const newRange = document.createRange();
|
|
643
|
+
newRange.setStartAfter(lastNode);
|
|
644
|
+
newRange.collapse(true);
|
|
645
|
+
sel.removeAllRanges();
|
|
646
|
+
sel.addRange(newRange);
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
saveSelection();
|
|
650
|
+
handleEditorChange();
|
|
651
|
+
}
|
|
652
|
+
}, [saveSelection, handleEditorChange]);
|
|
653
|
+
|
|
577
654
|
const renderControlItem = useCallback((item: ToolbarControlItem, index: number) => {
|
|
578
655
|
if (typeof item !== "string") {
|
|
579
656
|
return <div key={index}>{item}</div>;
|
|
@@ -945,6 +1022,7 @@ export function InputContentComponent({
|
|
|
945
1022
|
updateActiveStates();
|
|
946
1023
|
}}
|
|
947
1024
|
onKeyDown={handleKeyDown}
|
|
1025
|
+
onPaste={handlePaste}
|
|
948
1026
|
onMouseUp={() => {
|
|
949
1027
|
saveSelection();
|
|
950
1028
|
updateActiveStates();
|
|
@@ -64,7 +64,7 @@ export type TableSupervisionProps = {
|
|
|
64
64
|
shortcut ?: { key: string, description: string },
|
|
65
65
|
on ?: (item: Record<string, any>) => boolean,
|
|
66
66
|
} | ((
|
|
67
|
-
row :
|
|
67
|
+
row : Record<string, any>,
|
|
68
68
|
setModal ?: (type: "EDIT" | "DELETE") => void,
|
|
69
69
|
setDataSelected ?: () => void,
|
|
70
70
|
reset ?: () => void,
|