@ceedcv-maya/shared-editor-react 0.6.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/LICENSE +21 -0
- package/README.md +66 -0
- package/package.json +87 -0
- package/src/components/ColorPicker.tsx +100 -0
- package/src/components/CommentHoverPopover.tsx +82 -0
- package/src/components/EditorContentHtml.tsx +29 -0
- package/src/components/EditorToolbar.tsx +225 -0
- package/src/components/EditorToolbarButton.tsx +32 -0
- package/src/components/EditorToolbarGroups.tsx +401 -0
- package/src/components/FindReplaceBar.tsx +253 -0
- package/src/components/MayaEditor.tsx +379 -0
- package/src/components/SourceInputDialog.tsx +120 -0
- package/src/extensions/AlertBlock.ts +59 -0
- package/src/extensions/CommentMark.ts +57 -0
- package/src/extensions/IframeBlock.ts +76 -0
- package/src/extensions/Indent.ts +133 -0
- package/src/hooks/useEditorContent.ts +47 -0
- package/src/i18n/en.json +54 -0
- package/src/i18n/es.json +54 -0
- package/src/index.ts +47 -0
- package/src/lib/CommentAnchor.ts +68 -0
- package/src/lib/docxToHtml.ts +58 -0
- package/src/lib/dompurifyConfig.test.ts +98 -0
- package/src/lib/dompurifyConfig.ts +123 -0
- package/src/lib/editorExtensions.ts +73 -0
- package/src/lib/htmlToMarkdown.ts +166 -0
- package/src/lib/htmlToTiptapDoc.test.ts +52 -0
- package/src/lib/htmlToTiptapDoc.ts +26 -0
- package/src/lib/markdownToHtml.ts +234 -0
- package/src/lib/normalizeTableHtml.ts +74 -0
- package/src/lib/splitHtmlIntoBlocks.test.ts +86 -0
- package/src/lib/splitHtmlIntoBlocks.ts +136 -0
- package/src/serializers/BlockNoteToTiptap.ts +223 -0
- package/src/styles/maya-editor.css +538 -0
- package/src/types.ts +56 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,538 @@
|
|
|
1
|
+
/* MayaEditor — minimum visual baseline shared across consumers.
|
|
2
|
+
Consumers (DMS, logs, dashboard) layer their own tailwind classes for
|
|
3
|
+
typography and spacing of *rendered* content; these styles cover the
|
|
4
|
+
editor chrome itself (toolbar, content padding, focus ring). */
|
|
5
|
+
|
|
6
|
+
.maya-editor-wrapper {
|
|
7
|
+
display: flex;
|
|
8
|
+
flex-direction: column;
|
|
9
|
+
min-height: 0;
|
|
10
|
+
height: 100%;
|
|
11
|
+
border-radius: 8px;
|
|
12
|
+
background: var(--maya-editor-bg, #fff);
|
|
13
|
+
color: var(--maya-editor-fg, inherit);
|
|
14
|
+
overflow: hidden;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.maya-editor-wrapper.is-fullscreen {
|
|
18
|
+
position: fixed;
|
|
19
|
+
inset: 0;
|
|
20
|
+
z-index: 1000;
|
|
21
|
+
border-radius: 0;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.maya-editor-wrapper.is-dark {
|
|
25
|
+
--maya-editor-bg: #1f1f23;
|
|
26
|
+
--maya-editor-fg: #e6e6e8;
|
|
27
|
+
--maya-editor-toolbar-bg: #27272d;
|
|
28
|
+
--maya-editor-border: #3a3a42;
|
|
29
|
+
--maya-editor-btn-hover: #34343b;
|
|
30
|
+
--maya-editor-btn-active: #4a4a55;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/* ── Toolbar ──────────────────────────────────────────────────── */
|
|
34
|
+
.maya-editor-toolbar {
|
|
35
|
+
display: flex;
|
|
36
|
+
flex-wrap: wrap;
|
|
37
|
+
align-items: center;
|
|
38
|
+
gap: 4px;
|
|
39
|
+
padding: 6px 8px;
|
|
40
|
+
border-bottom: 1px solid var(--maya-editor-border, #e3e3e8);
|
|
41
|
+
background: var(--maya-editor-toolbar-bg, #f7f7f9);
|
|
42
|
+
position: sticky;
|
|
43
|
+
top: 0;
|
|
44
|
+
z-index: 2;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.maya-editor-toolbar__sep {
|
|
48
|
+
width: 1px;
|
|
49
|
+
align-self: stretch;
|
|
50
|
+
margin: 4px 4px;
|
|
51
|
+
background: var(--maya-editor-border, #e3e3e8);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.maya-editor-toolbar__btn {
|
|
55
|
+
display: inline-flex;
|
|
56
|
+
align-items: center;
|
|
57
|
+
justify-content: center;
|
|
58
|
+
min-width: 28px;
|
|
59
|
+
height: 28px;
|
|
60
|
+
padding: 0 6px;
|
|
61
|
+
border: 1px solid transparent;
|
|
62
|
+
border-radius: 6px;
|
|
63
|
+
background: transparent;
|
|
64
|
+
color: inherit;
|
|
65
|
+
font-size: 13px;
|
|
66
|
+
line-height: 1;
|
|
67
|
+
cursor: pointer;
|
|
68
|
+
user-select: none;
|
|
69
|
+
transition: background-color 80ms ease, border-color 80ms ease;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.maya-editor-toolbar__btn:hover:not(:disabled) {
|
|
73
|
+
background: var(--maya-editor-btn-hover, #ececf0);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.maya-editor-toolbar__btn.is-active {
|
|
77
|
+
background: var(--maya-editor-btn-active, #d6d6df);
|
|
78
|
+
border-color: var(--maya-editor-border, #d6d6df);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.maya-editor-toolbar__btn:disabled {
|
|
82
|
+
opacity: 0.4;
|
|
83
|
+
cursor: not-allowed;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/* Hidden file inputs reused by the toolbar (image, .docx) */
|
|
87
|
+
.maya-editor-hidden-input { display: none; }
|
|
88
|
+
|
|
89
|
+
/* ── Comment hover popover ─────────────────────────────────── */
|
|
90
|
+
.maya-comment-popover {
|
|
91
|
+
position: fixed;
|
|
92
|
+
z-index: 9998;
|
|
93
|
+
padding: 10px 12px;
|
|
94
|
+
background: #fff;
|
|
95
|
+
color: #1f1f23;
|
|
96
|
+
border: 1px solid #d6d6df;
|
|
97
|
+
border-radius: 8px;
|
|
98
|
+
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.16);
|
|
99
|
+
font-size: 13px;
|
|
100
|
+
line-height: 1.45;
|
|
101
|
+
pointer-events: none;
|
|
102
|
+
animation: maya-comment-popover-in 100ms ease-out;
|
|
103
|
+
}
|
|
104
|
+
.maya-comment-popover.is-dark {
|
|
105
|
+
background: #27272d;
|
|
106
|
+
color: #e6e6e8;
|
|
107
|
+
border-color: #3a3a42;
|
|
108
|
+
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
|
|
109
|
+
}
|
|
110
|
+
.maya-comment-popover__header {
|
|
111
|
+
display: flex;
|
|
112
|
+
align-items: baseline;
|
|
113
|
+
justify-content: space-between;
|
|
114
|
+
gap: 12px;
|
|
115
|
+
margin-bottom: 4px;
|
|
116
|
+
}
|
|
117
|
+
.maya-comment-popover__author { font-weight: 600; font-size: 12px; }
|
|
118
|
+
.maya-comment-popover__date {
|
|
119
|
+
font-size: 11px;
|
|
120
|
+
opacity: 0.7;
|
|
121
|
+
}
|
|
122
|
+
.maya-comment-popover__body {
|
|
123
|
+
white-space: pre-wrap;
|
|
124
|
+
word-break: break-word;
|
|
125
|
+
font-size: 13px;
|
|
126
|
+
}
|
|
127
|
+
@keyframes maya-comment-popover-in {
|
|
128
|
+
from { opacity: 0; transform: translateY(-2px); }
|
|
129
|
+
to { opacity: 1; transform: translateY(0); }
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/* ── Find / Replace bar ────────────────────────────────────── */
|
|
133
|
+
.maya-editor-find {
|
|
134
|
+
display: flex;
|
|
135
|
+
flex-direction: column;
|
|
136
|
+
gap: 4px;
|
|
137
|
+
padding: 6px 8px;
|
|
138
|
+
background: var(--maya-editor-toolbar-bg, #f7f7f9);
|
|
139
|
+
border-bottom: 1px solid var(--maya-editor-border, #e3e3e8);
|
|
140
|
+
}
|
|
141
|
+
.maya-editor-find__row {
|
|
142
|
+
display: flex;
|
|
143
|
+
align-items: center;
|
|
144
|
+
gap: 4px;
|
|
145
|
+
flex-wrap: wrap;
|
|
146
|
+
}
|
|
147
|
+
.maya-editor-find__input {
|
|
148
|
+
flex: 1;
|
|
149
|
+
min-width: 160px;
|
|
150
|
+
height: 28px;
|
|
151
|
+
padding: 0 10px;
|
|
152
|
+
border: 1px solid var(--maya-editor-border, #d6d6df);
|
|
153
|
+
border-radius: 6px;
|
|
154
|
+
background: var(--maya-editor-bg, #fff);
|
|
155
|
+
color: inherit;
|
|
156
|
+
font-size: 13px;
|
|
157
|
+
outline: none;
|
|
158
|
+
}
|
|
159
|
+
.maya-editor-find__input:focus {
|
|
160
|
+
border-color: var(--maya-editor-link, #7c3aed);
|
|
161
|
+
box-shadow: 0 0 0 2px rgba(124, 58, 237, 0.18);
|
|
162
|
+
}
|
|
163
|
+
.maya-editor-find__counter {
|
|
164
|
+
font-size: 12px;
|
|
165
|
+
color: rgba(127, 127, 140, 0.95);
|
|
166
|
+
padding: 0 4px;
|
|
167
|
+
min-width: 50px;
|
|
168
|
+
text-align: center;
|
|
169
|
+
}
|
|
170
|
+
.maya-editor-find__hidden { display: none; }
|
|
171
|
+
|
|
172
|
+
/* ── Color picker (text + highlight) ───────────────────────── */
|
|
173
|
+
.maya-editor-color { position: relative; display: inline-flex; }
|
|
174
|
+
.maya-editor-color__btn {
|
|
175
|
+
display: inline-flex;
|
|
176
|
+
flex-direction: column;
|
|
177
|
+
align-items: center;
|
|
178
|
+
justify-content: center;
|
|
179
|
+
gap: 1px;
|
|
180
|
+
padding: 2px 5px;
|
|
181
|
+
}
|
|
182
|
+
.maya-editor-color__glyph { font-size: 13px; line-height: 1; }
|
|
183
|
+
.maya-editor-color__swatch {
|
|
184
|
+
width: 18px;
|
|
185
|
+
height: 4px;
|
|
186
|
+
border-radius: 2px;
|
|
187
|
+
background: currentColor;
|
|
188
|
+
opacity: 0.95;
|
|
189
|
+
}
|
|
190
|
+
.maya-editor-color__panel {
|
|
191
|
+
position: absolute;
|
|
192
|
+
top: calc(100% + 4px);
|
|
193
|
+
left: 0;
|
|
194
|
+
z-index: 5;
|
|
195
|
+
display: grid;
|
|
196
|
+
grid-template-columns: repeat(6, 18px);
|
|
197
|
+
gap: 4px;
|
|
198
|
+
padding: 8px;
|
|
199
|
+
background: var(--maya-editor-bg, #fff);
|
|
200
|
+
border: 1px solid var(--maya-editor-border, #d6d6df);
|
|
201
|
+
border-radius: 6px;
|
|
202
|
+
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.18);
|
|
203
|
+
}
|
|
204
|
+
.maya-editor-color__cell {
|
|
205
|
+
width: 18px;
|
|
206
|
+
height: 18px;
|
|
207
|
+
border-radius: 4px;
|
|
208
|
+
border: 1px solid rgba(0, 0, 0, 0.08);
|
|
209
|
+
background-clip: padding-box;
|
|
210
|
+
cursor: pointer;
|
|
211
|
+
padding: 0;
|
|
212
|
+
}
|
|
213
|
+
.maya-editor-color__cell.is-active {
|
|
214
|
+
outline: 2px solid var(--maya-editor-link, #7c3aed);
|
|
215
|
+
outline-offset: 1px;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/* ── Content ──────────────────────────────────────────────────── */
|
|
219
|
+
/* The wrapper is flex column. TipTap's <EditorContent> renders a wrapping
|
|
220
|
+
div around the actual `.ProseMirror` view — that wrapping div is what
|
|
221
|
+
needs `flex: 1; min-height: 0; overflow: auto` so it shrinks inside the
|
|
222
|
+
flex layout and scrolls when content exceeds the available height.
|
|
223
|
+
Without this, the intermediate div sizes to its content and the inner
|
|
224
|
+
`.ProseMirror` (which is `display:block`) just grows the wrapper. */
|
|
225
|
+
.maya-editor-wrapper .maya-editor-content {
|
|
226
|
+
flex: 1 1 0;
|
|
227
|
+
min-height: 0;
|
|
228
|
+
max-height: 100%;
|
|
229
|
+
overflow-y: auto;
|
|
230
|
+
overflow-x: auto;
|
|
231
|
+
scrollbar-gutter: stable;
|
|
232
|
+
display: flex;
|
|
233
|
+
flex-direction: column;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.maya-editor-wrapper .ProseMirror {
|
|
237
|
+
flex: 1 1 auto;
|
|
238
|
+
min-height: 0;
|
|
239
|
+
padding: 16px 20px;
|
|
240
|
+
outline: none;
|
|
241
|
+
font-size: 15px;
|
|
242
|
+
line-height: 1.6;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
.maya-editor-wrapper .ProseMirror:focus {
|
|
246
|
+
outline: none;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/* When the wrapper is NOT given an explicit height by its parent layout,
|
|
250
|
+
fall back to a sensible viewport-relative cap so the toolbar stays put
|
|
251
|
+
and the content scrolls instead of pushing the page. */
|
|
252
|
+
.maya-editor-wrapper {
|
|
253
|
+
min-height: 320px;
|
|
254
|
+
}
|
|
255
|
+
.maya-editor-wrapper:not(.is-fullscreen) {
|
|
256
|
+
max-height: 75vh;
|
|
257
|
+
}
|
|
258
|
+
.maya-editor-wrapper.is-fullscreen {
|
|
259
|
+
max-height: none;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
.maya-editor-wrapper .ProseMirror p { margin: 0.5em 0; }
|
|
263
|
+
.maya-editor-wrapper .ProseMirror p:first-child { margin-top: 0; }
|
|
264
|
+
.maya-editor-wrapper .ProseMirror p:last-child { margin-bottom: 0; }
|
|
265
|
+
|
|
266
|
+
/* Indent attribute (Indent extension) — applied to paragraph/heading/blockquote. */
|
|
267
|
+
.maya-editor-wrapper .ProseMirror [data-indent="1"] { margin-left: 2em; }
|
|
268
|
+
.maya-editor-wrapper .ProseMirror [data-indent="2"] { margin-left: 4em; }
|
|
269
|
+
.maya-editor-wrapper .ProseMirror [data-indent="3"] { margin-left: 6em; }
|
|
270
|
+
.maya-editor-wrapper .ProseMirror [data-indent="4"] { margin-left: 8em; }
|
|
271
|
+
.maya-editor-wrapper .ProseMirror [data-indent="5"] { margin-left: 10em; }
|
|
272
|
+
.maya-editor-wrapper .ProseMirror [data-indent="6"] { margin-left: 12em; }
|
|
273
|
+
.maya-editor-wrapper .ProseMirror [data-indent="7"] { margin-left: 14em; }
|
|
274
|
+
.maya-editor-wrapper .ProseMirror [data-indent="8"] { margin-left: 16em; }
|
|
275
|
+
|
|
276
|
+
.maya-editor-wrapper .ProseMirror h1 { font-size: 1.7em; font-weight: 700; margin: 0.8em 0 0.3em; line-height: 1.25; }
|
|
277
|
+
.maya-editor-wrapper .ProseMirror h2 { font-size: 1.4em; font-weight: 700; margin: 0.8em 0 0.3em; line-height: 1.3; }
|
|
278
|
+
.maya-editor-wrapper .ProseMirror h3 { font-size: 1.2em; font-weight: 600; margin: 0.7em 0 0.25em; }
|
|
279
|
+
.maya-editor-wrapper .ProseMirror h4 { font-size: 1.05em; font-weight: 600; margin: 0.6em 0 0.2em; }
|
|
280
|
+
|
|
281
|
+
.maya-editor-wrapper .ProseMirror ul,
|
|
282
|
+
.maya-editor-wrapper .ProseMirror ol {
|
|
283
|
+
padding-left: 1.4em;
|
|
284
|
+
margin: 0.5em 0;
|
|
285
|
+
}
|
|
286
|
+
.maya-editor-wrapper .ProseMirror li { margin: 0.2em 0; }
|
|
287
|
+
|
|
288
|
+
.maya-editor-wrapper .ProseMirror ul[data-type="taskList"] {
|
|
289
|
+
list-style: none;
|
|
290
|
+
padding-left: 0.25em;
|
|
291
|
+
}
|
|
292
|
+
.maya-editor-wrapper .ProseMirror li[data-type="taskItem"] {
|
|
293
|
+
display: flex;
|
|
294
|
+
gap: 6px;
|
|
295
|
+
align-items: flex-start;
|
|
296
|
+
}
|
|
297
|
+
.maya-editor-wrapper .ProseMirror li[data-type="taskItem"] > label {
|
|
298
|
+
flex-shrink: 0;
|
|
299
|
+
margin-top: 0.35em;
|
|
300
|
+
}
|
|
301
|
+
.maya-editor-wrapper .ProseMirror li[data-type="taskItem"] > div { flex: 1; }
|
|
302
|
+
|
|
303
|
+
.maya-editor-wrapper .ProseMirror blockquote {
|
|
304
|
+
border-left: 3px solid var(--maya-editor-border, #d6d6df);
|
|
305
|
+
margin: 0.75em 0;
|
|
306
|
+
padding-left: 1em;
|
|
307
|
+
color: rgba(120, 120, 130, 0.95);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
.maya-editor-wrapper .ProseMirror code {
|
|
311
|
+
background: rgba(127, 127, 140, 0.18);
|
|
312
|
+
border-radius: 3px;
|
|
313
|
+
padding: 0.05em 0.4em;
|
|
314
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
315
|
+
font-size: 0.92em;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
.maya-editor-wrapper .ProseMirror pre {
|
|
319
|
+
background: rgba(127, 127, 140, 0.12);
|
|
320
|
+
border-radius: 6px;
|
|
321
|
+
padding: 0.8em 1em;
|
|
322
|
+
margin: 0.75em 0;
|
|
323
|
+
overflow-x: auto;
|
|
324
|
+
}
|
|
325
|
+
.maya-editor-wrapper .ProseMirror pre code {
|
|
326
|
+
background: transparent;
|
|
327
|
+
padding: 0;
|
|
328
|
+
font-size: 0.9em;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
.maya-editor-wrapper .ProseMirror a {
|
|
332
|
+
color: var(--maya-editor-link, #7c3aed);
|
|
333
|
+
text-decoration: underline;
|
|
334
|
+
text-underline-offset: 2px;
|
|
335
|
+
}
|
|
336
|
+
.maya-editor-wrapper.is-dark .ProseMirror a { color: #a78bfa; }
|
|
337
|
+
|
|
338
|
+
.maya-editor-wrapper .ProseMirror table {
|
|
339
|
+
border-collapse: collapse;
|
|
340
|
+
margin: 0.8em 0;
|
|
341
|
+
width: 100%;
|
|
342
|
+
table-layout: fixed;
|
|
343
|
+
}
|
|
344
|
+
.maya-editor-wrapper .ProseMirror table th,
|
|
345
|
+
.maya-editor-wrapper .ProseMirror table td {
|
|
346
|
+
border: 1px solid var(--maya-editor-border, #d6d6df);
|
|
347
|
+
padding: 0.5em 0.7em;
|
|
348
|
+
vertical-align: top;
|
|
349
|
+
}
|
|
350
|
+
.maya-editor-wrapper .ProseMirror table th {
|
|
351
|
+
background: rgba(127, 127, 140, 0.08);
|
|
352
|
+
text-align: left;
|
|
353
|
+
font-weight: 600;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
.maya-editor-wrapper .ProseMirror img {
|
|
357
|
+
max-width: 100%;
|
|
358
|
+
height: auto;
|
|
359
|
+
border-radius: 4px;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
.maya-editor-wrapper .ProseMirror aside.alert {
|
|
363
|
+
border-left: 4px solid var(--maya-editor-link, #7c3aed);
|
|
364
|
+
border-radius: 4px;
|
|
365
|
+
background: rgba(124, 58, 237, 0.06);
|
|
366
|
+
padding: 0.75em 1em;
|
|
367
|
+
margin: 0.75em 0;
|
|
368
|
+
}
|
|
369
|
+
.maya-editor-wrapper .ProseMirror aside.alert-warning { border-left-color: #f59e0b; background: rgba(245,158,11,0.08); }
|
|
370
|
+
.maya-editor-wrapper .ProseMirror aside.alert-success { border-left-color: #10b981; background: rgba(16,185,129,0.08); }
|
|
371
|
+
.maya-editor-wrapper .ProseMirror aside.alert-danger { border-left-color: #ef4444; background: rgba(239,68,68,0.08); }
|
|
372
|
+
|
|
373
|
+
.maya-editor-wrapper .ProseMirror iframe {
|
|
374
|
+
display: block;
|
|
375
|
+
max-width: 100%;
|
|
376
|
+
margin: 0.5em 0;
|
|
377
|
+
border: 1px solid var(--maya-editor-border, #d6d6df);
|
|
378
|
+
border-radius: 6px;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
.maya-editor-wrapper .ProseMirror .maya-anchored-comment {
|
|
382
|
+
background: rgba(245, 158, 11, 0.18);
|
|
383
|
+
border-bottom: 1px dashed #f59e0b;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/* Placeholder shown when the doc is empty */
|
|
387
|
+
.maya-editor-wrapper .ProseMirror p.is-editor-empty:first-child::before {
|
|
388
|
+
color: rgba(127, 127, 140, 0.7);
|
|
389
|
+
content: attr(data-placeholder);
|
|
390
|
+
float: left;
|
|
391
|
+
height: 0;
|
|
392
|
+
pointer-events: none;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/* ── Source view (HTML/Markdown toggle replaces EditorContent) ── */
|
|
396
|
+
.maya-editor-wrapper .maya-editor-source {
|
|
397
|
+
flex: 1;
|
|
398
|
+
min-height: 240px;
|
|
399
|
+
width: 100%;
|
|
400
|
+
box-sizing: border-box;
|
|
401
|
+
padding: 14px 18px;
|
|
402
|
+
border: 0;
|
|
403
|
+
outline: none;
|
|
404
|
+
resize: none;
|
|
405
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
406
|
+
font-size: 13px;
|
|
407
|
+
line-height: 1.55;
|
|
408
|
+
background: var(--maya-editor-bg, #fff);
|
|
409
|
+
color: var(--maya-editor-fg, inherit);
|
|
410
|
+
white-space: pre;
|
|
411
|
+
overflow: auto;
|
|
412
|
+
}
|
|
413
|
+
.maya-editor-wrapper.is-dark .maya-editor-source {
|
|
414
|
+
background: var(--maya-editor-bg, #1f1f23);
|
|
415
|
+
color: var(--maya-editor-fg, #e6e6e8);
|
|
416
|
+
caret-color: #e6e6e8;
|
|
417
|
+
}
|
|
418
|
+
.maya-editor-wrapper .maya-editor-source:focus {
|
|
419
|
+
background: var(--maya-editor-toolbar-bg, #f7f7f9);
|
|
420
|
+
}
|
|
421
|
+
.maya-editor-wrapper.is-dark .maya-editor-source:focus {
|
|
422
|
+
background: #27272d;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/* ── Source-input modal ────────────────────────────────────── */
|
|
426
|
+
/* z-index is intentionally very high: the dialog portals to <body>, so it
|
|
427
|
+
sits next to the app root. Apps in the Maya ecosystem use values up to
|
|
428
|
+
~1000 for popovers and ~9000 for the wizard's full-screen layer; 9999
|
|
429
|
+
keeps the source dialog above all of them without risk of restacking. */
|
|
430
|
+
.maya-editor-dialog-overlay {
|
|
431
|
+
position: fixed;
|
|
432
|
+
inset: 0;
|
|
433
|
+
background: rgba(20, 20, 28, 0.55);
|
|
434
|
+
display: flex;
|
|
435
|
+
align-items: center;
|
|
436
|
+
justify-content: center;
|
|
437
|
+
z-index: 9999;
|
|
438
|
+
padding: 24px;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
.maya-editor-dialog {
|
|
442
|
+
width: min(640px, 100%);
|
|
443
|
+
max-height: min(80vh, 720px);
|
|
444
|
+
display: flex;
|
|
445
|
+
flex-direction: column;
|
|
446
|
+
background: var(--maya-editor-bg, #fff);
|
|
447
|
+
color: var(--maya-editor-fg, inherit);
|
|
448
|
+
border-radius: 10px;
|
|
449
|
+
border: 1px solid var(--maya-editor-border, #d6d6df);
|
|
450
|
+
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.25);
|
|
451
|
+
overflow: hidden;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
.maya-editor-wrapper.is-dark + .maya-editor-dialog-overlay .maya-editor-dialog,
|
|
455
|
+
.maya-editor-dialog.is-dark {
|
|
456
|
+
background: #1f1f23;
|
|
457
|
+
color: #e6e6e8;
|
|
458
|
+
border-color: #3a3a42;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
.maya-editor-dialog__header {
|
|
462
|
+
display: flex;
|
|
463
|
+
align-items: center;
|
|
464
|
+
justify-content: space-between;
|
|
465
|
+
padding: 14px 18px;
|
|
466
|
+
border-bottom: 1px solid var(--maya-editor-border, #e3e3e8);
|
|
467
|
+
}
|
|
468
|
+
.maya-editor-dialog__title { margin: 0; font-size: 15px; font-weight: 600; }
|
|
469
|
+
.maya-editor-dialog__close {
|
|
470
|
+
background: transparent;
|
|
471
|
+
border: 0;
|
|
472
|
+
font-size: 16px;
|
|
473
|
+
cursor: pointer;
|
|
474
|
+
color: inherit;
|
|
475
|
+
padding: 4px 8px;
|
|
476
|
+
border-radius: 4px;
|
|
477
|
+
}
|
|
478
|
+
.maya-editor-dialog__close:hover { background: var(--maya-editor-btn-hover, #ececf0); }
|
|
479
|
+
|
|
480
|
+
.maya-editor-dialog__description {
|
|
481
|
+
margin: 12px 18px 0;
|
|
482
|
+
font-size: 13px;
|
|
483
|
+
color: rgba(127, 127, 140, 0.95);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
.maya-editor-dialog__textarea {
|
|
487
|
+
margin: 12px 18px;
|
|
488
|
+
flex: 1;
|
|
489
|
+
resize: vertical;
|
|
490
|
+
min-height: 160px;
|
|
491
|
+
border: 1px solid var(--maya-editor-border, #d6d6df);
|
|
492
|
+
border-radius: 6px;
|
|
493
|
+
padding: 10px 12px;
|
|
494
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
495
|
+
font-size: 13px;
|
|
496
|
+
line-height: 1.5;
|
|
497
|
+
background: var(--maya-editor-toolbar-bg, #f7f7f9);
|
|
498
|
+
color: inherit;
|
|
499
|
+
outline: none;
|
|
500
|
+
}
|
|
501
|
+
.maya-editor-dialog__textarea:focus {
|
|
502
|
+
border-color: var(--maya-editor-link, #7c3aed);
|
|
503
|
+
box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.18);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
.maya-editor-dialog__footer {
|
|
507
|
+
display: flex;
|
|
508
|
+
justify-content: flex-end;
|
|
509
|
+
gap: 8px;
|
|
510
|
+
padding: 12px 18px;
|
|
511
|
+
border-top: 1px solid var(--maya-editor-border, #e3e3e8);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
.maya-editor-dialog__btn {
|
|
515
|
+
height: 32px;
|
|
516
|
+
padding: 0 14px;
|
|
517
|
+
border-radius: 6px;
|
|
518
|
+
border: 1px solid transparent;
|
|
519
|
+
font-size: 13px;
|
|
520
|
+
cursor: pointer;
|
|
521
|
+
}
|
|
522
|
+
.maya-editor-dialog__btn:disabled { opacity: 0.45; cursor: not-allowed; }
|
|
523
|
+
.maya-editor-dialog__btn--ghost {
|
|
524
|
+
background: transparent;
|
|
525
|
+
border-color: var(--maya-editor-border, #d6d6df);
|
|
526
|
+
color: inherit;
|
|
527
|
+
}
|
|
528
|
+
.maya-editor-dialog__btn--ghost:hover:not(:disabled) {
|
|
529
|
+
background: var(--maya-editor-btn-hover, #ececf0);
|
|
530
|
+
}
|
|
531
|
+
.maya-editor-dialog__btn--primary {
|
|
532
|
+
background: var(--maya-editor-link, #7c3aed);
|
|
533
|
+
color: #fff;
|
|
534
|
+
border-color: var(--maya-editor-link, #7c3aed);
|
|
535
|
+
}
|
|
536
|
+
.maya-editor-dialog__btn--primary:hover:not(:disabled) {
|
|
537
|
+
filter: brightness(1.08);
|
|
538
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export type EditorMode = 'lite' | 'full';
|
|
2
|
+
|
|
3
|
+
export interface TiptapMark {
|
|
4
|
+
type: string;
|
|
5
|
+
attrs?: Record<string, unknown>;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface TiptapNode {
|
|
9
|
+
type: string;
|
|
10
|
+
attrs?: Record<string, unknown>;
|
|
11
|
+
content?: TiptapNode[];
|
|
12
|
+
text?: string;
|
|
13
|
+
marks?: TiptapMark[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface TiptapDoc {
|
|
17
|
+
type: 'doc';
|
|
18
|
+
content: TiptapNode[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface AnchoredComment {
|
|
22
|
+
id: number | string;
|
|
23
|
+
commentId: number | string;
|
|
24
|
+
resourceType: string;
|
|
25
|
+
resourceId: number | string;
|
|
26
|
+
anchorFrom: number;
|
|
27
|
+
anchorTo: number;
|
|
28
|
+
anchorTextSnapshot: string;
|
|
29
|
+
anchorIsValid: boolean;
|
|
30
|
+
anchorLastSyncedAt: string | null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface BlockNoteStyles {
|
|
34
|
+
bold?: boolean;
|
|
35
|
+
italic?: boolean;
|
|
36
|
+
underline?: boolean;
|
|
37
|
+
strike?: boolean;
|
|
38
|
+
code?: boolean;
|
|
39
|
+
textColor?: string;
|
|
40
|
+
backgroundColor?: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface BlockNoteInline {
|
|
44
|
+
type: string;
|
|
45
|
+
text?: string;
|
|
46
|
+
styles?: BlockNoteStyles;
|
|
47
|
+
href?: string;
|
|
48
|
+
content?: BlockNoteInline[];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface BlockNoteBlock {
|
|
52
|
+
type: string;
|
|
53
|
+
props?: Record<string, unknown>;
|
|
54
|
+
content?: BlockNoteInline[] | { rows?: Array<{ cells: unknown[] }> };
|
|
55
|
+
children?: BlockNoteBlock[];
|
|
56
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
"useDefineForClassFields": true,
|
|
5
|
+
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
|
6
|
+
"allowJs": false,
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
"esModuleInterop": false,
|
|
9
|
+
"allowSyntheticDefaultImports": true,
|
|
10
|
+
"strict": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
|
+
"module": "ESNext",
|
|
13
|
+
"moduleResolution": "bundler",
|
|
14
|
+
"resolveJsonModule": true,
|
|
15
|
+
"isolatedModules": true,
|
|
16
|
+
"noEmit": true,
|
|
17
|
+
"jsx": "react-jsx"
|
|
18
|
+
},
|
|
19
|
+
"include": ["src"]
|
|
20
|
+
}
|