@reacteditor/core 0.0.1-alpha.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.
Files changed (52) hide show
  1. package/README.md +85 -0
  2. package/dist/Editor-GBV2O5RD.css +415 -0
  3. package/dist/Editor-IKMJILGR.mjs +204 -0
  4. package/dist/Render-EFT7YD2C.css +103 -0
  5. package/dist/Render-VDC7AEQK.mjs +55 -0
  6. package/dist/actions-BCDhqbeL.d.mts +849 -0
  7. package/dist/actions-BCDhqbeL.d.ts +849 -0
  8. package/dist/chunk-2YLS65V2.mjs +103 -0
  9. package/dist/chunk-6B2Q5R3C.mjs +53 -0
  10. package/dist/chunk-DXGQXXQG.mjs +63 -0
  11. package/dist/chunk-F7S5S6I2.mjs +114 -0
  12. package/dist/chunk-GAUBBDIR.mjs +463 -0
  13. package/dist/chunk-GUMYXUO3.mjs +33 -0
  14. package/dist/chunk-M6W7YEVX.mjs +95 -0
  15. package/dist/chunk-MFI3RDA4.mjs +11 -0
  16. package/dist/chunk-QNHSXCWU.mjs +8692 -0
  17. package/dist/chunk-SURZYH7D.mjs +1726 -0
  18. package/dist/chunk-V2OPYD42.mjs +708 -0
  19. package/dist/chunk-VD3EVRUF.mjs +476 -0
  20. package/dist/chunk-VOLQMQPK.mjs +146 -0
  21. package/dist/chunk-VUEM62JF.mjs +523 -0
  22. package/dist/chunk-Y2EFNT5P.mjs +108 -0
  23. package/dist/full-ELX6RALJ.css +311 -0
  24. package/dist/full-OBTPW7TC.mjs +93 -0
  25. package/dist/index-ComBHfdn.d.ts +117 -0
  26. package/dist/index-DVwiIwYU.d.mts +117 -0
  27. package/dist/index.css +3033 -0
  28. package/dist/index.d.mts +396 -0
  29. package/dist/index.d.ts +396 -0
  30. package/dist/index.js +14688 -0
  31. package/dist/index.mjs +87 -0
  32. package/dist/internal.d.mts +27 -0
  33. package/dist/internal.d.ts +27 -0
  34. package/dist/internal.js +931 -0
  35. package/dist/internal.mjs +13 -0
  36. package/dist/loaded-35WC23HJ.mjs +60 -0
  37. package/dist/loaded-TBSVRJPY.css +90 -0
  38. package/dist/loaded-ULSROV73.mjs +57 -0
  39. package/dist/loaded-YYRJPIWZ.mjs +57 -0
  40. package/dist/no-external.css +3031 -0
  41. package/dist/no-external.d.mts +21 -0
  42. package/dist/no-external.d.ts +21 -0
  43. package/dist/no-external.js +14688 -0
  44. package/dist/no-external.mjs +87 -0
  45. package/dist/rsc.css +103 -0
  46. package/dist/rsc.d.mts +27 -0
  47. package/dist/rsc.d.ts +27 -0
  48. package/dist/rsc.js +1493 -0
  49. package/dist/rsc.mjs +148 -0
  50. package/dist/walk-tree-BPIigVTF.d.mts +29 -0
  51. package/dist/walk-tree-BZq1CPCH.d.ts +29 -0
  52. package/package.json +139 -0
package/README.md ADDED
@@ -0,0 +1,85 @@
1
+ ## What is React Editor?
2
+
3
+ React Editor is an open-source, visual editor for your react components. You can use React Editor to build custom drag-and-drop experiences for your application.
4
+
5
+ React Editor is a fork from [Puck](https://github.com/puckeditor), which is the foundation for this project.
6
+
7
+ React Editor is [licensed under MIT](https://github.com/frontend-inc/react-editor?tab=MIT-1-ov-file#readme).
8
+
9
+ ## Quick start
10
+
11
+ Install the package:
12
+
13
+ ```sh
14
+ npm i @reacteditor/core --save # or npx create-react-editor my-app
15
+ ```
16
+
17
+ Render the editor:
18
+
19
+ ```jsx
20
+ // Editor.jsx
21
+ import { Editor } from "@reacteditor/core";
22
+ import "@reacteditor/core/react-editor.css";
23
+
24
+ // Create React Editor component config
25
+ const config = {
26
+ components: {
27
+ HeadingBlock: {
28
+ fields: {
29
+ children: {
30
+ type: "text",
31
+ },
32
+ },
33
+ render: ({ children }) => {
34
+ return <h1>{children}</h1>;
35
+ },
36
+ },
37
+ },
38
+ };
39
+
40
+ // Describe the initial data
41
+ const initialData = {};
42
+
43
+ // Save the data to your database
44
+ const save = (data) => {};
45
+
46
+ // Render React Editor editor
47
+ export function Editor() {
48
+ return <Editor config={config} data={initialData} onPublish={save} />;
49
+ }
50
+ ```
51
+
52
+ Render the page:
53
+
54
+ ```jsx
55
+ // Page.jsx
56
+ import { Render } from "@reacteditor/core";
57
+ import "@reacteditor/core/react-editor.css";
58
+
59
+ export function Page() {
60
+ return <Render config={config} data={data} />;
61
+ }
62
+ ```
63
+
64
+ ## Recipes
65
+
66
+ Use `create-react-editor` to quickly spin up a a pre-configured app based on our provided [recipes](https://github.com/frontend-inc/react-editor/tree/main/recipes):
67
+
68
+ ```sh
69
+ npx create-react-editor my-app
70
+ ```
71
+
72
+ Available recipes include:
73
+
74
+ - [**next**](https://github.com/frontend-inc/react-editor/tree/main/recipes/next): Next.js example, using App Router and static page generation
75
+ - [**remix**](https://github.com/frontend-inc/react-editor/tree/main/recipes/remix): Remix Run v2 example, using dynamic routes at root-level
76
+ - [**react-router**](https://github.com/frontend-inc/react-editor/tree/main/recipes/react-router): React Router v7 app example, using dynamic routes to create pages at any level
77
+
78
+ ## Get support
79
+
80
+ If you have any questions about React Editor, please open a [GitHub issue](https://github.com/frontend-inc/react-editor/issues).
81
+
82
+
83
+ ## License
84
+
85
+ [MIT License](https://github.com/frontend-inc/react-editor/license.MD)
@@ -0,0 +1,415 @@
1
+ /* css-module:/Users/rami/Documents/apps/frontend-react-editor/packages/core/components/RichTextMenu/styles.module.css/#css-module-data */
2
+ ._RichTextMenu_7muaf_1 {
3
+ display: flex;
4
+ flex-direction: row;
5
+ flex-wrap: nowrap;
6
+ }
7
+ ._RichTextMenu--form_7muaf_7 {
8
+ border-top-left-radius: var(--re-radius-md);
9
+ border-top-right-radius: var(--re-radius-md);
10
+ padding: 6px 6px;
11
+ background-color: var(--re-surface-sunken);
12
+ position: relative;
13
+ scrollbar-width: none;
14
+ overflow-x: auto;
15
+ }
16
+ ._RichTextMenu-group_7muaf_17 {
17
+ display: flex;
18
+ align-items: space-between;
19
+ flex-direction: row;
20
+ flex-wrap: nowrap;
21
+ padding-inline: 6px;
22
+ gap: 2px;
23
+ position: relative;
24
+ }
25
+ ._RichTextMenu-group_7muaf_17:first-of-type {
26
+ padding-left: 0;
27
+ }
28
+ ._RichTextMenu-group_7muaf_17:last-of-type {
29
+ padding-right: 0;
30
+ }
31
+ ._RichTextMenu--inline_7muaf_35 ._RichTextMenu-group_7muaf_17 {
32
+ color: var(--re-text-inverse);
33
+ opacity: 0.85;
34
+ gap: 0px;
35
+ flex-wrap: nowrap;
36
+ }
37
+ ._RichTextMenu-group_7muaf_17 + ._RichTextMenu-group_7muaf_17 {
38
+ border-left: 1px solid var(--re-border-subtle);
39
+ }
40
+ ._RichTextMenu--inline_7muaf_35 ._RichTextMenu-group_7muaf_17 + ._RichTextMenu-group_7muaf_17 {
41
+ border-left: 0.5px solid rgba(255, 255, 255, 0.2);
42
+ }
43
+
44
+ /* css-module:/Users/rami/Documents/apps/frontend-react-editor/packages/core/components/IconButton/IconButton.module.css/#css-module-data */
45
+ ._IconButton_19x6h_1 {
46
+ align-items: center;
47
+ background: transparent;
48
+ border: none;
49
+ border-radius: var(--re-radius-md);
50
+ color: currentColor;
51
+ display: flex;
52
+ font-family: var(--re-font-family);
53
+ justify-content: center;
54
+ padding: 4px;
55
+ transition: background-color var(--re-motion-fast) var(--re-ease), color var(--re-motion-fast) var(--re-ease);
56
+ }
57
+ ._IconButton--active_19x6h_15 {
58
+ color: var(--re-text-accent);
59
+ background: var(--re-accent-soft);
60
+ }
61
+ ._IconButton_19x6h_1:focus-visible {
62
+ outline: none;
63
+ box-shadow: var(--re-ring);
64
+ }
65
+ @media (hover: hover) and (pointer: fine) {
66
+ ._IconButton_19x6h_1:hover:not(._IconButton--disabled_19x6h_26) {
67
+ background: var(--re-surface-hover);
68
+ color: var(--re-text-accent);
69
+ cursor: pointer;
70
+ transition: none;
71
+ }
72
+ }
73
+ ._IconButton_19x6h_1:active {
74
+ background: var(--re-accent-soft);
75
+ transition: none;
76
+ }
77
+ ._IconButton-title_19x6h_39 {
78
+ clip: rect(0 0 0 0);
79
+ clip-path: inset(100%);
80
+ height: 1px;
81
+ overflow: hidden;
82
+ position: absolute;
83
+ white-space: nowrap;
84
+ width: 1px;
85
+ }
86
+ ._IconButton--disabled_19x6h_26 {
87
+ color: var(--re-text-tertiary);
88
+ }
89
+
90
+ /* css-module:/Users/rami/Documents/apps/frontend-react-editor/packages/core/components/Loader/styles.module.css/#css-module-data */
91
+ @keyframes _loader-animation_nacdm_1 {
92
+ 0% {
93
+ transform: rotate(0deg) scale(1);
94
+ }
95
+ 50% {
96
+ transform: rotate(180deg) scale(0.8);
97
+ }
98
+ 100% {
99
+ transform: rotate(360deg) scale(1);
100
+ }
101
+ }
102
+ ._Loader_nacdm_13 {
103
+ background: transparent;
104
+ border-radius: 100%;
105
+ border: 2px solid currentColor;
106
+ border-bottom-color: transparent;
107
+ display: inline-block;
108
+ animation: _loader-animation_nacdm_1 1s 0s infinite linear;
109
+ animation-fill-mode: both;
110
+ }
111
+
112
+ /* css-module:/Users/rami/Documents/apps/frontend-react-editor/packages/core/components/ActionBar/styles.module.css/#css-module-data */
113
+ ._ActionBar_5kf61_1 {
114
+ align-items: center;
115
+ cursor: default;
116
+ display: flex;
117
+ width: auto;
118
+ padding: 4px;
119
+ padding-inline-start: 0;
120
+ padding-inline-end: 0;
121
+ border-top-left-radius: var(--re-radius-lg);
122
+ border-top-right-radius: var(--re-radius-lg);
123
+ border-radius: var(--re-radius-lg);
124
+ background: var(--re-primary);
125
+ color: var(--re-primary-foreground);
126
+ font-family: var(--re-font-family);
127
+ min-height: 26px;
128
+ box-shadow: var(--re-shadow-md);
129
+ }
130
+ ._ActionBar-label_5kf61_19 {
131
+ color: var(--re-primary-foreground);
132
+ opacity: 0.85;
133
+ font-size: var(--re-font-size-xxxs);
134
+ font-weight: 500;
135
+ padding-inline-start: 8px;
136
+ padding-inline-end: 8px;
137
+ margin-inline-start: 4px;
138
+ margin-inline-end: 4px;
139
+ text-overflow: ellipsis;
140
+ white-space: nowrap;
141
+ }
142
+ ._ActionBarAction_5kf61_32 + ._ActionBar-label_5kf61_19 {
143
+ padding-inline-start: 0;
144
+ }
145
+ ._ActionBar-label_5kf61_19 + ._ActionBarAction_5kf61_32 {
146
+ margin-inline-start: -4px;
147
+ }
148
+ ._ActionBar-group_5kf61_40 {
149
+ align-items: center;
150
+ border-inline-start: 0.5px solid rgba(255, 255, 255, 0.2);
151
+ display: flex;
152
+ height: 100%;
153
+ padding-inline-start: 4px;
154
+ padding-inline-end: 4px;
155
+ }
156
+ ._ActionBar-group_5kf61_40:first-of-type {
157
+ border-inline-start: 0;
158
+ }
159
+ ._ActionBar-group_5kf61_40:empty {
160
+ display: none;
161
+ }
162
+ ._ActionBarAction_5kf61_32 {
163
+ background: transparent;
164
+ border: none;
165
+ color: var(--re-primary-foreground);
166
+ opacity: 0.85;
167
+ cursor: pointer;
168
+ padding: 6px;
169
+ margin-inline-start: 4px;
170
+ margin-inline-end: 4px;
171
+ border-radius: var(--re-radius-sm);
172
+ overflow: hidden;
173
+ display: flex;
174
+ align-items: center;
175
+ justify-content: center;
176
+ transition: opacity var(--re-motion-fast) var(--re-ease), background-color var(--re-motion-fast) var(--re-ease);
177
+ }
178
+ ._ActionBarAction--disabled_5kf61_75 {
179
+ cursor: auto;
180
+ opacity: 0.4;
181
+ }
182
+ ._ActionBarAction_5kf61_32 svg {
183
+ max-width: none !important;
184
+ }
185
+ ._ActionBarAction_5kf61_32:focus-visible {
186
+ outline: none;
187
+ box-shadow: var(--re-ring);
188
+ }
189
+ @media (hover: hover) and (pointer: fine) {
190
+ ._ActionBarAction_5kf61_32:hover:not(._ActionBarAction--disabled_5kf61_75) {
191
+ opacity: 1;
192
+ background: rgba(255, 255, 255, 0.12);
193
+ transition: none;
194
+ }
195
+ }
196
+ ._ActionBarAction_5kf61_32:active:not(._ActionBarAction--disabled_5kf61_75),
197
+ ._ActionBarAction--active_5kf61_98 {
198
+ opacity: 1;
199
+ background: rgba(255, 255, 255, 0.18);
200
+ transition: none;
201
+ }
202
+ ._ActionBar-group_5kf61_40 * {
203
+ margin: 0;
204
+ }
205
+ ._ActionBar-separator_5kf61_108 {
206
+ background: rgba(255, 255, 255, 0.2);
207
+ margin-inline: 4px;
208
+ width: 0.5px;
209
+ height: 100%;
210
+ }
211
+
212
+ /* css-module:/Users/rami/Documents/apps/frontend-react-editor/packages/core/components/RichTextMenu/components/Control/styles.module.css/#css-module-data */
213
+ ._Control_1aveu_1 .lucide {
214
+ height: 18px;
215
+ width: 18px;
216
+ }
217
+ ._Control--inline_1aveu_6 .lucide {
218
+ height: 16px;
219
+ width: 16px;
220
+ }
221
+
222
+ /* css-module:/Users/rami/Documents/apps/frontend-react-editor/packages/core/components/Select/styles.module.css/#css-module-data */
223
+ ._Select_6nen1_1 {
224
+ position: relative;
225
+ z-index: 1;
226
+ }
227
+ ._Select-button_6nen1_6 {
228
+ align-items: center;
229
+ background: transparent;
230
+ border: none;
231
+ border-radius: var(--re-radius-sm);
232
+ display: flex;
233
+ justify-content: center;
234
+ gap: 0px;
235
+ height: 100%;
236
+ padding: 4px;
237
+ padding-right: 2px;
238
+ transition: background-color var(--re-motion-fast) var(--re-ease), color var(--re-motion-fast) var(--re-ease);
239
+ }
240
+ ._Select--hasOptions_6nen1_21 ._Select-button_6nen1_6 {
241
+ color: currentColor;
242
+ }
243
+ ._Select--hasOptions_6nen1_21:not(._Select--disabled_6nen1_25) ._Select-button_6nen1_6 {
244
+ cursor: pointer;
245
+ }
246
+ ._Select-buttonIcon_6nen1_29 {
247
+ align-items: center;
248
+ display: flex;
249
+ justify-content: center;
250
+ }
251
+ ._Select--standalone_6nen1_35 ._Select-buttonIcon_6nen1_29 .lucide {
252
+ height: 18px;
253
+ width: 18px;
254
+ }
255
+ ._Select--actionBar_6nen1_40 ._Select-buttonIcon_6nen1_29 .lucide {
256
+ height: 16px;
257
+ width: 16px;
258
+ }
259
+ ._Select--hasOptions_6nen1_21:not(._Select--disabled_6nen1_25) ._Select-button_6nen1_6:hover,
260
+ ._Select--hasValue_6nen1_46 ._Select-button_6nen1_6 {
261
+ background: var(--re-surface-hover);
262
+ color: var(--re-text-accent);
263
+ }
264
+ ._Select--disabled_6nen1_25 ._Select-button_6nen1_6 {
265
+ color: var(--re-text-tertiary);
266
+ }
267
+ ._Select--actionBar_6nen1_40 {
268
+ &._Select--hasOptions_6nen1_21 ._Select-button_6nen1_6:hover,
269
+ &._Select--hasValue_6nen1_46 ._Select-button_6nen1_6 {
270
+ background: rgba(255, 255, 255, 0.12);
271
+ color: var(--re-text-inverse);
272
+ }
273
+ }
274
+ ._Select-items_6nen1_63 {
275
+ background: var(--re-surface-panel);
276
+ border: 1px solid var(--re-border-subtle);
277
+ border-radius: var(--re-radius-lg);
278
+ box-shadow: var(--re-shadow-lg);
279
+ margin: 10px 8px;
280
+ margin-left: 0;
281
+ padding: 4px;
282
+ z-index: 2;
283
+ list-style: none;
284
+ }
285
+ ._SelectItem_6nen1_75 {
286
+ background: transparent;
287
+ border-radius: var(--re-radius-sm);
288
+ border: none;
289
+ color: var(--re-text-secondary);
290
+ cursor: pointer;
291
+ display: flex;
292
+ gap: 8px;
293
+ align-items: center;
294
+ font-size: var(--re-font-size-xxs);
295
+ margin: 0;
296
+ padding: 8px 12px;
297
+ width: 100%;
298
+ transition: background-color var(--re-motion-fast) var(--re-ease), color var(--re-motion-fast) var(--re-ease);
299
+ }
300
+ ._SelectItem--isSelected_6nen1_92 {
301
+ background: var(--re-accent-soft);
302
+ color: var(--re-text-accent);
303
+ font-weight: 500;
304
+ }
305
+ ._SelectItem--isSelected_6nen1_92 ._SelectItem-icon_6nen1_98 {
306
+ color: var(--re-text-accent);
307
+ }
308
+ ._SelectItem_6nen1_75:hover {
309
+ background: var(--re-surface-hover);
310
+ color: var(--re-text-accent);
311
+ }
312
+
313
+ /* css-module:/Users/rami/Documents/apps/frontend-react-editor/packages/core/components/RichTextEditor/styles.module.css/#css-module-data */
314
+ ._RichTextEditor_1grt5_1 .ProseMirror {
315
+ white-space: pre-wrap;
316
+ word-wrap: break-word;
317
+ cursor: text;
318
+ outline: none;
319
+ position: relative;
320
+ }
321
+ ._RichTextEditor_1grt5_1 .rich-text * {
322
+ white-space: pre-wrap;
323
+ user-select: auto;
324
+ -webkit-user-select: auto;
325
+ }
326
+ ._RichTextEditor_1grt5_1 .rich-text blockquote {
327
+ margin: 1em 0;
328
+ padding: 0 1em;
329
+ border-left: 4px solid var(--re-border-default);
330
+ }
331
+ ._RichTextEditor_1grt5_1 .rich-text code {
332
+ background-color: var(--re-surface-sunken);
333
+ padding: 4px 8px;
334
+ border-radius: var(--re-radius-sm);
335
+ }
336
+ ._RichTextEditor_1grt5_1 .rich-text p:empty::before {
337
+ content: "\a0";
338
+ }
339
+ ._RichTextEditor_1grt5_1 .rich-text pre code {
340
+ display: block;
341
+ padding: 8px 12px;
342
+ }
343
+ ._RichTextEditor_1grt5_1 .rich-text > *:first-child,
344
+ ._RichTextEditor_1grt5_1 .ProseMirror > *:first-child,
345
+ ._RichTextEditor_1grt5_1 .rich-text * p:first-of-type {
346
+ margin-top: 0;
347
+ }
348
+ ._RichTextEditor_1grt5_1 .rich-text > *:last-child,
349
+ ._RichTextEditor_1grt5_1 .ProseMirror > *:last-child,
350
+ ._RichTextEditor_1grt5_1 .rich-text * p:last-of-type {
351
+ margin-bottom: 0;
352
+ }
353
+ ._RichTextEditor--editor_1grt5_50 {
354
+ background: var(--re-surface-panel);
355
+ border-width: 1px;
356
+ border-style: solid;
357
+ border-color: var(--re-border-default);
358
+ border-radius: var(--re-radius-md);
359
+ box-sizing: border-box;
360
+ display: flex;
361
+ flex-direction: column;
362
+ font-family: inherit;
363
+ font-size: var(--re-font-size-xxs);
364
+ resize: vertical;
365
+ text-align: initial;
366
+ transition: border-color var(--re-motion-fast) var(--re-ease), box-shadow var(--re-motion-fast) var(--re-ease);
367
+ width: 100%;
368
+ max-width: 100%;
369
+ min-height: 128px;
370
+ }
371
+ ._RichTextEditor--editor_1grt5_50 .rich-text {
372
+ flex-grow: 1;
373
+ }
374
+ ._RichTextEditor--editor_1grt5_50 .rich-text:not(:has(.ProseMirror)),
375
+ ._RichTextEditor--editor_1grt5_50 .rich-text .ProseMirror {
376
+ height: 100%;
377
+ padding: 12px 15px;
378
+ }
379
+ ._RichTextEditor--editor_1grt5_50 .rich-text ul,
380
+ ._RichTextEditor--editor_1grt5_50 .rich-text ol {
381
+ padding-left: 24px;
382
+ }
383
+ ._RichTextEditor--editor_1grt5_50 .rich-text li {
384
+ line-height: 1.5;
385
+ }
386
+ ._RichTextEditor--editor_1grt5_50 .rich-text p {
387
+ margin-block: 12px;
388
+ }
389
+ ._RichTextEditor--editor_1grt5_50 .rich-text ul {
390
+ list-style: disc;
391
+ }
392
+ ._RichTextEditor--editor_1grt5_50 .rich-text ol {
393
+ list-style: decimal;
394
+ }
395
+ ._RichTextEditor--editor_1grt5_50:focus-within {
396
+ border-color: var(--re-accent);
397
+ outline: none;
398
+ box-shadow: var(--re-ring);
399
+ transition: none;
400
+ }
401
+ ._RichTextEditor--editor_1grt5_50._RichTextEditor--disabled_1grt5_109 {
402
+ background: var(--re-surface-sunken);
403
+ }
404
+ ._RichTextEditor_1grt5_1:not(:focus-within):not(._RichTextEditor--isActive_1grt5_113) .ProseMirror ::selection {
405
+ background-color: transparent;
406
+ }
407
+ ._RichTextEditor-menu_1grt5_119 {
408
+ border-bottom: 1px solid var(--re-border-subtle);
409
+ position: sticky;
410
+ top: 0;
411
+ z-index: 1;
412
+ }
413
+ ._RichTextEditor--disabled_1grt5_109 ._RichTextEditor-menu_1grt5_119 {
414
+ border-bottom: 1px solid var(--re-border-subtle);
415
+ }
@@ -0,0 +1,204 @@
1
+ import {
2
+ EditorRichText
3
+ } from "./chunk-2YLS65V2.mjs";
4
+ import {
5
+ EditorInner,
6
+ LoadedRichTextMenu
7
+ } from "./chunk-F7S5S6I2.mjs";
8
+ import "./chunk-MFI3RDA4.mjs";
9
+ import "./chunk-V2OPYD42.mjs";
10
+ import "./chunk-6B2Q5R3C.mjs";
11
+ import "./chunk-DXGQXXQG.mjs";
12
+ import "./chunk-GUMYXUO3.mjs";
13
+ import {
14
+ useAppStore,
15
+ useAppStoreApi
16
+ } from "./chunk-SURZYH7D.mjs";
17
+ import "./chunk-VUEM62JF.mjs";
18
+ import "./chunk-VOLQMQPK.mjs";
19
+ import "./chunk-Y2EFNT5P.mjs";
20
+ import "./chunk-GAUBBDIR.mjs";
21
+ import {
22
+ __spreadProps,
23
+ __spreadValues,
24
+ init_react_import
25
+ } from "./chunk-M6W7YEVX.mjs";
26
+
27
+ // components/RichTextEditor/components/Editor.tsx
28
+ init_react_import();
29
+ import { memo, useMemo } from "react";
30
+
31
+ // components/RichTextEditor/lib/use-synced-editor.ts
32
+ init_react_import();
33
+ import { useEditor } from "@tiptap/react";
34
+ import { useEffect, useRef } from "react";
35
+ import { useDebounce } from "use-debounce";
36
+ function useSyncedEditor({
37
+ content,
38
+ onChange,
39
+ extensions,
40
+ editable = true,
41
+ onFocusChange,
42
+ name
43
+ }) {
44
+ const [debouncedState, setDebouncedState] = useDebounce(null, 50, {
45
+ leading: true,
46
+ maxWait: 200
47
+ });
48
+ const syncingRef = useRef(false);
49
+ const lastSyncedRef = useRef("");
50
+ const editTimer = useRef(null);
51
+ const isPending = !!editTimer.current;
52
+ const isFocused = useAppStore((s) => s.state.ui.field.focus === name);
53
+ const resetTimer = (clearOn) => {
54
+ if (editTimer.current) {
55
+ clearTimeout(editTimer.current);
56
+ }
57
+ editTimer.current = setTimeout(() => {
58
+ if (lastSyncedRef.current === clearOn) {
59
+ editTimer.current = null;
60
+ }
61
+ }, 200);
62
+ };
63
+ const appStoreApi = useAppStoreApi();
64
+ const editor = useEditor({
65
+ extensions,
66
+ content,
67
+ editable,
68
+ immediatelyRender: false,
69
+ parseOptions: { preserveWhitespace: "full" },
70
+ onUpdate: ({ editor: editor2 }) => {
71
+ if (syncingRef.current || !isFocused) {
72
+ appStoreApi.getState().setUi({ field: { focus: name } });
73
+ return;
74
+ }
75
+ const html = editor2.getHTML();
76
+ const { from, to } = editor2.state.selection;
77
+ setDebouncedState({ from, to, html });
78
+ resetTimer(html);
79
+ lastSyncedRef.current = html;
80
+ }
81
+ });
82
+ useEffect(() => {
83
+ if (!editor) return;
84
+ const handleFocus = () => {
85
+ onFocusChange == null ? void 0 : onFocusChange(editor);
86
+ };
87
+ editor.on("focus", handleFocus);
88
+ return () => {
89
+ editor.off("focus", handleFocus);
90
+ };
91
+ }, [editor, onFocusChange]);
92
+ useEffect(() => {
93
+ if (debouncedState) {
94
+ const { ui } = appStoreApi.getState().state;
95
+ onChange(debouncedState.html, {
96
+ field: __spreadProps(__spreadValues({}, ui.field), {
97
+ metadata: { from: debouncedState.from, to: debouncedState.to }
98
+ })
99
+ });
100
+ }
101
+ }, [editor, debouncedState, onChange, appStoreApi, name]);
102
+ useEffect(() => {
103
+ editor == null ? void 0 : editor.setEditable(editable);
104
+ }, [editor, editable]);
105
+ useEffect(() => {
106
+ var _a;
107
+ if (!editor) return;
108
+ if (isPending) {
109
+ return;
110
+ }
111
+ const current = editor.getHTML();
112
+ if (current === content) return;
113
+ syncingRef.current = true;
114
+ editor.commands.setContent(content, { emitUpdate: false });
115
+ const { ui } = appStoreApi.getState().state;
116
+ if (typeof ((_a = ui.field.metadata) == null ? void 0 : _a.from) !== "undefined") {
117
+ editor.commands.setTextSelection({
118
+ from: ui.field.metadata.from,
119
+ to: ui.field.metadata.to
120
+ });
121
+ }
122
+ syncingRef.current = false;
123
+ }, [content, editor, appStoreApi]);
124
+ return editor;
125
+ }
126
+
127
+ // components/RichTextEditor/components/Editor.tsx
128
+ import { EditorContent } from "@tiptap/react";
129
+ import { jsx } from "react/jsx-runtime";
130
+ var Editor = memo((props) => {
131
+ const {
132
+ onChange,
133
+ content,
134
+ readOnly = false,
135
+ field,
136
+ inline = false,
137
+ onFocus,
138
+ id,
139
+ name
140
+ } = props;
141
+ const { tiptap = {}, options } = field;
142
+ const { extensions = [] } = tiptap;
143
+ const loadedExtensions = useMemo(
144
+ () => [EditorRichText.configure(options), ...extensions],
145
+ [field, extensions]
146
+ );
147
+ const appStoreApi = useAppStoreApi();
148
+ const focusName = `${name}${inline ? "::inline" : ""}`;
149
+ const editor = useSyncedEditor({
150
+ content,
151
+ onChange,
152
+ extensions: loadedExtensions,
153
+ editable: !readOnly,
154
+ name: focusName,
155
+ onFocusChange: (editor2) => {
156
+ if (editor2) {
157
+ const s = appStoreApi.getState();
158
+ appStoreApi.setState({
159
+ currentRichText: {
160
+ field,
161
+ editor: editor2,
162
+ id,
163
+ inline
164
+ },
165
+ state: __spreadProps(__spreadValues({}, s.state), {
166
+ ui: __spreadProps(__spreadValues({}, s.state.ui), {
167
+ field: __spreadProps(__spreadValues({}, s.state.ui.field), {
168
+ focus: focusName
169
+ })
170
+ })
171
+ })
172
+ });
173
+ onFocus == null ? void 0 : onFocus(editor2);
174
+ }
175
+ }
176
+ });
177
+ const menuEditor = useAppStore((s) => {
178
+ var _a, _b;
179
+ if (!inline && ((_a = s.currentRichText) == null ? void 0 : _a.id) === id && ((_b = s.currentRichText) == null ? void 0 : _b.inlineComponentId)) {
180
+ return s.currentRichText.editor;
181
+ }
182
+ return editor;
183
+ });
184
+ if (!editor) return null;
185
+ return /* @__PURE__ */ jsx(
186
+ EditorInner,
187
+ __spreadProps(__spreadValues({}, props), {
188
+ editor,
189
+ menu: /* @__PURE__ */ jsx(
190
+ LoadedRichTextMenu,
191
+ {
192
+ field,
193
+ editor: menuEditor,
194
+ readOnly
195
+ }
196
+ ),
197
+ children: /* @__PURE__ */ jsx(EditorContent, { editor, className: "rich-text" })
198
+ })
199
+ );
200
+ });
201
+ Editor.displayName = "Editor";
202
+ export {
203
+ Editor
204
+ };