@rh-support/components 2.5.226 → 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.
Files changed (61) hide show
  1. package/lib/esm/ConfirmationModal/ConfirmationDialog.js +1 -1
  2. package/lib/esm/Functional/CaseContactsSelectorExternal.d.ts +0 -2
  3. package/lib/esm/Functional/CaseContactsSelectorExternal.d.ts.map +1 -1
  4. package/lib/esm/Functional/CaseContactsSelectorExternal.js +82 -156
  5. package/lib/esm/InlineEdit/NewInlineEdit.d.ts +0 -2
  6. package/lib/esm/InlineEdit/NewInlineEdit.d.ts.map +1 -1
  7. package/lib/esm/InlineEdit/NewInlineEdit.js +2 -7
  8. package/lib/esm/MarkdownEditor/MarkdownEditor.d.ts +49 -0
  9. package/lib/esm/MarkdownEditor/MarkdownEditor.d.ts.map +1 -0
  10. package/lib/esm/MarkdownEditor/MarkdownEditor.js +601 -0
  11. package/lib/esm/MarkdownEditor/index.d.ts +2 -0
  12. package/lib/esm/MarkdownEditor/index.d.ts.map +1 -0
  13. package/lib/esm/MarkdownEditor/index.js +1 -0
  14. package/lib/esm/MarkdownEditor/markdownEditor.css +223 -0
  15. package/lib/esm/OwnerTypeaheadDropdown/OwnerTypeaheadDropdown.d.ts +0 -2
  16. package/lib/esm/OwnerTypeaheadDropdown/OwnerTypeaheadDropdown.d.ts.map +1 -1
  17. package/lib/esm/OwnerTypeaheadDropdown/OwnerTypeaheadDropdown.js +3 -8
  18. package/lib/esm/PhoneInput/PhoneInput.d.ts.map +1 -1
  19. package/lib/esm/PhoneInput/PhoneInput.js +1 -38
  20. package/lib/esm/SingleSelectDropdown/SingleSelectDropdown.d.ts +0 -2
  21. package/lib/esm/SingleSelectDropdown/SingleSelectDropdown.d.ts.map +1 -1
  22. package/lib/esm/SingleSelectDropdown/SingleSelectDropdown.js +3 -6
  23. package/lib/esm/SupportFeedbackForm/SupportFeedbackModal.d.ts.map +1 -1
  24. package/lib/esm/SupportFeedbackForm/SupportFeedbackModal.js +80 -62
  25. package/lib/esm/Table/TablePagination.d.ts +0 -1
  26. package/lib/esm/Table/TablePagination.d.ts.map +1 -1
  27. package/lib/esm/Table/TablePagination.js +1 -1
  28. package/lib/esm/helperFunctions/errorMessage.d.ts +1 -2
  29. package/lib/esm/helperFunctions/errorMessage.d.ts.map +1 -1
  30. package/lib/esm/helperFunctions/errorMessage.js +5 -19
  31. package/lib/esm/hooks/useCopyToClipboard.d.ts +1 -1
  32. package/lib/esm/hooks/useCopyToClipboard.d.ts.map +1 -1
  33. package/lib/esm/hooks/useCopyToClipboard.js +1 -3
  34. package/lib/esm/index.d.ts +1 -3
  35. package/lib/esm/index.d.ts.map +1 -1
  36. package/lib/esm/index.js +1 -4
  37. package/package.json +6 -9
  38. package/lib/esm/CaseLabelLoadErrorModal/CaseLabelLoadErrorModal.d.ts +0 -10
  39. package/lib/esm/CaseLabelLoadErrorModal/CaseLabelLoadErrorModal.d.ts.map +0 -1
  40. package/lib/esm/CaseLabelLoadErrorModal/CaseLabelLoadErrorModal.js +0 -17
  41. package/lib/esm/CaseLabelLoadErrorModal/CaseLabelLoadErrorModal.scss +0 -13
  42. package/lib/esm/CaseLabelLoadErrorModal/index.d.ts +0 -2
  43. package/lib/esm/CaseLabelLoadErrorModal/index.d.ts.map +0 -1
  44. package/lib/esm/CaseLabelLoadErrorModal/index.js +0 -1
  45. package/lib/esm/CustomDatePicker/CustomDatePicker.d.ts +0 -18
  46. package/lib/esm/CustomDatePicker/CustomDatePicker.d.ts.map +0 -1
  47. package/lib/esm/CustomDatePicker/CustomDatePicker.js +0 -27
  48. package/lib/esm/CustomDatePicker/customDatePicker.css +0 -52
  49. package/lib/esm/CustomDatePicker/index.d.ts +0 -2
  50. package/lib/esm/CustomDatePicker/index.d.ts.map +0 -1
  51. package/lib/esm/CustomDatePicker/index.js +0 -1
  52. package/lib/esm/RichTextEditor/RichTextEditor.d.ts +0 -45
  53. package/lib/esm/RichTextEditor/RichTextEditor.d.ts.map +0 -1
  54. package/lib/esm/RichTextEditor/RichTextEditor.js +0 -463
  55. package/lib/esm/RichTextEditor/index.d.ts +0 -4
  56. package/lib/esm/RichTextEditor/index.d.ts.map +0 -1
  57. package/lib/esm/RichTextEditor/index.js +0 -2
  58. package/lib/esm/RichTextEditor/richTextEditor.css +0 -153
  59. package/lib/esm/RichTextEditor/useQuillEditor.d.ts +0 -20
  60. package/lib/esm/RichTextEditor/useQuillEditor.d.ts.map +0 -1
  61. package/lib/esm/RichTextEditor/useQuillEditor.js +0 -81
@@ -1,463 +0,0 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
- import './richTextEditor.css';
11
- import { Button, ButtonVariant, Dropdown, DropdownItem, DropdownList, FormGroup, MenuToggle, Modal, ModalBody, ModalFooter, ModalHeader, ModalVariant, TextInput, Toolbar, ToolbarGroup, } from '@patternfly/react-core';
12
- import AlignCenterIcon from '@patternfly/react-icons/dist/js/icons/align-center-icon';
13
- import AlignJustifyIcon from '@patternfly/react-icons/dist/js/icons/align-justify-icon';
14
- import AlignLeftIcon from '@patternfly/react-icons/dist/js/icons/align-left-icon';
15
- import AlignRightIcon from '@patternfly/react-icons/dist/js/icons/align-right-icon';
16
- import CaretDownIcon from '@patternfly/react-icons/dist/js/icons/caret-down-icon';
17
- import IndentIcon from '@patternfly/react-icons/dist/js/icons/indent-icon';
18
- import LinkIcon from '@patternfly/react-icons/dist/js/icons/link-icon';
19
- import ListOlIcon from '@patternfly/react-icons/dist/js/icons/list-ol-icon';
20
- import ListUlIcon from '@patternfly/react-icons/dist/js/icons/list-ul-icon';
21
- import OutdentIcon from '@patternfly/react-icons/dist/js/icons/outdent-icon';
22
- import RemoveFormatIcon from '@patternfly/react-icons/dist/js/icons/remove-format-icon';
23
- import StrikethroughIcon from '@patternfly/react-icons/dist/js/icons/strikethrough-icon';
24
- import React, { useCallback, useEffect, useRef, useState } from 'react';
25
- import { useTranslation } from 'react-i18next';
26
- import { ToastNotification } from '../ToastNotification';
27
- import { useQuillEditor } from './useQuillEditor';
28
- const defaultCharLimit = 32000;
29
- const defaultMinCharsForCounter = 31800;
30
- const ALLOWED_IMAGE_TYPES = new Set(['image/jpeg', 'image/png', 'image/gif', 'image/svg+xml']);
31
- const IMAGE_SIZE_LIMIT = 2 * 1024 * 1024; // 2 MB
32
- export function RichTextEditor(props) {
33
- const { t } = useTranslation();
34
- const { value, onChange, onChangePlainText, placeholder = '', disabled = false, className = '', id = 'rich-text-editor', hideToolbar = false, charLimit = defaultCharLimit, minCharsForCounter = defaultMinCharsForCounter, onCharLimitExceeded, height, onFocus, onBlur, bindEditor, 'aria-label': ariaLabel, onImageUpload, } = props;
35
- const [isHeadingDropdownOpen, setIsHeadingDropdownOpen] = useState(false);
36
- const [charCount, setCharCount] = useState(0);
37
- const charLimitExceededRef = useRef(false);
38
- const [isLinkModalOpen, setIsLinkModalOpen] = useState(false);
39
- const [linkUrl, setLinkUrl] = useState('');
40
- const [linkText, setLinkText] = useState('');
41
- const savedSelectionRef = useRef(null);
42
- const [isImageModalOpen, setIsImageModalOpen] = useState(false);
43
- const [imageUrl, setImageUrl] = useState('');
44
- const [imageUrlError, setImageUrlError] = useState('');
45
- const savedImageSelectionRef = useRef(null);
46
- const [, setIsImageUploading] = useState(false);
47
- const fileInputRef = useRef(null);
48
- const { editorRef, quillRef, activeFormat, setActiveFormat, setContents, setReadOnly } = useQuillEditor({
49
- placeholder,
50
- readOnly: disabled,
51
- onChange: (html) => {
52
- onChange(html);
53
- },
54
- onChangePlainText: (text) => {
55
- onChangePlainText === null || onChangePlainText === void 0 ? void 0 : onChangePlainText(text);
56
- setCharCount(text.length);
57
- },
58
- onFocus,
59
- onBlur,
60
- });
61
- // Sync external value into Quill when it changes externally
62
- useEffect(() => {
63
- setContents(value);
64
- }, [value, setContents]);
65
- // Sync disabled state
66
- useEffect(() => {
67
- setReadOnly(disabled);
68
- }, [disabled, setReadOnly]);
69
- // Bind editor ref externally
70
- useEffect(() => {
71
- if (quillRef.current && bindEditor) {
72
- bindEditor(quillRef.current);
73
- }
74
- }, [bindEditor, quillRef]);
75
- // Character limit exceeded callback
76
- useEffect(() => {
77
- const exceeded = charCount > charLimit;
78
- if (exceeded !== charLimitExceededRef.current) {
79
- charLimitExceededRef.current = exceeded;
80
- onCharLimitExceeded === null || onCharLimitExceeded === void 0 ? void 0 : onCharLimitExceeded(exceeded);
81
- }
82
- }, [charCount, charLimit, onCharLimitExceeded]);
83
- const onImageUploadRef = useRef(onImageUpload);
84
- onImageUploadRef.current = onImageUpload;
85
- useEffect(() => {
86
- const editorEl = editorRef.current;
87
- if (!editorEl || !onImageUploadRef.current)
88
- return;
89
- const handlePaste = (e) => __awaiter(this, void 0, void 0, function* () {
90
- var _a;
91
- if (!((_a = e.clipboardData) === null || _a === void 0 ? void 0 : _a.items))
92
- return;
93
- const imageItem = Array.from(e.clipboardData.items).find((item) => item.type.startsWith('image/') && ALLOWED_IMAGE_TYPES.has(item.type));
94
- if (!imageItem)
95
- return;
96
- const file = imageItem.getAsFile();
97
- if (!file)
98
- return;
99
- if (file.size > IMAGE_SIZE_LIMIT) {
100
- e.preventDefault();
101
- e.stopPropagation();
102
- return;
103
- }
104
- e.preventDefault();
105
- e.stopPropagation();
106
- const quill = quillRef.current;
107
- if (!quill)
108
- return;
109
- const range = quill.getSelection() || { index: quill.getLength() - 1, length: 0 };
110
- setIsImageUploading(true);
111
- try {
112
- const url = yield onImageUploadRef.current(file);
113
- if (url) {
114
- quill.insertEmbed(range.index, 'image', url);
115
- quill.setSelection(range.index + 1, 0, 'silent');
116
- }
117
- }
118
- catch (_b) {
119
- // Error handled by the consumer's upload implementation
120
- }
121
- finally {
122
- setIsImageUploading(false);
123
- }
124
- });
125
- editorEl.addEventListener('paste', handlePaste);
126
- return () => {
127
- editorEl.removeEventListener('paste', handlePaste);
128
- };
129
- // eslint-disable-next-line react-hooks/exhaustive-deps
130
- }, [editorRef, quillRef]);
131
- const formatToggle = useCallback((format, value) => {
132
- const quill = quillRef.current;
133
- if (!quill)
134
- return;
135
- const selection = quill.getSelection();
136
- if (!selection)
137
- return;
138
- const newValue = value !== null && value !== void 0 ? value : !activeFormat[format];
139
- quill.format(format, newValue);
140
- setActiveFormat((prev) => {
141
- const next = Object.assign({}, prev);
142
- if (newValue) {
143
- next[format] = newValue;
144
- }
145
- else {
146
- delete next[format];
147
- }
148
- return next;
149
- });
150
- }, [activeFormat, quillRef, setActiveFormat]);
151
- const onLinkClick = useCallback(() => {
152
- const quill = quillRef.current;
153
- if (!quill)
154
- return;
155
- const range = quill.getSelection();
156
- if (!range)
157
- return;
158
- if (activeFormat.link) {
159
- quill.format('link', false);
160
- setActiveFormat((prev) => {
161
- const next = Object.assign({}, prev);
162
- delete next.link;
163
- return next;
164
- });
165
- }
166
- else {
167
- savedSelectionRef.current = { index: range.index, length: range.length };
168
- setLinkText(range.length > 0 ? quill.getText(range.index, range.length).trim() : '');
169
- setLinkUrl('');
170
- setIsLinkModalOpen(true);
171
- }
172
- }, [activeFormat, quillRef, setActiveFormat]);
173
- const onLinkInsert = useCallback(() => {
174
- const quill = quillRef.current;
175
- const saved = savedSelectionRef.current;
176
- const url = linkUrl.trim();
177
- const text = linkText.trim() || url;
178
- if (!quill || !saved || !url)
179
- return;
180
- if (saved.length > 0) {
181
- quill.setSelection(saved.index, saved.length, 'silent');
182
- quill.format('link', url);
183
- }
184
- else {
185
- quill.insertText(saved.index, text, 'link', url, 'user');
186
- quill.setSelection(saved.index + text.length, 0, 'silent');
187
- }
188
- setActiveFormat((prev) => (Object.assign(Object.assign({}, prev), { link: url })));
189
- savedSelectionRef.current = null;
190
- setIsLinkModalOpen(false);
191
- setLinkUrl('');
192
- setLinkText('');
193
- }, [linkUrl, linkText, quillRef, setActiveFormat]);
194
- const onLinkCancel = useCallback(() => {
195
- savedSelectionRef.current = null;
196
- setIsLinkModalOpen(false);
197
- setLinkText('');
198
- setLinkUrl('');
199
- }, []);
200
- const handleFileInputChange = useCallback((e) => __awaiter(this, void 0, void 0, function* () {
201
- var _a;
202
- const file = (_a = e.target.files) === null || _a === void 0 ? void 0 : _a[0];
203
- if (fileInputRef.current)
204
- fileInputRef.current.value = '';
205
- if (!file || !onImageUpload)
206
- return;
207
- if (!ALLOWED_IMAGE_TYPES.has(file.type)) {
208
- ToastNotification.addDangerMessage(t('Invalid file type. Only JPEG, PNG, GIF, and SVG images are allowed.'));
209
- return;
210
- }
211
- if (file.size > IMAGE_SIZE_LIMIT) {
212
- ToastNotification.addDangerMessage(t('File is too large. Maximum size is 2 MB.'));
213
- return;
214
- }
215
- const quill = quillRef.current;
216
- const saved = savedImageSelectionRef.current;
217
- if (!quill || !saved)
218
- return;
219
- setIsImageUploading(true);
220
- try {
221
- const url = yield onImageUpload(file);
222
- if (url) {
223
- quill.focus();
224
- quill.setSelection(saved.index, saved.length, 'silent');
225
- quill.insertEmbed(saved.index, 'image', url);
226
- }
227
- }
228
- catch (_b) {
229
- ToastNotification.addDangerMessage(t('Failed to upload image.'));
230
- }
231
- finally {
232
- setIsImageUploading(false);
233
- savedImageSelectionRef.current = null;
234
- }
235
- }), [onImageUpload, quillRef, t]);
236
- const onImageInsert = useCallback(() => {
237
- const quill = quillRef.current;
238
- const saved = savedImageSelectionRef.current;
239
- if (!quill || !saved || !imageUrl.trim())
240
- return;
241
- const url = imageUrl.trim();
242
- try {
243
- const parsed = new URL(url);
244
- if (parsed.hostname !== 'redhat.com' && !parsed.hostname.endsWith('.redhat.com')) {
245
- setImageUrlError(t('Only *.redhat.com URLs are allowed'));
246
- return;
247
- }
248
- }
249
- catch (_a) {
250
- setImageUrlError(t('Only *.redhat.com URLs are allowed'));
251
- return;
252
- }
253
- quill.setSelection(saved.index, saved.length, 'silent');
254
- quill.insertEmbed(saved.index, 'image', url);
255
- savedImageSelectionRef.current = null;
256
- setIsImageModalOpen(false);
257
- setImageUrl('');
258
- setImageUrlError('');
259
- }, [imageUrl, quillRef, t]);
260
- const onImageCancel = useCallback(() => {
261
- savedImageSelectionRef.current = null;
262
- setIsImageModalOpen(false);
263
- setImageUrl('');
264
- setImageUrlError('');
265
- }, []);
266
- const onImageUrlChange = useCallback((_e, val) => {
267
- setImageUrl(val);
268
- if (val.trim()) {
269
- try {
270
- const parsed = new URL(val.trim());
271
- if (parsed.hostname !== 'redhat.com' && !parsed.hostname.endsWith('.redhat.com')) {
272
- setImageUrlError(t('Only *.redhat.com URLs are allowed'));
273
- }
274
- else {
275
- setImageUrlError('');
276
- }
277
- }
278
- catch (_a) {
279
- setImageUrlError(t('Only *.redhat.com URLs are allowed'));
280
- }
281
- }
282
- else {
283
- setImageUrlError('');
284
- }
285
- }, [t]);
286
- const onImageUrlKeyDown = useCallback((e) => {
287
- if (e.key === 'Enter') {
288
- e.preventDefault();
289
- onImageInsert();
290
- }
291
- }, [onImageInsert]);
292
- const onLinkTextChange = useCallback((_e, val) => {
293
- setLinkText(val);
294
- }, []);
295
- const onLinkUrlChange = useCallback((_e, val) => {
296
- setLinkUrl(val);
297
- }, []);
298
- const onLinkUrlKeyDown = useCallback((e) => {
299
- if (e.key === 'Enter') {
300
- e.preventDefault();
301
- onLinkInsert();
302
- }
303
- }, [onLinkInsert]);
304
- const onToolbarMouseDown = useCallback((e) => {
305
- e.preventDefault();
306
- }, []);
307
- const onBoldClick = useCallback(() => formatToggle('bold'), [formatToggle]);
308
- const onItalicClick = useCallback(() => formatToggle('italic'), [formatToggle]);
309
- const onUnderlineClick = useCallback(() => formatToggle('underline'), [formatToggle]);
310
- const onStrikethroughClick = useCallback(() => formatToggle('strike'), [formatToggle]);
311
- const onIndentClick = useCallback(() => {
312
- const quill = quillRef.current;
313
- if (!quill)
314
- return;
315
- const range = quill.getSelection();
316
- if (!range)
317
- return;
318
- const current = quill.getFormat(range).indent || 0;
319
- quill.format('indent', current + 1);
320
- setActiveFormat((prev) => (Object.assign(Object.assign({}, prev), { indent: current + 1 })));
321
- }, [quillRef, setActiveFormat]);
322
- const onOutdentClick = useCallback(() => {
323
- const quill = quillRef.current;
324
- if (!quill)
325
- return;
326
- const range = quill.getSelection();
327
- if (!range)
328
- return;
329
- const current = quill.getFormat(range).indent || 0;
330
- if (current > 0) {
331
- quill.format('indent', current - 1 || false);
332
- setActiveFormat((prev) => (Object.assign(Object.assign({}, prev), { indent: current - 1 || false })));
333
- }
334
- }, [quillRef, setActiveFormat]);
335
- const onAlignClick = useCallback((alignment) => {
336
- const quill = quillRef.current;
337
- if (!quill)
338
- return;
339
- const range = quill.getSelection();
340
- if (!range)
341
- return;
342
- const currentAlign = activeFormat.align || false;
343
- const newValue = currentAlign === alignment ? false : alignment;
344
- quill.format('align', newValue);
345
- setActiveFormat((prev) => {
346
- const next = Object.assign({}, prev);
347
- if (newValue) {
348
- next.align = newValue;
349
- }
350
- else {
351
- delete next.align;
352
- }
353
- return next;
354
- });
355
- }, [activeFormat.align, quillRef, setActiveFormat]);
356
- const onAlignLeftClick = useCallback(() => onAlignClick(false), [onAlignClick]);
357
- const onAlignCenterClick = useCallback(() => onAlignClick('center'), [onAlignClick]);
358
- const onAlignRightClick = useCallback(() => onAlignClick('right'), [onAlignClick]);
359
- const onAlignJustifyClick = useCallback(() => onAlignClick('justify'), [onAlignClick]);
360
- const onRemoveFormatClick = useCallback(() => {
361
- const quill = quillRef.current;
362
- if (!quill)
363
- return;
364
- const range = quill.getSelection();
365
- if (!range)
366
- return;
367
- if (range.length === 0) {
368
- const [line, offset] = quill.getLine(range.index);
369
- if (line) {
370
- quill.removeFormat(range.index - offset, line.length());
371
- }
372
- }
373
- else {
374
- quill.removeFormat(range.index, range.length);
375
- }
376
- setActiveFormat(quill.getFormat(range));
377
- }, [quillRef, setActiveFormat]);
378
- const onHeadingSelect = useCallback(() => setIsHeadingDropdownOpen(false), []);
379
- const onHeadingToggleClick = useCallback(() => setIsHeadingDropdownOpen((prev) => !prev), []);
380
- const onHeading1Click = useCallback(() => formatToggle('header', 1), [formatToggle]);
381
- const onHeading2Click = useCallback(() => formatToggle('header', 2), [formatToggle]);
382
- const onHeading3Click = useCallback(() => formatToggle('header', 3), [formatToggle]);
383
- const onHeadingNormalClick = useCallback(() => formatToggle('header', false), [formatToggle]);
384
- const onBulletListClick = useCallback(() => formatToggle('list', activeFormat.list === 'bullet' ? false : 'bullet'), [formatToggle, activeFormat.list]);
385
- const onOrderedListClick = useCallback(() => formatToggle('list', activeFormat.list === 'ordered' ? false : 'ordered'), [formatToggle, activeFormat.list]);
386
- const headingToggleRenderer = useCallback((toggleRef) => {
387
- const headingLevel = activeFormat.header;
388
- const label = headingLevel ? `Heading ${headingLevel}` : 'Normal';
389
- return (React.createElement(MenuToggle, { ref: toggleRef, onClick: onHeadingToggleClick, isDisabled: disabled, variant: "plain", "aria-label": `Text style: ${label}`, className: `richtext-toolbar-btn ${headingLevel ? 'pf-m-active' : ''}` },
390
- React.createElement("span", { className: "toggle-content" },
391
- label,
392
- " ",
393
- React.createElement(CaretDownIcon, { className: "dropdown-caret" }))));
394
- }, [activeFormat.header, disabled, onHeadingToggleClick]);
395
- const editorStyle = {};
396
- if (height) {
397
- editorStyle.height = typeof height === 'number' ? `${height}px` : height;
398
- }
399
- const showCounter = charCount >= minCharsForCounter;
400
- const isOverLimit = charCount > charLimit;
401
- return (React.createElement("div", { id: id, className: `richtext-editor-container ${disabled ? 'richtext-editor-container--disabled' : ''} ${className}` },
402
- !hideToolbar && (React.createElement(Toolbar, { className: "richtext-toolbar", role: "toolbar", "aria-label": "Formatting options", onMouseDown: onToolbarMouseDown },
403
- React.createElement(ToolbarGroup, { className: "richtext-toolbar-left-section" },
404
- React.createElement(Button, { variant: ButtonVariant.plain, isClicked: !!activeFormat.bold, isDisabled: disabled, onClick: onBoldClick, "aria-label": "Bold", "aria-pressed": !!activeFormat.bold, className: "richtext-toolbar-btn" },
405
- React.createElement("strong", null, "B")),
406
- React.createElement(Button, { variant: ButtonVariant.plain, isClicked: !!activeFormat.italic, isDisabled: disabled, onClick: onItalicClick, "aria-label": "Italic", "aria-pressed": !!activeFormat.italic, className: "richtext-toolbar-btn" },
407
- React.createElement("em", null, "I")),
408
- React.createElement(Button, { variant: ButtonVariant.plain, isClicked: !!activeFormat.underline, isDisabled: disabled, onClick: onUnderlineClick, "aria-label": "Underline", "aria-pressed": !!activeFormat.underline, className: "richtext-toolbar-btn" },
409
- React.createElement("u", null, "U")),
410
- React.createElement(Button, { icon: React.createElement(StrikethroughIcon, null), variant: ButtonVariant.plain, isClicked: !!activeFormat.strike, isDisabled: disabled, onClick: onStrikethroughClick, "aria-label": "Strikethrough", "aria-pressed": !!activeFormat.strike, className: "richtext-toolbar-btn" }),
411
- React.createElement("div", { className: "btn-group-separator" }),
412
- React.createElement(Dropdown, { isOpen: isHeadingDropdownOpen, onSelect: onHeadingSelect, onOpenChange: setIsHeadingDropdownOpen, toggle: headingToggleRenderer },
413
- React.createElement(DropdownList, null,
414
- React.createElement(DropdownItem, { key: "h1", onClick: onHeading1Click }, "Heading 1"),
415
- React.createElement(DropdownItem, { key: "h2", onClick: onHeading2Click }, "Heading 2"),
416
- React.createElement(DropdownItem, { key: "h3", onClick: onHeading3Click }, "Heading 3"),
417
- React.createElement(DropdownItem, { key: "normal", onClick: onHeadingNormalClick }, "Normal"))),
418
- React.createElement("div", { className: "btn-group-separator" }),
419
- React.createElement(Button, { icon: React.createElement(ListUlIcon, null), variant: ButtonVariant.plain, isClicked: activeFormat.list === 'bullet', isDisabled: disabled, onClick: onBulletListClick, "aria-label": "Bullet List", "aria-pressed": activeFormat.list === 'bullet', className: "richtext-toolbar-btn" }),
420
- React.createElement(Button, { icon: React.createElement(ListOlIcon, null), variant: ButtonVariant.plain, isClicked: activeFormat.list === 'ordered', isDisabled: disabled, onClick: onOrderedListClick, "aria-label": "Ordered List", "aria-pressed": activeFormat.list === 'ordered', className: "richtext-toolbar-btn" }),
421
- React.createElement(Button, { icon: React.createElement(IndentIcon, null), variant: ButtonVariant.plain, isDisabled: disabled, onClick: onIndentClick, "aria-label": "Indent", className: "richtext-toolbar-btn" }),
422
- React.createElement(Button, { icon: React.createElement(OutdentIcon, null), variant: ButtonVariant.plain, isDisabled: disabled, onClick: onOutdentClick, "aria-label": "Outdent", className: "richtext-toolbar-btn" }),
423
- React.createElement("div", { className: "btn-group-separator" }),
424
- React.createElement(Button, { icon: React.createElement(AlignLeftIcon, null), variant: ButtonVariant.plain, isClicked: !activeFormat.align, isDisabled: disabled, onClick: onAlignLeftClick, "aria-label": "Align Left", "aria-pressed": !activeFormat.align, className: "richtext-toolbar-btn" }),
425
- React.createElement(Button, { icon: React.createElement(AlignCenterIcon, null), variant: ButtonVariant.plain, isClicked: activeFormat.align === 'center', isDisabled: disabled, onClick: onAlignCenterClick, "aria-label": "Align Center", "aria-pressed": activeFormat.align === 'center', className: "richtext-toolbar-btn" }),
426
- React.createElement(Button, { icon: React.createElement(AlignRightIcon, null), variant: ButtonVariant.plain, isClicked: activeFormat.align === 'right', isDisabled: disabled, onClick: onAlignRightClick, "aria-label": "Align Right", "aria-pressed": activeFormat.align === 'right', className: "richtext-toolbar-btn" }),
427
- React.createElement(Button, { icon: React.createElement(AlignJustifyIcon, null), variant: ButtonVariant.plain, isClicked: activeFormat.align === 'justify', isDisabled: disabled, onClick: onAlignJustifyClick, "aria-label": "Justify", "aria-pressed": activeFormat.align === 'justify', className: "richtext-toolbar-btn" }),
428
- React.createElement("div", { className: "btn-group-separator" }),
429
- React.createElement(Button, { icon: React.createElement(LinkIcon, null), variant: ButtonVariant.plain, isClicked: !!activeFormat.link, isDisabled: disabled, onClick: onLinkClick, "aria-label": "Link", "aria-pressed": !!activeFormat.link, className: "richtext-toolbar-btn" }),
430
- React.createElement(Button, { icon: React.createElement(RemoveFormatIcon, null), variant: ButtonVariant.plain, isDisabled: disabled, onClick: onRemoveFormatClick, "aria-label": "Remove Format", className: "richtext-toolbar-btn" })))),
431
- React.createElement("div", { ref: editorRef, role: "textbox", className: "richtext-editor-content", style: editorStyle, "aria-label": ariaLabel, tabIndex: -1, onClick: () => { var _a, _b; return (_b = (_a = editorRef.current) === null || _a === void 0 ? void 0 : _a.querySelector('[contenteditable="true"]')) === null || _b === void 0 ? void 0 : _b.focus(); }, onKeyDown: (e) => {
432
- var _a, _b;
433
- if (e.key === 'Enter' || e.key === ' ') {
434
- (_b = (_a = editorRef.current) === null || _a === void 0 ? void 0 : _a.querySelector('[contenteditable="true"]')) === null || _b === void 0 ? void 0 : _b.focus();
435
- }
436
- } }),
437
- showCounter && (React.createElement("div", { className: `richtext-char-counter ${isOverLimit ? 'richtext-char-counter--exceeded' : ''}` },
438
- charCount,
439
- "/",
440
- charLimit)),
441
- React.createElement(Modal, { variant: ModalVariant.small, isOpen: isLinkModalOpen, onClose: onLinkCancel, "aria-labelledby": "insert-link-title" },
442
- React.createElement(ModalHeader, { title: "Insert link", labelId: "insert-link-title" }),
443
- React.createElement(ModalBody, null,
444
- React.createElement(FormGroup, { label: "Display text", fieldId: "link-text-input" },
445
- React.createElement(TextInput, { id: "link-text-input", value: linkText, onChange: onLinkTextChange, placeholder: "Link text (defaults to URL)" })),
446
- React.createElement(FormGroup, { label: "URL", isRequired: true, fieldId: "link-url-input" },
447
- React.createElement(TextInput, { id: "link-url-input", type: "url", value: linkUrl, onChange: onLinkUrlChange, placeholder: "https://", onKeyDown: onLinkUrlKeyDown }))),
448
- React.createElement(ModalFooter, null,
449
- React.createElement(Button, { variant: ButtonVariant.primary, onClick: onLinkInsert, isDisabled: !linkUrl.trim() }, "Insert"),
450
- React.createElement(Button, { variant: ButtonVariant.link, onClick: onLinkCancel }, "Cancel"))),
451
- React.createElement("input", { ref: fileInputRef, type: "file", accept: "image/jpeg,image/png,image/gif,image/svg+xml", style: { display: 'none' }, onChange: handleFileInputChange, tabIndex: -1 }),
452
- !onImageUpload && (React.createElement(Modal, { variant: ModalVariant.small, isOpen: isImageModalOpen, onClose: onImageCancel, "aria-labelledby": "insert-image-title" },
453
- React.createElement(ModalHeader, { title: "Insert image", labelId: "insert-image-title" }),
454
- React.createElement(ModalBody, null,
455
- React.createElement(FormGroup, { label: "Image URL", isRequired: true, fieldId: "image-url-input" },
456
- React.createElement(TextInput, { id: "image-url-input", type: "url", value: imageUrl, validated: imageUrlError ? 'error' : 'default', onChange: onImageUrlChange, placeholder: "https://example.redhat.com/image.png", onKeyDown: onImageUrlKeyDown }),
457
- imageUrlError && (React.createElement(FormGroup, null,
458
- React.createElement("span", { className: "pf-v6-u-danger-color-100 pf-v6-u-font-size-sm" }, imageUrlError))))),
459
- React.createElement(ModalFooter, null,
460
- React.createElement(Button, { variant: ButtonVariant.primary, onClick: onImageInsert, isDisabled: !imageUrl.trim() || !!imageUrlError }, "Insert"),
461
- React.createElement(Button, { variant: ButtonVariant.link, onClick: onImageCancel }, "Cancel"))))));
462
- }
463
- export default RichTextEditor;
@@ -1,4 +0,0 @@
1
- export * from './RichTextEditor';
2
- export { useQuillEditor } from './useQuillEditor';
3
- export type { UseQuillEditorOptions } from './useQuillEditor';
4
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/RichTextEditor/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,YAAY,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -1,2 +0,0 @@
1
- export * from './RichTextEditor';
2
- export { useQuillEditor } from './useQuillEditor';
@@ -1,153 +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: auto;
17
- font-size: 15px;
18
- min-width: 100%;
19
- outline: none;
20
- border: none;
21
- min-height: 100px;
22
- }
23
-
24
- .richtext-editor-content.ql-container,
25
- .richtext-editor-container .ql-container.ql-container {
26
- border: none !important;
27
- outline: none !important;
28
- font-size: 15px;
29
- }
30
-
31
- .richtext-editor-content .ql-editor {
32
- padding: 0.8rem;
33
- outline: none;
34
- border: none;
35
- min-height: 100px;
36
- }
37
-
38
- .richtext-editor-content .ql-editor:focus {
39
- outline: none;
40
- border: none;
41
- box-shadow: none;
42
- }
43
-
44
- .richtext-editor-content:empty::before {
45
- content: attr(data-placeholder);
46
- color: var(--pf-t--global--text--color--placeholder, #6a6e73);
47
- pointer-events: none;
48
- }
49
-
50
- .richtext-editor-content ul,
51
- .richtext-editor-content ol {
52
- padding-left: 24px;
53
- }
54
-
55
- .richtext-editor-content li[data-list='bullet'] {
56
- list-style-type: disc;
57
- }
58
-
59
- .richtext-editor-content li[data-list='ordered'] {
60
- list-style-type: decimal;
61
- }
62
-
63
- .richtext-editor-content .ql-align-center {
64
- text-align: center;
65
- }
66
-
67
- .richtext-editor-content .ql-align-right {
68
- text-align: right;
69
- }
70
-
71
- .richtext-editor-content .ql-align-justify {
72
- text-align: justify;
73
- }
74
-
75
- .richtext-editor-content .ql-indent-1 {
76
- padding-left: 3em;
77
- }
78
-
79
- .richtext-editor-content .ql-indent-2 {
80
- padding-left: 6em;
81
- }
82
-
83
- .richtext-editor-content .ql-indent-3 {
84
- padding-left: 9em;
85
- }
86
-
87
- .richtext-editor-content .ql-indent-4 {
88
- padding-left: 12em;
89
- }
90
-
91
- .richtext-editor-content .ql-indent-5 {
92
- padding-left: 15em;
93
- }
94
-
95
- .richtext-editor-content a {
96
- color: var(--pf-t--global--text--color--link--default, #0066cc);
97
- text-decoration: underline;
98
- }
99
-
100
- .richtext-editor-content img {
101
- max-width: 100%;
102
- height: auto;
103
- display: block;
104
- margin: 8px 0;
105
- }
106
-
107
- .richtext-editor-container.is-private .richtext-editor-content {
108
- background-color: #f5eeee;
109
- }
110
-
111
- .richtext-toolbar {
112
- border-bottom: 1px solid var(--pf-t--global--border--color--default, #d2d2d2);
113
- padding: 4px 8px;
114
- }
115
-
116
- .richtext-toolbar-left-section {
117
- display: flex;
118
- align-items: center;
119
- flex-wrap: wrap;
120
- gap: 2px;
121
- }
122
-
123
- .btn-group-separator {
124
- display: inline-block;
125
- width: 1px;
126
- height: 24px;
127
- margin: 0 8px;
128
- background-color: var(--pf-t--global--border--color--default, #ccc);
129
- }
130
-
131
- .toggle-content {
132
- display: inline-flex;
133
- align-items: center;
134
- gap: 4px;
135
- font-size: 14px;
136
- }
137
-
138
- .dropdown-caret {
139
- font-size: 12px;
140
- }
141
-
142
- .richtext-char-counter {
143
- padding: 4px 8px;
144
- font-size: 12px;
145
- text-align: right;
146
- color: var(--pf-t--global--text--color--subtle, #6a6e73);
147
- border-top: 1px solid var(--pf-t--global--border--color--default, #d2d2d2);
148
- }
149
-
150
- .richtext-char-counter--exceeded {
151
- color: var(--pf-t--global--color--status--danger--default, #c9190b);
152
- font-weight: bold;
153
- }
@@ -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,KAAK,MAAM,OAAO,CAAC;AAG1B,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;AAID,wBAAgB,cAAc,CAAC,OAAO,EAAE,qBAAqB;;;;;wBAwDlB,MAAM;4BAgBF,OAAO;;EASrD"}