@rh-support/components 2.5.203 → 2.5.205

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.
@@ -0,0 +1,148 @@
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-content {
10
+ resize: vertical;
11
+ overflow: auto;
12
+ font-size: 15px;
13
+ min-width: 100%;
14
+ outline: none;
15
+ border: none;
16
+ min-height: 100px;
17
+ }
18
+
19
+ .richtext-editor-content.ql-container,
20
+ .richtext-editor-container .ql-container.ql-container {
21
+ border: none !important;
22
+ outline: none !important;
23
+ font-size: 15px;
24
+ }
25
+
26
+ .richtext-editor-content .ql-editor {
27
+ padding: 0.8rem;
28
+ outline: none;
29
+ border: none;
30
+ min-height: 100px;
31
+ }
32
+
33
+ .richtext-editor-content .ql-editor:focus {
34
+ outline: none;
35
+ border: none;
36
+ box-shadow: none;
37
+ }
38
+
39
+ .richtext-editor-content:empty::before {
40
+ content: attr(data-placeholder);
41
+ color: var(--pf-t--global--text--color--placeholder, #6a6e73);
42
+ pointer-events: none;
43
+ }
44
+
45
+ .richtext-editor-content ul,
46
+ .richtext-editor-content ol {
47
+ padding-left: 24px;
48
+ }
49
+
50
+ .richtext-editor-content li[data-list='bullet'] {
51
+ list-style-type: disc;
52
+ }
53
+
54
+ .richtext-editor-content li[data-list='ordered'] {
55
+ list-style-type: decimal;
56
+ }
57
+
58
+ .richtext-editor-content .ql-align-center {
59
+ text-align: center;
60
+ }
61
+
62
+ .richtext-editor-content .ql-align-right {
63
+ text-align: right;
64
+ }
65
+
66
+ .richtext-editor-content .ql-align-justify {
67
+ text-align: justify;
68
+ }
69
+
70
+ .richtext-editor-content .ql-indent-1 {
71
+ padding-left: 3em;
72
+ }
73
+
74
+ .richtext-editor-content .ql-indent-2 {
75
+ padding-left: 6em;
76
+ }
77
+
78
+ .richtext-editor-content .ql-indent-3 {
79
+ padding-left: 9em;
80
+ }
81
+
82
+ .richtext-editor-content .ql-indent-4 {
83
+ padding-left: 12em;
84
+ }
85
+
86
+ .richtext-editor-content .ql-indent-5 {
87
+ padding-left: 15em;
88
+ }
89
+
90
+ .richtext-editor-content a {
91
+ color: var(--pf-t--global--text--color--link--default, #0066cc);
92
+ text-decoration: underline;
93
+ }
94
+
95
+ .richtext-editor-content img {
96
+ max-width: 100%;
97
+ height: auto;
98
+ display: block;
99
+ margin: 8px 0;
100
+ }
101
+
102
+ .richtext-editor-container.is-private .richtext-editor-content {
103
+ background-color: #f5eeee;
104
+ }
105
+
106
+ .richtext-toolbar {
107
+ border-bottom: 1px solid var(--pf-t--global--border--color--default, #d2d2d2);
108
+ padding: 4px 8px;
109
+ }
110
+
111
+ .richtext-toolbar-left-section {
112
+ display: flex;
113
+ align-items: center;
114
+ flex-wrap: wrap;
115
+ gap: 2px;
116
+ }
117
+
118
+ .btn-group-separator {
119
+ display: inline-block;
120
+ width: 1px;
121
+ height: 24px;
122
+ margin: 0 8px;
123
+ background-color: var(--pf-t--global--border--color--default, #ccc);
124
+ }
125
+
126
+ .toggle-content {
127
+ display: inline-flex;
128
+ align-items: center;
129
+ gap: 4px;
130
+ font-size: 14px;
131
+ }
132
+
133
+ .dropdown-caret {
134
+ font-size: 12px;
135
+ }
136
+
137
+ .richtext-char-counter {
138
+ padding: 4px 8px;
139
+ font-size: 12px;
140
+ text-align: right;
141
+ color: var(--pf-t--global--text--color--subtle, #6a6e73);
142
+ border-top: 1px solid var(--pf-t--global--border--color--default, #d2d2d2);
143
+ }
144
+
145
+ .richtext-char-counter--exceeded {
146
+ color: var(--pf-t--global--color--status--danger--default, #c9190b);
147
+ font-weight: bold;
148
+ }
@@ -0,0 +1,20 @@
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
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,81 @@
1
+ import DOMPurify from 'dompurify';
2
+ import Quill from 'quill';
3
+ import { useCallback, useEffect, useRef, useState } from 'react';
4
+ const ALLOWED_FORMATS = ['header', 'bold', 'italic', 'underline', 'strike', 'list', 'indent', 'align', 'link', 'image'];
5
+ export function useQuillEditor(options) {
6
+ const editorRef = useRef(null);
7
+ const quillRef = useRef(null);
8
+ const [activeFormat, setActiveFormat] = useState({});
9
+ const optionsRef = useRef(options);
10
+ optionsRef.current = options;
11
+ // Track whether the last change was internal (from Quill) to avoid echo loops
12
+ const isInternalChange = useRef(false);
13
+ useEffect(() => {
14
+ if (!editorRef.current || quillRef.current)
15
+ return;
16
+ const quill = new Quill(editorRef.current, {
17
+ theme: false,
18
+ modules: {
19
+ toolbar: false,
20
+ clipboard: { matchVisual: false },
21
+ },
22
+ formats: ALLOWED_FORMATS,
23
+ placeholder: optionsRef.current.placeholder,
24
+ readOnly: optionsRef.current.readOnly,
25
+ });
26
+ quill.on('text-change', () => {
27
+ var _a, _b, _c, _d;
28
+ isInternalChange.current = true;
29
+ const html = DOMPurify.sanitize(quill.getSemanticHTML());
30
+ (_b = (_a = optionsRef.current).onChange) === null || _b === void 0 ? void 0 : _b.call(_a, html);
31
+ (_d = (_c = optionsRef.current).onChangePlainText) === null || _d === void 0 ? void 0 : _d.call(_c, quill.getText().trim());
32
+ const sel = quill.getSelection();
33
+ if (sel) {
34
+ setActiveFormat(quill.getFormat(sel));
35
+ }
36
+ isInternalChange.current = false;
37
+ });
38
+ quill.on('selection-change', (range) => {
39
+ var _a, _b, _c, _d, _e, _f;
40
+ if (range) {
41
+ setActiveFormat(quill.getFormat(range));
42
+ (_b = (_a = optionsRef.current).onSelectionChange) === null || _b === void 0 ? void 0 : _b.call(_a, quill.getFormat(range));
43
+ if (range.length === 0) {
44
+ (_d = (_c = optionsRef.current).onFocus) === null || _d === void 0 ? void 0 : _d.call(_c);
45
+ }
46
+ }
47
+ else {
48
+ (_f = (_e = optionsRef.current).onBlur) === null || _f === void 0 ? void 0 : _f.call(_e);
49
+ }
50
+ });
51
+ quillRef.current = quill;
52
+ return () => {
53
+ quillRef.current = null;
54
+ };
55
+ // eslint-disable-next-line react-hooks/exhaustive-deps
56
+ }, []);
57
+ const setContents = useCallback((html) => {
58
+ const quill = quillRef.current;
59
+ if (!quill || isInternalChange.current)
60
+ return;
61
+ const currentHtml = DOMPurify.sanitize(quill.getSemanticHTML());
62
+ if (currentHtml === html)
63
+ return;
64
+ const selection = quill.getSelection();
65
+ quill.clipboard.dangerouslyPasteHTML(html);
66
+ if (selection) {
67
+ const length = quill.getLength();
68
+ const safeIndex = Math.min(selection.index, length - 1);
69
+ quill.setSelection(safeIndex, 0, 'silent');
70
+ }
71
+ }, []);
72
+ const setReadOnly = useCallback((readOnly) => {
73
+ var _a;
74
+ (_a = quillRef.current) === null || _a === void 0 ? void 0 : _a.enable(!readOnly);
75
+ }, []);
76
+ const getPlainText = useCallback(() => {
77
+ var _a, _b;
78
+ return (_b = (_a = quillRef.current) === null || _a === void 0 ? void 0 : _a.getText().trim()) !== null && _b !== void 0 ? _b : '';
79
+ }, []);
80
+ return { editorRef, quillRef, activeFormat, setActiveFormat, setContents, setReadOnly, getPlainText };
81
+ }
@@ -5,7 +5,7 @@ export * from './ErrorBoundary';
5
5
  export * from './ErrorPages';
6
6
  export * from './LoginModal';
7
7
  export * from './Table';
8
- export * from './MarkdownEditor';
8
+ export * from './RichTextEditor';
9
9
  export * from './InlineEdit';
10
10
  export * from './CoverSpinner';
11
11
  export * from './hooks';
package/lib/esm/index.js CHANGED
@@ -6,7 +6,7 @@ export * from './ErrorBoundary';
6
6
  export * from './ErrorPages';
7
7
  export * from './LoginModal';
8
8
  export * from './Table';
9
- export * from './MarkdownEditor';
9
+ export * from './RichTextEditor';
10
10
  export * from './InlineEdit';
11
11
  export * from './CoverSpinner';
12
12
  export * from './hooks';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rh-support/components",
3
- "version": "2.5.203",
3
+ "version": "2.5.205",
4
4
  "description": "Contains all reusabel components for support app",
5
5
  "author": "Vikas Rathee <vrathee@redhat.com>",
6
6
  "license": "ISC",
@@ -62,13 +62,14 @@
62
62
  "@patternfly/react-icons": "6.2.1",
63
63
  "@patternfly/react-table": "6.2.1",
64
64
  "@rh-support/types": "2.0.26",
65
- "@rh-support/user-permissions": "2.5.150",
66
- "@rh-support/utils": "2.5.132",
65
+ "@rh-support/user-permissions": "2.5.152",
66
+ "@rh-support/utils": "2.5.134",
67
67
  "dompurify": "^2.2.6",
68
68
  "js-worker-search": "^1.4.1",
69
69
  "lazysizes": "^5.3.2",
70
70
  "lodash": "^4.17.21",
71
71
  "mark.js": "^8.11.1",
72
+ "quill": "~2.0.3",
72
73
  "react": "18.2.0",
73
74
  "react-dom": "18.2.0",
74
75
  "react-i18next": "15.6.0",
@@ -102,5 +103,5 @@
102
103
  "defaults and supports es6-module",
103
104
  "maintained node versions"
104
105
  ],
105
- "gitHead": "7c3e9bbcdaa616cf2174f44356011417e368911c"
106
+ "gitHead": "0a8c5a75fd70b1ec87b66604b4a25587f274540c"
106
107
  }
@@ -1,50 +0,0 @@
1
- import './markdownEditor.css';
2
- import { IAttachment } from '@cee-eng/hydrajs/@types/models/attachment';
3
- import { IMarkdownOptions } from '@cee-eng/ui-toolkit';
4
- import React, { HTMLProps } from 'react';
5
- export declare enum EditorMode {
6
- PLAIN = "plaintext",
7
- MARKDOWN = "markdown"
8
- }
9
- interface IFileSelectorProps {
10
- showFileSelectorInToolbar: boolean;
11
- filesList: Partial<IAttachment>[];
12
- onFileSelect: (file: Partial<IAttachment>) => void;
13
- onFileDelete: (file: Partial<IAttachment>) => void;
14
- onClipboardPaste: (file: any) => void;
15
- isSupportedFile: (extension: string) => boolean;
16
- attachFileBtn: React.ReactNode;
17
- isUploadingFile: boolean;
18
- }
19
- export interface IMDEditorProps extends Omit<HTMLProps<HTMLTextAreaElement>, 'onChange' | 'value' | 'ref'> {
20
- value: string;
21
- onChange: (value: string, mode?: EditorMode) => void;
22
- className?: string;
23
- id?: string;
24
- hidePreviewText?: string;
25
- showPreviewText?: string;
26
- bindTextArea?: (ref: HTMLTextAreaElement) => void;
27
- textAreaClassName?: string;
28
- mdPlaceholder?: string;
29
- plainTextPlaceholder?: string;
30
- allowEmoji?: boolean;
31
- hideHeadingOptions?: boolean;
32
- markedownOptions?: IMarkdownOptions;
33
- showMarkdownPlainTextToggle?: boolean;
34
- editorMode?: EditorMode;
35
- hideToolbars?: boolean;
36
- charLimit?: number;
37
- minCharsForCounter?: number;
38
- onCommentExceedCharsLimit: (val: boolean) => void;
39
- fileSelectorProps?: Partial<IFileSelectorProps>;
40
- }
41
- export declare const validateFile: (file: Partial<IAttachment>) => {
42
- isValid: boolean;
43
- errorMsg: string;
44
- };
45
- declare function MarkdownEditor(props: IMDEditorProps): React.JSX.Element;
46
- declare namespace MarkdownEditor {
47
- var defaultProps: Partial<IMDEditorProps>;
48
- }
49
- export { MarkdownEditor };
50
- //# sourceMappingURL=MarkdownEditor.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"MarkdownEditor.d.ts","sourceRoot":"","sources":["../../../src/MarkdownEditor/MarkdownEditor.tsx"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAE9B,OAAO,EAAE,WAAW,EAAE,MAAM,2CAA2C,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAwB,MAAM,qBAAqB,CAAC;AAiC7E,OAAO,KAAK,EAAE,EAAE,SAAS,EAA+B,MAAM,OAAO,CAAC;AAMtE,oBAAY,UAAU;IAClB,KAAK,cAAc;IACnB,QAAQ,aAAa;CACxB;AAED,UAAU,kBAAkB;IACxB,yBAAyB,EAAE,OAAO,CAAC;IACnC,SAAS,EAAE,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;IAClC,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;IACnD,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;IACnD,gBAAgB,EAAE,CAAC,IAAI,KAAA,KAAK,IAAI,CAAC;IACjC,eAAe,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;IAChD,aAAa,EAAE,KAAK,CAAC,SAAS,CAAC;IAC/B,eAAe,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,cAAe,SAAQ,IAAI,CAAC,SAAS,CAAC,mBAAmB,CAAC,EAAE,UAAU,GAAG,OAAO,GAAG,KAAK,CAAC;IACtG,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAClD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,yBAAyB,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD,iBAAiB,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;CACnD;AA4BD,eAAO,MAAM,YAAY,GAAI,MAAM,OAAO,CAAC,WAAW,CAAC,KAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAiB7F,CAAC;AAEF,iBAAS,cAAc,CAAC,KAAK,EAAE,cAAc,qBAo8B5C;kBAp8BQ,cAAc;;;AAw8BvB,OAAO,EAAE,cAAc,EAAE,CAAC"}