rj-editor 1.0.0 → 1.0.1
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 +156 -176
- package/dist/components/equation/EquationComponent.d.ts +1 -1
- package/dist/components/image/ImageComponent.d.ts +1 -1
- package/dist/components/rj-text-editor/RJTextEditor.types.d.ts +1 -1
- package/dist/components/rj-text-editor/createInitialConfig.d.ts +1 -1
- package/dist/components/toolbar/equation/utils.d.ts +2 -2
- package/dist/components/toolbar/image/utils.d.ts +3 -3
- package/dist/components/toolbar/insert/equation/EquationModal.d.ts +1 -1
- package/dist/components/toolbar/insert/equation/EquationPreview.d.ts +1 -1
- package/dist/constants/initialToolbarState.d.ts +1 -1
- package/dist/constants/insertEquationCommand.d.ts +1 -1
- package/dist/constants/insertImageCommand.d.ts +1 -1
- package/dist/constants/insertYouTubeCommand.d.ts +1 -1
- package/dist/i18n/I18nContext.d.ts +1 -1
- package/dist/i18n/RJEditorI18nContext.d.ts +1 -1
- package/dist/i18n/locales/en.d.ts +1 -1
- package/dist/i18n/locales/ru.d.ts +1 -1
- package/dist/i18n/locales/uz.d.ts +1 -1
- package/dist/i18n/mergeTranslations.d.ts +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/nodes/EquationNode.d.ts +1 -1
- package/dist/nodes/ImageNode.d.ts +1 -1
- package/dist/nodes/YouTubeNode.d.ts +1 -1
- package/dist/slice/toolbarSlice.d.ts +1 -1
- package/dist/store/hooks.d.ts +2 -2
- package/dist/store/index.d.ts +1 -1
- package/dist/types/AppDispatch.d.ts +1 -1
- package/dist/types/RootState.d.ts +1 -1
- package/dist/utils/helpers/renderEquationToHtml.d.ts +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,247 +1,228 @@
|
|
|
1
1
|
# RJ Editor
|
|
2
2
|
|
|
3
|
-
`rj-editor`
|
|
3
|
+
`rj-editor` is a React rich text editor package for building article editors, admin panels, CMS forms, learning platforms, notes, documentation tools, and other content-heavy interfaces.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
It provides a ready-to-use `RJTextEditor` component with a tabbed toolbar, text formatting, tables, links, images, YouTube embeds, fullscreen mode, i18n, theming, and Ant Design Form support.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
[Live demo](https://rj-editor.vercel.app)
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
## Features
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
Demo'ni lokal ishga tushirish:
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
git clone https://github.com/RavshanJumaqulov/rj-editor.git
|
|
17
|
-
cd rj-editor
|
|
18
|
-
npm install
|
|
19
|
-
npm run dev
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
Keyin browserda Vite ko'rsatgan lokal manzilni oching. Odatda:
|
|
23
|
-
|
|
24
|
-
```txt
|
|
25
|
-
http://localhost:5173
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
Demo sahifada quyidagilarni tekshirish mumkin:
|
|
29
|
-
|
|
30
|
-
- `RJTextEditor`ni oddiy component sifatida ishlatish;
|
|
31
|
-
- Ant Design `Form.Item` bilan qiymat yig'ish;
|
|
32
|
-
- HTML outputni real vaqt rejimida olish;
|
|
33
|
-
- table, image, link, YouTube, fullscreen va contextual toolbarlarni sinash;
|
|
34
|
-
- `defaultValue`/`value` orqali saqlangan HTML kontentni qayta editorga yuklash.
|
|
35
|
-
|
|
36
|
-
Demo kodi: [`src/App.tsx`](https://github.com/RavshanJumaqulov/rj-editor/blob/main/src/App.tsx)
|
|
37
|
-
|
|
38
|
-
## Imkoniyatlar
|
|
39
|
-
|
|
40
|
-
- Rich text: bold, italic, underline, strikethrough, subscript, superscript.
|
|
11
|
+
- Text formatting: bold, italic, underline, strikethrough, subscript, superscript.
|
|
41
12
|
- Style controls: font size, font family, text color, background color, clear formatting.
|
|
42
|
-
- Paragraph tools: alignment, ordered
|
|
13
|
+
- Paragraph tools: alignment, ordered list, unordered list, indent, outdent, line and paragraph spacing.
|
|
43
14
|
- Insert tools: table, link, image, YouTube video.
|
|
44
|
-
- Table
|
|
45
|
-
- Image
|
|
15
|
+
- Table editing: add/remove rows and columns, merge/split cells, header row/column, cell background, vertical alignment, delete table.
|
|
16
|
+
- Image editing: upload, drag-and-drop, paste from clipboard, resize, align, alt text, caption, link, border, border radius, shadow, object fit, wrapping, rotate, replace, delete.
|
|
46
17
|
- Browser fullscreen mode.
|
|
47
|
-
- Ant Design `Form.Item`
|
|
48
|
-
- `uz`, `en`, `ru`
|
|
49
|
-
-
|
|
18
|
+
- Ant Design `Form.Item` integration.
|
|
19
|
+
- Built-in `uz`, `en`, and `ru` translations.
|
|
20
|
+
- Custom locale and partial translation override support.
|
|
21
|
+
- Theme customization through CSS custom properties.
|
|
50
22
|
|
|
51
|
-
##
|
|
23
|
+
## Installation
|
|
52
24
|
|
|
53
25
|
```bash
|
|
54
26
|
npm install rj-editor
|
|
55
27
|
```
|
|
56
28
|
|
|
57
|
-
|
|
29
|
+
`react` and `react-dom` are peer dependencies. They must already exist in your application:
|
|
58
30
|
|
|
59
31
|
```bash
|
|
60
32
|
npm install react react-dom
|
|
61
33
|
```
|
|
62
34
|
|
|
63
|
-
##
|
|
35
|
+
## Quick Start
|
|
64
36
|
|
|
65
37
|
```tsx
|
|
66
|
-
import { RJTextEditor } from
|
|
38
|
+
import { RJTextEditor } from 'rj-editor'
|
|
67
39
|
|
|
68
40
|
export function App() {
|
|
69
41
|
return (
|
|
70
42
|
<RJTextEditor
|
|
71
43
|
autofocus
|
|
72
|
-
locale="
|
|
73
|
-
placeholder="
|
|
44
|
+
locale="en"
|
|
45
|
+
placeholder="Write your content..."
|
|
74
46
|
onChange={(html) => {
|
|
75
|
-
console.log(html)
|
|
47
|
+
console.log(html)
|
|
76
48
|
}}
|
|
77
49
|
/>
|
|
78
|
-
)
|
|
50
|
+
)
|
|
79
51
|
}
|
|
80
52
|
```
|
|
81
53
|
|
|
82
|
-
|
|
54
|
+
You do not need to import a separate stylesheet. The package styles are included when `RJTextEditor` is imported.
|
|
83
55
|
|
|
84
|
-
##
|
|
56
|
+
## Saving Content
|
|
85
57
|
|
|
86
|
-
|
|
58
|
+
`onChange` returns the editor content as an HTML string in the first argument. This is the value you usually store in your database.
|
|
87
59
|
|
|
88
60
|
```tsx
|
|
89
61
|
<RJTextEditor
|
|
90
|
-
|
|
91
|
-
|
|
62
|
+
onChange={(html) => {
|
|
63
|
+
saveDraft(html)
|
|
64
|
+
}}
|
|
92
65
|
/>
|
|
93
66
|
```
|
|
94
67
|
|
|
95
|
-
|
|
68
|
+
The callback also exposes a JSON string and the current editor state for advanced use cases:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
type OnChange = (
|
|
72
|
+
html: string,
|
|
73
|
+
json: string,
|
|
74
|
+
editorState: unknown,
|
|
75
|
+
) => void
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Initial Content
|
|
96
79
|
|
|
97
|
-
`
|
|
80
|
+
Use `defaultValue` when you want to load saved HTML once when the editor mounts:
|
|
98
81
|
|
|
99
82
|
```tsx
|
|
100
|
-
|
|
101
|
-
|
|
83
|
+
<RJTextEditor defaultValue="<p>Hello world</p>" />
|
|
84
|
+
```
|
|
102
85
|
|
|
103
|
-
|
|
104
|
-
|
|
86
|
+
Use `value` when your application controls the editor content from React state:
|
|
87
|
+
|
|
88
|
+
```tsx
|
|
89
|
+
import { useState } from 'react'
|
|
90
|
+
import { RJTextEditor } from 'rj-editor'
|
|
105
91
|
|
|
106
|
-
|
|
92
|
+
export function ControlledEditor() {
|
|
93
|
+
const [content, setContent] = useState('<p>Initial content</p>')
|
|
94
|
+
|
|
95
|
+
return (
|
|
96
|
+
<RJTextEditor
|
|
97
|
+
value={content}
|
|
98
|
+
onChange={(html) => setContent(html)}
|
|
99
|
+
/>
|
|
100
|
+
)
|
|
107
101
|
}
|
|
108
102
|
```
|
|
109
103
|
|
|
110
|
-
## Ant Design Form
|
|
104
|
+
## Ant Design Form
|
|
111
105
|
|
|
112
|
-
`RJTextEditor` Ant Design `Form.Item
|
|
106
|
+
`RJTextEditor` works inside Ant Design `Form.Item`. The form receives the HTML string as the field value.
|
|
113
107
|
|
|
114
108
|
```tsx
|
|
115
|
-
import { Button, Form } from
|
|
116
|
-
import { RJTextEditor } from
|
|
109
|
+
import { Button, Form } from 'antd'
|
|
110
|
+
import { RJTextEditor } from 'rj-editor'
|
|
117
111
|
|
|
118
112
|
export function ArticleForm() {
|
|
119
113
|
return (
|
|
120
114
|
<Form
|
|
121
115
|
layout="vertical"
|
|
122
116
|
onFinish={(values) => {
|
|
123
|
-
console.log(values.content)
|
|
117
|
+
console.log(values.content)
|
|
124
118
|
}}
|
|
125
119
|
>
|
|
126
120
|
<Form.Item
|
|
127
|
-
label="
|
|
121
|
+
label="Content"
|
|
128
122
|
name="content"
|
|
129
|
-
rules={[{ required: true, message:
|
|
123
|
+
rules={[{ required: true, message: 'Content is required' }]}
|
|
130
124
|
>
|
|
131
|
-
<RJTextEditor placeholder="
|
|
125
|
+
<RJTextEditor placeholder="Write your article..." />
|
|
132
126
|
</Form.Item>
|
|
133
127
|
|
|
134
128
|
<Button htmlType="submit" type="primary">
|
|
135
|
-
|
|
129
|
+
Save
|
|
136
130
|
</Button>
|
|
137
131
|
</Form>
|
|
138
|
-
)
|
|
132
|
+
)
|
|
139
133
|
}
|
|
140
134
|
```
|
|
141
135
|
|
|
142
|
-
|
|
136
|
+
When validation fails, the editor border follows the Ant Design error state.
|
|
143
137
|
|
|
144
138
|
## Props
|
|
145
139
|
|
|
146
|
-
| Prop
|
|
147
|
-
|
|
|
148
|
-
| `autofocus`
|
|
149
|
-
| `className`
|
|
150
|
-
| `defaultValue` | `string`
|
|
151
|
-
| `id`
|
|
152
|
-
| `locale`
|
|
153
|
-
| `locales`
|
|
154
|
-
| `namespace`
|
|
155
|
-
| `onBlur`
|
|
156
|
-
| `onChange`
|
|
157
|
-
| `onFocus`
|
|
158
|
-
| `placeholder`
|
|
159
|
-
| `translations` | `DeepPartial<RJEditorTranslations>`
|
|
160
|
-
| `value`
|
|
161
|
-
|
|
162
|
-
## onChange
|
|
163
|
-
|
|
164
|
-
`onChange` uchta argument qaytaradi:
|
|
165
|
-
|
|
166
|
-
```ts
|
|
167
|
-
type OnChange = (
|
|
168
|
-
html: string,
|
|
169
|
-
json: string,
|
|
170
|
-
editorState: unknown,
|
|
171
|
-
) => void;
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
- `html` - kontentning HTML string ko'rinishi. Serverga saqlash va keyin `defaultValue` yoki `value` sifatida qayta berish uchun qulay.
|
|
175
|
-
- `json` - editor holatining JSON string ko'rinishi.
|
|
176
|
-
- `editorState` - editorning joriy runtime holati.
|
|
140
|
+
| Prop | Type | Default | Description |
|
|
141
|
+
| --- | --- | --- | --- |
|
|
142
|
+
| `autofocus` | `boolean` | `false` | Focuses the editor after mount. |
|
|
143
|
+
| `className` | `string` | `undefined` | Adds a custom class to the editor root. |
|
|
144
|
+
| `defaultValue` | `string` | `undefined` | Initial HTML content. Applied once on mount. |
|
|
145
|
+
| `id` | `string` | `undefined` | Adds an `id` to the editor root. |
|
|
146
|
+
| `locale` | `'uz' \| 'en' \| 'ru' \| string` | `'uz'` | Active editor language. |
|
|
147
|
+
| `locales` | `Record<string, DeepPartial<RJEditorTranslations>>` | `undefined` | Adds custom locales. |
|
|
148
|
+
| `namespace` | `string` | `'RJEditor'` | Unique editor namespace. Useful when multiple editor instances exist on one page. |
|
|
149
|
+
| `onBlur` | `React.FocusEventHandler<HTMLDivElement>` | `undefined` | Called when the editor root loses focus. |
|
|
150
|
+
| `onChange` | `(html, json, editorState) => void` | `undefined` | Called whenever editor content changes. |
|
|
151
|
+
| `onFocus` | `React.FocusEventHandler<HTMLDivElement>` | `undefined` | Called when the editor root receives focus. |
|
|
152
|
+
| `placeholder` | `string` | Locale-based text | Placeholder shown when the editor is empty. |
|
|
153
|
+
| `translations` | `DeepPartial<RJEditorTranslations>` | `undefined` | Overrides translations for the active locale. |
|
|
154
|
+
| `value` | `string` | `undefined` | Controlled HTML content. |
|
|
177
155
|
|
|
178
156
|
## Toolbar
|
|
179
157
|
|
|
180
|
-
|
|
158
|
+
The toolbar is organized by tabs:
|
|
181
159
|
|
|
182
|
-
- `Home
|
|
183
|
-
- `Insert
|
|
184
|
-
- `Image
|
|
185
|
-
- `Table
|
|
160
|
+
- `Home`: text formatting, styles, lists, alignment, indentation, and spacing.
|
|
161
|
+
- `Insert`: table, link, image, and YouTube video insertion.
|
|
162
|
+
- `Image`: shown when an image is selected.
|
|
163
|
+
- `Table`: shown when the cursor is inside a table.
|
|
186
164
|
|
|
187
|
-
|
|
165
|
+
Contextual tabs are only visible when they are useful, keeping the editor interface focused.
|
|
188
166
|
|
|
189
|
-
##
|
|
167
|
+
## Images
|
|
190
168
|
|
|
191
|
-
|
|
169
|
+
Images can be inserted from the local file picker, drag-and-drop, or clipboard paste. The image is stored as a base64 data URL inside the editor content.
|
|
192
170
|
|
|
193
|
-
|
|
171
|
+
Important details:
|
|
194
172
|
|
|
195
|
-
-
|
|
196
|
-
- Base64 HTML
|
|
197
|
-
-
|
|
173
|
+
- Maximum image size is `5MB`.
|
|
174
|
+
- Base64 images increase HTML size.
|
|
175
|
+
- For large production systems, a server upload flow or storage adapter is recommended.
|
|
198
176
|
|
|
199
|
-
|
|
177
|
+
Image tools include:
|
|
200
178
|
|
|
201
|
-
-
|
|
202
|
-
- width
|
|
203
|
-
- 25%, 50%, 100
|
|
179
|
+
- left, center, and right alignment;
|
|
180
|
+
- custom width percentage;
|
|
181
|
+
- quick resize: 25%, 50%, 100%;
|
|
204
182
|
- alt text;
|
|
205
183
|
- caption;
|
|
206
|
-
-
|
|
184
|
+
- link;
|
|
207
185
|
- border;
|
|
208
186
|
- border radius;
|
|
209
187
|
- shadow;
|
|
210
188
|
- object fit: contain, cover, fill;
|
|
211
|
-
- text wrapping: top-bottom
|
|
189
|
+
- text wrapping: top-bottom and square;
|
|
212
190
|
- rotate left/right;
|
|
213
191
|
- replace image;
|
|
214
192
|
- delete image.
|
|
215
193
|
|
|
216
|
-
##
|
|
194
|
+
## Tables
|
|
217
195
|
|
|
218
|
-
|
|
196
|
+
Tables can be created from the `Insert` tab with a grid picker or by entering row and column counts.
|
|
219
197
|
|
|
220
|
-
|
|
198
|
+
Available table tools:
|
|
221
199
|
|
|
222
|
-
- row/
|
|
223
|
-
-
|
|
224
|
-
-
|
|
225
|
-
-
|
|
226
|
-
-
|
|
227
|
-
-
|
|
228
|
-
-
|
|
200
|
+
- add row above/below;
|
|
201
|
+
- add column left/right;
|
|
202
|
+
- delete row/column;
|
|
203
|
+
- merge cells;
|
|
204
|
+
- split cells;
|
|
205
|
+
- toggle header row;
|
|
206
|
+
- toggle header column;
|
|
207
|
+
- set cell background;
|
|
208
|
+
- set vertical alignment;
|
|
209
|
+
- delete table.
|
|
229
210
|
|
|
230
|
-
##
|
|
211
|
+
## Links
|
|
231
212
|
|
|
232
|
-
|
|
213
|
+
Links are created with a custom modal. The modal supports URL and display text fields and works correctly in fullscreen mode.
|
|
233
214
|
|
|
234
|
-
## YouTube
|
|
215
|
+
## YouTube Embeds
|
|
235
216
|
|
|
236
|
-
`Insert` tab
|
|
217
|
+
Paste a YouTube URL from the `Insert` tab to add an embedded video. The editor converts supported YouTube links into an iframe embed.
|
|
237
218
|
|
|
238
219
|
## Fullscreen
|
|
239
220
|
|
|
240
|
-
|
|
221
|
+
The fullscreen button uses the browser Fullscreen API. The editor is opened in real fullscreen mode, not only enlarged with CSS.
|
|
241
222
|
|
|
242
|
-
##
|
|
223
|
+
## Internationalization
|
|
243
224
|
|
|
244
|
-
|
|
225
|
+
Built-in locales:
|
|
245
226
|
|
|
246
227
|
```tsx
|
|
247
228
|
<RJTextEditor locale="uz" />
|
|
@@ -249,20 +230,20 @@ Kutubxona ichida `uz`, `en`, `ru` tarjimalar mavjud.
|
|
|
249
230
|
<RJTextEditor locale="ru" />
|
|
250
231
|
```
|
|
251
232
|
|
|
252
|
-
|
|
233
|
+
Override only the text you need:
|
|
253
234
|
|
|
254
235
|
```tsx
|
|
255
236
|
<RJTextEditor
|
|
256
|
-
locale="
|
|
237
|
+
locale="en"
|
|
257
238
|
translations={{
|
|
258
239
|
placeholders: {
|
|
259
|
-
editor:
|
|
240
|
+
editor: 'Start writing...',
|
|
260
241
|
},
|
|
261
242
|
}}
|
|
262
243
|
/>
|
|
263
244
|
```
|
|
264
245
|
|
|
265
|
-
|
|
246
|
+
Add a custom locale:
|
|
266
247
|
|
|
267
248
|
```tsx
|
|
268
249
|
<RJTextEditor
|
|
@@ -270,11 +251,11 @@ Yangi locale qo'shish:
|
|
|
270
251
|
locales={{
|
|
271
252
|
kaa: {
|
|
272
253
|
placeholders: {
|
|
273
|
-
editor:
|
|
254
|
+
editor: 'Maqalanı usı jerge jazıń...',
|
|
274
255
|
},
|
|
275
256
|
tabs: {
|
|
276
|
-
home:
|
|
277
|
-
insert:
|
|
257
|
+
home: 'Bas bet',
|
|
258
|
+
insert: 'Qosıw',
|
|
278
259
|
},
|
|
279
260
|
},
|
|
280
261
|
}}
|
|
@@ -283,9 +264,9 @@ Yangi locale qo'shish:
|
|
|
283
264
|
|
|
284
265
|
## Theme
|
|
285
266
|
|
|
286
|
-
|
|
267
|
+
`rj-editor` exposes CSS custom properties. Override them in your application stylesheet to match your design system.
|
|
287
268
|
|
|
288
|
-
```
|
|
269
|
+
```css
|
|
289
270
|
:root {
|
|
290
271
|
--rj-color-brand: #2563eb;
|
|
291
272
|
--rj-color-brand-tint: #eaf2ff;
|
|
@@ -301,42 +282,41 @@ Kutubxona ranglarni CSS custom property sifatida chiqaradi. Loyihangizda theme q
|
|
|
301
282
|
}
|
|
302
283
|
```
|
|
303
284
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
| Variable | Vazifasi |
|
|
307
|
-
| -------------------------------------- | ------------------------------------- |
|
|
308
|
-
| `--rj-editor-bg` | Editor content background. |
|
|
309
|
-
| `--rj-editor-border` | Editor border rangi. |
|
|
310
|
-
| `--rj-editor-text` | Asosiy text rangi. |
|
|
311
|
-
| `--rj-editor-placeholder` | Placeholder rangi. |
|
|
312
|
-
| `--rj-editor-toolbar-bg` | Toolbar background. |
|
|
313
|
-
| `--rj-editor-toolbar-button-bg` | Toolbar button background. |
|
|
314
|
-
| `--rj-editor-toolbar-button-active-bg` | Active button background. |
|
|
315
|
-
| `--rj-editor-link` | Link rangi. |
|
|
316
|
-
| `--rj-editor-focus-border` | Focus/active border rangi. |
|
|
317
|
-
| `--rj-editor-error-border` | Form validation error border rangi. |
|
|
318
|
-
| `--rj-editor-warning-border` | Form validation warning border rangi. |
|
|
319
|
-
| `--rj-editor-table-border` | Table border rangi. |
|
|
320
|
-
| `--rj-editor-table-header-bg` | Table header background. |
|
|
321
|
-
| `--rj-editor-image-border` | Image selection/border rangi. |
|
|
322
|
-
| `--rj-editor-danger` | Delete/clear action rangi. |
|
|
285
|
+
Common variables:
|
|
323
286
|
|
|
324
|
-
|
|
287
|
+
| Variable | Description |
|
|
288
|
+
| --- | --- |
|
|
289
|
+
| `--rj-editor-bg` | Editor content background. |
|
|
290
|
+
| `--rj-editor-border` | Editor border color. |
|
|
291
|
+
| `--rj-editor-text` | Main text color. |
|
|
292
|
+
| `--rj-editor-placeholder` | Placeholder color. |
|
|
293
|
+
| `--rj-editor-toolbar-bg` | Toolbar background. |
|
|
294
|
+
| `--rj-editor-toolbar-button-bg` | Toolbar button background. |
|
|
295
|
+
| `--rj-editor-toolbar-button-active-bg` | Active toolbar button background. |
|
|
296
|
+
| `--rj-editor-link` | Link color. |
|
|
297
|
+
| `--rj-editor-focus-border` | Focus border color. |
|
|
298
|
+
| `--rj-editor-error-border` | Validation error border color. |
|
|
299
|
+
| `--rj-editor-warning-border` | Validation warning border color. |
|
|
300
|
+
| `--rj-editor-table-border` | Table border color. |
|
|
301
|
+
| `--rj-editor-table-header-bg` | Table header background. |
|
|
302
|
+
| `--rj-editor-image-border` | Image selection border color. |
|
|
303
|
+
| `--rj-editor-danger` | Dangerous action color. |
|
|
325
304
|
|
|
326
|
-
|
|
305
|
+
## SSR
|
|
327
306
|
|
|
328
|
-
|
|
307
|
+
`rj-editor` depends on browser APIs such as DOM selection, clipboard, file input, and fullscreen. In SSR frameworks, render the editor only on the client.
|
|
329
308
|
|
|
330
|
-
|
|
309
|
+
Example for Next.js:
|
|
331
310
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
3. `npm pack --dry-run`
|
|
335
|
-
4. `package.json` ichida `version` qiymatini yangilash
|
|
336
|
-
5. `npm publish`
|
|
311
|
+
```tsx
|
|
312
|
+
import dynamic from 'next/dynamic'
|
|
337
313
|
|
|
338
|
-
|
|
314
|
+
const RJTextEditor = dynamic(
|
|
315
|
+
() => import('rj-editor').then((mod) => mod.RJTextEditor),
|
|
316
|
+
{ ssr: false },
|
|
317
|
+
)
|
|
318
|
+
```
|
|
339
319
|
|
|
340
320
|
## License
|
|
341
321
|
|
|
342
|
-
|
|
322
|
+
MIT
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type NodeKey } from 'lexical';
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import type { EquationDisplayMode } from '
|
|
3
|
+
import type { EquationDisplayMode } from '../../types/index';
|
|
4
4
|
type EquationComponentProps = {
|
|
5
5
|
displayMode: EquationDisplayMode;
|
|
6
6
|
equation: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type NodeKey } from 'lexical';
|
|
2
|
-
import type { ImageAlignment, ImageObjectFit, ImageTextWrap } from '
|
|
2
|
+
import type { ImageAlignment, ImageObjectFit, ImageTextWrap } from '../../types/index';
|
|
3
3
|
type ImageComponentProps = {
|
|
4
4
|
alignment: ImageAlignment;
|
|
5
5
|
altText: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type React from 'react';
|
|
2
2
|
import type { EditorState } from 'lexical';
|
|
3
|
-
import type { DeepPartial, RJEditorLocaleCode, RJEditorTranslations } from '
|
|
3
|
+
import type { DeepPartial, RJEditorLocaleCode, RJEditorTranslations } from '../../types/index';
|
|
4
4
|
export type RJTextEditorProps = {
|
|
5
5
|
autofocus?: boolean;
|
|
6
6
|
className?: string;
|
|
@@ -2,7 +2,7 @@ import { LinkNode } from '@lexical/link';
|
|
|
2
2
|
import { ListItemNode, ListNode } from '@lexical/list';
|
|
3
3
|
import { TableCellNode, TableNode, TableRowNode } from '@lexical/table';
|
|
4
4
|
import { TextNode, type LexicalEditor } from 'lexical';
|
|
5
|
-
import { EquationNode, ExtendedTextNode, ImageNode, YouTubeNode, replaceTextNodeWithExtendedTextNode } from '
|
|
5
|
+
import { EquationNode, ExtendedTextNode, ImageNode, YouTubeNode, replaceTextNodeWithExtendedTextNode } from '../../nodes/index';
|
|
6
6
|
type CreateInitialConfigOptions = {
|
|
7
7
|
defaultValue?: string;
|
|
8
8
|
namespace: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type LexicalEditor } from 'lexical';
|
|
2
|
-
import type { EquationDisplayMode } from '
|
|
3
|
-
export declare function getSelectedEquationNode(): import("
|
|
2
|
+
import type { EquationDisplayMode } from '../../../types/index';
|
|
3
|
+
export declare function getSelectedEquationNode(): import("../../../nodes/index").EquationNode | null;
|
|
4
4
|
export declare function getEquationSelectionState(): {
|
|
5
5
|
isEquationSelected: boolean;
|
|
6
6
|
selectedEquation: string | undefined;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type LexicalEditor } from 'lexical';
|
|
2
|
-
import type { ImageAlignment, ImageTextWrap } from '
|
|
3
|
-
export declare function getSelectedImageNode(): import("
|
|
2
|
+
import type { ImageAlignment, ImageTextWrap } from '../../../types/index';
|
|
3
|
+
export declare function getSelectedImageNode(): import("../../../nodes/index").ImageNode | null;
|
|
4
4
|
export declare function getImageSelectionState(): {
|
|
5
5
|
isImageSelected: boolean;
|
|
6
6
|
selectedImageAlignment: ImageAlignment | undefined;
|
|
@@ -12,7 +12,7 @@ export declare function getImageSelectionState(): {
|
|
|
12
12
|
selectedImageHeight: number | undefined;
|
|
13
13
|
selectedImageKey: string | undefined;
|
|
14
14
|
selectedImageLinkUrl: string | undefined;
|
|
15
|
-
selectedImageObjectFit: import("
|
|
15
|
+
selectedImageObjectFit: import("../../../types/index").ImageObjectFit | undefined;
|
|
16
16
|
selectedImageRotation: number | undefined;
|
|
17
17
|
selectedImageShadowEnabled: boolean | undefined;
|
|
18
18
|
selectedImageTextWrap: ImageTextWrap | undefined;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { ToolbarState } from '
|
|
1
|
+
import type { ToolbarState } from '../types/index';
|
|
2
2
|
export declare const INITIAL_TOOLBAR_STATE: ToolbarState;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { InsertEquationPayload } from '
|
|
1
|
+
import type { InsertEquationPayload } from '../types/index';
|
|
2
2
|
export declare const INSERT_EQUATION_COMMAND: import("lexical").LexicalCommand<InsertEquationPayload>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { InsertImagePayload } from '
|
|
1
|
+
import type { InsertImagePayload } from '../types/index';
|
|
2
2
|
export declare const INSERT_IMAGE_COMMAND: import("lexical").LexicalCommand<InsertImagePayload>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { InsertYouTubePayload } from '
|
|
1
|
+
import type { InsertYouTubePayload } from '../types/index';
|
|
2
2
|
export declare const INSERT_YOUTUBE_COMMAND: import("lexical").LexicalCommand<InsertYouTubePayload>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import type { DeepPartial, RJEditorLocaleCode, RJEditorTranslations } from '
|
|
2
|
+
import type { DeepPartial, RJEditorLocaleCode, RJEditorTranslations } from '../types/index';
|
|
3
3
|
export type RJEditorI18nProviderProps = {
|
|
4
4
|
children: React.ReactNode;
|
|
5
5
|
locale?: RJEditorLocaleCode;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { RJEditorTranslations } from '
|
|
1
|
+
import type { RJEditorTranslations } from '../../types/index';
|
|
2
2
|
export declare const enTranslations: RJEditorTranslations;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { RJEditorTranslations } from '
|
|
1
|
+
import type { RJEditorTranslations } from '../../types/index';
|
|
2
2
|
export declare const ruTranslations: RJEditorTranslations;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { RJEditorTranslations } from '
|
|
1
|
+
import type { RJEditorTranslations } from '../../types/index';
|
|
2
2
|
export declare const uzTranslations: RJEditorTranslations;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { DeepPartial } from '
|
|
1
|
+
import type { DeepPartial } from '../types/index';
|
|
2
2
|
export declare function mergeTranslations<T extends object>(base: T, ...overrides: Array<DeepPartial<T> | undefined>): T;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { RJTextEditor } from '
|
|
2
|
-
export { enTranslations, mergeTranslations, RJEditorI18nProvider, ruTranslations, useRJEditorI18n, uzTranslations, } from '
|
|
3
|
-
export type { RJTextEditorProps } from '
|
|
4
|
-
export type { DeepPartial, RJEditorLocaleCode, RJEditorTranslations, RJTextEditorValue, } from '
|
|
1
|
+
export { RJTextEditor } from './components/RJTextEditor';
|
|
2
|
+
export { enTranslations, mergeTranslations, RJEditorI18nProvider, ruTranslations, useRJEditorI18n, uzTranslations, } from './i18n/index';
|
|
3
|
+
export type { RJTextEditorProps } from './components/RJTextEditor';
|
|
4
|
+
export type { DeepPartial, RJEditorLocaleCode, RJEditorTranslations, RJTextEditorValue, } from './types/index';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { DOMConversionMap, DOMExportOutput, EditorConfig, LexicalNode, NodeKey } from 'lexical';
|
|
2
2
|
import { DecoratorNode } from 'lexical';
|
|
3
3
|
import type { ReactNode } from 'react';
|
|
4
|
-
import type { EquationDisplayMode, InsertEquationPayload, SerializedEquationNode } from '
|
|
4
|
+
import type { EquationDisplayMode, InsertEquationPayload, SerializedEquationNode } from '../types/index';
|
|
5
5
|
export declare class EquationNode extends DecoratorNode<ReactNode> {
|
|
6
6
|
__displayMode: EquationDisplayMode;
|
|
7
7
|
__equation: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { DOMConversionMap, DOMExportOutput, EditorConfig, LexicalNode, NodeKey } from 'lexical';
|
|
2
2
|
import { DecoratorNode } from 'lexical';
|
|
3
3
|
import type { ReactNode } from 'react';
|
|
4
|
-
import type { ImageAlignment, ImageObjectFit, ImageTextWrap, InsertImagePayload, SerializedImageNode } from '
|
|
4
|
+
import type { ImageAlignment, ImageObjectFit, ImageTextWrap, InsertImagePayload, SerializedImageNode } from '../types/index';
|
|
5
5
|
export declare class ImageNode extends DecoratorNode<ReactNode> {
|
|
6
6
|
__alignment: ImageAlignment;
|
|
7
7
|
__aspectRatioLocked: boolean;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { DOMConversionMap, DOMExportOutput, EditorConfig, LexicalNode, NodeKey } from 'lexical';
|
|
2
2
|
import { DecoratorNode } from 'lexical';
|
|
3
3
|
import type { ReactNode } from 'react';
|
|
4
|
-
import type { InsertYouTubePayload, SerializedYouTubeNode } from '
|
|
4
|
+
import type { InsertYouTubePayload, SerializedYouTubeNode } from '../types/index';
|
|
5
5
|
export declare class YouTubeNode extends DecoratorNode<ReactNode> {
|
|
6
6
|
__title: string;
|
|
7
7
|
__videoId: string;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type { ToolbarState } from '
|
|
1
|
+
import type { ToolbarState } from '../types/index';
|
|
2
2
|
export declare const setBlockFormats: import("@reduxjs/toolkit").ActionCreatorWithPayload<Pick<ToolbarState, "alignment" | "listType">, "toolbar/setBlockFormats">, setCanRedo: import("@reduxjs/toolkit").ActionCreatorWithPayload<boolean, "toolbar/setCanRedo">, setCanUndo: import("@reduxjs/toolkit").ActionCreatorWithPayload<boolean, "toolbar/setCanUndo">, setEquationFormats: import("@reduxjs/toolkit").ActionCreatorWithPayload<Pick<ToolbarState, "isEquationSelected" | "selectedEquation" | "selectedEquationDisplayMode" | "selectedEquationKey">, "toolbar/setEquationFormats">, setImageFormats: import("@reduxjs/toolkit").ActionCreatorWithPayload<Pick<ToolbarState, "isImageSelected" | "selectedImageAspectRatioLocked" | "selectedImageAlignment" | "selectedImageAltText" | "selectedImageBorderEnabled" | "selectedImageBorderRadius" | "selectedImageCaption" | "selectedImageHeight" | "selectedImageKey" | "selectedImageLinkUrl" | "selectedImageObjectFit" | "selectedImageRotation" | "selectedImageShadowEnabled" | "selectedImageTextWrap" | "selectedImageWidth">, "toolbar/setImageFormats">, setStyleFormats: import("@reduxjs/toolkit").ActionCreatorWithPayload<Pick<ToolbarState, "backgroundColor" | "fontFamily" | "fontSize" | "lineHeight" | "textColor">, "toolbar/setStyleFormats">, setTableFormats: import("@reduxjs/toolkit").ActionCreatorWithPayload<Pick<ToolbarState, "isInTable" | "selectedTableCellsCount" | "tableCellBackgroundColor" | "tableCellVerticalAlign" | "tableHasMergedCell">, "toolbar/setTableFormats">, setTextFormats: import("@reduxjs/toolkit").ActionCreatorWithPayload<Pick<ToolbarState, "isBold" | "isItalic" | "isStrikethrough" | "isSubscript" | "isSuperscript" | "isUnderline">, "toolbar/setTextFormats">;
|
|
3
3
|
export declare const toolbarReducer: import("redux").Reducer<ToolbarState>;
|
package/dist/store/hooks.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export declare const useAppDispatch: import("react-redux").UseDispatch<import("redux-thunk").ThunkDispatch<{
|
|
2
|
-
toolbar: import("
|
|
2
|
+
toolbar: import("../types/index").ToolbarState;
|
|
3
3
|
}, undefined, import("redux").UnknownAction> & import("redux").Dispatch<import("redux").UnknownAction>>;
|
|
4
4
|
export declare const useAppSelector: import("react-redux").UseSelector<{
|
|
5
|
-
toolbar: import("
|
|
5
|
+
toolbar: import("../types/index").ToolbarState;
|
|
6
6
|
}>;
|
package/dist/store/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { store } from '
|
|
1
|
+
import type { store } from '../store/store';
|
|
2
2
|
export type AppDispatch = typeof store.dispatch;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { store } from '
|
|
1
|
+
import type { store } from '../store/store';
|
|
2
2
|
export type RootState = ReturnType<typeof store.getState>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rj-editor",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "React rich text editor: toolbar tabs, table, image, link, YouTube, i18n, theme va Ant Design Form integratsiyasi.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
],
|
|
47
47
|
"scripts": {
|
|
48
48
|
"dev": "vite",
|
|
49
|
-
"build": "vite build && tsc -p tsconfig.lib.json",
|
|
49
|
+
"build": "vite build && tsc -p tsconfig.lib.json && node scripts/fix-dts-aliases.mjs",
|
|
50
50
|
"build:demo": "vite build --config vite.demo.config.ts",
|
|
51
51
|
"lint": "eslint .",
|
|
52
52
|
"preview": "vite preview"
|