@rh-support/components 2.5.230 → 2.5.231
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/lib/esm/ConfirmationModal/ConfirmationDialog.js +1 -1
- package/lib/esm/Functional/CaseContactsSelectorExternal.d.ts +0 -2
- package/lib/esm/Functional/CaseContactsSelectorExternal.d.ts.map +1 -1
- package/lib/esm/Functional/CaseContactsSelectorExternal.js +82 -176
- package/lib/esm/InlineEdit/NewInlineEdit.d.ts +0 -2
- package/lib/esm/InlineEdit/NewInlineEdit.d.ts.map +1 -1
- package/lib/esm/InlineEdit/NewInlineEdit.js +2 -7
- package/lib/esm/MarkdownEditor/MarkdownEditor.d.ts +49 -0
- package/lib/esm/MarkdownEditor/MarkdownEditor.d.ts.map +1 -0
- package/lib/esm/MarkdownEditor/MarkdownEditor.js +601 -0
- package/lib/esm/MarkdownEditor/index.d.ts +2 -0
- package/lib/esm/MarkdownEditor/index.d.ts.map +1 -0
- package/lib/esm/MarkdownEditor/index.js +1 -0
- package/lib/esm/MarkdownEditor/markdownEditor.css +223 -0
- package/lib/esm/OwnerTypeaheadDropdown/OwnerTypeaheadDropdown.d.ts +0 -2
- package/lib/esm/OwnerTypeaheadDropdown/OwnerTypeaheadDropdown.d.ts.map +1 -1
- package/lib/esm/OwnerTypeaheadDropdown/OwnerTypeaheadDropdown.js +3 -8
- package/lib/esm/PhoneInput/PhoneInput.d.ts.map +1 -1
- package/lib/esm/PhoneInput/PhoneInput.js +1 -38
- package/lib/esm/SingleSelectDropdown/SingleSelectDropdown.d.ts +0 -2
- package/lib/esm/SingleSelectDropdown/SingleSelectDropdown.d.ts.map +1 -1
- package/lib/esm/SingleSelectDropdown/SingleSelectDropdown.js +6 -7
- package/lib/esm/SupportFeedbackForm/SupportFeedbackModal.d.ts.map +1 -1
- package/lib/esm/SupportFeedbackForm/SupportFeedbackModal.js +80 -62
- package/lib/esm/Table/TablePagination.d.ts +0 -1
- package/lib/esm/Table/TablePagination.d.ts.map +1 -1
- package/lib/esm/Table/TablePagination.js +1 -1
- package/lib/esm/ToastNotification/ToastNotification.d.ts +1 -5
- package/lib/esm/ToastNotification/ToastNotification.d.ts.map +1 -1
- package/lib/esm/ToastNotification/ToastNotification.js +3 -16
- package/lib/esm/ToastNotification/toastNotification.css +0 -7
- package/lib/esm/helperFunctions/errorMessage.d.ts +1 -2
- package/lib/esm/helperFunctions/errorMessage.d.ts.map +1 -1
- package/lib/esm/helperFunctions/errorMessage.js +5 -19
- package/lib/esm/hooks/useCopyToClipboard.d.ts +1 -1
- package/lib/esm/hooks/useCopyToClipboard.d.ts.map +1 -1
- package/lib/esm/hooks/useCopyToClipboard.js +1 -3
- package/lib/esm/index.d.ts +1 -3
- package/lib/esm/index.d.ts.map +1 -1
- package/lib/esm/index.js +1 -4
- package/package.json +6 -9
- package/lib/esm/CaseLabelLoadErrorModal/CaseLabelLoadErrorModal.d.ts +0 -10
- package/lib/esm/CaseLabelLoadErrorModal/CaseLabelLoadErrorModal.d.ts.map +0 -1
- package/lib/esm/CaseLabelLoadErrorModal/CaseLabelLoadErrorModal.js +0 -17
- package/lib/esm/CaseLabelLoadErrorModal/CaseLabelLoadErrorModal.scss +0 -13
- package/lib/esm/CaseLabelLoadErrorModal/index.d.ts +0 -2
- package/lib/esm/CaseLabelLoadErrorModal/index.d.ts.map +0 -1
- package/lib/esm/CaseLabelLoadErrorModal/index.js +0 -1
- package/lib/esm/CustomDatePicker/CustomDatePicker.d.ts +0 -18
- package/lib/esm/CustomDatePicker/CustomDatePicker.d.ts.map +0 -1
- package/lib/esm/CustomDatePicker/CustomDatePicker.js +0 -27
- package/lib/esm/CustomDatePicker/customDatePicker.css +0 -52
- package/lib/esm/CustomDatePicker/index.d.ts +0 -2
- package/lib/esm/CustomDatePicker/index.d.ts.map +0 -1
- package/lib/esm/CustomDatePicker/index.js +0 -1
- package/lib/esm/RichTextEditor/RichTextEditor.d.ts +0 -45
- package/lib/esm/RichTextEditor/RichTextEditor.d.ts.map +0 -1
- package/lib/esm/RichTextEditor/RichTextEditor.js +0 -464
- package/lib/esm/RichTextEditor/autoLinkModule.d.ts +0 -18
- package/lib/esm/RichTextEditor/autoLinkModule.d.ts.map +0 -1
- package/lib/esm/RichTextEditor/autoLinkModule.js +0 -156
- package/lib/esm/RichTextEditor/index.d.ts +0 -4
- package/lib/esm/RichTextEditor/index.d.ts.map +0 -1
- package/lib/esm/RichTextEditor/index.js +0 -2
- package/lib/esm/RichTextEditor/linkUrl.d.ts +0 -7
- package/lib/esm/RichTextEditor/linkUrl.d.ts.map +0 -1
- package/lib/esm/RichTextEditor/linkUrl.js +0 -26
- package/lib/esm/RichTextEditor/richTextEditor.css +0 -182
- package/lib/esm/RichTextEditor/useQuillEditor.d.ts +0 -20
- package/lib/esm/RichTextEditor/useQuillEditor.d.ts.map +0 -1
- package/lib/esm/RichTextEditor/useQuillEditor.js +0 -180
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Returns a normalized http(s)/mailto URL, or null if the value is not allowed.
|
|
3
|
-
* Protocol-less hosts (e.g. example.com) are treated as https.
|
|
4
|
-
*/
|
|
5
|
-
export declare function normalizeLinkUrl(url: string): string | null;
|
|
6
|
-
export declare function isValidUrl(url: string): boolean;
|
|
7
|
-
//# sourceMappingURL=linkUrl.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"linkUrl.d.ts","sourceRoot":"","sources":["../../../src/RichTextEditor/linkUrl.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAa3D;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAE/C"}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
const ALLOWED_PROTOCOLS = new Set(['http:', 'https:', 'mailto:']);
|
|
2
|
-
/**
|
|
3
|
-
* Returns a normalized http(s)/mailto URL, or null if the value is not allowed.
|
|
4
|
-
* Protocol-less hosts (e.g. example.com) are treated as https.
|
|
5
|
-
*/
|
|
6
|
-
export function normalizeLinkUrl(url) {
|
|
7
|
-
const trimmed = url.trim();
|
|
8
|
-
if (!trimmed)
|
|
9
|
-
return null;
|
|
10
|
-
try {
|
|
11
|
-
const hasAllowedPrefix = /^https?:\/\//i.test(trimmed) || /^mailto:/i.test(trimmed);
|
|
12
|
-
const candidate = hasAllowedPrefix ? trimmed : `https://${trimmed}`;
|
|
13
|
-
const parsed = new URL(candidate);
|
|
14
|
-
if (!ALLOWED_PROTOCOLS.has(parsed.protocol))
|
|
15
|
-
return null;
|
|
16
|
-
if (parsed.protocol !== 'mailto:' && !parsed.hostname.includes('.'))
|
|
17
|
-
return null;
|
|
18
|
-
return candidate;
|
|
19
|
-
}
|
|
20
|
-
catch (_a) {
|
|
21
|
-
return null;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
export function isValidUrl(url) {
|
|
25
|
-
return normalizeLinkUrl(url) !== null;
|
|
26
|
-
}
|
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
.richtext-editor-container {
|
|
2
|
-
background: var(--pf-t--global--background--color--primary--default, #fff);
|
|
3
|
-
border: 1px solid var(--pf-t--global--border--color--default, #d2d2d2);
|
|
4
|
-
border-radius: var(--pf-t--global--border--radius--small, 3px);
|
|
5
|
-
display: block;
|
|
6
|
-
min-height: 100px;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
.richtext-editor-container--disabled {
|
|
10
|
-
background: var(--pf-t--global--background--color--disabled--default, #f0f0f0);
|
|
11
|
-
pointer-events: none;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
.richtext-editor-content {
|
|
15
|
-
resize: vertical;
|
|
16
|
-
overflow-y: auto;
|
|
17
|
-
overflow-x: hidden;
|
|
18
|
-
font-size: 15px;
|
|
19
|
-
min-width: 100%;
|
|
20
|
-
outline: none;
|
|
21
|
-
border: none;
|
|
22
|
-
min-height: 100px;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
.richtext-editor-content.ql-container,
|
|
26
|
-
.richtext-editor-container .ql-container.ql-container {
|
|
27
|
-
border: none !important;
|
|
28
|
-
outline: none !important;
|
|
29
|
-
font-size: 15px;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
.richtext-editor-content .ql-editor {
|
|
33
|
-
padding: 0.8rem;
|
|
34
|
-
outline: none;
|
|
35
|
-
border: none;
|
|
36
|
-
min-height: 100px;
|
|
37
|
-
overflow-wrap: break-word;
|
|
38
|
-
word-break: break-word;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
.richtext-editor-content .ql-editor:focus {
|
|
42
|
-
outline: none;
|
|
43
|
-
border: none;
|
|
44
|
-
box-shadow: none;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
.richtext-editor-content .ql-editor.ql-blank::before {
|
|
48
|
-
content: attr(data-placeholder);
|
|
49
|
-
color: var(--pf-t--global--text--color--placeholder, #6a6e73);
|
|
50
|
-
pointer-events: none;
|
|
51
|
-
position: absolute;
|
|
52
|
-
font-style: normal;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
.richtext-editor-content ul,
|
|
56
|
-
.richtext-editor-content ol {
|
|
57
|
-
padding-left: 24px;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
.richtext-editor-content li[data-list='bullet'] {
|
|
61
|
-
list-style-type: disc;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
.richtext-editor-content li[data-list='bullet'].ql-indent-1 {
|
|
65
|
-
list-style-type: circle;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
.richtext-editor-content li[data-list='bullet'].ql-indent-2 {
|
|
69
|
-
list-style-type: square;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
.richtext-editor-content li[data-list='bullet'].ql-indent-3 {
|
|
73
|
-
list-style-type: disc;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
.richtext-editor-content li[data-list='bullet'].ql-indent-4 {
|
|
77
|
-
list-style-type: circle;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
.richtext-editor-content li[data-list='ordered'] {
|
|
81
|
-
list-style-type: decimal;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
.richtext-editor-content li[data-list='ordered'].ql-indent-1 {
|
|
85
|
-
list-style-type: lower-alpha;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
.richtext-editor-content li[data-list='ordered'].ql-indent-2 {
|
|
89
|
-
list-style-type: lower-roman;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
.richtext-editor-content .ql-align-center {
|
|
93
|
-
text-align: center;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
.richtext-editor-content .ql-align-right {
|
|
97
|
-
text-align: right;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
.richtext-editor-content .ql-align-justify {
|
|
101
|
-
text-align: justify;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
.richtext-editor-content .ql-indent-1 {
|
|
105
|
-
margin-left: 3em;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
.richtext-editor-content .ql-indent-2 {
|
|
109
|
-
margin-left: 6em;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
.richtext-editor-content .ql-indent-3 {
|
|
113
|
-
margin-left: 9em;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
.richtext-editor-content .ql-indent-4 {
|
|
117
|
-
margin-left: 12em;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
.richtext-editor-content .ql-indent-5 {
|
|
121
|
-
margin-left: 15em;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
.richtext-editor-content a {
|
|
125
|
-
color: var(--pf-t--global--text--color--link--default, #0066cc);
|
|
126
|
-
text-decoration: underline;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
.richtext-editor-content img {
|
|
130
|
-
max-width: 100%;
|
|
131
|
-
height: auto;
|
|
132
|
-
display: block;
|
|
133
|
-
margin: 8px 0;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
.richtext-editor-container.is-private .richtext-editor-content {
|
|
137
|
-
background-color: #f5eeee;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
.richtext-toolbar {
|
|
141
|
-
border-bottom: 1px solid var(--pf-t--global--border--color--default, #d2d2d2);
|
|
142
|
-
padding: 4px 8px;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
.richtext-toolbar-left-section {
|
|
146
|
-
display: flex;
|
|
147
|
-
align-items: center;
|
|
148
|
-
flex-wrap: wrap;
|
|
149
|
-
gap: 2px;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
.btn-group-separator {
|
|
153
|
-
display: inline-block;
|
|
154
|
-
width: 1px;
|
|
155
|
-
height: 24px;
|
|
156
|
-
margin: 0 8px;
|
|
157
|
-
background-color: var(--pf-t--global--border--color--default, #ccc);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
.toggle-content {
|
|
161
|
-
display: inline-flex;
|
|
162
|
-
align-items: center;
|
|
163
|
-
gap: 4px;
|
|
164
|
-
font-size: 14px;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
.dropdown-caret {
|
|
168
|
-
font-size: 12px;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
.richtext-char-counter {
|
|
172
|
-
padding: 4px 8px;
|
|
173
|
-
font-size: 12px;
|
|
174
|
-
text-align: right;
|
|
175
|
-
color: var(--pf-t--global--text--color--subtle, #6a6e73);
|
|
176
|
-
border-top: 1px solid var(--pf-t--global--border--color--default, #d2d2d2);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
.richtext-char-counter--exceeded {
|
|
180
|
-
color: var(--pf-t--global--color--status--danger--default, #c9190b);
|
|
181
|
-
font-weight: bold;
|
|
182
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import Quill from 'quill';
|
|
2
|
-
export interface UseQuillEditorOptions {
|
|
3
|
-
placeholder?: string;
|
|
4
|
-
readOnly?: boolean;
|
|
5
|
-
onChange?: (html: string) => void;
|
|
6
|
-
onChangePlainText?: (text: string) => void;
|
|
7
|
-
onSelectionChange?: (format: Record<string, unknown>) => void;
|
|
8
|
-
onFocus?: () => void;
|
|
9
|
-
onBlur?: () => void;
|
|
10
|
-
}
|
|
11
|
-
export declare function useQuillEditor(options: UseQuillEditorOptions): {
|
|
12
|
-
editorRef: import("react").MutableRefObject<HTMLDivElement>;
|
|
13
|
-
quillRef: import("react").MutableRefObject<Quill>;
|
|
14
|
-
activeFormat: Record<string, unknown>;
|
|
15
|
-
setActiveFormat: import("react").Dispatch<import("react").SetStateAction<Record<string, unknown>>>;
|
|
16
|
-
setContents: (html: string) => void;
|
|
17
|
-
setReadOnly: (readOnly: boolean) => void;
|
|
18
|
-
getPlainText: () => string;
|
|
19
|
-
};
|
|
20
|
-
//# sourceMappingURL=useQuillEditor.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useQuillEditor.d.ts","sourceRoot":"","sources":["../../../src/RichTextEditor/useQuillEditor.ts"],"names":[],"mappings":"AACA,OAAO,KAAmC,MAAM,OAAO,CAAC;AAKxD,MAAM,WAAW,qBAAqB;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC9D,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AAoFD,wBAAgB,cAAc,CAAC,OAAO,EAAE,qBAAqB;;;;;wBA+ElB,MAAM;4BAgBF,OAAO;;EASrD"}
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
import DOMPurify from 'dompurify';
|
|
2
|
-
import Quill from 'quill';
|
|
3
|
-
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
4
|
-
import { linkifyFullDocument, registerAutoLinkModule } from './autoLinkModule';
|
|
5
|
-
const ALLOWED_FORMATS = ['header', 'bold', 'italic', 'underline', 'strike', 'list', 'indent', 'align', 'link', 'image'];
|
|
6
|
-
/**
|
|
7
|
-
* Quill 2 internally represents ALL lists as <ol> and distinguishes bullet vs.
|
|
8
|
-
* ordered via data-list attributes on <li>. root.innerHTML preserves text-entity
|
|
9
|
-
* encoding (important for literal angle-brackets), but outputs this internal
|
|
10
|
-
* format. This helper converts it to semantic <ul>/<ol> and nests indented
|
|
11
|
-
* items before sanitization.
|
|
12
|
-
*/
|
|
13
|
-
function normalizeQuillListHtml(rawHtml) {
|
|
14
|
-
const tmp = document.createElement('div');
|
|
15
|
-
tmp.innerHTML = rawHtml;
|
|
16
|
-
tmp.querySelectorAll('.ql-ui').forEach((el) => el.remove());
|
|
17
|
-
tmp.querySelectorAll('ol').forEach((ol) => {
|
|
18
|
-
const items = Array.from(ol.querySelectorAll(':scope > li'));
|
|
19
|
-
const allBullet = items.length > 0 && items.every((li) => li instanceof HTMLElement && li.dataset.list === 'bullet');
|
|
20
|
-
if (allBullet) {
|
|
21
|
-
const ul = document.createElement('ul');
|
|
22
|
-
for (const attr of Array.from(ol.attributes)) {
|
|
23
|
-
ul.setAttribute(attr.name, attr.value);
|
|
24
|
-
}
|
|
25
|
-
while (ol.firstChild)
|
|
26
|
-
ul.appendChild(ol.firstChild);
|
|
27
|
-
ol.replaceWith(ul);
|
|
28
|
-
}
|
|
29
|
-
items.forEach((li) => {
|
|
30
|
-
if (li instanceof HTMLElement) {
|
|
31
|
-
delete li.dataset.list;
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
});
|
|
35
|
-
tmp.querySelectorAll('ul, ol').forEach((list) => {
|
|
36
|
-
if (list instanceof HTMLElement)
|
|
37
|
-
nestIndentedItems(list);
|
|
38
|
-
});
|
|
39
|
-
return tmp.innerHTML;
|
|
40
|
-
}
|
|
41
|
-
function tryNestIndentedItem(item, list) {
|
|
42
|
-
var _a;
|
|
43
|
-
const indentMatch = /ql-indent-(\d+)/.exec((_a = item.className) !== null && _a !== void 0 ? _a : '');
|
|
44
|
-
if (!indentMatch)
|
|
45
|
-
return false;
|
|
46
|
-
const level = Number.parseInt(indentMatch[1], 10);
|
|
47
|
-
item.classList.remove(`ql-indent-${level}`);
|
|
48
|
-
if (!item.className.trim())
|
|
49
|
-
item.removeAttribute('class');
|
|
50
|
-
let prev = item.previousElementSibling;
|
|
51
|
-
while (prev && prev.tagName !== 'LI')
|
|
52
|
-
prev = prev.previousElementSibling;
|
|
53
|
-
if (!prev)
|
|
54
|
-
return false;
|
|
55
|
-
let nested = prev.querySelector(':scope > ul, :scope > ol');
|
|
56
|
-
if (!(nested instanceof HTMLElement)) {
|
|
57
|
-
nested = document.createElement(list.tagName.toLowerCase());
|
|
58
|
-
prev.appendChild(nested);
|
|
59
|
-
}
|
|
60
|
-
nested.appendChild(item);
|
|
61
|
-
if (level > 1)
|
|
62
|
-
item.classList.add(`ql-indent-${level - 1}`);
|
|
63
|
-
return true;
|
|
64
|
-
}
|
|
65
|
-
function nestIndentedItems(list) {
|
|
66
|
-
let changed = true;
|
|
67
|
-
while (changed) {
|
|
68
|
-
changed = false;
|
|
69
|
-
const items = Array.from(list.querySelectorAll(':scope > li'));
|
|
70
|
-
for (const item of items) {
|
|
71
|
-
if (tryNestIndentedItem(item, list))
|
|
72
|
-
changed = true;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
// Newly created nested lists are not in the original querySelectorAll snapshot.
|
|
76
|
-
// Recurse so indent 2+ items become true nested lists instead of leftover ql-indent-* siblings.
|
|
77
|
-
for (const nested of Array.from(list.querySelectorAll(':scope > li > ul, :scope > li > ol'))) {
|
|
78
|
-
if (nested instanceof HTMLElement)
|
|
79
|
-
nestIndentedItems(nested);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
export function useQuillEditor(options) {
|
|
83
|
-
const editorRef = useRef(null);
|
|
84
|
-
const quillRef = useRef(null);
|
|
85
|
-
const [activeFormat, setActiveFormat] = useState({});
|
|
86
|
-
const optionsRef = useRef(options);
|
|
87
|
-
optionsRef.current = options;
|
|
88
|
-
// Track whether the last change was internal (from Quill) to avoid echo loops
|
|
89
|
-
const isInternalChange = useRef(false);
|
|
90
|
-
useEffect(() => {
|
|
91
|
-
if (!editorRef.current || quillRef.current)
|
|
92
|
-
return;
|
|
93
|
-
const quill = new Quill(editorRef.current, {
|
|
94
|
-
modules: {
|
|
95
|
-
toolbar: false,
|
|
96
|
-
keyboard: {
|
|
97
|
-
bindings: {
|
|
98
|
-
indent: {
|
|
99
|
-
key: 'Tab',
|
|
100
|
-
format: ['list'],
|
|
101
|
-
handler(_range, _context) {
|
|
102
|
-
this.quill.format('indent', '+1', 'user');
|
|
103
|
-
return false;
|
|
104
|
-
},
|
|
105
|
-
},
|
|
106
|
-
outdent: {
|
|
107
|
-
key: 'Tab',
|
|
108
|
-
shiftKey: true,
|
|
109
|
-
format: ['list'],
|
|
110
|
-
handler(_range, _context) {
|
|
111
|
-
this.quill.format('indent', '-1', 'user');
|
|
112
|
-
return false;
|
|
113
|
-
},
|
|
114
|
-
},
|
|
115
|
-
},
|
|
116
|
-
},
|
|
117
|
-
clipboard: { matchVisual: false },
|
|
118
|
-
},
|
|
119
|
-
formats: ALLOWED_FORMATS,
|
|
120
|
-
placeholder: optionsRef.current.placeholder,
|
|
121
|
-
readOnly: optionsRef.current.readOnly,
|
|
122
|
-
});
|
|
123
|
-
registerAutoLinkModule(quill);
|
|
124
|
-
quill.on('text-change', () => {
|
|
125
|
-
var _a, _b, _c, _d;
|
|
126
|
-
isInternalChange.current = true;
|
|
127
|
-
const html = DOMPurify.sanitize(normalizeQuillListHtml(quill.root.innerHTML));
|
|
128
|
-
(_b = (_a = optionsRef.current).onChange) === null || _b === void 0 ? void 0 : _b.call(_a, html);
|
|
129
|
-
(_d = (_c = optionsRef.current).onChangePlainText) === null || _d === void 0 ? void 0 : _d.call(_c, quill.getText().trim());
|
|
130
|
-
const sel = quill.getSelection();
|
|
131
|
-
if (sel) {
|
|
132
|
-
setActiveFormat(quill.getFormat(sel));
|
|
133
|
-
}
|
|
134
|
-
isInternalChange.current = false;
|
|
135
|
-
});
|
|
136
|
-
quill.on('selection-change', (range) => {
|
|
137
|
-
var _a, _b, _c, _d, _e, _f;
|
|
138
|
-
if (range) {
|
|
139
|
-
setActiveFormat(quill.getFormat(range));
|
|
140
|
-
(_b = (_a = optionsRef.current).onSelectionChange) === null || _b === void 0 ? void 0 : _b.call(_a, quill.getFormat(range));
|
|
141
|
-
if (range.length === 0) {
|
|
142
|
-
(_d = (_c = optionsRef.current).onFocus) === null || _d === void 0 ? void 0 : _d.call(_c);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
else {
|
|
146
|
-
linkifyFullDocument(quill);
|
|
147
|
-
(_f = (_e = optionsRef.current).onBlur) === null || _f === void 0 ? void 0 : _f.call(_e);
|
|
148
|
-
}
|
|
149
|
-
});
|
|
150
|
-
quillRef.current = quill;
|
|
151
|
-
return () => {
|
|
152
|
-
quillRef.current = null;
|
|
153
|
-
};
|
|
154
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
155
|
-
}, []);
|
|
156
|
-
const setContents = useCallback((html) => {
|
|
157
|
-
const quill = quillRef.current;
|
|
158
|
-
if (!quill || isInternalChange.current)
|
|
159
|
-
return;
|
|
160
|
-
const currentHtml = DOMPurify.sanitize(normalizeQuillListHtml(quill.root.innerHTML));
|
|
161
|
-
if (currentHtml === html)
|
|
162
|
-
return;
|
|
163
|
-
const selection = quill.getSelection();
|
|
164
|
-
quill.clipboard.dangerouslyPasteHTML(html);
|
|
165
|
-
if (selection) {
|
|
166
|
-
const length = quill.getLength();
|
|
167
|
-
const safeIndex = Math.min(selection.index, length - 1);
|
|
168
|
-
quill.setSelection(safeIndex, 0, 'silent');
|
|
169
|
-
}
|
|
170
|
-
}, []);
|
|
171
|
-
const setReadOnly = useCallback((readOnly) => {
|
|
172
|
-
var _a;
|
|
173
|
-
(_a = quillRef.current) === null || _a === void 0 ? void 0 : _a.enable(!readOnly);
|
|
174
|
-
}, []);
|
|
175
|
-
const getPlainText = useCallback(() => {
|
|
176
|
-
var _a, _b;
|
|
177
|
-
return (_b = (_a = quillRef.current) === null || _a === void 0 ? void 0 : _a.getText().trim()) !== null && _b !== void 0 ? _b : '';
|
|
178
|
-
}, []);
|
|
179
|
-
return { editorRef, quillRef, activeFormat, setActiveFormat, setContents, setReadOnly, getPlainText };
|
|
180
|
-
}
|