@procore/text-editor 0.0.3 → 0.2.0
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/CHANGELOG.md +15 -0
- package/README.md +50 -24
- package/codemod/__fixtures__/src/components/MultilineFormRichText.tsx +2 -1
- package/codemod/text-editor-migrate.js +54 -0
- package/codemod/text-editor-migrate.test.js +9 -0
- package/dist/DebouncedTextEditor/DebouncedTextEditor.d.ts +35 -0
- package/dist/DebouncedTextEditor/DebouncedTextEditor.js +71 -0
- package/dist/DebouncedTextEditor/DebouncedTextEditor.js.map +1 -0
- package/dist/DebouncedTextEditor/index.d.ts +1 -0
- package/dist/DebouncedTextEditor/index.js +2 -0
- package/dist/DebouncedTextEditor/index.js.map +1 -0
- package/dist/TextEditor/TextEditor.d.ts +1 -1
- package/dist/TextEditor/TextEditor.js +90 -36
- package/dist/TextEditor/TextEditor.js.map +1 -1
- package/dist/TextEditor/TextEditor.styles.js +1 -1
- package/dist/TextEditor/TextEditor.types.d.ts +38 -30
- package/dist/TextEditor/TextEditor.types.js.map +1 -1
- package/dist/TextEditor/textEditorTheming/textEditorTheming.styles.js +2 -1
- package/dist/TextEditor/textEditorTheming/textEditorTheming.styles.js.map +1 -1
- package/dist/TextEditor/utils/config.js +3 -3
- package/dist/TextEditor/utils/config.js.map +1 -1
- package/dist/TextEditor/utils/index.d.ts +0 -1
- package/dist/TextEditor/utils/index.js +0 -1
- package/dist/TextEditor/utils/index.js.map +1 -1
- package/dist/TextEditorOutput/TextEditorOutput.styles.js +1 -1
- package/dist/_storyHelpers/constants.d.ts +1 -0
- package/dist/_storyHelpers/constants.js +2 -1
- package/dist/_storyHelpers/constants.js.map +1 -1
- package/dist/_typedoc/TextEditor/TextEditor.types.json +57 -47
- package/dist/_typedoc/TextEditor/TextEditorProvider.types.json +2 -2
- package/dist/_typedoc/TextEditorOutput/TextEditorOutput.types.json +3 -3
- package/dist/_typedoc/deprecations.json +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/utils/debounce.d.ts +1 -0
- package/dist/utils/debounce.js +24 -0
- package/dist/utils/debounce.js.map +1 -0
- package/package.json +13 -12
- package/dist/TextEditor/utils/plugins.d.ts +0 -7
- package/dist/TextEditor/utils/plugins.js +0 -184
- package/dist/TextEditor/utils/plugins.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @procore/text-editor
|
|
2
2
|
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- ffdc97f: - Add optional `readonly` prop to display content in read-only mode.
|
|
8
|
+
- Remove Accessibility icons from the toolbar.
|
|
9
|
+
- Expose `DebouncedTextEditor` component for debounced value updates.
|
|
10
|
+
|
|
11
|
+
## 0.1.0
|
|
12
|
+
|
|
13
|
+
### Minor Changes
|
|
14
|
+
|
|
15
|
+
- New toolbar defaults. Remove `plugins` and `config` props to rely on the TextEditor package's default internal configuration.
|
|
16
|
+
- Add Enter key `stopPropagation` to prevent form submission when pressing Enter in the editor.
|
|
17
|
+
|
|
3
18
|
## 0.0.3
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ yarn add @procore/text-editor
|
|
|
10
10
|
|
|
11
11
|
## Usage
|
|
12
12
|
|
|
13
|
-
###
|
|
13
|
+
### Standalone Usage
|
|
14
14
|
|
|
15
15
|
```tsx
|
|
16
16
|
import { TextEditor } from '@procore/text-editor'
|
|
@@ -27,47 +27,39 @@ function MyComponent() {
|
|
|
27
27
|
}
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
### With
|
|
30
|
+
### With @procore/core-react Forms
|
|
31
31
|
|
|
32
32
|
```tsx
|
|
33
|
+
import { Form } from '@procore/core-react'
|
|
33
34
|
import { TextEditor } from '@procore/text-editor'
|
|
34
35
|
|
|
35
36
|
function MyComponent() {
|
|
36
|
-
const [value, setValue] = React.useState('')
|
|
37
|
-
|
|
38
37
|
return (
|
|
39
|
-
<
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
config={(defaultConfig) => ({
|
|
44
|
-
...defaultConfig,
|
|
45
|
-
// Your custom CKEditor configuration
|
|
46
|
-
})}
|
|
38
|
+
<Form.RichText
|
|
39
|
+
name="richtext"
|
|
40
|
+
label="Richtext"
|
|
41
|
+
textEditorComponent={TextEditor}
|
|
47
42
|
/>
|
|
48
43
|
)
|
|
49
44
|
}
|
|
50
45
|
```
|
|
51
46
|
|
|
52
|
-
### TextEditorProvider
|
|
53
47
|
|
|
54
|
-
|
|
48
|
+
### Displaying Read-Only Content
|
|
49
|
+
|
|
50
|
+
You can display formatted text in two ways:
|
|
51
|
+
|
|
52
|
+
**Option 1:** Use `TextEditor` with `readonly` prop:
|
|
55
53
|
|
|
56
54
|
```tsx
|
|
57
|
-
import { TextEditor
|
|
55
|
+
import { TextEditor } from '@procore/text-editor'
|
|
58
56
|
|
|
59
|
-
function MyComponent() {
|
|
60
|
-
return
|
|
61
|
-
<TextEditorProvider features={{ stickyToolbar: true, tabAsNavigation: true }}>
|
|
62
|
-
<TextEditor value={value} onChange={setValue} />
|
|
63
|
-
</TextEditorProvider>
|
|
64
|
-
)
|
|
57
|
+
function MyComponent({ htmlContent }) {
|
|
58
|
+
return <TextEditor value={htmlContent} readonly />
|
|
65
59
|
}
|
|
66
60
|
```
|
|
67
61
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
Display formatted text from the editor:
|
|
62
|
+
**Option 2:** Use the `TextEditorOutput` component:
|
|
71
63
|
|
|
72
64
|
```tsx
|
|
73
65
|
import { TextEditorOutput } from '@procore/text-editor'
|
|
@@ -77,6 +69,40 @@ function MyComponent({ htmlContent }) {
|
|
|
77
69
|
}
|
|
78
70
|
```
|
|
79
71
|
|
|
72
|
+
## Features
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
### Toolbar Features
|
|
76
|
+
|
|
77
|
+
The editor includes a comprehensive toolbar with the following capabilities:
|
|
78
|
+
|
|
79
|
+
| Feature | Description |
|
|
80
|
+
|---------|-------------|
|
|
81
|
+
| **Bold** | Apply bold formatting |
|
|
82
|
+
| **Italic** | Apply italic formatting |
|
|
83
|
+
| **Underline** | Apply underline formatting |
|
|
84
|
+
| **Strikethrough** | Apply strikethrough formatting |
|
|
85
|
+
| **Alignment** | Left, center, and right text alignment |
|
|
86
|
+
| **Bulleted List** | Create unordered lists |
|
|
87
|
+
| **Numbered List** | Create ordered lists with start index and reversed options |
|
|
88
|
+
| **Indent/Outdent** | Increase or decrease text indentation |
|
|
89
|
+
| **Cut/Paste** | Cut and paste content with clipboard support |
|
|
90
|
+
| **Paste as Text** | Paste content as plain text without formatting |
|
|
91
|
+
| **Font Size** | Choose from 8pt, 10pt, 12pt, 14pt, 18pt, 24pt, 36pt |
|
|
92
|
+
| **Font Color** | Apply text color from a 22-color palette |
|
|
93
|
+
| **Background Color** | Apply background highlight from a 22-color palette |
|
|
94
|
+
| **Insert Table** | Create and edit tables with cell properties |
|
|
95
|
+
| **Link** | Insert and edit hyperlinks with auto-link detection |
|
|
96
|
+
| **Block Quote** | Create block quotations |
|
|
97
|
+
| **Heading** | Apply heading styles |
|
|
98
|
+
| **Horizontal Line** | Insert horizontal dividers |
|
|
99
|
+
| **Remove Format** | Clear all formatting from selected text |
|
|
100
|
+
| **Special Characters** | Insert special characters and symbols |
|
|
101
|
+
| **Subscript** | Apply subscript formatting |
|
|
102
|
+
| **Superscript** | Apply superscript formatting |
|
|
103
|
+
| **Code Block** | Insert formatted code blocks |
|
|
104
|
+
| **Undo/Redo** | Undo and redo editing actions |
|
|
105
|
+
|
|
80
106
|
## Jest Configuration
|
|
81
107
|
|
|
82
108
|
To ensure your Jest tests work with CKEditor, wrap your Jest configuration with `textEditorJestConfig`:
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Form } from '@procore/core-react'
|
|
1
|
+
import { Form, TextEditor } from '@procore/core-react'
|
|
2
2
|
import React from 'react'
|
|
3
3
|
|
|
4
4
|
export const MultilineFormRichText = () => {
|
|
@@ -9,6 +9,7 @@ export const MultilineFormRichText = () => {
|
|
|
9
9
|
label="Description"
|
|
10
10
|
plugins={['table']}
|
|
11
11
|
/>
|
|
12
|
+
<TextEditor value="notes" plugins={['links']} />
|
|
12
13
|
</Form>
|
|
13
14
|
)
|
|
14
15
|
}
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* 2. Updates Form.RichText usage to include textEditorComponent prop
|
|
10
10
|
* 3. Updates Jest configuration to use textEditorJestConfig
|
|
11
11
|
* 4. Adds ckeditor5 singleton to module federation shared config
|
|
12
|
+
* 5. Remove deprecated plugins prop from TextEditor and Form.RichText components
|
|
12
13
|
*/
|
|
13
14
|
|
|
14
15
|
const fs = require('fs')
|
|
@@ -168,6 +169,52 @@ function transformImports(fileContent) {
|
|
|
168
169
|
return { content: newContent, modified, needsTextEditorImport }
|
|
169
170
|
}
|
|
170
171
|
|
|
172
|
+
/**
|
|
173
|
+
* Remove deprecated plugins prop from TextEditor and Form.RichText components
|
|
174
|
+
*/
|
|
175
|
+
function removeDeprecatedProps(fileContent) {
|
|
176
|
+
let modified = false
|
|
177
|
+
let newContent = fileContent
|
|
178
|
+
|
|
179
|
+
// Pattern to match TextEditor components with plugins prop
|
|
180
|
+
const textEditorRegex = /(<TextEditor)([\s\S]*?)(\/>|>)/g
|
|
181
|
+
newContent = newContent.replace(
|
|
182
|
+
textEditorRegex,
|
|
183
|
+
(match, opening, props, closing) => {
|
|
184
|
+
let updatedProps = props
|
|
185
|
+
const hasPlugins = props.includes('plugins=')
|
|
186
|
+
|
|
187
|
+
if (hasPlugins) {
|
|
188
|
+
// Remove plugins prop
|
|
189
|
+
updatedProps = updatedProps.replace(/\s*plugins\s*=\s*\{[^}]*\}/g, '')
|
|
190
|
+
modified = true
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return opening + updatedProps + closing
|
|
194
|
+
}
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
// Pattern to match Form.RichText components with plugins prop
|
|
198
|
+
const formRichTextRegex = /(<Form\.RichText(?:Field)?)([\s\S]*?)(\/>|>)/g
|
|
199
|
+
newContent = newContent.replace(
|
|
200
|
+
formRichTextRegex,
|
|
201
|
+
(match, opening, props, closing) => {
|
|
202
|
+
let updatedProps = props
|
|
203
|
+
const hasPlugins = props.includes('plugins=')
|
|
204
|
+
|
|
205
|
+
if (hasPlugins) {
|
|
206
|
+
// Remove plugins prop
|
|
207
|
+
updatedProps = updatedProps.replace(/\s*plugins\s*=\s*\{[^}]*\}/g, '')
|
|
208
|
+
modified = true
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return opening + updatedProps + closing
|
|
212
|
+
}
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
return { content: newContent, modified }
|
|
216
|
+
}
|
|
217
|
+
|
|
171
218
|
/**
|
|
172
219
|
* Transform Form.RichText usage
|
|
173
220
|
*/
|
|
@@ -692,6 +739,13 @@ function processFile(filePath) {
|
|
|
692
739
|
newContent = formResult.content
|
|
693
740
|
wasModified = true
|
|
694
741
|
}
|
|
742
|
+
|
|
743
|
+
// Remove deprecated plugins prop
|
|
744
|
+
const deprecatedPropsResult = removeDeprecatedProps(newContent)
|
|
745
|
+
if (deprecatedPropsResult.modified) {
|
|
746
|
+
newContent = deprecatedPropsResult.content
|
|
747
|
+
wasModified = true
|
|
748
|
+
}
|
|
695
749
|
}
|
|
696
750
|
|
|
697
751
|
// Write back if modified
|
|
@@ -129,6 +129,15 @@ describe('text-editor-migrate codemod', () => {
|
|
|
129
129
|
expect(content).not.toContain('textEditorComponent={TextEditor}')
|
|
130
130
|
expect(content).not.toContain('@procore/text-editor')
|
|
131
131
|
})
|
|
132
|
+
|
|
133
|
+
it('should remove deprecated plugins prop from Form.RichText', () => {
|
|
134
|
+
execFileSync('node', [codemodPath, testDir], { stdio: 'ignore' })
|
|
135
|
+
|
|
136
|
+
const content = readFile('src/components/MultilineFormRichText.tsx')
|
|
137
|
+
|
|
138
|
+
expect(content).not.toContain('plugins=')
|
|
139
|
+
expect(content).toContain('textEditorComponent={TextEditor}')
|
|
140
|
+
})
|
|
132
141
|
})
|
|
133
142
|
|
|
134
143
|
describe('Jest configuration transformations', () => {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { TextEditorProps } from '../TextEditor';
|
|
3
|
+
/**
|
|
4
|
+
* A performance-optimized version of `TextEditor` with built-in debounce on the `onChange` callback.
|
|
5
|
+
*
|
|
6
|
+
* ## When to use `DebouncedTextEditor`
|
|
7
|
+
*
|
|
8
|
+
* Use this component when:
|
|
9
|
+
* - The `onChange` handler triggers expensive operations (API calls, complex state updates, re-renders)
|
|
10
|
+
* - You want to reduce the frequency of updates while the user is actively typing
|
|
11
|
+
* - Performance is a concern in forms with multiple rich text editors
|
|
12
|
+
*
|
|
13
|
+
* ## How it works
|
|
14
|
+
*
|
|
15
|
+
* The component waits 300ms after the user stops typing before calling `onChange`.
|
|
16
|
+
* If the user continues typing, the timer resets. This reduces unnecessary updates
|
|
17
|
+
* while maintaining a responsive editing experience.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```tsx
|
|
21
|
+
* import { DebouncedTextEditor } from '@procore/text-editor'
|
|
22
|
+
*
|
|
23
|
+
* function MyComponent() {
|
|
24
|
+
* const [value, setValue] = React.useState('')
|
|
25
|
+
*
|
|
26
|
+
* return (
|
|
27
|
+
* <DebouncedTextEditor
|
|
28
|
+
* value={value}
|
|
29
|
+
* onChange={(newValue) => setValue(newValue)}
|
|
30
|
+
* />
|
|
31
|
+
* )
|
|
32
|
+
* }
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare const DebouncedTextEditor: ({ onChange, value, ...rest }: TextEditorProps) => React.JSX.Element;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
var _excluded = ["onChange", "value"];
|
|
2
|
+
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|
3
|
+
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
|
|
4
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
5
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
6
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
7
|
+
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
8
|
+
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
|
|
9
|
+
function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
|
|
10
|
+
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
|
|
11
|
+
import React, { useCallback, useEffect, useState } from 'react';
|
|
12
|
+
import { TextEditor } from '../TextEditor';
|
|
13
|
+
import { debounce } from '../utils/debounce';
|
|
14
|
+
var DEBOUNCE_MS = 300;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* A performance-optimized version of `TextEditor` with built-in debounce on the `onChange` callback.
|
|
18
|
+
*
|
|
19
|
+
* ## When to use `DebouncedTextEditor`
|
|
20
|
+
*
|
|
21
|
+
* Use this component when:
|
|
22
|
+
* - The `onChange` handler triggers expensive operations (API calls, complex state updates, re-renders)
|
|
23
|
+
* - You want to reduce the frequency of updates while the user is actively typing
|
|
24
|
+
* - Performance is a concern in forms with multiple rich text editors
|
|
25
|
+
*
|
|
26
|
+
* ## How it works
|
|
27
|
+
*
|
|
28
|
+
* The component waits 300ms after the user stops typing before calling `onChange`.
|
|
29
|
+
* If the user continues typing, the timer resets. This reduces unnecessary updates
|
|
30
|
+
* while maintaining a responsive editing experience.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```tsx
|
|
34
|
+
* import { DebouncedTextEditor } from '@procore/text-editor'
|
|
35
|
+
*
|
|
36
|
+
* function MyComponent() {
|
|
37
|
+
* const [value, setValue] = React.useState('')
|
|
38
|
+
*
|
|
39
|
+
* return (
|
|
40
|
+
* <DebouncedTextEditor
|
|
41
|
+
* value={value}
|
|
42
|
+
* onChange={(newValue) => setValue(newValue)}
|
|
43
|
+
* />
|
|
44
|
+
* )
|
|
45
|
+
* }
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export var DebouncedTextEditor = function DebouncedTextEditor(_ref) {
|
|
49
|
+
var onChange = _ref.onChange,
|
|
50
|
+
value = _ref.value,
|
|
51
|
+
rest = _objectWithoutProperties(_ref, _excluded);
|
|
52
|
+
var _useState = useState(value !== null && value !== void 0 ? value : ''),
|
|
53
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
54
|
+
internalValue = _useState2[0],
|
|
55
|
+
setInternalValue = _useState2[1];
|
|
56
|
+
var debouncedOnChange = useCallback(debounce(function (newValue) {
|
|
57
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(newValue);
|
|
58
|
+
}, DEBOUNCE_MS), []);
|
|
59
|
+
function handleChange(newValue) {
|
|
60
|
+
setInternalValue(newValue);
|
|
61
|
+
debouncedOnChange(newValue);
|
|
62
|
+
}
|
|
63
|
+
useEffect(function () {
|
|
64
|
+
setInternalValue(value !== null && value !== void 0 ? value : '');
|
|
65
|
+
}, [value]);
|
|
66
|
+
return /*#__PURE__*/React.createElement(TextEditor, _extends({}, rest, {
|
|
67
|
+
value: internalValue,
|
|
68
|
+
onChange: handleChange
|
|
69
|
+
}));
|
|
70
|
+
};
|
|
71
|
+
//# sourceMappingURL=DebouncedTextEditor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DebouncedTextEditor.js","names":["React","useCallback","useEffect","useState","TextEditor","debounce","DEBOUNCE_MS","DebouncedTextEditor","_ref","onChange","value","rest","_objectWithoutProperties","_excluded","_useState","_useState2","_slicedToArray","internalValue","setInternalValue","debouncedOnChange","newValue","handleChange","createElement","_extends"],"sources":["../../src/DebouncedTextEditor/DebouncedTextEditor.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useState } from 'react'\nimport type { TextEditorProps } from '../TextEditor'\nimport { TextEditor } from '../TextEditor'\nimport { debounce } from '../utils/debounce'\n\nconst DEBOUNCE_MS = 300\n\n/**\n * A performance-optimized version of `TextEditor` with built-in debounce on the `onChange` callback.\n *\n * ## When to use `DebouncedTextEditor`\n *\n * Use this component when:\n * - The `onChange` handler triggers expensive operations (API calls, complex state updates, re-renders)\n * - You want to reduce the frequency of updates while the user is actively typing\n * - Performance is a concern in forms with multiple rich text editors\n *\n * ## How it works\n *\n * The component waits 300ms after the user stops typing before calling `onChange`.\n * If the user continues typing, the timer resets. This reduces unnecessary updates\n * while maintaining a responsive editing experience.\n *\n * @example\n * ```tsx\n * import { DebouncedTextEditor } from '@procore/text-editor'\n *\n * function MyComponent() {\n * const [value, setValue] = React.useState('')\n *\n * return (\n * <DebouncedTextEditor\n * value={value}\n * onChange={(newValue) => setValue(newValue)}\n * />\n * )\n * }\n * ```\n */\nexport const DebouncedTextEditor = ({\n onChange,\n value,\n ...rest\n}: TextEditorProps) => {\n const [internalValue, setInternalValue] = useState(value ?? '')\n\n const debouncedOnChange = useCallback(\n debounce((newValue: string) => {\n onChange?.(newValue)\n }, DEBOUNCE_MS),\n []\n )\n\n function handleChange(newValue: string) {\n setInternalValue(newValue)\n debouncedOnChange(newValue)\n }\n\n useEffect(() => {\n setInternalValue(value ?? '')\n }, [value])\n\n return <TextEditor {...rest} value={internalValue} onChange={handleChange} />\n}\n"],"mappings":";;;;;;;;;;AAAA,OAAOA,KAAK,IAAIC,WAAW,EAAEC,SAAS,EAAEC,QAAQ,QAAQ,OAAO;AAE/D,SAASC,UAAU,QAAQ,eAAe;AAC1C,SAASC,QAAQ,QAAQ,mBAAmB;AAE5C,IAAMC,WAAW,GAAG,GAAG;;AAEvB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,IAAMC,mBAAmB,GAAG,SAAtBA,mBAAmBA,CAAAC,IAAA,EAIT;EAAA,IAHrBC,QAAQ,GAAAD,IAAA,CAARC,QAAQ;IACRC,KAAK,GAAAF,IAAA,CAALE,KAAK;IACFC,IAAI,GAAAC,wBAAA,CAAAJ,IAAA,EAAAK,SAAA;EAEP,IAAAC,SAAA,GAA0CX,QAAQ,CAACO,KAAK,aAALA,KAAK,cAALA,KAAK,GAAI,EAAE,CAAC;IAAAK,UAAA,GAAAC,cAAA,CAAAF,SAAA;IAAxDG,aAAa,GAAAF,UAAA;IAAEG,gBAAgB,GAAAH,UAAA;EAEtC,IAAMI,iBAAiB,GAAGlB,WAAW,CACnCI,QAAQ,CAAC,UAACe,QAAgB,EAAK;IAC7BX,QAAQ,aAARA,QAAQ,uBAARA,QAAQ,CAAGW,QAAQ,CAAC;EACtB,CAAC,EAAEd,WAAW,CAAC,EACf,EACF,CAAC;EAED,SAASe,YAAYA,CAACD,QAAgB,EAAE;IACtCF,gBAAgB,CAACE,QAAQ,CAAC;IAC1BD,iBAAiB,CAACC,QAAQ,CAAC;EAC7B;EAEAlB,SAAS,CAAC,YAAM;IACdgB,gBAAgB,CAACR,KAAK,aAALA,KAAK,cAALA,KAAK,GAAI,EAAE,CAAC;EAC/B,CAAC,EAAE,CAACA,KAAK,CAAC,CAAC;EAEX,oBAAOV,KAAA,CAAAsB,aAAA,CAAClB,UAAU,EAAAmB,QAAA,KAAKZ,IAAI;IAAED,KAAK,EAAEO,aAAc;IAACR,QAAQ,EAAEY;EAAa,EAAE,CAAC;AAC/E,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { DebouncedTextEditor } from './DebouncedTextEditor';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["DebouncedTextEditor"],"sources":["../../src/DebouncedTextEditor/index.ts"],"sourcesContent":["export { DebouncedTextEditor } from './DebouncedTextEditor'\n"],"mappings":"AAAA,SAASA,mBAAmB,QAAQ,uBAAuB"}
|
|
@@ -41,4 +41,4 @@ import type { TextEditorProps } from './TextEditor.types';
|
|
|
41
41
|
* }),
|
|
42
42
|
* })
|
|
43
43
|
*/
|
|
44
|
-
export declare function TextEditor(
|
|
44
|
+
export declare function TextEditor(props: Readonly<TextEditorProps>): React.JSX.Element | null;
|
|
@@ -1,11 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
var _excluded = ["disabled", "error", "value", "initialValue", "onChange", "onInit", "onBlur", "onKeyDown", "config", "plugins", "locale", "onDirty"];
|
|
1
|
+
var _excluded = ["disabled", "error", "readonly", "value", "initialValue", "onChange", "onInit", "onBlur", "onKeyDown", "locale", "onDirty"];
|
|
3
2
|
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|
4
|
-
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
5
|
-
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
6
|
-
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
7
|
-
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
|
|
8
|
-
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
9
3
|
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
|
|
10
4
|
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
11
5
|
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
@@ -18,13 +12,14 @@ import { CKEditor } from '@ckeditor/ckeditor5-react';
|
|
|
18
12
|
import { ClassicEditor } from 'ckeditor5';
|
|
19
13
|
import React from 'react';
|
|
20
14
|
import { useI18nContext, useZIndexContext } from '@procore/core-react';
|
|
15
|
+
import { TextEditorOutput } from '../TextEditorOutput';
|
|
21
16
|
import { useStickyToolbar } from './StickyToolbar';
|
|
22
17
|
import { GlobalEditorStyles, StyledTextEditor } from './TextEditor.styles';
|
|
23
18
|
import { TextEditorContext } from './TextEditorProvider';
|
|
24
19
|
import { TextEditorTheme } from './textEditorTheming';
|
|
25
20
|
import { useCKEditorCss } from './useCKEditorCss';
|
|
26
21
|
import { useTabAsNavigation } from './useTabAsNavigation';
|
|
27
|
-
import { addButtonDataAttributes,
|
|
22
|
+
import { addButtonDataAttributes, getDefaultConfig } from './utils';
|
|
28
23
|
|
|
29
24
|
/**
|
|
30
25
|
* To ensure your Jest tests work with the CKEditor implementation, wrap your Jest configuration with `textEditorJestConfig`:
|
|
@@ -67,20 +62,21 @@ import { addButtonDataAttributes, addPluginsFromStringArray, getDefaultConfig }
|
|
|
67
62
|
* }),
|
|
68
63
|
* })
|
|
69
64
|
*/
|
|
70
|
-
export function TextEditor(
|
|
71
|
-
var disabled =
|
|
72
|
-
error =
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
65
|
+
export function TextEditor(props) {
|
|
66
|
+
var disabled = props.disabled,
|
|
67
|
+
error = props.error,
|
|
68
|
+
readonly = props.readonly,
|
|
69
|
+
value = props.value,
|
|
70
|
+
initialValue = props.initialValue,
|
|
71
|
+
onChange = props.onChange,
|
|
72
|
+
onInit = props.onInit,
|
|
73
|
+
onBlur = props.onBlur,
|
|
74
|
+
onKeyDown = props.onKeyDown,
|
|
75
|
+
propLocale = props.locale,
|
|
76
|
+
onDirty = props.onDirty,
|
|
77
|
+
restProps = _objectWithoutProperties(props, _excluded);
|
|
78
|
+
var ariaLabel = props['aria-label'];
|
|
79
|
+
var ariaDescription = props['aria-description'];
|
|
84
80
|
var _useCKEditorCss = useCKEditorCss(),
|
|
85
81
|
cssLoading = _useCKEditorCss.isLoading;
|
|
86
82
|
var editorRef = React.useRef(null);
|
|
@@ -113,6 +109,42 @@ export function TextEditor(_ref) {
|
|
|
113
109
|
}
|
|
114
110
|
};
|
|
115
111
|
}, []);
|
|
112
|
+
|
|
113
|
+
// Update aria-label when ariaLabel prop changes
|
|
114
|
+
React.useEffect(function () {
|
|
115
|
+
if (!isEditorReady || !editorInstanceRef.current) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
var editor = editorInstanceRef.current;
|
|
119
|
+
editor.editing.view.change(function (writer) {
|
|
120
|
+
var viewEditableRoot = editor.editing.view.document.getRoot();
|
|
121
|
+
if (viewEditableRoot) {
|
|
122
|
+
if (ariaLabel) {
|
|
123
|
+
writer.setAttribute('aria-label', ariaLabel, viewEditableRoot);
|
|
124
|
+
} else {
|
|
125
|
+
writer.removeAttribute('aria-label', viewEditableRoot);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
}, [ariaLabel, isEditorReady]);
|
|
130
|
+
|
|
131
|
+
// Update aria-description when ariaDescription prop changes
|
|
132
|
+
React.useEffect(function () {
|
|
133
|
+
if (!isEditorReady || !editorInstanceRef.current) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
var editor = editorInstanceRef.current;
|
|
137
|
+
editor.editing.view.change(function (writer) {
|
|
138
|
+
var viewEditableRoot = editor.editing.view.document.getRoot();
|
|
139
|
+
if (viewEditableRoot) {
|
|
140
|
+
if (ariaDescription) {
|
|
141
|
+
writer.setAttribute('aria-description', ariaDescription, viewEditableRoot);
|
|
142
|
+
} else {
|
|
143
|
+
writer.removeAttribute('aria-description', viewEditableRoot);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
}, [ariaDescription, isEditorReady]);
|
|
116
148
|
var _useZIndexContext = useZIndexContext(),
|
|
117
149
|
zIndex = _useZIndexContext.value;
|
|
118
150
|
var _React$useContext = React.useContext(TextEditorContext),
|
|
@@ -122,19 +154,14 @@ export function TextEditor(_ref) {
|
|
|
122
154
|
var mergedConfig = React.useMemo(function () {
|
|
123
155
|
var defaultConfig = getDefaultConfig(locale);
|
|
124
156
|
|
|
125
|
-
//
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
var externalResult = typeof externalConfig === 'function' ? externalConfig(configWithPlugins) : undefined;
|
|
130
|
-
// Merge default config (with plugins) and consumer overrides
|
|
131
|
-
var finalConfig = _objectSpread(_objectSpread({}, configWithPlugins), externalResult !== null && externalResult !== void 0 ? externalResult : {});
|
|
132
|
-
return finalConfig;
|
|
133
|
-
}, [externalConfig, locale, stringPlugins]);
|
|
134
|
-
var bindKeyDownHandler = React.useCallback(function (editor) {
|
|
135
|
-
if (!onKeyDown) {
|
|
136
|
-
return;
|
|
157
|
+
// Set accessible label for the editable area if provided
|
|
158
|
+
// This is used by screen readers to announce the editor's purpose
|
|
159
|
+
if (ariaLabel) {
|
|
160
|
+
defaultConfig.label = ariaLabel;
|
|
137
161
|
}
|
|
162
|
+
return defaultConfig;
|
|
163
|
+
}, [ariaLabel, locale]);
|
|
164
|
+
var bindKeyDownHandler = React.useCallback(function (editor) {
|
|
138
165
|
var editorElement = editor.editing.view.document.getRoot();
|
|
139
166
|
if (!editorElement) {
|
|
140
167
|
return;
|
|
@@ -148,7 +175,12 @@ export function TextEditor(_ref) {
|
|
|
148
175
|
// Create and store the new listener
|
|
149
176
|
var keyDownListener = function keyDownListener(_event, data) {
|
|
150
177
|
var domEvent = data.domEvent;
|
|
151
|
-
|
|
178
|
+
// Prevent Enter from propagating to parent forms so the
|
|
179
|
+
// editor can handle newlines without accidentally submitting.
|
|
180
|
+
if (domEvent.key === 'Enter') {
|
|
181
|
+
domEvent.stopPropagation();
|
|
182
|
+
}
|
|
183
|
+
onKeyDown === null || onKeyDown === void 0 ? void 0 : onKeyDown(domEvent, editor);
|
|
152
184
|
};
|
|
153
185
|
keyDownListenerRef.current = keyDownListener;
|
|
154
186
|
|
|
@@ -174,6 +206,20 @@ export function TextEditor(_ref) {
|
|
|
174
206
|
editor.setData(initialValue);
|
|
175
207
|
}
|
|
176
208
|
|
|
209
|
+
// Set aria-label and aria-description on the editable area if provided
|
|
210
|
+
// These provide accessible context to screen reader users
|
|
211
|
+
editor.editing.view.change(function (writer) {
|
|
212
|
+
var viewEditableRoot = editor.editing.view.document.getRoot();
|
|
213
|
+
if (viewEditableRoot) {
|
|
214
|
+
if (ariaLabel) {
|
|
215
|
+
writer.setAttribute('aria-label', ariaLabel, viewEditableRoot);
|
|
216
|
+
}
|
|
217
|
+
if (ariaDescription) {
|
|
218
|
+
writer.setAttribute('aria-description', ariaDescription, viewEditableRoot);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
|
|
177
223
|
// Bind keydown handler when editor is ready
|
|
178
224
|
bindKeyDownHandler(editor);
|
|
179
225
|
onInit === null || onInit === void 0 ? void 0 : onInit(editor);
|
|
@@ -197,10 +243,18 @@ export function TextEditor(_ref) {
|
|
|
197
243
|
if (cssLoading) {
|
|
198
244
|
return null;
|
|
199
245
|
}
|
|
246
|
+
if (readonly) {
|
|
247
|
+
return /*#__PURE__*/React.createElement(TextEditorOutput, {
|
|
248
|
+
value: value,
|
|
249
|
+
"aria-label": ariaLabel,
|
|
250
|
+
"aria-description": ariaDescription
|
|
251
|
+
});
|
|
252
|
+
}
|
|
200
253
|
return /*#__PURE__*/React.createElement(StyledTextEditor, {
|
|
201
254
|
ref: editorRef,
|
|
202
255
|
key: editorKey,
|
|
203
|
-
error: error
|
|
256
|
+
error: error,
|
|
257
|
+
"aria-invalid": error ? 'true' : 'false'
|
|
204
258
|
}, /*#__PURE__*/React.createElement(GlobalEditorStyles, {
|
|
205
259
|
zIndex: zIndex + 1
|
|
206
260
|
}), /*#__PURE__*/React.createElement(TextEditorTheme, null), /*#__PURE__*/React.createElement(CKEditor, _extends({}, restProps, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextEditor.js","names":["CKEditor","ClassicEditor","React","useI18nContext","useZIndexContext","useStickyToolbar","GlobalEditorStyles","StyledTextEditor","TextEditorContext","TextEditorTheme","useCKEditorCss","useTabAsNavigation","addButtonDataAttributes","addPluginsFromStringArray","getDefaultConfig","TextEditor","_ref","disabled","error","value","initialValue","onChange","onInit","onBlur","onKeyDown","externalConfig","config","stringPlugins","plugins","propLocale","locale","onDirty","restProps","_objectWithoutProperties","_excluded","_useCKEditorCss","cssLoading","isLoading","editorRef","useRef","editorInstanceRef","initialValueRef","keyDownListenerRef","_React$useState","useState","_React$useState2","_slicedToArray","isDirtyState","setIsDirtyState","_React$useState3","_React$useState4","isEditorReady","setIsEditorReady","_useI18nContext","contextLocale","useEffect","undefined","current","editing","view","document","off","_useZIndexContext","zIndex","_React$useContext","useContext","features","enableStickyToolbar","stickyToolbar","enableTabAsNavigation","tabAsNavigation","mergedConfig","useMemo","defaultConfig","configWithPlugins","length","externalResult","finalConfig","_objectSpread","bindKeyDownHandler","useCallback","editor","editorElement","getRoot","keyDownListener","_event","data","domEvent","on","handleChange","getData","isDirty","handleReady","setData","handleBlur","event","enabled","_useTabAsNavigation","editorKey","concat","createElement","ref","key","_extends","onReady"],"sources":["../../src/TextEditor/TextEditor.tsx"],"sourcesContent":["import { CKEditor } from '@ckeditor/ckeditor5-react'\nimport type { EditorConfig } from 'ckeditor5'\nimport { ClassicEditor, type EventInfo } from 'ckeditor5'\nimport React from 'react'\n\nimport { useI18nContext, useZIndexContext } from '@procore/core-react'\nimport { useStickyToolbar } from './StickyToolbar'\nimport { GlobalEditorStyles, StyledTextEditor } from './TextEditor.styles'\nimport type { KeyDownListener, TextEditorProps } from './TextEditor.types'\nimport { TextEditorContext } from './TextEditorProvider'\nimport { TextEditorTheme } from './textEditorTheming'\nimport { useCKEditorCss } from './useCKEditorCss'\nimport { useTabAsNavigation } from './useTabAsNavigation'\nimport {\n addButtonDataAttributes,\n addPluginsFromStringArray,\n getDefaultConfig,\n} from './utils'\n\n/**\n * To ensure your Jest tests work with the CKEditor implementation, wrap your Jest configuration with `textEditorJestConfig`:\n *\n * @example\n *\n * // Using Jest config file\n *\n * const { textEditorJestConfig } = require('@procore/text-editor/jestConfig')\n *\n * module.exports = textEditorJestConfig({\n * // Your existing Jest config\n * })\n *\n * @example\n *\n * // Using Hammer\n *\n * import { textEditorJestConfig } from '@procore/text-editor/jestConfig'\n *\n * export default {\n * testJest: (defaultConfig) =>\n * textEditorJestConfig({\n * ...defaultConfig,\n * // Your existing Jest config\n * }),\n * }\n *\n * @example\n *\n * // Using Core Scripts\n *\n * const { textEditorJestConfig } = require('@procore/text-editor/jestConfig')\n *\n * module.exports = () => ({\n * jestOverride: (defaultConfig) =>\n * textEditorJestConfig({\n * ...defaultConfig,\n * // Your existing Jest config\n * }),\n * })\n */\nexport function TextEditor({\n disabled,\n error,\n value,\n initialValue,\n onChange,\n onInit,\n onBlur,\n onKeyDown,\n config: externalConfig,\n plugins: stringPlugins,\n locale: propLocale,\n onDirty,\n ...restProps\n}: TextEditorProps) {\n const { isLoading: cssLoading } = useCKEditorCss()\n\n const editorRef = React.useRef<HTMLDivElement>(null)\n const editorInstanceRef = React.useRef<ClassicEditor | null>(null)\n const initialValueRef = React.useRef<string>(value || initialValue || '')\n const keyDownListenerRef = React.useRef<KeyDownListener | null>(null)\n const [isDirtyState, setIsDirtyState] = React.useState(false)\n const [isEditorReady, setIsEditorReady] = React.useState(false)\n const { locale: contextLocale } = useI18nContext()\n const locale = propLocale || contextLocale\n\n React.useEffect(() => {\n if (value !== undefined) {\n initialValueRef.current = value\n }\n }, [value])\n\n // Cleanup keydown listener on unmount\n React.useEffect(() => {\n return () => {\n if (keyDownListenerRef.current && editorInstanceRef.current) {\n editorInstanceRef.current.editing.view.document.off(\n 'keydown',\n keyDownListenerRef.current\n )\n keyDownListenerRef.current = null\n }\n }\n }, [])\n\n const { value: zIndex } = useZIndexContext()\n\n const { features } = React.useContext(TextEditorContext)\n const enableStickyToolbar = !!features?.stickyToolbar\n const enableTabAsNavigation = !!features?.tabAsNavigation\n\n const mergedConfig = React.useMemo(() => {\n const defaultConfig = getDefaultConfig(locale)\n\n // Handle string plugins for backward compatibility\n const configWithPlugins = stringPlugins?.length\n ? addPluginsFromStringArray(defaultConfig, stringPlugins)\n : defaultConfig\n\n // Apply any external CKEditor config overrides provided by the consumer\n const externalResult =\n typeof externalConfig === 'function'\n ? externalConfig(configWithPlugins)\n : undefined\n // Merge default config (with plugins) and consumer overrides\n let finalConfig: EditorConfig = {\n ...configWithPlugins,\n ...(externalResult ?? {}),\n }\n\n return finalConfig\n }, [externalConfig, locale, stringPlugins])\n\n const bindKeyDownHandler = React.useCallback(\n (editor: ClassicEditor) => {\n if (!onKeyDown) {\n return\n }\n\n const editorElement = editor.editing.view.document.getRoot()\n if (!editorElement) {\n return\n }\n\n // Remove existing keydown listener\n if (keyDownListenerRef.current) {\n editor.editing.view.document.off('keydown', keyDownListenerRef.current)\n }\n\n // Create and store the new listener\n const keyDownListener = (\n _event: EventInfo,\n data: { domEvent: Event }\n ) => {\n const domEvent = data.domEvent as KeyboardEvent\n onKeyDown(domEvent, editor)\n }\n\n keyDownListenerRef.current = keyDownListener\n\n // Add the keydown listener\n editor.editing.view.document.on('keydown', keyDownListener)\n },\n [onKeyDown]\n )\n\n const handleChange = (\n _event: EventInfo<string, unknown>,\n editor: ClassicEditor\n ) => {\n const data = editor.getData()\n const isDirty = data !== initialValueRef.current\n\n // Call onDirty only on first content modification\n if (isDirty && !isDirtyState) {\n setIsDirtyState(true)\n onDirty?.()\n }\n\n onChange?.(data, isDirty)\n }\n\n const handleReady = (editor: ClassicEditor) => {\n addButtonDataAttributes(editor)\n editorInstanceRef.current = editor\n setIsEditorReady(true)\n\n if (initialValue) {\n editor.setData(initialValue)\n }\n\n // Bind keydown handler when editor is ready\n bindKeyDownHandler(editor)\n\n onInit?.(editor)\n }\n\n const handleBlur = (\n event: EventInfo<string, unknown>,\n editor: ClassicEditor\n ) => {\n onBlur?.(event, editor)\n }\n\n useStickyToolbar({\n enabled: enableStickyToolbar,\n editor: isEditorReady ? editorInstanceRef.current : null,\n editorRef,\n cssLoading,\n })\n\n const { config } = useTabAsNavigation({\n config: mergedConfig,\n enabled: enableTabAsNavigation,\n editor: isEditorReady ? editorInstanceRef.current : null,\n })\n\n const editorKey = `${locale}-${enableTabAsNavigation}`\n\n if (cssLoading) {\n return null\n }\n\n return (\n <StyledTextEditor ref={editorRef} key={editorKey} error={error}>\n <GlobalEditorStyles zIndex={zIndex + 1} />\n <TextEditorTheme />\n <CKEditor\n {...restProps}\n editor={ClassicEditor}\n config={config}\n disabled={disabled}\n data={value}\n onChange={handleChange}\n onReady={handleReady}\n onBlur={handleBlur}\n />\n </StyledTextEditor>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TextEditor.js","names":["CKEditor","ClassicEditor","React","useI18nContext","useZIndexContext","TextEditorOutput","useStickyToolbar","GlobalEditorStyles","StyledTextEditor","TextEditorContext","TextEditorTheme","useCKEditorCss","useTabAsNavigation","addButtonDataAttributes","getDefaultConfig","TextEditor","props","disabled","error","readonly","value","initialValue","onChange","onInit","onBlur","onKeyDown","propLocale","locale","onDirty","restProps","_objectWithoutProperties","_excluded","ariaLabel","ariaDescription","_useCKEditorCss","cssLoading","isLoading","editorRef","useRef","editorInstanceRef","initialValueRef","keyDownListenerRef","_React$useState","useState","_React$useState2","_slicedToArray","isDirtyState","setIsDirtyState","_React$useState3","_React$useState4","isEditorReady","setIsEditorReady","_useI18nContext","contextLocale","useEffect","undefined","current","editing","view","document","off","editor","change","writer","viewEditableRoot","getRoot","setAttribute","removeAttribute","_useZIndexContext","zIndex","_React$useContext","useContext","features","enableStickyToolbar","stickyToolbar","enableTabAsNavigation","tabAsNavigation","mergedConfig","useMemo","defaultConfig","label","bindKeyDownHandler","useCallback","editorElement","keyDownListener","_event","data","domEvent","key","stopPropagation","on","handleChange","getData","isDirty","handleReady","setData","handleBlur","event","enabled","_useTabAsNavigation","config","editorKey","concat","createElement","ref","_extends","onReady"],"sources":["../../src/TextEditor/TextEditor.tsx"],"sourcesContent":["import { CKEditor } from '@ckeditor/ckeditor5-react'\nimport { ClassicEditor, type EventInfo } from 'ckeditor5'\nimport React from 'react'\n\nimport { useI18nContext, useZIndexContext } from '@procore/core-react'\nimport { TextEditorOutput } from '../TextEditorOutput'\nimport { useStickyToolbar } from './StickyToolbar'\nimport { GlobalEditorStyles, StyledTextEditor } from './TextEditor.styles'\nimport type { KeyDownListener, TextEditorProps } from './TextEditor.types'\nimport { TextEditorContext } from './TextEditorProvider'\nimport { TextEditorTheme } from './textEditorTheming'\nimport { useCKEditorCss } from './useCKEditorCss'\nimport { useTabAsNavigation } from './useTabAsNavigation'\nimport { addButtonDataAttributes, getDefaultConfig } from './utils'\n\n/**\n * To ensure your Jest tests work with the CKEditor implementation, wrap your Jest configuration with `textEditorJestConfig`:\n *\n * @example\n *\n * // Using Jest config file\n *\n * const { textEditorJestConfig } = require('@procore/text-editor/jestConfig')\n *\n * module.exports = textEditorJestConfig({\n * // Your existing Jest config\n * })\n *\n * @example\n *\n * // Using Hammer\n *\n * import { textEditorJestConfig } from '@procore/text-editor/jestConfig'\n *\n * export default {\n * testJest: (defaultConfig) =>\n * textEditorJestConfig({\n * ...defaultConfig,\n * // Your existing Jest config\n * }),\n * }\n *\n * @example\n *\n * // Using Core Scripts\n *\n * const { textEditorJestConfig } = require('@procore/text-editor/jestConfig')\n *\n * module.exports = () => ({\n * jestOverride: (defaultConfig) =>\n * textEditorJestConfig({\n * ...defaultConfig,\n * // Your existing Jest config\n * }),\n * })\n */\nexport function TextEditor(props: Readonly<TextEditorProps>) {\n const {\n disabled,\n error,\n readonly,\n value,\n initialValue,\n onChange,\n onInit,\n onBlur,\n onKeyDown,\n locale: propLocale,\n onDirty,\n ...restProps\n } = props\n const ariaLabel = props['aria-label']\n const ariaDescription = props['aria-description']\n const { isLoading: cssLoading } = useCKEditorCss()\n\n const editorRef = React.useRef<HTMLDivElement>(null)\n const editorInstanceRef = React.useRef<ClassicEditor | null>(null)\n const initialValueRef = React.useRef<string>(value || initialValue || '')\n const keyDownListenerRef = React.useRef<KeyDownListener | null>(null)\n const [isDirtyState, setIsDirtyState] = React.useState(false)\n const [isEditorReady, setIsEditorReady] = React.useState(false)\n const { locale: contextLocale } = useI18nContext()\n const locale = propLocale || contextLocale\n\n React.useEffect(() => {\n if (value !== undefined) {\n initialValueRef.current = value\n }\n }, [value])\n\n // Cleanup keydown listener on unmount\n React.useEffect(() => {\n return () => {\n if (keyDownListenerRef.current && editorInstanceRef.current) {\n editorInstanceRef.current.editing.view.document.off(\n 'keydown',\n keyDownListenerRef.current\n )\n keyDownListenerRef.current = null\n }\n }\n }, [])\n\n // Update aria-label when ariaLabel prop changes\n React.useEffect(() => {\n if (!isEditorReady || !editorInstanceRef.current) {\n return\n }\n\n const editor = editorInstanceRef.current\n editor.editing.view.change((writer) => {\n const viewEditableRoot = editor.editing.view.document.getRoot()\n if (viewEditableRoot) {\n if (ariaLabel) {\n writer.setAttribute('aria-label', ariaLabel, viewEditableRoot)\n } else {\n writer.removeAttribute('aria-label', viewEditableRoot)\n }\n }\n })\n }, [ariaLabel, isEditorReady])\n\n // Update aria-description when ariaDescription prop changes\n React.useEffect(() => {\n if (!isEditorReady || !editorInstanceRef.current) {\n return\n }\n\n const editor = editorInstanceRef.current\n editor.editing.view.change((writer) => {\n const viewEditableRoot = editor.editing.view.document.getRoot()\n if (viewEditableRoot) {\n if (ariaDescription) {\n writer.setAttribute(\n 'aria-description',\n ariaDescription,\n viewEditableRoot\n )\n } else {\n writer.removeAttribute('aria-description', viewEditableRoot)\n }\n }\n })\n }, [ariaDescription, isEditorReady])\n\n const { value: zIndex } = useZIndexContext()\n\n const { features } = React.useContext(TextEditorContext)\n const enableStickyToolbar = !!features?.stickyToolbar\n const enableTabAsNavigation = !!features?.tabAsNavigation\n\n const mergedConfig = React.useMemo(() => {\n const defaultConfig = getDefaultConfig(locale)\n\n // Set accessible label for the editable area if provided\n // This is used by screen readers to announce the editor's purpose\n if (ariaLabel) {\n defaultConfig.label = ariaLabel\n }\n\n return defaultConfig\n }, [ariaLabel, locale])\n\n const bindKeyDownHandler = React.useCallback(\n (editor: ClassicEditor) => {\n const editorElement = editor.editing.view.document.getRoot()\n if (!editorElement) {\n return\n }\n\n // Remove existing keydown listener\n if (keyDownListenerRef.current) {\n editor.editing.view.document.off('keydown', keyDownListenerRef.current)\n }\n\n // Create and store the new listener\n const keyDownListener = (\n _event: EventInfo,\n data: { domEvent: Event }\n ) => {\n const domEvent = data.domEvent as KeyboardEvent\n // Prevent Enter from propagating to parent forms so the\n // editor can handle newlines without accidentally submitting.\n if (domEvent.key === 'Enter') {\n domEvent.stopPropagation()\n }\n\n onKeyDown?.(domEvent, editor)\n }\n\n keyDownListenerRef.current = keyDownListener\n\n // Add the keydown listener\n editor.editing.view.document.on('keydown', keyDownListener)\n },\n [onKeyDown]\n )\n\n const handleChange = (\n _event: EventInfo<string, unknown>,\n editor: ClassicEditor\n ) => {\n const data = editor.getData()\n const isDirty = data !== initialValueRef.current\n\n // Call onDirty only on first content modification\n if (isDirty && !isDirtyState) {\n setIsDirtyState(true)\n onDirty?.()\n }\n\n onChange?.(data, isDirty)\n }\n\n const handleReady = (editor: ClassicEditor) => {\n addButtonDataAttributes(editor)\n editorInstanceRef.current = editor\n setIsEditorReady(true)\n\n if (initialValue) {\n editor.setData(initialValue)\n }\n\n // Set aria-label and aria-description on the editable area if provided\n // These provide accessible context to screen reader users\n editor.editing.view.change((writer) => {\n const viewEditableRoot = editor.editing.view.document.getRoot()\n if (viewEditableRoot) {\n if (ariaLabel) {\n writer.setAttribute('aria-label', ariaLabel, viewEditableRoot)\n }\n if (ariaDescription) {\n writer.setAttribute(\n 'aria-description',\n ariaDescription,\n viewEditableRoot\n )\n }\n }\n })\n\n // Bind keydown handler when editor is ready\n bindKeyDownHandler(editor)\n\n onInit?.(editor)\n }\n\n const handleBlur = (\n event: EventInfo<string, unknown>,\n editor: ClassicEditor\n ) => {\n onBlur?.(event, editor)\n }\n\n useStickyToolbar({\n enabled: enableStickyToolbar,\n editor: isEditorReady ? editorInstanceRef.current : null,\n editorRef,\n cssLoading,\n })\n\n const { config } = useTabAsNavigation({\n config: mergedConfig,\n enabled: enableTabAsNavigation,\n editor: isEditorReady ? editorInstanceRef.current : null,\n })\n\n const editorKey = `${locale}-${enableTabAsNavigation}`\n\n if (cssLoading) {\n return null\n }\n\n if (readonly) {\n return (\n <TextEditorOutput\n value={value}\n aria-label={ariaLabel}\n aria-description={ariaDescription}\n />\n )\n }\n\n return (\n <StyledTextEditor\n ref={editorRef}\n key={editorKey}\n error={error}\n aria-invalid={error ? 'true' : 'false'}\n >\n <GlobalEditorStyles zIndex={zIndex + 1} />\n <TextEditorTheme />\n <CKEditor\n {...restProps}\n editor={ClassicEditor}\n config={config}\n disabled={disabled}\n data={value}\n onChange={handleChange}\n onReady={handleReady}\n onBlur={handleBlur}\n />\n </StyledTextEditor>\n )\n}\n"],"mappings":";;;;;;;;;;AAAA,SAASA,QAAQ,QAAQ,2BAA2B;AACpD,SAASC,aAAa,QAAwB,WAAW;AACzD,OAAOC,KAAK,MAAM,OAAO;AAEzB,SAASC,cAAc,EAAEC,gBAAgB,QAAQ,qBAAqB;AACtE,SAASC,gBAAgB,QAAQ,qBAAqB;AACtD,SAASC,gBAAgB,QAAQ,iBAAiB;AAClD,SAASC,kBAAkB,EAAEC,gBAAgB,QAAQ,qBAAqB;AAE1E,SAASC,iBAAiB,QAAQ,sBAAsB;AACxD,SAASC,eAAe,QAAQ,qBAAqB;AACrD,SAASC,cAAc,QAAQ,kBAAkB;AACjD,SAASC,kBAAkB,QAAQ,sBAAsB;AACzD,SAASC,uBAAuB,EAAEC,gBAAgB,QAAQ,SAAS;;AAEnE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,UAAUA,CAACC,KAAgC,EAAE;EAC3D,IACEC,QAAQ,GAYND,KAAK,CAZPC,QAAQ;IACRC,KAAK,GAWHF,KAAK,CAXPE,KAAK;IACLC,QAAQ,GAUNH,KAAK,CAVPG,QAAQ;IACRC,KAAK,GASHJ,KAAK,CATPI,KAAK;IACLC,YAAY,GAQVL,KAAK,CARPK,YAAY;IACZC,QAAQ,GAONN,KAAK,CAPPM,QAAQ;IACRC,MAAM,GAMJP,KAAK,CANPO,MAAM;IACNC,MAAM,GAKJR,KAAK,CALPQ,MAAM;IACNC,SAAS,GAIPT,KAAK,CAJPS,SAAS;IACDC,UAAU,GAGhBV,KAAK,CAHPW,MAAM;IACNC,OAAO,GAELZ,KAAK,CAFPY,OAAO;IACJC,SAAS,GAAAC,wBAAA,CACVd,KAAK,EAAAe,SAAA;EACT,IAAMC,SAAS,GAAGhB,KAAK,CAAC,YAAY,CAAC;EACrC,IAAMiB,eAAe,GAAGjB,KAAK,CAAC,kBAAkB,CAAC;EACjD,IAAAkB,eAAA,GAAkCvB,cAAc,CAAC,CAAC;IAA/BwB,UAAU,GAAAD,eAAA,CAArBE,SAAS;EAEjB,IAAMC,SAAS,GAAGnC,KAAK,CAACoC,MAAM,CAAiB,IAAI,CAAC;EACpD,IAAMC,iBAAiB,GAAGrC,KAAK,CAACoC,MAAM,CAAuB,IAAI,CAAC;EAClE,IAAME,eAAe,GAAGtC,KAAK,CAACoC,MAAM,CAASlB,KAAK,IAAIC,YAAY,IAAI,EAAE,CAAC;EACzE,IAAMoB,kBAAkB,GAAGvC,KAAK,CAACoC,MAAM,CAAyB,IAAI,CAAC;EACrE,IAAAI,eAAA,GAAwCxC,KAAK,CAACyC,QAAQ,CAAC,KAAK,CAAC;IAAAC,gBAAA,GAAAC,cAAA,CAAAH,eAAA;IAAtDI,YAAY,GAAAF,gBAAA;IAAEG,eAAe,GAAAH,gBAAA;EACpC,IAAAI,gBAAA,GAA0C9C,KAAK,CAACyC,QAAQ,CAAC,KAAK,CAAC;IAAAM,gBAAA,GAAAJ,cAAA,CAAAG,gBAAA;IAAxDE,aAAa,GAAAD,gBAAA;IAAEE,gBAAgB,GAAAF,gBAAA;EACtC,IAAAG,eAAA,GAAkCjD,cAAc,CAAC,CAAC;IAAlCkD,aAAa,GAAAD,eAAA,CAArBzB,MAAM;EACd,IAAMA,MAAM,GAAGD,UAAU,IAAI2B,aAAa;EAE1CnD,KAAK,CAACoD,SAAS,CAAC,YAAM;IACpB,IAAIlC,KAAK,KAAKmC,SAAS,EAAE;MACvBf,eAAe,CAACgB,OAAO,GAAGpC,KAAK;IACjC;EACF,CAAC,EAAE,CAACA,KAAK,CAAC,CAAC;;EAEX;EACAlB,KAAK,CAACoD,SAAS,CAAC,YAAM;IACpB,OAAO,YAAM;MACX,IAAIb,kBAAkB,CAACe,OAAO,IAAIjB,iBAAiB,CAACiB,OAAO,EAAE;QAC3DjB,iBAAiB,CAACiB,OAAO,CAACC,OAAO,CAACC,IAAI,CAACC,QAAQ,CAACC,GAAG,CACjD,SAAS,EACTnB,kBAAkB,CAACe,OACrB,CAAC;QACDf,kBAAkB,CAACe,OAAO,GAAG,IAAI;MACnC;IACF,CAAC;EACH,CAAC,EAAE,EAAE,CAAC;;EAEN;EACAtD,KAAK,CAACoD,SAAS,CAAC,YAAM;IACpB,IAAI,CAACJ,aAAa,IAAI,CAACX,iBAAiB,CAACiB,OAAO,EAAE;MAChD;IACF;IAEA,IAAMK,MAAM,GAAGtB,iBAAiB,CAACiB,OAAO;IACxCK,MAAM,CAACJ,OAAO,CAACC,IAAI,CAACI,MAAM,CAAC,UAACC,MAAM,EAAK;MACrC,IAAMC,gBAAgB,GAAGH,MAAM,CAACJ,OAAO,CAACC,IAAI,CAACC,QAAQ,CAACM,OAAO,CAAC,CAAC;MAC/D,IAAID,gBAAgB,EAAE;QACpB,IAAIhC,SAAS,EAAE;UACb+B,MAAM,CAACG,YAAY,CAAC,YAAY,EAAElC,SAAS,EAAEgC,gBAAgB,CAAC;QAChE,CAAC,MAAM;UACLD,MAAM,CAACI,eAAe,CAAC,YAAY,EAAEH,gBAAgB,CAAC;QACxD;MACF;IACF,CAAC,CAAC;EACJ,CAAC,EAAE,CAAChC,SAAS,EAAEkB,aAAa,CAAC,CAAC;;EAE9B;EACAhD,KAAK,CAACoD,SAAS,CAAC,YAAM;IACpB,IAAI,CAACJ,aAAa,IAAI,CAACX,iBAAiB,CAACiB,OAAO,EAAE;MAChD;IACF;IAEA,IAAMK,MAAM,GAAGtB,iBAAiB,CAACiB,OAAO;IACxCK,MAAM,CAACJ,OAAO,CAACC,IAAI,CAACI,MAAM,CAAC,UAACC,MAAM,EAAK;MACrC,IAAMC,gBAAgB,GAAGH,MAAM,CAACJ,OAAO,CAACC,IAAI,CAACC,QAAQ,CAACM,OAAO,CAAC,CAAC;MAC/D,IAAID,gBAAgB,EAAE;QACpB,IAAI/B,eAAe,EAAE;UACnB8B,MAAM,CAACG,YAAY,CACjB,kBAAkB,EAClBjC,eAAe,EACf+B,gBACF,CAAC;QACH,CAAC,MAAM;UACLD,MAAM,CAACI,eAAe,CAAC,kBAAkB,EAAEH,gBAAgB,CAAC;QAC9D;MACF;IACF,CAAC,CAAC;EACJ,CAAC,EAAE,CAAC/B,eAAe,EAAEiB,aAAa,CAAC,CAAC;EAEpC,IAAAkB,iBAAA,GAA0BhE,gBAAgB,CAAC,CAAC;IAA7BiE,MAAM,GAAAD,iBAAA,CAAbhD,KAAK;EAEb,IAAAkD,iBAAA,GAAqBpE,KAAK,CAACqE,UAAU,CAAC9D,iBAAiB,CAAC;IAAhD+D,QAAQ,GAAAF,iBAAA,CAARE,QAAQ;EAChB,IAAMC,mBAAmB,GAAG,CAAC,EAACD,QAAQ,aAARA,QAAQ,eAARA,QAAQ,CAAEE,aAAa;EACrD,IAAMC,qBAAqB,GAAG,CAAC,EAACH,QAAQ,aAARA,QAAQ,eAARA,QAAQ,CAAEI,eAAe;EAEzD,IAAMC,YAAY,GAAG3E,KAAK,CAAC4E,OAAO,CAAC,YAAM;IACvC,IAAMC,aAAa,GAAGjE,gBAAgB,CAACa,MAAM,CAAC;;IAE9C;IACA;IACA,IAAIK,SAAS,EAAE;MACb+C,aAAa,CAACC,KAAK,GAAGhD,SAAS;IACjC;IAEA,OAAO+C,aAAa;EACtB,CAAC,EAAE,CAAC/C,SAAS,EAAEL,MAAM,CAAC,CAAC;EAEvB,IAAMsD,kBAAkB,GAAG/E,KAAK,CAACgF,WAAW,CAC1C,UAACrB,MAAqB,EAAK;IACzB,IAAMsB,aAAa,GAAGtB,MAAM,CAACJ,OAAO,CAACC,IAAI,CAACC,QAAQ,CAACM,OAAO,CAAC,CAAC;IAC5D,IAAI,CAACkB,aAAa,EAAE;MAClB;IACF;;IAEA;IACA,IAAI1C,kBAAkB,CAACe,OAAO,EAAE;MAC9BK,MAAM,CAACJ,OAAO,CAACC,IAAI,CAACC,QAAQ,CAACC,GAAG,CAAC,SAAS,EAAEnB,kBAAkB,CAACe,OAAO,CAAC;IACzE;;IAEA;IACA,IAAM4B,eAAe,GAAG,SAAlBA,eAAeA,CACnBC,MAAiB,EACjBC,IAAyB,EACtB;MACH,IAAMC,QAAQ,GAAGD,IAAI,CAACC,QAAyB;MAC/C;MACA;MACA,IAAIA,QAAQ,CAACC,GAAG,KAAK,OAAO,EAAE;QAC5BD,QAAQ,CAACE,eAAe,CAAC,CAAC;MAC5B;MAEAhE,SAAS,aAATA,SAAS,uBAATA,SAAS,CAAG8D,QAAQ,EAAE1B,MAAM,CAAC;IAC/B,CAAC;IAEDpB,kBAAkB,CAACe,OAAO,GAAG4B,eAAe;;IAE5C;IACAvB,MAAM,CAACJ,OAAO,CAACC,IAAI,CAACC,QAAQ,CAAC+B,EAAE,CAAC,SAAS,EAAEN,eAAe,CAAC;EAC7D,CAAC,EACD,CAAC3D,SAAS,CACZ,CAAC;EAED,IAAMkE,YAAY,GAAG,SAAfA,YAAYA,CAChBN,MAAkC,EAClCxB,MAAqB,EAClB;IACH,IAAMyB,IAAI,GAAGzB,MAAM,CAAC+B,OAAO,CAAC,CAAC;IAC7B,IAAMC,OAAO,GAAGP,IAAI,KAAK9C,eAAe,CAACgB,OAAO;;IAEhD;IACA,IAAIqC,OAAO,IAAI,CAAC/C,YAAY,EAAE;MAC5BC,eAAe,CAAC,IAAI,CAAC;MACrBnB,OAAO,aAAPA,OAAO,uBAAPA,OAAO,CAAG,CAAC;IACb;IAEAN,QAAQ,aAARA,QAAQ,uBAARA,QAAQ,CAAGgE,IAAI,EAAEO,OAAO,CAAC;EAC3B,CAAC;EAED,IAAMC,WAAW,GAAG,SAAdA,WAAWA,CAAIjC,MAAqB,EAAK;IAC7ChD,uBAAuB,CAACgD,MAAM,CAAC;IAC/BtB,iBAAiB,CAACiB,OAAO,GAAGK,MAAM;IAClCV,gBAAgB,CAAC,IAAI,CAAC;IAEtB,IAAI9B,YAAY,EAAE;MAChBwC,MAAM,CAACkC,OAAO,CAAC1E,YAAY,CAAC;IAC9B;;IAEA;IACA;IACAwC,MAAM,CAACJ,OAAO,CAACC,IAAI,CAACI,MAAM,CAAC,UAACC,MAAM,EAAK;MACrC,IAAMC,gBAAgB,GAAGH,MAAM,CAACJ,OAAO,CAACC,IAAI,CAACC,QAAQ,CAACM,OAAO,CAAC,CAAC;MAC/D,IAAID,gBAAgB,EAAE;QACpB,IAAIhC,SAAS,EAAE;UACb+B,MAAM,CAACG,YAAY,CAAC,YAAY,EAAElC,SAAS,EAAEgC,gBAAgB,CAAC;QAChE;QACA,IAAI/B,eAAe,EAAE;UACnB8B,MAAM,CAACG,YAAY,CACjB,kBAAkB,EAClBjC,eAAe,EACf+B,gBACF,CAAC;QACH;MACF;IACF,CAAC,CAAC;;IAEF;IACAiB,kBAAkB,CAACpB,MAAM,CAAC;IAE1BtC,MAAM,aAANA,MAAM,uBAANA,MAAM,CAAGsC,MAAM,CAAC;EAClB,CAAC;EAED,IAAMmC,UAAU,GAAG,SAAbA,UAAUA,CACdC,KAAiC,EACjCpC,MAAqB,EAClB;IACHrC,MAAM,aAANA,MAAM,uBAANA,MAAM,CAAGyE,KAAK,EAAEpC,MAAM,CAAC;EACzB,CAAC;EAEDvD,gBAAgB,CAAC;IACf4F,OAAO,EAAEzB,mBAAmB;IAC5BZ,MAAM,EAAEX,aAAa,GAAGX,iBAAiB,CAACiB,OAAO,GAAG,IAAI;IACxDnB,SAAS,EAATA,SAAS;IACTF,UAAU,EAAVA;EACF,CAAC,CAAC;EAEF,IAAAgE,mBAAA,GAAmBvF,kBAAkB,CAAC;MACpCwF,MAAM,EAAEvB,YAAY;MACpBqB,OAAO,EAAEvB,qBAAqB;MAC9Bd,MAAM,EAAEX,aAAa,GAAGX,iBAAiB,CAACiB,OAAO,GAAG;IACtD,CAAC,CAAC;IAJM4C,MAAM,GAAAD,mBAAA,CAANC,MAAM;EAMd,IAAMC,SAAS,MAAAC,MAAA,CAAM3E,MAAM,OAAA2E,MAAA,CAAI3B,qBAAqB,CAAE;EAEtD,IAAIxC,UAAU,EAAE;IACd,OAAO,IAAI;EACb;EAEA,IAAIhB,QAAQ,EAAE;IACZ,oBACEjB,KAAA,CAAAqG,aAAA,CAAClG,gBAAgB;MACfe,KAAK,EAAEA,KAAM;MACb,cAAYY,SAAU;MACtB,oBAAkBC;IAAgB,CACnC,CAAC;EAEN;EAEA,oBACE/B,KAAA,CAAAqG,aAAA,CAAC/F,gBAAgB;IACfgG,GAAG,EAAEnE,SAAU;IACfmD,GAAG,EAAEa,SAAU;IACfnF,KAAK,EAAEA,KAAM;IACb,gBAAcA,KAAK,GAAG,MAAM,GAAG;EAAQ,gBAEvChB,KAAA,CAAAqG,aAAA,CAAChG,kBAAkB;IAAC8D,MAAM,EAAEA,MAAM,GAAG;EAAE,CAAE,CAAC,eAC1CnE,KAAA,CAAAqG,aAAA,CAAC7F,eAAe,MAAE,CAAC,eACnBR,KAAA,CAAAqG,aAAA,CAACvG,QAAQ,EAAAyG,QAAA,KACH5E,SAAS;IACbgC,MAAM,EAAE5D,aAAc;IACtBmG,MAAM,EAAEA,MAAO;IACfnF,QAAQ,EAAEA,QAAS;IACnBqE,IAAI,EAAElE,KAAM;IACZE,QAAQ,EAAEqE,YAAa;IACvBe,OAAO,EAAEZ,WAAY;IACrBtE,MAAM,EAAEwE;EAAW,EACpB,CACe,CAAC;AAEvB"}
|