@malaya_jeeva/rich-text-editor 1.0.11 → 1.0.13
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 +53 -6
- package/dist/index.d.mts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +125 -69
- package/dist/index.mjs +128 -69
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,7 +26,13 @@ export default function Page() {
|
|
|
26
26
|
const [value, setValue] = useState('')
|
|
27
27
|
|
|
28
28
|
return (
|
|
29
|
-
<RichTextEditor
|
|
29
|
+
<RichTextEditor
|
|
30
|
+
value={value}
|
|
31
|
+
onChange={setValue}
|
|
32
|
+
placeholder="Write something..."
|
|
33
|
+
height={400}
|
|
34
|
+
theme="light"
|
|
35
|
+
/>
|
|
30
36
|
)
|
|
31
37
|
}
|
|
32
38
|
```
|
|
@@ -45,11 +51,14 @@ export default function Page() {
|
|
|
45
51
|
|
|
46
52
|
## ⚙️ Props
|
|
47
53
|
|
|
48
|
-
| Prop
|
|
49
|
-
|
|
|
50
|
-
| `value`
|
|
51
|
-
| `onChange`
|
|
52
|
-
| `toolbar`
|
|
54
|
+
| Prop | Type | Required | Default | Description |
|
|
55
|
+
| ------------- | ----------------------------- | -------- | -------------------- | --------------------------------------------------------------------------- |
|
|
56
|
+
| `value` | `string` | No | — | Initial HTML content (read on first mount only) |
|
|
57
|
+
| `onChange` | `(value: string) => void` | No | — | Fires with full `innerHTML` on every change |
|
|
58
|
+
| `toolbar` | `ToolbarItem[]` | No | all items | Controls which toolbar buttons are shown. If omitted, all buttons are shown |
|
|
59
|
+
| `placeholder` | `string` | No | `"Start typing..."` | Placeholder text shown when the editor is empty |
|
|
60
|
+
| `height` | `number \| string` | No | auto (max `350px`) | Editor content area height — `500`, `"400px"`, `"60vh"` etc. |
|
|
61
|
+
| `theme` | `"light" \| "dark" \| "auto"` | No | `"auto"` | Color theme. `"auto"` follows the OS `prefers-color-scheme` setting |
|
|
53
62
|
|
|
54
63
|
### Type export
|
|
55
64
|
|
|
@@ -59,6 +68,44 @@ import type { RichTextEditorProps, ToolbarItem } from '@malaya_jeeva/rich-text-e
|
|
|
59
68
|
|
|
60
69
|
---
|
|
61
70
|
|
|
71
|
+
## 📐 Height
|
|
72
|
+
|
|
73
|
+
Control the height of the editor content area via the `height` prop. Accepts a number (pixels) or any valid CSS string.
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
<RichTextEditor height={500} /> // 500px fixed
|
|
77
|
+
<RichTextEditor height="60vh" /> // viewport-relative
|
|
78
|
+
<RichTextEditor height="400px" /> // explicit px string
|
|
79
|
+
<RichTextEditor /> // default — grows with content, caps at 350px
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## 💬 Placeholder
|
|
85
|
+
|
|
86
|
+
Set the placeholder text shown when the editor is empty.
|
|
87
|
+
|
|
88
|
+
```tsx
|
|
89
|
+
<RichTextEditor placeholder="Write something..." />
|
|
90
|
+
// omit it — defaults to "Start typing..."
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## 🌗 Theme
|
|
96
|
+
|
|
97
|
+
Three options: `"light"`, `"dark"`, or `"auto"` (default).
|
|
98
|
+
|
|
99
|
+
```tsx
|
|
100
|
+
<RichTextEditor theme="light" /> // always light
|
|
101
|
+
<RichTextEditor theme="dark" /> // always dark
|
|
102
|
+
<RichTextEditor /> // auto — follows OS prefers-color-scheme
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
> When `theme="auto"` (or the prop is omitted) the editor automatically switches between light and dark based on the user's OS setting — no extra code needed.
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
62
109
|
## 🛠️ Toolbar Customization
|
|
63
110
|
|
|
64
111
|
Pass a `toolbar` array to control exactly which buttons appear. If the prop is omitted, **all buttons are shown** — fully backward compatible.
|
package/dist/index.d.mts
CHANGED
|
@@ -5,8 +5,11 @@ type RichTextEditorProps = {
|
|
|
5
5
|
value?: string;
|
|
6
6
|
onChange?: (value: string) => void;
|
|
7
7
|
toolbar?: ToolbarItem[];
|
|
8
|
+
theme?: "light" | "dark";
|
|
9
|
+
height?: number | string;
|
|
10
|
+
placeholder?: string;
|
|
8
11
|
};
|
|
9
12
|
|
|
10
|
-
declare function RichTextEditor({ value, onChange, toolbar }: RichTextEditorProps): ReactElement;
|
|
13
|
+
declare function RichTextEditor({ value, onChange, toolbar, theme, height, placeholder }: RichTextEditorProps): ReactElement;
|
|
11
14
|
|
|
12
15
|
export { type RichTextEditorProps, RichTextEditor as default };
|
package/dist/index.d.ts
CHANGED
|
@@ -5,8 +5,11 @@ type RichTextEditorProps = {
|
|
|
5
5
|
value?: string;
|
|
6
6
|
onChange?: (value: string) => void;
|
|
7
7
|
toolbar?: ToolbarItem[];
|
|
8
|
+
theme?: "light" | "dark";
|
|
9
|
+
height?: number | string;
|
|
10
|
+
placeholder?: string;
|
|
8
11
|
};
|
|
9
12
|
|
|
10
|
-
declare function RichTextEditor({ value, onChange, toolbar }: RichTextEditorProps): ReactElement;
|
|
13
|
+
declare function RichTextEditor({ value, onChange, toolbar, theme, height, placeholder }: RichTextEditorProps): ReactElement;
|
|
11
14
|
|
|
12
15
|
export { type RichTextEditorProps, RichTextEditor as default };
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,21 @@
|
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
6
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
8
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
9
|
+
var __spreadValues = (a, b) => {
|
|
10
|
+
for (var prop in b || (b = {}))
|
|
11
|
+
if (__hasOwnProp.call(b, prop))
|
|
12
|
+
__defNormalProp(a, prop, b[prop]);
|
|
13
|
+
if (__getOwnPropSymbols)
|
|
14
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
15
|
+
if (__propIsEnum.call(b, prop))
|
|
16
|
+
__defNormalProp(a, prop, b[prop]);
|
|
17
|
+
}
|
|
18
|
+
return a;
|
|
19
|
+
};
|
|
6
20
|
var __export = (target, all) => {
|
|
7
21
|
for (var name in all)
|
|
8
22
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -64,64 +78,107 @@ var PALETTE = [
|
|
|
64
78
|
"#20124d",
|
|
65
79
|
"#4c1130"
|
|
66
80
|
];
|
|
81
|
+
var DARK = `
|
|
82
|
+
--rte-toolbar-bg:#1e1e1e;--rte-toolbar-border:#333;
|
|
83
|
+
--rte-btn:#ccc;--rte-btn-hover-bg:#2e2e2e;--rte-btn-active-bg:#1a3a5c;--rte-btn-active:#90c4ff;
|
|
84
|
+
--rte-btn-danger:#ff6b6b;--rte-btn-danger-hover-bg:#3a1a1a;
|
|
85
|
+
--rte-sep:#3a3a3a;
|
|
86
|
+
--rte-select-bg:#2a2a2a;--rte-select-border:#444;--rte-select:#ccc;
|
|
87
|
+
--rte-cpick-bg:#222;--rte-cpick-border:#444;
|
|
88
|
+
--rte-cactions-border:#333;--rte-caction-hover-bg:#2a2a2a;--rte-caction-hover-border:#444;
|
|
89
|
+
--rte-tpick-bg:#222;--rte-tpick-border:#444;
|
|
90
|
+
--rte-tpcell-bg:#2a2a2a;--rte-tpcell-border:#444;--rte-tpcell-on-bg:#1a3a5c;--rte-tpcell-on-border:#90c4ff;
|
|
91
|
+
--rte-ipick-bg:#222;--rte-ipick-border:#444;
|
|
92
|
+
--rte-itabs-border:#333;--rte-itab-hover-bg:#2a2a2a;
|
|
93
|
+
--rte-idrop-border:#555;--rte-idrop-hover-bg:#1a3a5c;--rte-idrop-hover-border:#90c4ff;
|
|
94
|
+
--rte-float-bg:#222;--rte-float-border:#444;--rte-float-arrow-border:#444;--rte-float-arrow-bg:#222;
|
|
95
|
+
--rte-linkinput-bg:#1a1a1a;--rte-linkinput-border:#555;--rte-linkinput:#ddd;
|
|
96
|
+
--rte-area-bg:#141414;
|
|
97
|
+
--rte-body:#ddd;--rte-table-border:#444;--rte-th-bg:#2a2a2a;
|
|
98
|
+
--rte-pre-bg:#1e1e2e;--rte-pre-border:#333;
|
|
99
|
+
--rte-footer-bg:#1a1a1a;--rte-footer-border:#2a2a2a;--rte-footer:#aaa;
|
|
100
|
+
--rte-iepanel-bg:#222;--rte-iepanel-border:#444;
|
|
101
|
+
--rte-ietabs-border:#333;--rte-ietab-hover-bg:#2a2a2a;
|
|
102
|
+
--rte-ieinput-bg:#1a1a1a;--rte-ieinput-border:#444;--rte-ieinput:#ddd;
|
|
103
|
+
`;
|
|
67
104
|
var CSS = `
|
|
68
105
|
*{box-sizing:border-box;}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
106
|
+
|
|
107
|
+
/* \u2500\u2500\u2500 Theme tokens \u2500\u2500\u2500 */
|
|
108
|
+
.customeditor{
|
|
109
|
+
max-height:350px;overflow-y:auto;position:relative;
|
|
110
|
+
/* light (default) */
|
|
111
|
+
--rte-toolbar-bg:#f8f8f8;--rte-toolbar-border:#e0e0e0;
|
|
112
|
+
--rte-btn:#444;--rte-btn-hover-bg:#e8e8e8;--rte-btn-active-bg:#d0e4ff;--rte-btn-active:#1a5fb4;
|
|
113
|
+
--rte-btn-danger:#c0392b;--rte-btn-danger-hover-bg:#fdecea;
|
|
114
|
+
--rte-sep:#d8d8d8;
|
|
115
|
+
--rte-select-bg:#fff;--rte-select-border:#d8d8d8;--rte-select:#333;
|
|
116
|
+
--rte-cpick-bg:#fff;--rte-cpick-border:#ccc;
|
|
117
|
+
--rte-cactions-border:#eee;--rte-caction-hover-bg:#f0f0f0;--rte-caction-hover-border:#ddd;
|
|
118
|
+
--rte-tpick-bg:#fff;--rte-tpick-border:#d8d8d8;
|
|
119
|
+
--rte-tpcell-bg:#fff;--rte-tpcell-border:#ddd;--rte-tpcell-on-bg:#d0e4ff;--rte-tpcell-on-border:#1a5fb4;
|
|
120
|
+
--rte-ipick-bg:#fff;--rte-ipick-border:#ccc;
|
|
121
|
+
--rte-itabs-border:#eee;--rte-itab-hover-bg:#f8f8f8;
|
|
122
|
+
--rte-idrop-border:#ccc;--rte-idrop-hover-bg:#f0f4ff;--rte-idrop-hover-border:#1a5fb4;
|
|
123
|
+
--rte-float-bg:#fff;--rte-float-border:#d0d0d0;--rte-float-arrow-border:#d0d0d0;--rte-float-arrow-bg:#fff;
|
|
124
|
+
--rte-linkinput-bg:#fff;--rte-linkinput-border:#ccc;--rte-linkinput:#222;
|
|
125
|
+
--rte-area-bg:#fff;
|
|
126
|
+
--rte-body:#222;--rte-table-border:#ccc;--rte-th-bg:#f5f5f5;
|
|
127
|
+
--rte-pre-bg:#f4f4f4;--rte-pre-border:#e0e0e0;
|
|
128
|
+
--rte-footer-bg:#fafafa;--rte-footer-border:#e8e8e8;--rte-footer:#999;
|
|
129
|
+
--rte-iepanel-bg:#fff;--rte-iepanel-border:#d0d0d0;
|
|
130
|
+
--rte-ietabs-border:#eee;--rte-ietab-hover-bg:#f8f8f8;
|
|
131
|
+
--rte-ieinput-bg:#fff;--rte-ieinput-border:#ccc;--rte-ieinput:#222;
|
|
132
|
+
}
|
|
133
|
+
/* Explicit dark */
|
|
134
|
+
.customeditor.rte-dark{${DARK}}
|
|
135
|
+
/* OS-level auto dark (ignored when an explicit theme class is present) */
|
|
136
|
+
@media(prefers-color-scheme:dark){
|
|
137
|
+
.customeditor:not(.rte-light):not(.rte-dark){${DARK}}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/* \u2500\u2500\u2500 Component styles \u2500\u2500\u2500 */
|
|
141
|
+
.rte-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:1px;padding:4px 8px;background:var(--rte-toolbar-bg);border-bottom:1px solid var(--rte-toolbar-border);position:sticky;top:0;z-index:9;}
|
|
142
|
+
.rte-btn{background:transparent;border:none;border-radius:3px;cursor:pointer;height:30px;min-width:30px;padding:0 6px;color:var(--rte-btn);font-size:13px;font-weight:500;font-family:var(--font-sans);display:inline-flex;align-items:center;justify-content:center;user-select:none;white-space:nowrap;transition:background 0.1s;flex-shrink:0;}
|
|
143
|
+
.rte-btn:hover{background:var(--rte-btn-hover-bg);}
|
|
144
|
+
.rte-btn.active{background:var(--rte-btn-active-bg);color:var(--rte-btn-active);}
|
|
145
|
+
.rte-btn.danger{color:var(--rte-btn-danger);}
|
|
146
|
+
.rte-btn.danger:hover{background:var(--rte-btn-danger-hover-bg);}
|
|
147
|
+
.rte-sep{width:1px;height:20px;background:var(--rte-sep);margin:0 4px;flex-shrink:0;}
|
|
148
|
+
.rte-select{height:28px;border:1px solid var(--rte-select-border);border-radius:3px;background:var(--rte-select-bg);color:var(--rte-select);font-size:12px;padding:0 22px 0 7px;cursor:pointer;outline:none;font-family:var(--font-sans);appearance:none;-webkit-appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 6px center;}
|
|
79
149
|
.rte-swatch{width:14px;height:3px;border-radius:1px;margin-top:2px;}
|
|
80
|
-
.rte-cpick{background
|
|
81
|
-
@media(prefers-color-scheme:dark){.rte-cpick{background:#222;border-color:#444;}}
|
|
150
|
+
.rte-cpick{background:var(--rte-cpick-bg);border:1px solid var(--rte-cpick-border);border-radius:8px;box-shadow:0 4px 20px rgba(0,0,0,0.15);padding:8px;min-width:190px;}
|
|
82
151
|
.rte-cgrid{display:grid;grid-template-columns:repeat(8,20px);gap:2px;margin-bottom:6px;}
|
|
83
152
|
.rte-ccell{width:20px;height:20px;border-radius:3px;cursor:pointer;border:1px solid rgba(0,0,0,0.12);transition:transform 0.08s,box-shadow 0.08s;}
|
|
84
153
|
.rte-ccell:hover{transform:scale(1.2);box-shadow:0 1px 4px rgba(0,0,0,0.3);z-index:1;position:relative;}
|
|
85
154
|
.rte-ccell.sel{outline:2px solid #1a5fb4;outline-offset:1px;}
|
|
86
|
-
.rte-cactions{display:flex;align-items:center;gap:2px;border-top:1px solid
|
|
87
|
-
@media(prefers-color-scheme:dark){.rte-cactions{border-color:#333;}}
|
|
155
|
+
.rte-cactions{display:flex;align-items:center;gap:2px;border-top:1px solid var(--rte-cactions-border);padding-top:6px;margin-top:2px;}
|
|
88
156
|
.rte-caction{flex:1;height:28px;display:flex;align-items:center;justify-content:center;border-radius:4px;cursor:pointer;border:1px solid transparent;transition:background 0.1s;}
|
|
89
|
-
.rte-caction:hover{background
|
|
90
|
-
|
|
91
|
-
.rte-tpick{background:#fff;border:1px solid #d8d8d8;border-radius:6px;box-shadow:0 4px 16px rgba(0,0,0,0.12);padding:10px;}
|
|
92
|
-
@media(prefers-color-scheme:dark){.rte-tpick{background:#222;border-color:#444;}}
|
|
157
|
+
.rte-caction:hover{background:var(--rte-caction-hover-bg);border-color:var(--rte-caction-hover-border);}
|
|
158
|
+
.rte-tpick{background:var(--rte-tpick-bg);border:1px solid var(--rte-tpick-border);border-radius:6px;box-shadow:0 4px 16px rgba(0,0,0,0.12);padding:10px;}
|
|
93
159
|
.rte-tplbl{font-size:11px;color:#888;text-align:center;margin-bottom:8px;font-family:var(--font-sans);}
|
|
94
160
|
.rte-tpgrid{display:grid;grid-template-columns:repeat(8,18px);gap:2px;}
|
|
95
|
-
.rte-tpcell{width:18px;height:18px;border-radius:2px;border:1px solid
|
|
96
|
-
.rte-tpcell.on{background
|
|
97
|
-
|
|
98
|
-
.rte-
|
|
99
|
-
@media(prefers-color-scheme:dark){.rte-ipick{background:#222;border-color:#444;}}
|
|
100
|
-
.rte-itabs{display:flex;border-bottom:1px solid #eee;}
|
|
101
|
-
@media(prefers-color-scheme:dark){.rte-itabs{border-color:#333;}}
|
|
161
|
+
.rte-tpcell{width:18px;height:18px;border-radius:2px;border:1px solid var(--rte-tpcell-border);cursor:pointer;background:var(--rte-tpcell-bg);transition:background 0.08s;}
|
|
162
|
+
.rte-tpcell.on{background:var(--rte-tpcell-on-bg);border-color:var(--rte-tpcell-on-border);}
|
|
163
|
+
.rte-ipick{background:var(--rte-ipick-bg);border:1px solid var(--rte-ipick-border);border-radius:8px;box-shadow:0 4px 20px rgba(0,0,0,0.15);width:300px;overflow:hidden;}
|
|
164
|
+
.rte-itabs{display:flex;border-bottom:1px solid var(--rte-itabs-border);}
|
|
102
165
|
.rte-itab{flex:1;padding:8px 4px;font-size:12px;font-weight:500;background:none;border:none;border-bottom:2px solid transparent;cursor:pointer;color:#888;font-family:var(--font-sans);}
|
|
103
|
-
.rte-itab:hover{color:#444;background
|
|
104
|
-
|
|
166
|
+
.rte-itab:hover{color:#444;background:var(--rte-itab-hover-bg);}
|
|
167
|
+
.rte-itab.active{color:#1a5fb4;border-bottom-color:#1a5fb4;}
|
|
105
168
|
.rte-ipbody{padding:12px;display:flex;flex-direction:column;gap:10px;}
|
|
106
|
-
.rte-idrop{border:2px dashed
|
|
107
|
-
.rte-idrop:hover,.rte-idrop.drag{border-color
|
|
108
|
-
@media(prefers-color-scheme:dark){.rte-idrop{border-color:#555;}.rte-idrop:hover,.rte-idrop.drag{background:#1a3a5c;border-color:#90c4ff;}}
|
|
169
|
+
.rte-idrop{border:2px dashed var(--rte-idrop-border);border-radius:6px;padding:24px 12px;text-align:center;cursor:pointer;transition:border-color 0.15s,background 0.15s;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;min-height:110px;}
|
|
170
|
+
.rte-idrop:hover,.rte-idrop.drag{border-color:var(--rte-idrop-hover-border);background:var(--rte-idrop-hover-bg);}
|
|
109
171
|
.rte-iinsert{width:100%;height:30px;background:#1a6fc4;color:#fff;border:none;border-radius:4px;font-size:12px;font-weight:600;cursor:pointer;}
|
|
110
172
|
.rte-iinsert:disabled{opacity:0.4;cursor:not-allowed;}
|
|
111
|
-
.rte-float{position:absolute;z-index:50;background
|
|
112
|
-
@media(prefers-color-scheme:dark){.rte-float{background:#222;border-color:#444;}}
|
|
173
|
+
.rte-float{position:absolute;z-index:50;background:var(--rte-float-bg);border:1px solid var(--rte-float-border);border-radius:8px;box-shadow:0 4px 20px rgba(0,0,0,0.13);padding:4px 6px;display:flex;align-items:center;gap:1px;flex-wrap:wrap;}
|
|
113
174
|
.rte-float-arrow{position:absolute;top:-7px;width:14px;height:7px;}
|
|
114
175
|
.rte-float-arrow::before,.rte-float-arrow::after{content:'';position:absolute;left:0;border-left:7px solid transparent;border-right:7px solid transparent;}
|
|
115
|
-
.rte-float-arrow::before{top:0;border-bottom:7px solid
|
|
116
|
-
.rte-float-arrow::after{top:1px;border-bottom:6px solid
|
|
117
|
-
@media(prefers-color-scheme:dark){.rte-float-arrow::before{border-bottom-color:#444;}.rte-float-arrow::after{border-bottom-color:#222;}}
|
|
176
|
+
.rte-float-arrow::before{top:0;border-bottom:7px solid var(--rte-float-arrow-border);}
|
|
177
|
+
.rte-float-arrow::after{top:1px;border-bottom:6px solid var(--rte-float-arrow-bg);}
|
|
118
178
|
.rte-linkbar{min-width:340px;}
|
|
119
|
-
.rte-linkbar input{flex:1;height:26px;border:1px solid
|
|
120
|
-
|
|
121
|
-
.rte-
|
|
122
|
-
@media(prefers-color-scheme:dark){.rte-area{background:#141414;}}
|
|
123
|
-
.rte-body{min-height:280px;outline:none;font-size:15px;line-height:1.75;color:#222;caret-color:#222;padding:18px 20px;}
|
|
124
|
-
@media(prefers-color-scheme:dark){.rte-body{color:#ddd;caret-color:#ddd;}}
|
|
179
|
+
.rte-linkbar input{flex:1;height:26px;border:1px solid var(--rte-linkinput-border);border-radius:3px;padding:0 8px;font-size:13px;outline:none;font-family:var(--font-sans);background:var(--rte-linkinput-bg);color:var(--rte-linkinput);min-width:0;}
|
|
180
|
+
.rte-area{position:relative;background:var(--rte-area-bg);}
|
|
181
|
+
.rte-body{height:200px;overflow-y: auto;outline:none;font-size:15px;line-height:1.75;color:var(--rte-body);caret-color:var(--rte-body);padding:18px 20px;}
|
|
125
182
|
.rte-body h1{font-size:26px;font-weight:600;margin:0.6em 0 0.2em;}
|
|
126
183
|
.rte-body h2{font-size:20px;font-weight:600;margin:0.6em 0 0.2em;}
|
|
127
184
|
.rte-body h3{font-size:16px;font-weight:600;margin:0.6em 0 0.2em;}
|
|
@@ -135,32 +192,26 @@ var CSS = `
|
|
|
135
192
|
.rte-body ul ul ul{list-style-type:square;padding-left:1.6em;}
|
|
136
193
|
.rte-body li{margin:0.1em 0;}
|
|
137
194
|
.rte-body a{color:#1a6fc4;text-decoration:underline;cursor:pointer;}
|
|
138
|
-
.rte-body pre{background
|
|
195
|
+
.rte-body pre{background:var(--rte-pre-bg);border:1px solid var(--rte-pre-border);border-radius:4px;padding:12px 14px;margin:0.6em 0;overflow-x:auto;}
|
|
139
196
|
.rte-body code{font-family:var(--font-mono);font-size:13px;}
|
|
140
197
|
.rte-body:empty:before{content:attr(data-ph);color:#aaa;pointer-events:none;}
|
|
141
198
|
.rte-body table{border-collapse:collapse;width:100%;margin:0.8em 0;}
|
|
142
|
-
.rte-body td,.rte-body th{border:1px solid
|
|
143
|
-
.rte-body th{background
|
|
144
|
-
@media(prefers-color-scheme:dark){.rte-body td,.rte-body th{border-color:#444;}.rte-body th{background:#2a2a2a;}}
|
|
199
|
+
.rte-body td,.rte-body th{border:1px solid var(--rte-table-border);padding:7px 10px;min-width:60px;text-align:left;vertical-align:top;}
|
|
200
|
+
.rte-body th{background:var(--rte-th-bg);font-weight:600;}
|
|
145
201
|
.rte-body td.rte-sel,.rte-body th.rte-sel{background:rgba(26,95,180,0.15)!important;outline:2px solid #1a5fb4;outline-offset:-2px;}
|
|
146
202
|
.rte-body img{max-width:100%;height:auto;display:block;margin:4px 0;cursor:pointer;}
|
|
147
203
|
.rte-body figure{margin:0.8em 0;display:block;overflow:hidden;}
|
|
148
204
|
.rte-body figcaption{font-size:13px;color:#666;text-align:center;padding:4px 0;outline:none;clear:both;display:block;}
|
|
149
205
|
.rte-code{min-height:280px;width:100%;background:#1e1e2e;color:#cdd6f4;font-family:var(--font-mono);font-size:13px;line-height:1.6;padding:18px 20px;border:none;outline:none;resize:vertical;}
|
|
150
|
-
.rte-footer{font-size:11px;color
|
|
151
|
-
|
|
152
|
-
.rte-ie-
|
|
153
|
-
@media(prefers-color-scheme:dark){.rte-ie-panel{background:#222;border-color:#444;}}
|
|
154
|
-
.rte-ie-tabs{display:flex;border-bottom:1px solid #eee;}
|
|
155
|
-
@media(prefers-color-scheme:dark){.rte-ie-tabs{border-color:#333;}}
|
|
206
|
+
.rte-footer{font-size:11px;color:var(--rte-footer);padding:4px 20px 5px;border-top:1px solid var(--rte-footer-border);background:var(--rte-footer-bg);}
|
|
207
|
+
.rte-ie-panel{position:absolute;z-index:52;background:var(--rte-iepanel-bg);border:1px solid var(--rte-iepanel-border);border-radius:8px;box-shadow:0 4px 20px rgba(0,0,0,0.15);width:210px;overflow:hidden;}
|
|
208
|
+
.rte-ie-tabs{display:flex;border-bottom:1px solid var(--rte-ietabs-border);}
|
|
156
209
|
.rte-ie-tab{flex:1;padding:7px 4px;font-size:11px;font-weight:500;background:none;border:none;border-bottom:2px solid transparent;cursor:pointer;color:#888;font-family:var(--font-sans);}
|
|
157
210
|
.rte-ie-tab.active{color:#1a5fb4;border-bottom-color:#1a5fb4;}
|
|
158
|
-
.rte-ie-tab:hover{background
|
|
159
|
-
@media(prefers-color-scheme:dark){.rte-ie-tab:hover{background:#2a2a2a;}}
|
|
211
|
+
.rte-ie-tab:hover{background:var(--rte-ietab-hover-bg);}
|
|
160
212
|
.rte-ie-body{padding:10px;display:flex;flex-direction:column;gap:8px;}
|
|
161
213
|
.rte-ie-label{font-size:10px;color:#888;margin-bottom:3px;font-family:var(--font-sans);}
|
|
162
|
-
.rte-ie-input{width:100%;height:26px;border:1px solid
|
|
163
|
-
@media(prefers-color-scheme:dark){.rte-ie-input{background:#1a1a1a;border-color:#444;color:#ddd;}}
|
|
214
|
+
.rte-ie-input{width:100%;height:26px;border:1px solid var(--rte-ieinput-border);border-radius:4px;padding:0 8px;font-size:11px;outline:none;font-family:var(--font-sans);background:var(--rte-ieinput-bg);color:var(--rte-ieinput);}
|
|
164
215
|
.rte-ie-row{display:flex;gap:4px;}
|
|
165
216
|
.rte-ie-seg-btn{flex:1;height:26px;font-size:11px;border:1px solid #ccc;border-radius:4px;background:transparent;color:#444;cursor:pointer;font-family:var(--font-sans);transition:all 0.1s;}
|
|
166
217
|
.rte-ie-seg-btn.active{background:#d0e4ff;border-color:#1a5fb4;color:#1a5fb4;}
|
|
@@ -170,12 +221,13 @@ var CSS = `
|
|
|
170
221
|
.rte-ie-apply{flex:1;height:26px;background:#1a6fc4;color:#fff;border:none;border-radius:4px;font-size:11px;font-weight:600;cursor:pointer;}
|
|
171
222
|
.rte-ie-remove{flex:1;height:26px;background:#fdecea;color:#c0392b;border:1px solid #f5c6c2;border-radius:4px;font-size:11px;cursor:pointer;}
|
|
172
223
|
.rte-handle{position:absolute;width:10px;height:10px;background:#fff;border:2px solid #1a5fb4;border-radius:2px;pointer-events:all;z-index:53;}
|
|
173
|
-
.
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
224
|
+
.rte-body blockquote{background-color: rgb(245, 243, 255);
|
|
225
|
+
border-left: 4px solid rgb(100, 80, 220);
|
|
226
|
+
margin: 8px 0;
|
|
227
|
+
padding: 10px 16px;
|
|
228
|
+
font-style: italic;
|
|
229
|
+
color: rgb(75, 85, 99);
|
|
230
|
+
border-radius: 0 4px 4px 0;}
|
|
179
231
|
`;
|
|
180
232
|
|
|
181
233
|
// src/rte/utils.ts
|
|
@@ -1150,13 +1202,14 @@ function ImageEditor({ img, containerRef, onClose, onDelete, onChange }) {
|
|
|
1150
1202
|
|
|
1151
1203
|
// src/RichTextEditor.tsx
|
|
1152
1204
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
1153
|
-
function RichTextEditor({ value, onChange, toolbar }) {
|
|
1205
|
+
function RichTextEditor({ value, onChange, toolbar, theme, height, placeholder = "Start typing..." }) {
|
|
1154
1206
|
var _a;
|
|
1155
1207
|
const editorRef = (0, import_react5.useRef)(null);
|
|
1156
1208
|
const editorAreaRef = (0, import_react5.useRef)(null);
|
|
1157
1209
|
const savedRangeRef = (0, import_react5.useRef)(null);
|
|
1158
1210
|
const dragStartCell = (0, import_react5.useRef)(null);
|
|
1159
1211
|
const isDragging = (0, import_react5.useRef)(false);
|
|
1212
|
+
const isMounting = (0, import_react5.useRef)(true);
|
|
1160
1213
|
const [isCode, setIsCode] = (0, import_react5.useState)(false);
|
|
1161
1214
|
const [codeVal, setCodeVal] = (0, import_react5.useState)("");
|
|
1162
1215
|
const [fmt, setFmt] = (0, import_react5.useState)({ block: "p" });
|
|
@@ -1243,7 +1296,9 @@ function RichTextEditor({ value, onChange, toolbar }) {
|
|
|
1243
1296
|
else setLinkInfoFP(null);
|
|
1244
1297
|
const txt = (_b = (_a2 = editorRef.current) == null ? void 0 : _a2.innerText) != null ? _b : "";
|
|
1245
1298
|
setWords(txt.trim() ? txt.trim().split(/\s+/).length : 0);
|
|
1246
|
-
|
|
1299
|
+
if (!isMounting.current) {
|
|
1300
|
+
onChange == null ? void 0 : onChange(sanitizeScriptTags((_d = (_c = editorRef.current) == null ? void 0 : _c.innerHTML) != null ? _d : ""));
|
|
1301
|
+
}
|
|
1247
1302
|
}, [onChange, calcFloat, linkBar, sanitizeScriptTags]);
|
|
1248
1303
|
const fixListInParagraph = (0, import_react5.useCallback)(() => {
|
|
1249
1304
|
var _a2;
|
|
@@ -1681,8 +1736,9 @@ function RichTextEditor({ value, onChange, toolbar }) {
|
|
|
1681
1736
|
(0, import_react5.useEffect)(() => {
|
|
1682
1737
|
if (editorRef.current) {
|
|
1683
1738
|
document.execCommand("defaultParagraphSeparator", false, "p");
|
|
1684
|
-
editorRef.current.innerHTML = sanitizeScriptTags(value != null ? value : "
|
|
1739
|
+
editorRef.current.innerHTML = sanitizeScriptTags(value != null ? value : "");
|
|
1685
1740
|
refresh();
|
|
1741
|
+
isMounting.current = false;
|
|
1686
1742
|
}
|
|
1687
1743
|
}, []);
|
|
1688
1744
|
const canMerge = selCells.length >= 2;
|
|
@@ -1691,7 +1747,7 @@ function RichTextEditor({ value, onChange, toolbar }) {
|
|
|
1691
1747
|
const show = (key) => !toolbar || toolbar.includes(key);
|
|
1692
1748
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { padding: "1rem 0" }, children: [
|
|
1693
1749
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("style", { children: CSS }),
|
|
1694
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className:
|
|
1750
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: `customeditor${theme ? ` rte-${theme}` : ""}`, style: __spreadValues({ border: "1px solid #d8d8d8", borderRadius: 4, boxShadow: "0 1px 3px rgba(0,0,0,0.06)" }, height != null && { maxHeight: "none" }), children: [
|
|
1695
1751
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "rte-toolbar", children: [
|
|
1696
1752
|
!isCode && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
1697
1753
|
show("bold") && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { onClick: () => exec("bold"), title: "Bold (Ctrl+B)", active: fmt.bold, style: { fontWeight: 800, fontFamily: "Georgia,serif" }, children: "B" }),
|
|
@@ -1707,7 +1763,7 @@ function RichTextEditor({ value, onChange, toolbar }) {
|
|
|
1707
1763
|
active: showColor,
|
|
1708
1764
|
style: { flexDirection: "column", gap: 1, padding: "3px 6px" },
|
|
1709
1765
|
children: [
|
|
1710
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { fontSize: 13, fontWeight: 800, fontFamily: "Georgia,serif", lineHeight: 1
|
|
1766
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { fontSize: 13, fontWeight: 800, fontFamily: "Georgia,serif", lineHeight: 1 }, children: "A" }),
|
|
1711
1767
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "rte-swatch", style: { background: color } })
|
|
1712
1768
|
]
|
|
1713
1769
|
}
|
|
@@ -1813,7 +1869,7 @@ function RichTextEditor({ value, onChange, toolbar }) {
|
|
|
1813
1869
|
value: codeVal,
|
|
1814
1870
|
onChange: (e) => setCodeVal(e.target.value),
|
|
1815
1871
|
spellCheck: false,
|
|
1816
|
-
style: { display: isCode ? "block" : "none" }
|
|
1872
|
+
style: __spreadValues({ display: isCode ? "block" : "none" }, height != null && { height, minHeight: 0 })
|
|
1817
1873
|
}
|
|
1818
1874
|
),
|
|
1819
1875
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
@@ -1823,7 +1879,7 @@ function RichTextEditor({ value, onChange, toolbar }) {
|
|
|
1823
1879
|
className: "rte-body",
|
|
1824
1880
|
contentEditable: true,
|
|
1825
1881
|
suppressContentEditableWarning: true,
|
|
1826
|
-
"data-ph":
|
|
1882
|
+
"data-ph": placeholder,
|
|
1827
1883
|
onMouseDown: handleEditorMouseDown,
|
|
1828
1884
|
onMouseMove: handleEditorMouseMove,
|
|
1829
1885
|
onMouseUp: () => {
|
|
@@ -1844,7 +1900,7 @@ function RichTextEditor({ value, onChange, toolbar }) {
|
|
|
1844
1900
|
onDragOver: (e) => {
|
|
1845
1901
|
if (e.dataTransfer.types.includes("Files")) e.preventDefault();
|
|
1846
1902
|
},
|
|
1847
|
-
style: { display: isCode ? "none" : "block" }
|
|
1903
|
+
style: __spreadValues({ display: isCode ? "none" : "block" }, height != null && { height, minHeight: 0 })
|
|
1848
1904
|
}
|
|
1849
1905
|
),
|
|
1850
1906
|
!isCode && selectedImg && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
3
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
4
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
5
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
6
|
+
var __spreadValues = (a, b) => {
|
|
7
|
+
for (var prop in b || (b = {}))
|
|
8
|
+
if (__hasOwnProp.call(b, prop))
|
|
9
|
+
__defNormalProp(a, prop, b[prop]);
|
|
10
|
+
if (__getOwnPropSymbols)
|
|
11
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
12
|
+
if (__propIsEnum.call(b, prop))
|
|
13
|
+
__defNormalProp(a, prop, b[prop]);
|
|
14
|
+
}
|
|
15
|
+
return a;
|
|
16
|
+
};
|
|
17
|
+
|
|
1
18
|
// src/RichTextEditor.tsx
|
|
2
19
|
import {
|
|
3
20
|
useState as useState5,
|
|
@@ -43,64 +60,107 @@ var PALETTE = [
|
|
|
43
60
|
"#20124d",
|
|
44
61
|
"#4c1130"
|
|
45
62
|
];
|
|
63
|
+
var DARK = `
|
|
64
|
+
--rte-toolbar-bg:#1e1e1e;--rte-toolbar-border:#333;
|
|
65
|
+
--rte-btn:#ccc;--rte-btn-hover-bg:#2e2e2e;--rte-btn-active-bg:#1a3a5c;--rte-btn-active:#90c4ff;
|
|
66
|
+
--rte-btn-danger:#ff6b6b;--rte-btn-danger-hover-bg:#3a1a1a;
|
|
67
|
+
--rte-sep:#3a3a3a;
|
|
68
|
+
--rte-select-bg:#2a2a2a;--rte-select-border:#444;--rte-select:#ccc;
|
|
69
|
+
--rte-cpick-bg:#222;--rte-cpick-border:#444;
|
|
70
|
+
--rte-cactions-border:#333;--rte-caction-hover-bg:#2a2a2a;--rte-caction-hover-border:#444;
|
|
71
|
+
--rte-tpick-bg:#222;--rte-tpick-border:#444;
|
|
72
|
+
--rte-tpcell-bg:#2a2a2a;--rte-tpcell-border:#444;--rte-tpcell-on-bg:#1a3a5c;--rte-tpcell-on-border:#90c4ff;
|
|
73
|
+
--rte-ipick-bg:#222;--rte-ipick-border:#444;
|
|
74
|
+
--rte-itabs-border:#333;--rte-itab-hover-bg:#2a2a2a;
|
|
75
|
+
--rte-idrop-border:#555;--rte-idrop-hover-bg:#1a3a5c;--rte-idrop-hover-border:#90c4ff;
|
|
76
|
+
--rte-float-bg:#222;--rte-float-border:#444;--rte-float-arrow-border:#444;--rte-float-arrow-bg:#222;
|
|
77
|
+
--rte-linkinput-bg:#1a1a1a;--rte-linkinput-border:#555;--rte-linkinput:#ddd;
|
|
78
|
+
--rte-area-bg:#141414;
|
|
79
|
+
--rte-body:#ddd;--rte-table-border:#444;--rte-th-bg:#2a2a2a;
|
|
80
|
+
--rte-pre-bg:#1e1e2e;--rte-pre-border:#333;
|
|
81
|
+
--rte-footer-bg:#1a1a1a;--rte-footer-border:#2a2a2a;--rte-footer:#aaa;
|
|
82
|
+
--rte-iepanel-bg:#222;--rte-iepanel-border:#444;
|
|
83
|
+
--rte-ietabs-border:#333;--rte-ietab-hover-bg:#2a2a2a;
|
|
84
|
+
--rte-ieinput-bg:#1a1a1a;--rte-ieinput-border:#444;--rte-ieinput:#ddd;
|
|
85
|
+
`;
|
|
46
86
|
var CSS = `
|
|
47
87
|
*{box-sizing:border-box;}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
88
|
+
|
|
89
|
+
/* \u2500\u2500\u2500 Theme tokens \u2500\u2500\u2500 */
|
|
90
|
+
.customeditor{
|
|
91
|
+
max-height:350px;overflow-y:auto;position:relative;
|
|
92
|
+
/* light (default) */
|
|
93
|
+
--rte-toolbar-bg:#f8f8f8;--rte-toolbar-border:#e0e0e0;
|
|
94
|
+
--rte-btn:#444;--rte-btn-hover-bg:#e8e8e8;--rte-btn-active-bg:#d0e4ff;--rte-btn-active:#1a5fb4;
|
|
95
|
+
--rte-btn-danger:#c0392b;--rte-btn-danger-hover-bg:#fdecea;
|
|
96
|
+
--rte-sep:#d8d8d8;
|
|
97
|
+
--rte-select-bg:#fff;--rte-select-border:#d8d8d8;--rte-select:#333;
|
|
98
|
+
--rte-cpick-bg:#fff;--rte-cpick-border:#ccc;
|
|
99
|
+
--rte-cactions-border:#eee;--rte-caction-hover-bg:#f0f0f0;--rte-caction-hover-border:#ddd;
|
|
100
|
+
--rte-tpick-bg:#fff;--rte-tpick-border:#d8d8d8;
|
|
101
|
+
--rte-tpcell-bg:#fff;--rte-tpcell-border:#ddd;--rte-tpcell-on-bg:#d0e4ff;--rte-tpcell-on-border:#1a5fb4;
|
|
102
|
+
--rte-ipick-bg:#fff;--rte-ipick-border:#ccc;
|
|
103
|
+
--rte-itabs-border:#eee;--rte-itab-hover-bg:#f8f8f8;
|
|
104
|
+
--rte-idrop-border:#ccc;--rte-idrop-hover-bg:#f0f4ff;--rte-idrop-hover-border:#1a5fb4;
|
|
105
|
+
--rte-float-bg:#fff;--rte-float-border:#d0d0d0;--rte-float-arrow-border:#d0d0d0;--rte-float-arrow-bg:#fff;
|
|
106
|
+
--rte-linkinput-bg:#fff;--rte-linkinput-border:#ccc;--rte-linkinput:#222;
|
|
107
|
+
--rte-area-bg:#fff;
|
|
108
|
+
--rte-body:#222;--rte-table-border:#ccc;--rte-th-bg:#f5f5f5;
|
|
109
|
+
--rte-pre-bg:#f4f4f4;--rte-pre-border:#e0e0e0;
|
|
110
|
+
--rte-footer-bg:#fafafa;--rte-footer-border:#e8e8e8;--rte-footer:#999;
|
|
111
|
+
--rte-iepanel-bg:#fff;--rte-iepanel-border:#d0d0d0;
|
|
112
|
+
--rte-ietabs-border:#eee;--rte-ietab-hover-bg:#f8f8f8;
|
|
113
|
+
--rte-ieinput-bg:#fff;--rte-ieinput-border:#ccc;--rte-ieinput:#222;
|
|
114
|
+
}
|
|
115
|
+
/* Explicit dark */
|
|
116
|
+
.customeditor.rte-dark{${DARK}}
|
|
117
|
+
/* OS-level auto dark (ignored when an explicit theme class is present) */
|
|
118
|
+
@media(prefers-color-scheme:dark){
|
|
119
|
+
.customeditor:not(.rte-light):not(.rte-dark){${DARK}}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/* \u2500\u2500\u2500 Component styles \u2500\u2500\u2500 */
|
|
123
|
+
.rte-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:1px;padding:4px 8px;background:var(--rte-toolbar-bg);border-bottom:1px solid var(--rte-toolbar-border);position:sticky;top:0;z-index:9;}
|
|
124
|
+
.rte-btn{background:transparent;border:none;border-radius:3px;cursor:pointer;height:30px;min-width:30px;padding:0 6px;color:var(--rte-btn);font-size:13px;font-weight:500;font-family:var(--font-sans);display:inline-flex;align-items:center;justify-content:center;user-select:none;white-space:nowrap;transition:background 0.1s;flex-shrink:0;}
|
|
125
|
+
.rte-btn:hover{background:var(--rte-btn-hover-bg);}
|
|
126
|
+
.rte-btn.active{background:var(--rte-btn-active-bg);color:var(--rte-btn-active);}
|
|
127
|
+
.rte-btn.danger{color:var(--rte-btn-danger);}
|
|
128
|
+
.rte-btn.danger:hover{background:var(--rte-btn-danger-hover-bg);}
|
|
129
|
+
.rte-sep{width:1px;height:20px;background:var(--rte-sep);margin:0 4px;flex-shrink:0;}
|
|
130
|
+
.rte-select{height:28px;border:1px solid var(--rte-select-border);border-radius:3px;background:var(--rte-select-bg);color:var(--rte-select);font-size:12px;padding:0 22px 0 7px;cursor:pointer;outline:none;font-family:var(--font-sans);appearance:none;-webkit-appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23999'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 6px center;}
|
|
58
131
|
.rte-swatch{width:14px;height:3px;border-radius:1px;margin-top:2px;}
|
|
59
|
-
.rte-cpick{background
|
|
60
|
-
@media(prefers-color-scheme:dark){.rte-cpick{background:#222;border-color:#444;}}
|
|
132
|
+
.rte-cpick{background:var(--rte-cpick-bg);border:1px solid var(--rte-cpick-border);border-radius:8px;box-shadow:0 4px 20px rgba(0,0,0,0.15);padding:8px;min-width:190px;}
|
|
61
133
|
.rte-cgrid{display:grid;grid-template-columns:repeat(8,20px);gap:2px;margin-bottom:6px;}
|
|
62
134
|
.rte-ccell{width:20px;height:20px;border-radius:3px;cursor:pointer;border:1px solid rgba(0,0,0,0.12);transition:transform 0.08s,box-shadow 0.08s;}
|
|
63
135
|
.rte-ccell:hover{transform:scale(1.2);box-shadow:0 1px 4px rgba(0,0,0,0.3);z-index:1;position:relative;}
|
|
64
136
|
.rte-ccell.sel{outline:2px solid #1a5fb4;outline-offset:1px;}
|
|
65
|
-
.rte-cactions{display:flex;align-items:center;gap:2px;border-top:1px solid
|
|
66
|
-
@media(prefers-color-scheme:dark){.rte-cactions{border-color:#333;}}
|
|
137
|
+
.rte-cactions{display:flex;align-items:center;gap:2px;border-top:1px solid var(--rte-cactions-border);padding-top:6px;margin-top:2px;}
|
|
67
138
|
.rte-caction{flex:1;height:28px;display:flex;align-items:center;justify-content:center;border-radius:4px;cursor:pointer;border:1px solid transparent;transition:background 0.1s;}
|
|
68
|
-
.rte-caction:hover{background
|
|
69
|
-
|
|
70
|
-
.rte-tpick{background:#fff;border:1px solid #d8d8d8;border-radius:6px;box-shadow:0 4px 16px rgba(0,0,0,0.12);padding:10px;}
|
|
71
|
-
@media(prefers-color-scheme:dark){.rte-tpick{background:#222;border-color:#444;}}
|
|
139
|
+
.rte-caction:hover{background:var(--rte-caction-hover-bg);border-color:var(--rte-caction-hover-border);}
|
|
140
|
+
.rte-tpick{background:var(--rte-tpick-bg);border:1px solid var(--rte-tpick-border);border-radius:6px;box-shadow:0 4px 16px rgba(0,0,0,0.12);padding:10px;}
|
|
72
141
|
.rte-tplbl{font-size:11px;color:#888;text-align:center;margin-bottom:8px;font-family:var(--font-sans);}
|
|
73
142
|
.rte-tpgrid{display:grid;grid-template-columns:repeat(8,18px);gap:2px;}
|
|
74
|
-
.rte-tpcell{width:18px;height:18px;border-radius:2px;border:1px solid
|
|
75
|
-
.rte-tpcell.on{background
|
|
76
|
-
|
|
77
|
-
.rte-
|
|
78
|
-
@media(prefers-color-scheme:dark){.rte-ipick{background:#222;border-color:#444;}}
|
|
79
|
-
.rte-itabs{display:flex;border-bottom:1px solid #eee;}
|
|
80
|
-
@media(prefers-color-scheme:dark){.rte-itabs{border-color:#333;}}
|
|
143
|
+
.rte-tpcell{width:18px;height:18px;border-radius:2px;border:1px solid var(--rte-tpcell-border);cursor:pointer;background:var(--rte-tpcell-bg);transition:background 0.08s;}
|
|
144
|
+
.rte-tpcell.on{background:var(--rte-tpcell-on-bg);border-color:var(--rte-tpcell-on-border);}
|
|
145
|
+
.rte-ipick{background:var(--rte-ipick-bg);border:1px solid var(--rte-ipick-border);border-radius:8px;box-shadow:0 4px 20px rgba(0,0,0,0.15);width:300px;overflow:hidden;}
|
|
146
|
+
.rte-itabs{display:flex;border-bottom:1px solid var(--rte-itabs-border);}
|
|
81
147
|
.rte-itab{flex:1;padding:8px 4px;font-size:12px;font-weight:500;background:none;border:none;border-bottom:2px solid transparent;cursor:pointer;color:#888;font-family:var(--font-sans);}
|
|
82
|
-
.rte-itab:hover{color:#444;background
|
|
83
|
-
|
|
148
|
+
.rte-itab:hover{color:#444;background:var(--rte-itab-hover-bg);}
|
|
149
|
+
.rte-itab.active{color:#1a5fb4;border-bottom-color:#1a5fb4;}
|
|
84
150
|
.rte-ipbody{padding:12px;display:flex;flex-direction:column;gap:10px;}
|
|
85
|
-
.rte-idrop{border:2px dashed
|
|
86
|
-
.rte-idrop:hover,.rte-idrop.drag{border-color
|
|
87
|
-
@media(prefers-color-scheme:dark){.rte-idrop{border-color:#555;}.rte-idrop:hover,.rte-idrop.drag{background:#1a3a5c;border-color:#90c4ff;}}
|
|
151
|
+
.rte-idrop{border:2px dashed var(--rte-idrop-border);border-radius:6px;padding:24px 12px;text-align:center;cursor:pointer;transition:border-color 0.15s,background 0.15s;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;min-height:110px;}
|
|
152
|
+
.rte-idrop:hover,.rte-idrop.drag{border-color:var(--rte-idrop-hover-border);background:var(--rte-idrop-hover-bg);}
|
|
88
153
|
.rte-iinsert{width:100%;height:30px;background:#1a6fc4;color:#fff;border:none;border-radius:4px;font-size:12px;font-weight:600;cursor:pointer;}
|
|
89
154
|
.rte-iinsert:disabled{opacity:0.4;cursor:not-allowed;}
|
|
90
|
-
.rte-float{position:absolute;z-index:50;background
|
|
91
|
-
@media(prefers-color-scheme:dark){.rte-float{background:#222;border-color:#444;}}
|
|
155
|
+
.rte-float{position:absolute;z-index:50;background:var(--rte-float-bg);border:1px solid var(--rte-float-border);border-radius:8px;box-shadow:0 4px 20px rgba(0,0,0,0.13);padding:4px 6px;display:flex;align-items:center;gap:1px;flex-wrap:wrap;}
|
|
92
156
|
.rte-float-arrow{position:absolute;top:-7px;width:14px;height:7px;}
|
|
93
157
|
.rte-float-arrow::before,.rte-float-arrow::after{content:'';position:absolute;left:0;border-left:7px solid transparent;border-right:7px solid transparent;}
|
|
94
|
-
.rte-float-arrow::before{top:0;border-bottom:7px solid
|
|
95
|
-
.rte-float-arrow::after{top:1px;border-bottom:6px solid
|
|
96
|
-
@media(prefers-color-scheme:dark){.rte-float-arrow::before{border-bottom-color:#444;}.rte-float-arrow::after{border-bottom-color:#222;}}
|
|
158
|
+
.rte-float-arrow::before{top:0;border-bottom:7px solid var(--rte-float-arrow-border);}
|
|
159
|
+
.rte-float-arrow::after{top:1px;border-bottom:6px solid var(--rte-float-arrow-bg);}
|
|
97
160
|
.rte-linkbar{min-width:340px;}
|
|
98
|
-
.rte-linkbar input{flex:1;height:26px;border:1px solid
|
|
99
|
-
|
|
100
|
-
.rte-
|
|
101
|
-
@media(prefers-color-scheme:dark){.rte-area{background:#141414;}}
|
|
102
|
-
.rte-body{min-height:280px;outline:none;font-size:15px;line-height:1.75;color:#222;caret-color:#222;padding:18px 20px;}
|
|
103
|
-
@media(prefers-color-scheme:dark){.rte-body{color:#ddd;caret-color:#ddd;}}
|
|
161
|
+
.rte-linkbar input{flex:1;height:26px;border:1px solid var(--rte-linkinput-border);border-radius:3px;padding:0 8px;font-size:13px;outline:none;font-family:var(--font-sans);background:var(--rte-linkinput-bg);color:var(--rte-linkinput);min-width:0;}
|
|
162
|
+
.rte-area{position:relative;background:var(--rte-area-bg);}
|
|
163
|
+
.rte-body{height:200px;overflow-y: auto;outline:none;font-size:15px;line-height:1.75;color:var(--rte-body);caret-color:var(--rte-body);padding:18px 20px;}
|
|
104
164
|
.rte-body h1{font-size:26px;font-weight:600;margin:0.6em 0 0.2em;}
|
|
105
165
|
.rte-body h2{font-size:20px;font-weight:600;margin:0.6em 0 0.2em;}
|
|
106
166
|
.rte-body h3{font-size:16px;font-weight:600;margin:0.6em 0 0.2em;}
|
|
@@ -114,32 +174,26 @@ var CSS = `
|
|
|
114
174
|
.rte-body ul ul ul{list-style-type:square;padding-left:1.6em;}
|
|
115
175
|
.rte-body li{margin:0.1em 0;}
|
|
116
176
|
.rte-body a{color:#1a6fc4;text-decoration:underline;cursor:pointer;}
|
|
117
|
-
.rte-body pre{background
|
|
177
|
+
.rte-body pre{background:var(--rte-pre-bg);border:1px solid var(--rte-pre-border);border-radius:4px;padding:12px 14px;margin:0.6em 0;overflow-x:auto;}
|
|
118
178
|
.rte-body code{font-family:var(--font-mono);font-size:13px;}
|
|
119
179
|
.rte-body:empty:before{content:attr(data-ph);color:#aaa;pointer-events:none;}
|
|
120
180
|
.rte-body table{border-collapse:collapse;width:100%;margin:0.8em 0;}
|
|
121
|
-
.rte-body td,.rte-body th{border:1px solid
|
|
122
|
-
.rte-body th{background
|
|
123
|
-
@media(prefers-color-scheme:dark){.rte-body td,.rte-body th{border-color:#444;}.rte-body th{background:#2a2a2a;}}
|
|
181
|
+
.rte-body td,.rte-body th{border:1px solid var(--rte-table-border);padding:7px 10px;min-width:60px;text-align:left;vertical-align:top;}
|
|
182
|
+
.rte-body th{background:var(--rte-th-bg);font-weight:600;}
|
|
124
183
|
.rte-body td.rte-sel,.rte-body th.rte-sel{background:rgba(26,95,180,0.15)!important;outline:2px solid #1a5fb4;outline-offset:-2px;}
|
|
125
184
|
.rte-body img{max-width:100%;height:auto;display:block;margin:4px 0;cursor:pointer;}
|
|
126
185
|
.rte-body figure{margin:0.8em 0;display:block;overflow:hidden;}
|
|
127
186
|
.rte-body figcaption{font-size:13px;color:#666;text-align:center;padding:4px 0;outline:none;clear:both;display:block;}
|
|
128
187
|
.rte-code{min-height:280px;width:100%;background:#1e1e2e;color:#cdd6f4;font-family:var(--font-mono);font-size:13px;line-height:1.6;padding:18px 20px;border:none;outline:none;resize:vertical;}
|
|
129
|
-
.rte-footer{font-size:11px;color
|
|
130
|
-
|
|
131
|
-
.rte-ie-
|
|
132
|
-
@media(prefers-color-scheme:dark){.rte-ie-panel{background:#222;border-color:#444;}}
|
|
133
|
-
.rte-ie-tabs{display:flex;border-bottom:1px solid #eee;}
|
|
134
|
-
@media(prefers-color-scheme:dark){.rte-ie-tabs{border-color:#333;}}
|
|
188
|
+
.rte-footer{font-size:11px;color:var(--rte-footer);padding:4px 20px 5px;border-top:1px solid var(--rte-footer-border);background:var(--rte-footer-bg);}
|
|
189
|
+
.rte-ie-panel{position:absolute;z-index:52;background:var(--rte-iepanel-bg);border:1px solid var(--rte-iepanel-border);border-radius:8px;box-shadow:0 4px 20px rgba(0,0,0,0.15);width:210px;overflow:hidden;}
|
|
190
|
+
.rte-ie-tabs{display:flex;border-bottom:1px solid var(--rte-ietabs-border);}
|
|
135
191
|
.rte-ie-tab{flex:1;padding:7px 4px;font-size:11px;font-weight:500;background:none;border:none;border-bottom:2px solid transparent;cursor:pointer;color:#888;font-family:var(--font-sans);}
|
|
136
192
|
.rte-ie-tab.active{color:#1a5fb4;border-bottom-color:#1a5fb4;}
|
|
137
|
-
.rte-ie-tab:hover{background
|
|
138
|
-
@media(prefers-color-scheme:dark){.rte-ie-tab:hover{background:#2a2a2a;}}
|
|
193
|
+
.rte-ie-tab:hover{background:var(--rte-ietab-hover-bg);}
|
|
139
194
|
.rte-ie-body{padding:10px;display:flex;flex-direction:column;gap:8px;}
|
|
140
195
|
.rte-ie-label{font-size:10px;color:#888;margin-bottom:3px;font-family:var(--font-sans);}
|
|
141
|
-
.rte-ie-input{width:100%;height:26px;border:1px solid
|
|
142
|
-
@media(prefers-color-scheme:dark){.rte-ie-input{background:#1a1a1a;border-color:#444;color:#ddd;}}
|
|
196
|
+
.rte-ie-input{width:100%;height:26px;border:1px solid var(--rte-ieinput-border);border-radius:4px;padding:0 8px;font-size:11px;outline:none;font-family:var(--font-sans);background:var(--rte-ieinput-bg);color:var(--rte-ieinput);}
|
|
143
197
|
.rte-ie-row{display:flex;gap:4px;}
|
|
144
198
|
.rte-ie-seg-btn{flex:1;height:26px;font-size:11px;border:1px solid #ccc;border-radius:4px;background:transparent;color:#444;cursor:pointer;font-family:var(--font-sans);transition:all 0.1s;}
|
|
145
199
|
.rte-ie-seg-btn.active{background:#d0e4ff;border-color:#1a5fb4;color:#1a5fb4;}
|
|
@@ -149,12 +203,13 @@ var CSS = `
|
|
|
149
203
|
.rte-ie-apply{flex:1;height:26px;background:#1a6fc4;color:#fff;border:none;border-radius:4px;font-size:11px;font-weight:600;cursor:pointer;}
|
|
150
204
|
.rte-ie-remove{flex:1;height:26px;background:#fdecea;color:#c0392b;border:1px solid #f5c6c2;border-radius:4px;font-size:11px;cursor:pointer;}
|
|
151
205
|
.rte-handle{position:absolute;width:10px;height:10px;background:#fff;border:2px solid #1a5fb4;border-radius:2px;pointer-events:all;z-index:53;}
|
|
152
|
-
.
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
206
|
+
.rte-body blockquote{background-color: rgb(245, 243, 255);
|
|
207
|
+
border-left: 4px solid rgb(100, 80, 220);
|
|
208
|
+
margin: 8px 0;
|
|
209
|
+
padding: 10px 16px;
|
|
210
|
+
font-style: italic;
|
|
211
|
+
color: rgb(75, 85, 99);
|
|
212
|
+
border-radius: 0 4px 4px 0;}
|
|
158
213
|
`;
|
|
159
214
|
|
|
160
215
|
// src/rte/utils.ts
|
|
@@ -1129,13 +1184,14 @@ function ImageEditor({ img, containerRef, onClose, onDelete, onChange }) {
|
|
|
1129
1184
|
|
|
1130
1185
|
// src/RichTextEditor.tsx
|
|
1131
1186
|
import { Fragment as Fragment4, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1132
|
-
function RichTextEditor({ value, onChange, toolbar }) {
|
|
1187
|
+
function RichTextEditor({ value, onChange, toolbar, theme, height, placeholder = "Start typing..." }) {
|
|
1133
1188
|
var _a;
|
|
1134
1189
|
const editorRef = useRef4(null);
|
|
1135
1190
|
const editorAreaRef = useRef4(null);
|
|
1136
1191
|
const savedRangeRef = useRef4(null);
|
|
1137
1192
|
const dragStartCell = useRef4(null);
|
|
1138
1193
|
const isDragging = useRef4(false);
|
|
1194
|
+
const isMounting = useRef4(true);
|
|
1139
1195
|
const [isCode, setIsCode] = useState5(false);
|
|
1140
1196
|
const [codeVal, setCodeVal] = useState5("");
|
|
1141
1197
|
const [fmt, setFmt] = useState5({ block: "p" });
|
|
@@ -1222,7 +1278,9 @@ function RichTextEditor({ value, onChange, toolbar }) {
|
|
|
1222
1278
|
else setLinkInfoFP(null);
|
|
1223
1279
|
const txt = (_b = (_a2 = editorRef.current) == null ? void 0 : _a2.innerText) != null ? _b : "";
|
|
1224
1280
|
setWords(txt.trim() ? txt.trim().split(/\s+/).length : 0);
|
|
1225
|
-
|
|
1281
|
+
if (!isMounting.current) {
|
|
1282
|
+
onChange == null ? void 0 : onChange(sanitizeScriptTags((_d = (_c = editorRef.current) == null ? void 0 : _c.innerHTML) != null ? _d : ""));
|
|
1283
|
+
}
|
|
1226
1284
|
}, [onChange, calcFloat, linkBar, sanitizeScriptTags]);
|
|
1227
1285
|
const fixListInParagraph = useCallback3(() => {
|
|
1228
1286
|
var _a2;
|
|
@@ -1660,8 +1718,9 @@ function RichTextEditor({ value, onChange, toolbar }) {
|
|
|
1660
1718
|
useEffect3(() => {
|
|
1661
1719
|
if (editorRef.current) {
|
|
1662
1720
|
document.execCommand("defaultParagraphSeparator", false, "p");
|
|
1663
|
-
editorRef.current.innerHTML = sanitizeScriptTags(value != null ? value : "
|
|
1721
|
+
editorRef.current.innerHTML = sanitizeScriptTags(value != null ? value : "");
|
|
1664
1722
|
refresh();
|
|
1723
|
+
isMounting.current = false;
|
|
1665
1724
|
}
|
|
1666
1725
|
}, []);
|
|
1667
1726
|
const canMerge = selCells.length >= 2;
|
|
@@ -1670,7 +1729,7 @@ function RichTextEditor({ value, onChange, toolbar }) {
|
|
|
1670
1729
|
const show = (key) => !toolbar || toolbar.includes(key);
|
|
1671
1730
|
return /* @__PURE__ */ jsxs6("div", { style: { padding: "1rem 0" }, children: [
|
|
1672
1731
|
/* @__PURE__ */ jsx7("style", { children: CSS }),
|
|
1673
|
-
/* @__PURE__ */ jsxs6("div", { className:
|
|
1732
|
+
/* @__PURE__ */ jsxs6("div", { className: `customeditor${theme ? ` rte-${theme}` : ""}`, style: __spreadValues({ border: "1px solid #d8d8d8", borderRadius: 4, boxShadow: "0 1px 3px rgba(0,0,0,0.06)" }, height != null && { maxHeight: "none" }), children: [
|
|
1674
1733
|
/* @__PURE__ */ jsxs6("div", { className: "rte-toolbar", children: [
|
|
1675
1734
|
!isCode && /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
1676
1735
|
show("bold") && /* @__PURE__ */ jsx7(Btn, { onClick: () => exec("bold"), title: "Bold (Ctrl+B)", active: fmt.bold, style: { fontWeight: 800, fontFamily: "Georgia,serif" }, children: "B" }),
|
|
@@ -1686,7 +1745,7 @@ function RichTextEditor({ value, onChange, toolbar }) {
|
|
|
1686
1745
|
active: showColor,
|
|
1687
1746
|
style: { flexDirection: "column", gap: 1, padding: "3px 6px" },
|
|
1688
1747
|
children: [
|
|
1689
|
-
/* @__PURE__ */ jsx7("span", { style: { fontSize: 13, fontWeight: 800, fontFamily: "Georgia,serif", lineHeight: 1
|
|
1748
|
+
/* @__PURE__ */ jsx7("span", { style: { fontSize: 13, fontWeight: 800, fontFamily: "Georgia,serif", lineHeight: 1 }, children: "A" }),
|
|
1690
1749
|
/* @__PURE__ */ jsx7("span", { className: "rte-swatch", style: { background: color } })
|
|
1691
1750
|
]
|
|
1692
1751
|
}
|
|
@@ -1792,7 +1851,7 @@ function RichTextEditor({ value, onChange, toolbar }) {
|
|
|
1792
1851
|
value: codeVal,
|
|
1793
1852
|
onChange: (e) => setCodeVal(e.target.value),
|
|
1794
1853
|
spellCheck: false,
|
|
1795
|
-
style: { display: isCode ? "block" : "none" }
|
|
1854
|
+
style: __spreadValues({ display: isCode ? "block" : "none" }, height != null && { height, minHeight: 0 })
|
|
1796
1855
|
}
|
|
1797
1856
|
),
|
|
1798
1857
|
/* @__PURE__ */ jsx7(
|
|
@@ -1802,7 +1861,7 @@ function RichTextEditor({ value, onChange, toolbar }) {
|
|
|
1802
1861
|
className: "rte-body",
|
|
1803
1862
|
contentEditable: true,
|
|
1804
1863
|
suppressContentEditableWarning: true,
|
|
1805
|
-
"data-ph":
|
|
1864
|
+
"data-ph": placeholder,
|
|
1806
1865
|
onMouseDown: handleEditorMouseDown,
|
|
1807
1866
|
onMouseMove: handleEditorMouseMove,
|
|
1808
1867
|
onMouseUp: () => {
|
|
@@ -1823,7 +1882,7 @@ function RichTextEditor({ value, onChange, toolbar }) {
|
|
|
1823
1882
|
onDragOver: (e) => {
|
|
1824
1883
|
if (e.dataTransfer.types.includes("Files")) e.preventDefault();
|
|
1825
1884
|
},
|
|
1826
|
-
style: { display: isCode ? "none" : "block" }
|
|
1885
|
+
style: __spreadValues({ display: isCode ? "none" : "block" }, height != null && { height, minHeight: 0 })
|
|
1827
1886
|
}
|
|
1828
1887
|
),
|
|
1829
1888
|
!isCode && selectedImg && /* @__PURE__ */ jsx7(
|