oneuxi-editor 1.0.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.
@@ -0,0 +1,518 @@
1
+ /* ==========================================================================
2
+ ONEUXI EDITOR STYLESHEET
3
+ ========================================================================== */
4
+
5
+ :root {
6
+ --oue-bg: #ffffff;
7
+ --oue-surface: #f9fafb;
8
+ --oue-text: #111827;
9
+ --oue-text-muted: #6b7280;
10
+ --oue-border: #e5e7eb;
11
+ --oue-primary: #2563eb;
12
+ --oue-primary-foreground: #ffffff;
13
+ --oue-hover: #f3f4f6;
14
+ --oue-active: #e5e7eb;
15
+ --oue-selection: #dbeafe;
16
+ --oue-code-bg: #f3f4f6;
17
+ --oue-toolbar-bg: #ffffff;
18
+ --oue-toolbar-border: #e5e7eb;
19
+ --oue-popup-bg: #ffffff;
20
+ --oue-radius: 8px;
21
+ --oue-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.05);
22
+ --oue-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
23
+ --oue-font-size: 15px;
24
+ --oue-line-height: 1.6;
25
+ }
26
+
27
+ .oue-editor-wrapper[data-theme="dark"] {
28
+ --oue-bg: #0f172a;
29
+ --oue-surface: #1e293b;
30
+ --oue-text: #f8fafc;
31
+ --oue-text-muted: #94a3b8;
32
+ --oue-border: #334155;
33
+ --oue-primary: #3b82f6;
34
+ --oue-primary-foreground: #ffffff;
35
+ --oue-hover: #1e293b;
36
+ --oue-active: #334155;
37
+ --oue-selection: #1e3a8a;
38
+ --oue-code-bg: #1e293b;
39
+ --oue-toolbar-bg: #0f172a;
40
+ --oue-toolbar-border: #334155;
41
+ --oue-popup-bg: #1e293b;
42
+ --oue-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.4), 0 4px 6px -4px rgba(0, 0, 0, 0.4);
43
+ }
44
+
45
+ /* Wrapper */
46
+ .oue-editor-container {
47
+ display: flex;
48
+ flex-direction: column;
49
+ background-color: var(--oue-bg);
50
+ color: var(--oue-text);
51
+ border: 1px solid var(--oue-border);
52
+ border-radius: var(--oue-radius);
53
+ font-family: var(--oue-font-family);
54
+ font-size: var(--oue-font-size);
55
+ line-height: var(--oue-line-height);
56
+ position: relative;
57
+ transition: border-color 0.2s ease, box-shadow 0.2s ease;
58
+ overflow: hidden;
59
+ }
60
+
61
+ .oue-editor-container:focus-within {
62
+ border-color: var(--oue-primary);
63
+ box-shadow: 0 0 0 1px var(--oue-primary);
64
+ }
65
+
66
+ .oue-editor-container.oue-fullscreen {
67
+ position: fixed;
68
+ top: 0;
69
+ left: 0;
70
+ right: 0;
71
+ bottom: 0;
72
+ z-index: 9999;
73
+ border-radius: 0;
74
+ border: none;
75
+ height: 100vh;
76
+ width: 100vw;
77
+ }
78
+
79
+ .oue-editor-container.oue-disabled {
80
+ opacity: 0.65;
81
+ cursor: not-allowed;
82
+ background-color: var(--oue-surface);
83
+ }
84
+
85
+ /* Content Editable Area */
86
+ .oue-content-editable {
87
+ min-height: 160px;
88
+ padding: 16px 20px;
89
+ outline: none;
90
+ overflow-y: auto;
91
+ position: relative;
92
+ }
93
+
94
+ .oue-fullscreen .oue-content-editable {
95
+ flex: 1;
96
+ }
97
+
98
+ .oue-placeholder {
99
+ position: absolute;
100
+ top: 16px;
101
+ left: 20px;
102
+ color: var(--oue-text-muted);
103
+ pointer-events: none;
104
+ user-select: none;
105
+ font-size: var(--oue-font-size);
106
+ }
107
+
108
+ /* Typography in Editor */
109
+ .oue-content-editable p {
110
+ margin: 0 0 0.8em 0;
111
+ }
112
+
113
+ .oue-content-editable p:last-child {
114
+ margin-bottom: 0;
115
+ }
116
+
117
+ .oue-content-editable h1 {
118
+ font-size: 2em;
119
+ margin: 0.67em 0 0.4em 0;
120
+ font-weight: 700;
121
+ line-height: 1.25;
122
+ }
123
+
124
+ .oue-content-editable h2 {
125
+ font-size: 1.6em;
126
+ margin: 0.67em 0 0.4em 0;
127
+ font-weight: 600;
128
+ line-height: 1.3;
129
+ }
130
+
131
+ .oue-content-editable h3 {
132
+ font-size: 1.3em;
133
+ margin: 0.67em 0 0.4em 0;
134
+ font-weight: 600;
135
+ line-height: 1.35;
136
+ }
137
+
138
+ .oue-content-editable h4 {
139
+ font-size: 1.1em;
140
+ margin: 0.67em 0 0.4em 0;
141
+ font-weight: 600;
142
+ }
143
+
144
+ .oue-content-editable h5 {
145
+ font-size: 0.95em;
146
+ margin: 0.67em 0 0.4em 0;
147
+ font-weight: 600;
148
+ text-transform: uppercase;
149
+ }
150
+
151
+ .oue-content-editable h6 {
152
+ font-size: 0.85em;
153
+ margin: 0.67em 0 0.4em 0;
154
+ font-weight: 600;
155
+ color: var(--oue-text-muted);
156
+ }
157
+
158
+ .oue-content-editable blockquote {
159
+ border-left: 4px solid var(--oue-primary);
160
+ margin: 1em 0;
161
+ padding-left: 16px;
162
+ color: var(--oue-text-muted);
163
+ font-style: italic;
164
+ }
165
+
166
+ .oue-content-editable hr {
167
+ border: none;
168
+ border-top: 1px solid var(--oue-border);
169
+ margin: 1.5em 0;
170
+ }
171
+
172
+ .oue-content-editable code:not(pre code) {
173
+ background-color: var(--oue-code-bg);
174
+ padding: 0.2em 0.4em;
175
+ border-radius: 4px;
176
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
177
+ font-size: 0.9em;
178
+ }
179
+
180
+ .oue-content-editable pre {
181
+ background-color: var(--oue-code-bg);
182
+ padding: 12px 16px;
183
+ border-radius: var(--oue-radius);
184
+ overflow-x: auto;
185
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
186
+ font-size: 0.9em;
187
+ line-height: 1.45;
188
+ margin: 1em 0;
189
+ position: relative;
190
+ }
191
+
192
+ .oue-content-editable pre code {
193
+ background: transparent;
194
+ padding: 0;
195
+ }
196
+
197
+ /* Lists */
198
+ .oue-content-editable ul,
199
+ .oue-content-editable ol {
200
+ padding-left: 24px;
201
+ margin: 0.5em 0;
202
+ }
203
+
204
+ .oue-content-editable li {
205
+ margin-bottom: 0.3em;
206
+ }
207
+
208
+ .oue-checklist {
209
+ list-style-type: none;
210
+ padding-left: 0 !important;
211
+ }
212
+
213
+ .oue-checklist-item {
214
+ display: flex;
215
+ align-items: flex-start;
216
+ gap: 8px;
217
+ }
218
+
219
+ .oue-checklist-item input[type="checkbox"] {
220
+ margin-top: 4px;
221
+ cursor: pointer;
222
+ }
223
+
224
+ .oue-checklist-item-checked {
225
+ text-decoration: line-through;
226
+ color: var(--oue-text-muted);
227
+ }
228
+
229
+ /* Links */
230
+ .oue-content-editable a {
231
+ color: var(--oue-primary);
232
+ text-decoration: underline;
233
+ cursor: pointer;
234
+ }
235
+
236
+ /* Toolbar */
237
+ .oue-toolbar {
238
+ display: flex;
239
+ flex-wrap: wrap;
240
+ align-items: center;
241
+ gap: 2px;
242
+ padding: 6px 10px;
243
+ background-color: var(--oue-toolbar-bg);
244
+ border-bottom: 1px solid var(--oue-toolbar-border);
245
+ user-select: none;
246
+ }
247
+
248
+ .oue-toolbar-group {
249
+ display: flex;
250
+ align-items: center;
251
+ gap: 2px;
252
+ }
253
+
254
+ .oue-toolbar-separator {
255
+ width: 1px;
256
+ height: 20px;
257
+ background-color: var(--oue-border);
258
+ margin: 0 6px;
259
+ }
260
+
261
+ .oue-toolbar-btn {
262
+ display: inline-flex;
263
+ align-items: center;
264
+ justify-content: center;
265
+ height: 32px;
266
+ min-width: 32px;
267
+ padding: 0 6px;
268
+ border: none;
269
+ background: transparent;
270
+ color: var(--oue-text);
271
+ border-radius: 4px;
272
+ cursor: pointer;
273
+ font-size: 14px;
274
+ font-weight: 500;
275
+ transition: background-color 0.15s ease, color 0.15s ease;
276
+ }
277
+
278
+ .oue-toolbar-btn:hover:not(:disabled) {
279
+ background-color: var(--oue-hover);
280
+ }
281
+
282
+ .oue-toolbar-btn.oue-active {
283
+ background-color: var(--oue-active);
284
+ color: var(--oue-primary);
285
+ }
286
+
287
+ .oue-toolbar-btn:disabled {
288
+ opacity: 0.4;
289
+ cursor: not-allowed;
290
+ }
291
+
292
+ .oue-toolbar-select {
293
+ height: 32px;
294
+ padding: 0 8px;
295
+ border-radius: 4px;
296
+ border: 1px solid var(--oue-border);
297
+ background-color: var(--oue-bg);
298
+ color: var(--oue-text);
299
+ font-size: 13px;
300
+ outline: none;
301
+ cursor: pointer;
302
+ }
303
+
304
+ /* Bubble Toolbar */
305
+ .oue-bubble-toolbar {
306
+ position: absolute;
307
+ z-index: 100;
308
+ display: flex;
309
+ align-items: center;
310
+ gap: 2px;
311
+ padding: 4px;
312
+ background-color: var(--oue-popup-bg);
313
+ border: 1px solid var(--oue-border);
314
+ border-radius: 6px;
315
+ box-shadow: var(--oue-shadow);
316
+ animation: oue-fade-in 0.15s ease-out;
317
+ }
318
+
319
+ @keyframes oue-fade-in {
320
+ from {
321
+ opacity: 0;
322
+ transform: translateY(4px);
323
+ }
324
+
325
+ to {
326
+ opacity: 1;
327
+ transform: translateY(0);
328
+ }
329
+ }
330
+
331
+ /* Footer / Status Bar */
332
+ .oue-footer {
333
+ display: flex;
334
+ align-items: center;
335
+ justify-content: space-between;
336
+ padding: 6px 16px;
337
+ background-color: var(--oue-surface);
338
+ border-top: 1px solid var(--oue-border);
339
+ font-size: 12px;
340
+ color: var(--oue-text-muted);
341
+ }
342
+
343
+ /* Table Styling */
344
+ .oue-table-wrapper {
345
+ overflow-x: auto;
346
+ margin: 1em 0;
347
+ max-width: 100%;
348
+ }
349
+
350
+ .oue-content-editable table {
351
+ border-collapse: collapse;
352
+ width: 100%;
353
+ border: 1px solid var(--oue-border);
354
+ }
355
+
356
+ .oue-content-editable th,
357
+ .oue-content-editable td {
358
+ border: 1px solid var(--oue-border);
359
+ padding: 8px 12px;
360
+ min-width: 60px;
361
+ position: relative;
362
+ }
363
+
364
+ .oue-content-editable th {
365
+ background-color: var(--oue-surface);
366
+ font-weight: 600;
367
+ }
368
+
369
+ /* Image Styling */
370
+ .oue-image-container {
371
+ display: inline-block;
372
+ max-width: 100%;
373
+ position: relative;
374
+ margin: 0.5em 0;
375
+ }
376
+
377
+ .oue-image-container img {
378
+ max-width: 100%;
379
+ height: auto;
380
+ border-radius: 4px;
381
+ display: block;
382
+ }
383
+
384
+ .oue-image-container.oue-align-left {
385
+ float: left;
386
+ margin-right: 1em;
387
+ }
388
+
389
+ .oue-image-container.oue-align-center {
390
+ display: block;
391
+ margin: 0.5em auto;
392
+ text-align: center;
393
+ }
394
+
395
+ .oue-image-container.oue-align-right {
396
+ float: right;
397
+ margin-left: 1em;
398
+ }
399
+
400
+ .oue-image-caption {
401
+ font-size: 0.85em;
402
+ color: var(--oue-text-muted);
403
+ text-align: center;
404
+ margin-top: 4px;
405
+ }
406
+
407
+ /* Popups and Dialogs */
408
+ .oue-dialog-overlay {
409
+ position: fixed;
410
+ top: 0;
411
+ left: 0;
412
+ right: 0;
413
+ bottom: 0;
414
+ background-color: rgba(0, 0, 0, 0.4);
415
+ z-index: 10000;
416
+ display: flex;
417
+ align-items: center;
418
+ justify-content: center;
419
+ }
420
+
421
+ .oue-dialog {
422
+ background-color: var(--oue-popup-bg);
423
+ border: 1px solid var(--oue-border);
424
+ border-radius: var(--oue-radius);
425
+ box-shadow: var(--oue-shadow);
426
+ padding: 20px;
427
+ min-width: 320px;
428
+ max-width: 480px;
429
+ width: 100%;
430
+ }
431
+
432
+ .oue-dialog-title {
433
+ font-weight: 600;
434
+ font-size: 16px;
435
+ margin-bottom: 12px;
436
+ }
437
+
438
+ .oue-dialog-field {
439
+ display: flex;
440
+ flex-direction: column;
441
+ gap: 4px;
442
+ margin-bottom: 12px;
443
+ }
444
+
445
+ .oue-dialog-label {
446
+ font-size: 12px;
447
+ font-weight: 500;
448
+ color: var(--oue-text-muted);
449
+ }
450
+
451
+ .oue-dialog-input {
452
+ height: 36px;
453
+ padding: 0 10px;
454
+ border: 1px solid var(--oue-border);
455
+ border-radius: 4px;
456
+ background-color: var(--oue-bg);
457
+ color: var(--oue-text);
458
+ outline: none;
459
+ font-size: 14px;
460
+ }
461
+
462
+ .oue-dialog-input:focus {
463
+ border-color: var(--oue-primary);
464
+ }
465
+
466
+ .oue-dialog-actions {
467
+ display: flex;
468
+ justify-content: flex-end;
469
+ gap: 8px;
470
+ margin-top: 16px;
471
+ }
472
+
473
+ /* Dropdown Menu / Slash Menu / Mentions */
474
+ .oue-menu {
475
+ position: absolute;
476
+ z-index: 1000;
477
+ background-color: var(--oue-popup-bg);
478
+ border: 1px solid var(--oue-border);
479
+ border-radius: 6px;
480
+ box-shadow: var(--oue-shadow);
481
+ padding: 4px;
482
+ min-width: 180px;
483
+ max-height: 260px;
484
+ overflow-y: auto;
485
+ }
486
+
487
+ .oue-menu-item {
488
+ display: flex;
489
+ align-items: center;
490
+ gap: 8px;
491
+ padding: 6px 10px;
492
+ border-radius: 4px;
493
+ cursor: pointer;
494
+ font-size: 13px;
495
+ color: var(--oue-text);
496
+ transition: background-color 0.1s ease;
497
+ }
498
+
499
+ .oue-menu-item:hover,
500
+ .oue-menu-item.oue-selected {
501
+ background-color: var(--oue-hover);
502
+ color: var(--oue-primary);
503
+ }
504
+
505
+ /* Source HTML Editor */
506
+ .oue-source-textarea {
507
+ width: 100%;
508
+ min-height: 200px;
509
+ padding: 16px;
510
+ border: none;
511
+ background-color: var(--oue-code-bg);
512
+ color: var(--oue-text);
513
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
514
+ font-size: 13px;
515
+ line-height: 1.5;
516
+ resize: vertical;
517
+ outline: none;
518
+ }
package/package.json ADDED
@@ -0,0 +1,86 @@
1
+ {
2
+ "name": "oneuxi-editor",
3
+ "version": "1.0.0",
4
+ "description": "A production-ready, lightweight, modular rich text and HTML editor for React applications built on Lexical",
5
+ "author": "thedebuglab",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/thedebuglab/oneuxi-editor.git"
10
+ },
11
+ "bugs": {
12
+ "url": "https://github.com/thedebuglab/oneuxi-editor/issues"
13
+ },
14
+ "homepage": "https://github.com/thedebuglab/oneuxi-editor#readme",
15
+ "keywords": [
16
+ "react",
17
+ "editor",
18
+ "rich-text",
19
+ "lexical",
20
+ "wysiwyg",
21
+ "html-editor",
22
+ "react-editor",
23
+ "contenteditable",
24
+ "saas"
25
+ ],
26
+ "publishConfig": {
27
+ "access": "public"
28
+ },
29
+ "main": "./dist/index.js",
30
+ "module": "./dist/index.mjs",
31
+ "types": "./dist/index.d.ts",
32
+ "style": "./dist/styles.css",
33
+ "exports": {
34
+ ".": {
35
+ "types": "./dist/index.d.ts",
36
+ "import": "./dist/index.mjs",
37
+ "require": "./dist/index.js"
38
+ },
39
+ "./styles.css": "./dist/styles.css"
40
+ },
41
+ "files": [
42
+ "dist"
43
+ ],
44
+ "scripts": {
45
+ "build": "tsup",
46
+ "dev": "tsup --watch",
47
+ "typecheck": "tsc --noEmit",
48
+ "test": "vitest run",
49
+ "test:watch": "vitest",
50
+ "test:e2e": "playwright test",
51
+ "prepublishOnly": "npm run build && npm run typecheck && npm run test",
52
+ "release": "npm publish --access public"
53
+ },
54
+ "peerDependencies": {
55
+ "react": "^18.0.0 || ^19.0.0",
56
+ "react-dom": "^18.0.0 || ^19.0.0"
57
+ },
58
+ "dependencies": {
59
+ "@lexical/code": "^0.24.0",
60
+ "@lexical/history": "^0.24.0",
61
+ "@lexical/html": "^0.24.0",
62
+ "@lexical/link": "^0.24.0",
63
+ "@lexical/list": "^0.24.0",
64
+ "@lexical/overflow": "^0.24.0",
65
+ "@lexical/react": "^0.24.0",
66
+ "@lexical/rich-text": "^0.24.0",
67
+ "@lexical/selection": "^0.24.0",
68
+ "@lexical/table": "^0.24.0",
69
+ "@lexical/utils": "^0.24.0",
70
+ "dompurify": "^3.2.4",
71
+ "lexical": "^0.24.0"
72
+ },
73
+ "devDependencies": {
74
+ "@playwright/test": "^1.50.0",
75
+ "@testing-library/jest-dom": "^6.6.3",
76
+ "@testing-library/react": "^16.2.0",
77
+ "@types/dompurify": "^3.2.0",
78
+ "@types/node": "^22.13.0",
79
+ "@types/react": "^19.0.8",
80
+ "@types/react-dom": "^19.0.3",
81
+ "jsdom": "^26.0.0",
82
+ "tsup": "^8.3.6",
83
+ "typescript": "^5.7.3",
84
+ "vitest": "^3.0.5"
85
+ }
86
+ }