jodit-react 5.0.7 → 5.0.10
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 +6 -2
- package/build/jodit-react.js +1 -1
- package/build/types/JoditEditor.js +101 -0
- package/build/types/include.jodit.d.ts +1 -1
- package/build/types/include.jodit.js +5 -0
- package/build/types/index.js +4 -0
- package/package.json +2 -2
- package/src/JoditEditor.tsx +11 -11
- package/tests/ref.test.tsx +46 -0
- package/tests/theme.test.tsx +18 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import React, { useEffect, useRef, forwardRef } from 'react';
|
|
2
|
+
import { Jodit } from './include.jodit';
|
|
3
|
+
function usePrevious(value) {
|
|
4
|
+
const ref = useRef('');
|
|
5
|
+
useEffect(() => {
|
|
6
|
+
ref.current = value;
|
|
7
|
+
}, [value]);
|
|
8
|
+
return ref.current;
|
|
9
|
+
}
|
|
10
|
+
const JoditEditor = forwardRef(({ JoditConstructor = Jodit, className, config, id, name, onBlur, onChange, tabIndex, value, editorRef }, ref) => {
|
|
11
|
+
const textAreaRef = useRef(null);
|
|
12
|
+
const joditRef = useRef(null);
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
const element = textAreaRef.current;
|
|
15
|
+
const jodit = JoditConstructor.make(element, config);
|
|
16
|
+
joditRef.current = jodit;
|
|
17
|
+
if (typeof editorRef === 'function') {
|
|
18
|
+
editorRef(jodit);
|
|
19
|
+
}
|
|
20
|
+
return () => {
|
|
21
|
+
if (jodit.isReady) {
|
|
22
|
+
jodit.destruct();
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
jodit
|
|
26
|
+
.waitForReady()
|
|
27
|
+
.then(joditInstance => joditInstance.destruct());
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
}, [JoditConstructor, config, editorRef]);
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
if (ref) {
|
|
33
|
+
if (typeof ref === 'function') {
|
|
34
|
+
ref(joditRef.current);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
ref.current = joditRef.current;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}, [textAreaRef, ref, joditRef]);
|
|
41
|
+
const preClassName = usePrevious(className ?? '');
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
const classList = joditRef.current?.container?.classList;
|
|
44
|
+
if (preClassName !== className &&
|
|
45
|
+
typeof preClassName === 'string') {
|
|
46
|
+
preClassName
|
|
47
|
+
.split(/\s+/)
|
|
48
|
+
.filter(Boolean)
|
|
49
|
+
.forEach(cl => classList?.remove(cl));
|
|
50
|
+
}
|
|
51
|
+
if (className && typeof className === 'string') {
|
|
52
|
+
className
|
|
53
|
+
.split(/\s+/)
|
|
54
|
+
.filter(Boolean)
|
|
55
|
+
.forEach(cl => classList?.add(cl));
|
|
56
|
+
}
|
|
57
|
+
}, [className, preClassName]);
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
if (joditRef.current?.workplace) {
|
|
60
|
+
joditRef.current.workplace.tabIndex = tabIndex || -1;
|
|
61
|
+
}
|
|
62
|
+
}, [tabIndex]);
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
const jodit = joditRef.current;
|
|
65
|
+
if (!jodit?.events || !(onBlur || onChange)) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const onBlurHandler = (event) => onBlur && onBlur(joditRef?.current?.value ?? '', event);
|
|
69
|
+
const onChangeHandler = (value) => onChange && onChange(value);
|
|
70
|
+
// adding event handlers
|
|
71
|
+
jodit.events
|
|
72
|
+
.on('blur', onBlurHandler)
|
|
73
|
+
.on('change', onChangeHandler);
|
|
74
|
+
return () => {
|
|
75
|
+
// Remove event handlers
|
|
76
|
+
jodit.events
|
|
77
|
+
?.off('blur', onBlurHandler)
|
|
78
|
+
.off('change', onChangeHandler);
|
|
79
|
+
};
|
|
80
|
+
}, [onBlur, onChange]);
|
|
81
|
+
useEffect(() => {
|
|
82
|
+
const jodit = joditRef.current;
|
|
83
|
+
const updateValue = () => {
|
|
84
|
+
if (jodit && value !== undefined && jodit.value !== value) {
|
|
85
|
+
jodit.value = value;
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
if (jodit) {
|
|
89
|
+
if (jodit.isReady) {
|
|
90
|
+
updateValue();
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
jodit.waitForReady().then(updateValue);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}, [value]);
|
|
97
|
+
return (React.createElement("div", { className: 'jodit-react-container' },
|
|
98
|
+
React.createElement("textarea", { defaultValue: value, name: name, id: id, ref: textAreaRef })));
|
|
99
|
+
});
|
|
100
|
+
JoditEditor.displayName = 'JoditEditor';
|
|
101
|
+
export default JoditEditor;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jodit-react",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.10",
|
|
4
4
|
"description": "Jodit is awesome and usefully wysiwyg editor with filebrowser",
|
|
5
5
|
"main": "build/jodit-react.js",
|
|
6
6
|
"author": "Chupurnov <chupurnov@gmail.com> (https://xdsoft.net/)",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"start": "npm run demo",
|
|
67
67
|
"build": "npm run build:react && npm run build:types",
|
|
68
68
|
"build:react": "NODE_ENV=production node -r @swc-node/register ./node_modules/.bin/webpack --mode production",
|
|
69
|
-
"build:types": "rm -rf ./build/types && tsc --project tsconfig.types.json
|
|
69
|
+
"build:types": "rm -rf ./build/types && tsc --project tsconfig.types.json && npm run remove-css",
|
|
70
70
|
"remove-css": "replace \"import '[^']+.css';\" '' ./build/**/*.ts",
|
|
71
71
|
"github": "npm run git && git push --tags origin HEAD:main",
|
|
72
72
|
"git": "git add --all && git commit -m \"New version $npm_package_version. Read more https://github.com/jodit/jodit-react/releases/tag/$npm_package_version \" && git tag $npm_package_version",
|
package/src/JoditEditor.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useEffect, useRef, forwardRef
|
|
1
|
+
import React, { useEffect, useRef, forwardRef } from 'react';
|
|
2
2
|
import type { IJodit } from 'jodit/types/types/jodit';
|
|
3
3
|
import type { Jodit as JoditBaseConstructor } from 'jodit/types/index';
|
|
4
4
|
import type { Config as BaseConfig } from 'jodit/config';
|
|
@@ -46,16 +46,6 @@ const JoditEditor = forwardRef<IJodit, Props>(
|
|
|
46
46
|
const textAreaRef = useRef<HTMLTextAreaElement | null>(null);
|
|
47
47
|
const joditRef = useRef<IJodit | null>(null);
|
|
48
48
|
|
|
49
|
-
useLayoutEffect(() => {
|
|
50
|
-
if (ref) {
|
|
51
|
-
if (typeof ref === 'function') {
|
|
52
|
-
ref(joditRef.current);
|
|
53
|
-
} else {
|
|
54
|
-
ref.current = joditRef.current;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}, [textAreaRef, ref]);
|
|
58
|
-
|
|
59
49
|
useEffect(() => {
|
|
60
50
|
const element = textAreaRef.current!;
|
|
61
51
|
const jodit = JoditConstructor.make(element, config);
|
|
@@ -76,6 +66,16 @@ const JoditEditor = forwardRef<IJodit, Props>(
|
|
|
76
66
|
};
|
|
77
67
|
}, [JoditConstructor, config, editorRef]);
|
|
78
68
|
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
if (ref) {
|
|
71
|
+
if (typeof ref === 'function') {
|
|
72
|
+
ref(joditRef.current);
|
|
73
|
+
} else {
|
|
74
|
+
ref.current = joditRef.current;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}, [textAreaRef, ref, joditRef]);
|
|
78
|
+
|
|
79
79
|
const preClassName = usePrevious(className ?? '');
|
|
80
80
|
|
|
81
81
|
useEffect(() => {
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { describe, it } from '@jest/globals';
|
|
3
|
+
import { render, act } from '@testing-library/react';
|
|
4
|
+
import '@testing-library/jest-dom';
|
|
5
|
+
import JoditEditor from '../src';
|
|
6
|
+
import type { IJodit } from 'jodit/types/types/jodit';
|
|
7
|
+
|
|
8
|
+
describe('Ref Test', () => {
|
|
9
|
+
describe('Ref as function', () => {
|
|
10
|
+
it('should be instance of imperative Jodit', () => {
|
|
11
|
+
const ref = React.createRef<IJodit>();
|
|
12
|
+
|
|
13
|
+
const App = () => (
|
|
14
|
+
<JoditEditor
|
|
15
|
+
ref={newRef => {
|
|
16
|
+
ref.current = newRef;
|
|
17
|
+
}}
|
|
18
|
+
/>
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
const elm = render(<App />);
|
|
22
|
+
|
|
23
|
+
act(() => {
|
|
24
|
+
elm.rerender(<App />);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
expect(ref.current?.isJodit).toBe(true);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
describe('Ref as object', () => {
|
|
32
|
+
it('should be instance of imperative Jodit', () => {
|
|
33
|
+
const ref = React.createRef<IJodit>();
|
|
34
|
+
|
|
35
|
+
const App = () => <JoditEditor ref={ref} />;
|
|
36
|
+
|
|
37
|
+
const elm = render(<App />);
|
|
38
|
+
|
|
39
|
+
act(() => {
|
|
40
|
+
elm.rerender(<App />);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
expect(ref.current?.isJodit).toBe(true);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { describe, it } from '@jest/globals';
|
|
3
|
+
import { render } from '@testing-library/react';
|
|
4
|
+
import '@testing-library/jest-dom';
|
|
5
|
+
import JoditEditor from '../src';
|
|
6
|
+
|
|
7
|
+
describe('Theme Test', () => {
|
|
8
|
+
it('should render with theme classname', () => {
|
|
9
|
+
const { container } = render(
|
|
10
|
+
<JoditEditor config={{ theme: 'summer' }} />
|
|
11
|
+
);
|
|
12
|
+
expect(
|
|
13
|
+
container
|
|
14
|
+
.querySelector('.jodit-container')!
|
|
15
|
+
.classList.contains('jodit_theme_summer')
|
|
16
|
+
).toBe(true);
|
|
17
|
+
});
|
|
18
|
+
});
|