@vector-im/matrix-wysiwyg 2.37.11
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/README.md +98 -0
- package/dist/index.d.ts +246 -0
- package/dist/matrix-wysiwyg.js +2079 -0
- package/dist/matrix-wysiwyg.umd.cjs +11 -0
- package/package.json +84 -0
package/README.md
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# React Matrix Rich Text Editor
|
|
2
|
+
|
|
3
|
+
[](https://github.com/element-hq/matrix-rich-text-editor/actions/workflows/react-build.yml)
|
|
4
|
+
|
|
5
|
+
The Matrix Rich Text Editor is a React library.
|
|
6
|
+
|
|
7
|
+
## TODO NPM / Usage documentation
|
|
8
|
+
|
|
9
|
+
The wysiwyg composer API is a react hook.
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
const { ref, isWysiwygReady, wysiwyg } = useWysiwyg();
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<div>
|
|
16
|
+
<button type="button" onClick={wysiwyg.bold}>
|
|
17
|
+
bold
|
|
18
|
+
</button>
|
|
19
|
+
<div ref={ref} contentEditable={isWysiwygReady} />
|
|
20
|
+
</div>
|
|
21
|
+
);
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Contribute
|
|
25
|
+
|
|
26
|
+
### Install
|
|
27
|
+
|
|
28
|
+
#### Generate WASM bindings
|
|
29
|
+
|
|
30
|
+
The composer uses a cross-platform rust library. In order to work as intended, the WASM bindings must be generated according to the [Matrix Rich Text Editor README.md](../../README.md)
|
|
31
|
+
|
|
32
|
+
#### Yarn install
|
|
33
|
+
|
|
34
|
+
Requirements:
|
|
35
|
+
|
|
36
|
+
- node >= 8.X
|
|
37
|
+
- yarn 1.X
|
|
38
|
+
|
|
39
|
+
```sh
|
|
40
|
+
yarn install
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Dev
|
|
44
|
+
|
|
45
|
+
#### Folder structure
|
|
46
|
+
|
|
47
|
+
- Inside the `lib` folder, the wysiwyg composer library files are located with `useWysiwyg` as en entrypoint
|
|
48
|
+
- Inside the `src` folder, the demo page of the composer is located.
|
|
49
|
+
|
|
50
|
+
### Dev mode
|
|
51
|
+
|
|
52
|
+
Launch:
|
|
53
|
+
|
|
54
|
+
```sh
|
|
55
|
+
yarn dev
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
A dev server with hot reload is launched on `http://localhost:5173/` by default.
|
|
59
|
+
|
|
60
|
+
For more information, see [Vite](https://vitejs.dev/guide/features.html#hot-module-replacement) for more information.
|
|
61
|
+
|
|
62
|
+
### Build
|
|
63
|
+
|
|
64
|
+
[Vite](https://vitejs.dev/) is the Wysiwyg Composer builder.
|
|
65
|
+
|
|
66
|
+
To build:
|
|
67
|
+
|
|
68
|
+
```sh
|
|
69
|
+
yarn build
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The builded files are located in the `dist` folder
|
|
73
|
+
|
|
74
|
+
### Testing
|
|
75
|
+
|
|
76
|
+
The tests are powered by [Vitest](https://vitest.dev/).
|
|
77
|
+
|
|
78
|
+
To run them, different options are available:
|
|
79
|
+
|
|
80
|
+
- Classic run
|
|
81
|
+
|
|
82
|
+
```sh
|
|
83
|
+
yarn test
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
- Watch mode
|
|
87
|
+
|
|
88
|
+
```sh
|
|
89
|
+
yarn test:watch
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
- Code coverage
|
|
93
|
+
|
|
94
|
+
```sh
|
|
95
|
+
yarn coverage
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The coverage report is located in the `coverage` folder.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import { RefObject } from 'react';
|
|
2
|
+
|
|
3
|
+
export declare const ACTION_TYPES: readonly ["bold", "italic", "strikeThrough", "underline", "undo", "redo", "orderedList", "unorderedList", "inlineCode", "clear", "link", "codeBlock", "quote", "indent", "unindent"];
|
|
4
|
+
|
|
5
|
+
export declare type ActionState = 'enabled' | 'reversed' | 'disabled';
|
|
6
|
+
|
|
7
|
+
export declare type ActionTypes = (typeof ACTION_TYPES)[number];
|
|
8
|
+
|
|
9
|
+
export declare type AllActionStates = Record<ActionTypes, ActionState>;
|
|
10
|
+
|
|
11
|
+
export declare type AllowedMentionAttributes = Map<'style' | 'data-mention-type', string>;
|
|
12
|
+
|
|
13
|
+
export declare type BlockType = InputEvent['inputType'] | 'formatInlineCode' | 'clear';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
*/
|
|
17
|
+
export declare class ComposerUpdate {
|
|
18
|
+
free(): void;
|
|
19
|
+
/**
|
|
20
|
+
* @returns {TextUpdate}
|
|
21
|
+
*/
|
|
22
|
+
text_update(): TextUpdate;
|
|
23
|
+
/**
|
|
24
|
+
* @returns {MenuState}
|
|
25
|
+
*/
|
|
26
|
+
menu_state(): MenuState;
|
|
27
|
+
/**
|
|
28
|
+
* @returns {MenuAction}
|
|
29
|
+
*/
|
|
30
|
+
menu_action(): MenuAction;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export declare type FormattingFunctions = Record<Exclude<ActionTypes, 'link'>, () => void> & {
|
|
34
|
+
insertText: (text: string) => void;
|
|
35
|
+
link: (url: string, text?: string) => void;
|
|
36
|
+
mention: (url: string, text: string, attributes: AllowedMentionAttributes) => void;
|
|
37
|
+
mentionAtRoom: (attributes: AllowedMentionAttributes) => void;
|
|
38
|
+
command: (text: string) => void;
|
|
39
|
+
removeLinks: () => void;
|
|
40
|
+
getLink: () => string;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export declare type InputEventProcessor = (event: WysiwygEvent, wysiwyg: Wysiwyg, editor: HTMLElement) => WysiwygEvent | null;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
*/
|
|
47
|
+
export declare class Keep {
|
|
48
|
+
free(): void;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export declare type LinkEvent = Omit<InputEvent, 'data'> & {
|
|
52
|
+
inputType: 'insertLink';
|
|
53
|
+
data: {
|
|
54
|
+
url: string;
|
|
55
|
+
text?: string;
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export declare type MappedSuggestion = {
|
|
60
|
+
keyChar: SuggestionChar;
|
|
61
|
+
text: string;
|
|
62
|
+
type: SuggestionType;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
*/
|
|
67
|
+
export declare class MenuAction {
|
|
68
|
+
free(): void;
|
|
69
|
+
/**
|
|
70
|
+
* @returns {boolean}
|
|
71
|
+
*/
|
|
72
|
+
keep(): boolean;
|
|
73
|
+
/**
|
|
74
|
+
* @returns {boolean}
|
|
75
|
+
*/
|
|
76
|
+
none(): boolean;
|
|
77
|
+
/**
|
|
78
|
+
* @returns {MenuActionSuggestion | undefined}
|
|
79
|
+
*/
|
|
80
|
+
suggestion(): MenuActionSuggestion | undefined;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
*/
|
|
85
|
+
export declare class MenuActionSuggestion {
|
|
86
|
+
free(): void;
|
|
87
|
+
/**
|
|
88
|
+
*/
|
|
89
|
+
suggestion_pattern: SuggestionPattern;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
*/
|
|
94
|
+
export declare class MenuState {
|
|
95
|
+
free(): void;
|
|
96
|
+
/**
|
|
97
|
+
* @returns {boolean}
|
|
98
|
+
*/
|
|
99
|
+
keep(): boolean;
|
|
100
|
+
/**
|
|
101
|
+
* @returns {MenuStateUpdate | undefined}
|
|
102
|
+
*/
|
|
103
|
+
update(): MenuStateUpdate | undefined;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
*/
|
|
108
|
+
export declare class MenuStateUpdate {
|
|
109
|
+
free(): void;
|
|
110
|
+
/**
|
|
111
|
+
*/
|
|
112
|
+
action_states: Map<any, any>;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
*/
|
|
117
|
+
export declare class PatternKey {
|
|
118
|
+
free(): void;
|
|
119
|
+
/**
|
|
120
|
+
*/
|
|
121
|
+
custom_key_value?: string;
|
|
122
|
+
/**
|
|
123
|
+
*/
|
|
124
|
+
key_type: PatternKeyType;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
*/
|
|
129
|
+
export declare enum PatternKeyType {
|
|
130
|
+
At = 0,
|
|
131
|
+
Hash = 1,
|
|
132
|
+
Slash = 2,
|
|
133
|
+
Custom = 3,
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export declare function plainToRich(plainText: string, inMessageFormat: boolean): Promise<string>;
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
*/
|
|
140
|
+
export declare class ReplaceAll {
|
|
141
|
+
free(): void;
|
|
142
|
+
/**
|
|
143
|
+
*/
|
|
144
|
+
end_utf16_codeunit: number;
|
|
145
|
+
/**
|
|
146
|
+
*/
|
|
147
|
+
replacement_html: string;
|
|
148
|
+
/**
|
|
149
|
+
*/
|
|
150
|
+
start_utf16_codeunit: number;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export declare function richToPlain(richText: string, inMessageFormat: boolean): Promise<string>;
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
*/
|
|
157
|
+
export declare class Selection_2 {
|
|
158
|
+
free(): void;
|
|
159
|
+
/**
|
|
160
|
+
*/
|
|
161
|
+
end_utf16_codeunit: number;
|
|
162
|
+
/**
|
|
163
|
+
*/
|
|
164
|
+
start_utf16_codeunit: number;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export declare type SuggestionChar = (typeof SUGGESTIONS)[number] | '';
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
*/
|
|
171
|
+
export declare class SuggestionPattern {
|
|
172
|
+
free(): void;
|
|
173
|
+
/**
|
|
174
|
+
*/
|
|
175
|
+
end: number;
|
|
176
|
+
/**
|
|
177
|
+
*/
|
|
178
|
+
key: PatternKey;
|
|
179
|
+
/**
|
|
180
|
+
*/
|
|
181
|
+
start: number;
|
|
182
|
+
/**
|
|
183
|
+
*/
|
|
184
|
+
text: string;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export declare const SUGGESTIONS: readonly ["@", "#", "/", ""];
|
|
188
|
+
|
|
189
|
+
export declare type SuggestionType = 'mention' | 'command' | 'custom' | 'unknown';
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
*/
|
|
193
|
+
export declare class TextUpdate {
|
|
194
|
+
free(): void;
|
|
195
|
+
/**
|
|
196
|
+
*/
|
|
197
|
+
keep?: Keep;
|
|
198
|
+
/**
|
|
199
|
+
*/
|
|
200
|
+
replace_all?: ReplaceAll;
|
|
201
|
+
/**
|
|
202
|
+
*/
|
|
203
|
+
select?: Selection_2;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export declare type TraceAction = (update: ComposerUpdate | null, name: string, value1?: string | number, value2?: string | number) => ComposerUpdate | null;
|
|
207
|
+
|
|
208
|
+
export declare type UseWysiwyg = {
|
|
209
|
+
ref: React.MutableRefObject<HTMLDivElement | null>;
|
|
210
|
+
isWysiwygReady: boolean;
|
|
211
|
+
wysiwyg: FormattingFunctions;
|
|
212
|
+
content: string | null;
|
|
213
|
+
actionStates: AllActionStates;
|
|
214
|
+
debug: {
|
|
215
|
+
modelRef: RefObject<HTMLDivElement>;
|
|
216
|
+
testRef: RefObject<HTMLDivElement>;
|
|
217
|
+
resetTestCase: () => void | null;
|
|
218
|
+
traceAction: TraceAction;
|
|
219
|
+
};
|
|
220
|
+
suggestion: MappedSuggestion | null;
|
|
221
|
+
messageContent: string | null;
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
export declare function useWysiwyg(wysiwygProps?: WysiwygProps): UseWysiwyg;
|
|
225
|
+
|
|
226
|
+
export declare type Wysiwyg = {
|
|
227
|
+
actions: FormattingFunctions;
|
|
228
|
+
content: () => string;
|
|
229
|
+
messageContent: () => string;
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
export declare type WysiwygEvent = WysiwygInputEvent | KeyboardEvent;
|
|
233
|
+
|
|
234
|
+
export declare type WysiwygInputEvent = ClipboardEvent | LinkEvent | (InputEvent & {
|
|
235
|
+
inputType: BlockType;
|
|
236
|
+
data?: string | null;
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
export declare type WysiwygProps = {
|
|
240
|
+
isAutoFocusEnabled?: boolean;
|
|
241
|
+
inputEventProcessor?: InputEventProcessor;
|
|
242
|
+
initialContent?: string;
|
|
243
|
+
emojiSuggestions?: Map<string, string>;
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
export { }
|