@malaya_jeeva/rich-text-editor 1.0.5 → 1.0.7

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/dist/index.js CHANGED
@@ -20,13 +20,159 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
- RichTextEditor: () => RichTextEditor
23
+ default: () => RichTextEditor
24
24
  });
25
25
  module.exports = __toCommonJS(index_exports);
26
26
 
27
27
  // src/RichTextEditor.tsx
28
- var import_react = require("react");
29
- var import_jsx_runtime = require("react/jsx-runtime");
28
+ var import_react5 = require("react");
29
+
30
+ // src/rte/constants.ts
31
+ var PALETTE = [
32
+ "#000000",
33
+ "#434343",
34
+ "#666666",
35
+ "#999999",
36
+ "#b7b7b7",
37
+ "#cccccc",
38
+ "#d9d9d9",
39
+ "#ffffff",
40
+ "#ff0000",
41
+ "#ff4500",
42
+ "#ff9900",
43
+ "#ffff00",
44
+ "#00ff00",
45
+ "#00ffff",
46
+ "#4a86e8",
47
+ "#0000ff",
48
+ "#9900ff",
49
+ "#ff00ff",
50
+ "#e06666",
51
+ "#f6b26b",
52
+ "#ffd966",
53
+ "#93c47d",
54
+ "#76a5af",
55
+ "#6fa8dc",
56
+ "#8e7cc3",
57
+ "#c27ba0",
58
+ "#a61c00",
59
+ "#783f04",
60
+ "#7f6000",
61
+ "#274e13",
62
+ "#0c343d",
63
+ "#073763",
64
+ "#20124d",
65
+ "#4c1130"
66
+ ];
67
+ var CSS = `
68
+ *{box-sizing:border-box;}
69
+ .rte-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:1px;padding:4px 8px;background:#f8f8f8;border-bottom:1px solid #e0e0e0;}
70
+ @media(prefers-color-scheme:dark){.rte-toolbar{background:#1e1e1e;border-color:#333;}}
71
+ .rte-btn{background:transparent;border:none;border-radius:3px;cursor:pointer;height:30px;min-width:30px;padding:0 6px;color:#444;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;}
72
+ .rte-btn:hover{background:#e8e8e8;}.rte-btn.active{background:#d0e4ff;color:#1a5fb4;}
73
+ .rte-btn.danger{color:#c0392b;}.rte-btn.danger:hover{background:#fdecea;}
74
+ @media(prefers-color-scheme:dark){.rte-btn{color:#ccc;}.rte-btn:hover{background:#2e2e2e;}.rte-btn.active{background:#1a3a5c;color:#90c4ff;}.rte-btn.danger{color:#ff6b6b;}.rte-btn.danger:hover{background:#3a1a1a;}}
75
+ .rte-sep{width:1px;height:20px;background:#d8d8d8;margin:0 4px;flex-shrink:0;}
76
+ @media(prefers-color-scheme:dark){.rte-sep{background:#3a3a3a;}}
77
+ .rte-select{height:28px;border:1px solid #d8d8d8;border-radius:3px;background:#fff;color:#333;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;}
78
+ @media(prefers-color-scheme:dark){.rte-select{background-color:#2a2a2a;border-color:#444;color:#ccc;}}
79
+ .rte-swatch{width:14px;height:3px;border-radius:1px;margin-top:2px;}
80
+ .rte-cpick{background:#fff;border:1px solid #ccc;border-radius:8px;box-shadow:0 4px 20px rgba(0,0,0,0.15);padding:8px;min-width:190px;}
81
+ @media(prefers-color-scheme:dark){.rte-cpick{background:#222;border-color:#444;}}
82
+ .rte-cgrid{display:grid;grid-template-columns:repeat(8,20px);gap:2px;margin-bottom:6px;}
83
+ .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
+ .rte-ccell:hover{transform:scale(1.2);box-shadow:0 1px 4px rgba(0,0,0,0.3);z-index:1;position:relative;}
85
+ .rte-ccell.sel{outline:2px solid #1a5fb4;outline-offset:1px;}
86
+ .rte-cactions{display:flex;align-items:center;gap:2px;border-top:1px solid #eee;padding-top:6px;margin-top:2px;}
87
+ @media(prefers-color-scheme:dark){.rte-cactions{border-color:#333;}}
88
+ .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:#f0f0f0;border-color:#ddd;}
90
+ @media(prefers-color-scheme:dark){.rte-caction:hover{background:#2a2a2a;border-color:#444;}}
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;}}
93
+ .rte-tplbl{font-size:11px;color:#888;text-align:center;margin-bottom:8px;font-family:var(--font-sans);}
94
+ .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 #ddd;cursor:pointer;background:#fff;transition:background 0.08s;}
96
+ .rte-tpcell.on{background:#d0e4ff;border-color:#1a5fb4;}
97
+ @media(prefers-color-scheme:dark){.rte-tpcell{background:#2a2a2a;border-color:#444;}.rte-tpcell.on{background:#1a3a5c;border-color:#90c4ff;}}
98
+ .rte-ipick{background:#fff;border:1px solid #ccc;border-radius:8px;box-shadow:0 4px 20px rgba(0,0,0,0.15);width:300px;overflow:hidden;}
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;}}
102
+ .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:#f8f8f8;}.rte-itab.active{color:#1a5fb4;border-bottom-color:#1a5fb4;}
104
+ @media(prefers-color-scheme:dark){.rte-itab:hover{background:#2a2a2a;}}
105
+ .rte-ipbody{padding:12px;display:flex;flex-direction:column;gap:10px;}
106
+ .rte-idrop{border:2px dashed #ccc;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;}
107
+ .rte-idrop:hover,.rte-idrop.drag{border-color:#1a5fb4;background:#f0f4ff;}
108
+ @media(prefers-color-scheme:dark){.rte-idrop{border-color:#555;}.rte-idrop:hover,.rte-idrop.drag{background:#1a3a5c;border-color:#90c4ff;}}
109
+ .rte-iinsert{width:100%;height:30px;background:#1a6fc4;color:#fff;border:none;border-radius:4px;font-size:12px;font-weight:600;cursor:pointer;}
110
+ .rte-iinsert:disabled{opacity:0.4;cursor:not-allowed;}
111
+ .rte-float{position:absolute;z-index:50;background:#fff;border:1px solid #d0d0d0;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;}
112
+ @media(prefers-color-scheme:dark){.rte-float{background:#222;border-color:#444;}}
113
+ .rte-float-arrow{position:absolute;top:-7px;width:14px;height:7px;}
114
+ .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 #d0d0d0;}
116
+ .rte-float-arrow::after{top:1px;border-bottom:6px solid #fff;}
117
+ @media(prefers-color-scheme:dark){.rte-float-arrow::before{border-bottom-color:#444;}.rte-float-arrow::after{border-bottom-color:#222;}}
118
+ .rte-linkbar{min-width:340px;}
119
+ .rte-linkbar input{flex:1;height:26px;border:1px solid #ccc;border-radius:3px;padding:0 8px;font-size:13px;outline:none;font-family:var(--font-sans);background:#fff;color:#222;min-width:0;}
120
+ @media(prefers-color-scheme:dark){.rte-linkbar input{background:#1a1a1a;border-color:#555;color:#ddd;}}
121
+ .rte-area{position:relative;background:#fff;}
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;}}
125
+ .rte-body h1{font-size:26px;font-weight:600;margin:0.6em 0 0.2em;}
126
+ .rte-body h2{font-size:20px;font-weight:600;margin:0.6em 0 0.2em;}
127
+ .rte-body h3{font-size:16px;font-weight:600;margin:0.6em 0 0.2em;}
128
+ .rte-body p{margin:0.2em 0;}
129
+ .rte-body ol{list-style-type:decimal;padding-left:1.6em;margin:0.3em 0;}
130
+ .rte-body ol ol{list-style-type:lower-alpha;padding-left:1.6em;}
131
+ .rte-body ol ol ol{list-style-type:lower-roman;padding-left:1.6em;}
132
+ .rte-body ol ol ol ol{list-style-type:decimal;padding-left:1.6em;}
133
+ .rte-body ul{list-style-type:disc;padding-left:1.6em;margin:0.3em 0;}
134
+ .rte-body ul ul{list-style-type:circle;padding-left:1.6em;}
135
+ .rte-body ul ul ul{list-style-type:square;padding-left:1.6em;}
136
+ .rte-body li{margin:0.1em 0;}
137
+ .rte-body a{color:#1a6fc4;text-decoration:underline;cursor:pointer;}
138
+ .rte-body pre{background:#f4f4f4;border:1px solid #e0e0e0;border-radius:4px;padding:12px 14px;margin:0.6em 0;overflow-x:auto;}
139
+ .rte-body code{font-family:var(--font-mono);font-size:13px;}
140
+ .rte-body:empty:before{content:attr(data-ph);color:#aaa;pointer-events:none;}
141
+ .rte-body table{border-collapse:collapse;width:100%;margin:0.8em 0;}
142
+ .rte-body td,.rte-body th{border:1px solid #ccc;padding:7px 10px;min-width:60px;text-align:left;vertical-align:top;}
143
+ .rte-body th{background:#f5f5f5;font-weight:600;}
144
+ @media(prefers-color-scheme:dark){.rte-body td,.rte-body th{border-color:#444;}.rte-body th{background:#2a2a2a;}}
145
+ .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
+ .rte-body img{max-width:100%;height:auto;display:block;margin:4px 0;cursor:pointer;}
147
+ .rte-body figure{margin:0.8em 0;display:block;overflow:hidden;}
148
+ .rte-body figcaption{font-size:13px;color:#666;text-align:center;padding:4px 0;outline:none;clear:both;display:block;}
149
+ .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:#999;padding:4px 20px 5px;border-top:1px solid #e8e8e8;background:#fafafa;}
151
+ @media(prefers-color-scheme:dark){.rte-footer{border-color:#2a2a2a;background:#1a1a1a;color:#555;}}
152
+ .rte-ie-panel{position:absolute;z-index:52;background:#fff;border:1px solid #d0d0d0;border-radius:8px;box-shadow:0 4px 20px rgba(0,0,0,0.15);width:210px;overflow:hidden;}
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;}}
156
+ .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
+ .rte-ie-tab.active{color:#1a5fb4;border-bottom-color:#1a5fb4;}
158
+ .rte-ie-tab:hover{background:#f8f8f8;}
159
+ @media(prefers-color-scheme:dark){.rte-ie-tab:hover{background:#2a2a2a;}}
160
+ .rte-ie-body{padding:10px;display:flex;flex-direction:column;gap:8px;}
161
+ .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 #ccc;border-radius:4px;padding:0 8px;font-size:11px;outline:none;font-family:var(--font-sans);background:#fff;color:#222;}
163
+ @media(prefers-color-scheme:dark){.rte-ie-input{background:#1a1a1a;border-color:#444;color:#ddd;}}
164
+ .rte-ie-row{display:flex;gap:4px;}
165
+ .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
+ .rte-ie-seg-btn.active{background:#d0e4ff;border-color:#1a5fb4;color:#1a5fb4;}
167
+ .rte-ie-preset{flex:1;height:22px;font-size:10px;border:1px solid #ccc;border-radius:3px;background:transparent;cursor:pointer;font-family:var(--font-sans);}
168
+ .rte-ie-preset:hover{background:#e8e8e8;}
169
+ .rte-ie-delete{width:100%;height:28px;background:#fdecea;color:#c0392b;border:1px solid #f5c6c2;border-radius:4px;font-size:11px;font-weight:600;cursor:pointer;font-family:var(--font-sans);}
170
+ .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
+ .rte-ie-remove{flex:1;height:26px;background:#fdecea;color:#c0392b;border:1px solid #f5c6c2;border-radius:4px;font-size:11px;cursor:pointer;}
172
+ .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
+ // src/rte/utils.ts
30
176
  function hsv2rgb(h, s, v) {
31
177
  const f = (n) => {
32
178
  const k = (n + h / 60) % 6;
@@ -64,135 +210,105 @@ function getColorAtCursor(editor) {
64
210
  const c = (_b = el.style) == null ? void 0 : _b.color;
65
211
  if (c) {
66
212
  const m = c.match(/\d+/g);
67
- if (m && m.length >= 3) return "#" + m.slice(0, 3).map((n) => parseInt(n).toString(16).padStart(2, "0")).join("");
213
+ if (m && m.length >= 3)
214
+ return "#" + m.slice(0, 3).map((n) => parseInt(n).toString(16).padStart(2, "0")).join("");
68
215
  if (c.startsWith("#")) return c;
69
216
  }
70
217
  el = el.parentElement;
71
218
  }
72
219
  return "#000000";
73
220
  }
74
- var PALETTE = [
75
- "#000000",
76
- "#434343",
77
- "#666666",
78
- "#999999",
79
- "#b7b7b7",
80
- "#cccccc",
81
- "#d9d9d9",
82
- "#ffffff",
83
- "#ff0000",
84
- "#ff4500",
85
- "#ff9900",
86
- "#ffff00",
87
- "#00ff00",
88
- "#00ffff",
89
- "#4a86e8",
90
- "#0000ff",
91
- "#9900ff",
92
- "#ff00ff",
93
- "#e06666",
94
- "#f6b26b",
95
- "#ffd966",
96
- "#93c47d",
97
- "#76a5af",
98
- "#6fa8dc",
99
- "#8e7cc3",
100
- "#c27ba0",
101
- "#a61c00",
102
- "#783f04",
103
- "#7f6000",
104
- "#274e13",
105
- "#0c343d",
106
- "#073763",
107
- "#20124d",
108
- "#4c1130"
109
- ];
110
- var CSS = `
111
- * { box-sizing: border-box; }
112
- .rte-toolbar { display:flex; flex-wrap:wrap; align-items:center; gap:1px; padding:4px 8px; background:#f8f8f8; border-bottom:1px solid #e0e0e0; }
113
- @media(prefers-color-scheme:dark){ .rte-toolbar{background:#1e1e1e;border-color:#333;} }
114
- .rte-btn { background:transparent; border:none; border-radius:3px; cursor:pointer; height:30px; min-width:30px; padding:0 6px; color:#444; 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; }
115
- .rte-btn:hover { background:#e8e8e8; }
116
- .rte-btn.active { background:#d0e4ff; color:#1a5fb4; }
117
- .rte-btn.danger { color:#c0392b; } .rte-btn.danger:hover { background:#fdecea; }
118
- @media(prefers-color-scheme:dark){ .rte-btn{color:#ccc;} .rte-btn:hover{background:#2e2e2e;} .rte-btn.active{background:#1a3a5c;color:#90c4ff;} .rte-btn.danger{color:#ff6b6b;} .rte-btn.danger:hover{background:#3a1a1a;} }
119
- .rte-sep { width:1px; height:20px; background:#d8d8d8; margin:0 4px; flex-shrink:0; }
120
- @media(prefers-color-scheme:dark){ .rte-sep{background:#3a3a3a;} }
121
- .rte-select { height:28px; border:1px solid #d8d8d8; border-radius:3px; background:#fff; color:#333; 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; }
122
- @media(prefers-color-scheme:dark){ .rte-select{background-color:#2a2a2a;border-color:#444;color:#ccc;} }
123
- .rte-swatch { width:14px; height:3px; border-radius:1px; margin-top:2px; }
124
- .rte-cpick { background:#fff; border:1px solid #ccc; border-radius:8px; box-shadow:0 4px 20px rgba(0,0,0,0.15); padding:8px; min-width:190px; }
125
- @media(prefers-color-scheme:dark){ .rte-cpick{background:#222;border-color:#444;} }
126
- .rte-cgrid { display:grid; grid-template-columns:repeat(8,20px); gap:2px; margin-bottom:6px; }
127
- .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; }
128
- .rte-ccell:hover { transform:scale(1.2); box-shadow:0 1px 4px rgba(0,0,0,0.3); z-index:1; position:relative; }
129
- .rte-ccell.sel { outline:2px solid #1a5fb4; outline-offset:1px; }
130
- .rte-cactions { display:flex; align-items:center; gap:2px; border-top:1px solid #eee; padding-top:6px; margin-top:2px; }
131
- @media(prefers-color-scheme:dark){ .rte-cactions{border-color:#333;} }
132
- .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; }
133
- .rte-caction:hover { background:#f0f0f0; border-color:#ddd; }
134
- @media(prefers-color-scheme:dark){ .rte-caction:hover{background:#2a2a2a;border-color:#444;} }
135
- .rte-tpick { background:#fff; border:1px solid #d8d8d8; border-radius:6px; box-shadow:0 4px 16px rgba(0,0,0,0.12); padding:10px; }
136
- @media(prefers-color-scheme:dark){ .rte-tpick{background:#222;border-color:#444;} }
137
- .rte-tplbl { font-size:11px; color:#888; text-align:center; margin-bottom:8px; font-family:var(--font-sans); }
138
- .rte-tpgrid { display:grid; grid-template-columns:repeat(8,18px); gap:2px; }
139
- .rte-tpcell { width:18px; height:18px; border-radius:2px; border:1px solid #ddd; cursor:pointer; background:#fff; transition:background 0.08s; }
140
- .rte-tpcell.on { background:#d0e4ff; border-color:#1a5fb4; }
141
- @media(prefers-color-scheme:dark){ .rte-tpcell{background:#2a2a2a;border-color:#444;} .rte-tpcell.on{background:#1a3a5c;border-color:#90c4ff;} }
142
- .rte-ipick { background:#fff; border:1px solid #ccc; border-radius:8px; box-shadow:0 4px 20px rgba(0,0,0,0.15); width:300px; overflow:hidden; }
143
- @media(prefers-color-scheme:dark){ .rte-ipick{background:#222;border-color:#444;} }
144
- .rte-itabs { display:flex; border-bottom:1px solid #eee; }
145
- @media(prefers-color-scheme:dark){ .rte-itabs{border-color:#333;} }
146
- .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); }
147
- .rte-itab:hover { color:#444; background:#f8f8f8; }
148
- .rte-itab.active { color:#1a5fb4; border-bottom-color:#1a5fb4; }
149
- @media(prefers-color-scheme:dark){ .rte-itab:hover{background:#2a2a2a;} }
150
- .rte-ipbody { padding:12px; display:flex; flex-direction:column; gap:10px; }
151
- .rte-idrop { border:2px dashed #ccc; 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:#1a5fb4; background:#f0f4ff; }
153
- @media(prefers-color-scheme:dark){ .rte-idrop{border-color:#555;} .rte-idrop:hover,.rte-idrop.drag{background:#1a3a5c;border-color:#90c4ff;} }
154
- .rte-iinsert { width:100%; height:30px; background:#1a6fc4; color:#fff; border:none; border-radius:4px; font-size:12px; font-weight:600; cursor:pointer; }
155
- .rte-iinsert:disabled { opacity:0.4; cursor:not-allowed; }
156
- .rte-float { position:absolute; z-index:50; background:#fff; border:1px solid #d0d0d0; 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; }
157
- @media(prefers-color-scheme:dark){ .rte-float{background:#222;border-color:#444;} }
158
- .rte-float-arrow { position:absolute; top:-7px; width:14px; height:7px; }
159
- .rte-float-arrow::before,.rte-float-arrow::after { content:''; position:absolute; left:0; border-left:7px solid transparent; border-right:7px solid transparent; }
160
- .rte-float-arrow::before { top:0; border-bottom:7px solid #d0d0d0; }
161
- .rte-float-arrow::after { top:1px; border-bottom:6px solid #fff; }
162
- @media(prefers-color-scheme:dark){ .rte-float-arrow::before{border-bottom-color:#444;} .rte-float-arrow::after{border-bottom-color:#222;} }
163
- .rte-linkbar { min-width:340px; }
164
- .rte-linkbar input { flex:1; height:26px; border:1px solid #ccc; border-radius:3px; padding:0 8px; font-size:13px; outline:none; font-family:var(--font-sans); background:#fff; color:#222; min-width:0; }
165
- @media(prefers-color-scheme:dark){ .rte-linkbar input{background:#1a1a1a;border-color:#555;color:#ddd;} }
166
- .rte-area { position:relative; background:#fff; }
167
- @media(prefers-color-scheme:dark){ .rte-area{background:#141414;} }
168
- .rte-body { min-height:280px; outline:none; font-size:15px; line-height:1.75; color:#222; caret-color:#222; padding:18px 20px; }
169
- @media(prefers-color-scheme:dark){ .rte-body{color:#ddd;caret-color:#ddd;} }
170
- .rte-body h1 { font-size:26px; font-weight:600; margin:0.6em 0 0.2em; }
171
- .rte-body h2 { font-size:20px; font-weight:600; margin:0.6em 0 0.2em; }
172
- .rte-body h3 { font-size:16px; font-weight:600; margin:0.6em 0 0.2em; }
173
- .rte-body p { margin:0.2em 0; }
174
- .rte-body ol { list-style-type:decimal; padding-left:1.6em; margin:0.3em 0; }
175
- .rte-body ol ol { list-style-type:lower-alpha; padding-left:1.6em; }
176
- .rte-body ol ol ol { list-style-type:lower-roman; padding-left:1.6em; }
177
- .rte-body ul { list-style-type:disc; padding-left:1.6em; margin:0.3em 0; }
178
- .rte-body ul ul { list-style-type:circle; padding-left:1.6em; }
179
- .rte-body ul ul ul { list-style-type:square; padding-left:1.6em; }
180
- .rte-body li { margin:0.1em 0; }
181
- .rte-body a { color:#1a6fc4; text-decoration:underline; cursor:pointer; }
182
- .rte-body pre { background:#f4f4f4; border:1px solid #e0e0e0; border-radius:4px; padding:12px 14px; margin:0.6em 0; overflow-x:auto; }
183
- .rte-body code { font-family:var(--font-mono); font-size:13px; }
184
- .rte-body:empty:before { content:attr(data-ph); color:#aaa; pointer-events:none; }
185
- .rte-body table { border-collapse:collapse; width:100%; margin:0.8em 0; }
186
- .rte-body td,.rte-body th { border:1px solid #ccc; padding:7px 10px; min-width:60px; text-align:left; vertical-align:top; }
187
- .rte-body th { background:#f5f5f5; font-weight:600; }
188
- @media(prefers-color-scheme:dark){ .rte-body td,.rte-body th{border-color:#444;} .rte-body th{background:#2a2a2a;} }
189
- .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; }
190
- .rte-body img { max-width:100%; height:auto; display:block; margin:4px 0; cursor:pointer; }
191
- .rte-body img.rte-img-sel { outline:2px solid #1a5fb4; outline-offset:2px; }
192
- .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; }
193
- .rte-footer { font-size:11px; color:#999; padding:4px 20px 5px; border-top:1px solid #e8e8e8; background:#fafafa; }
194
- @media(prefers-color-scheme:dark){ .rte-footer{border-color:#2a2a2a;background:#1a1a1a;color:#555;} }
195
- `;
221
+ function prettifyHtml(html) {
222
+ const INLINE = /* @__PURE__ */ new Set(["a", "b", "i", "u", "em", "strong", "span", "code", "br", "small", "sub", "sup"]);
223
+ let indent = 0;
224
+ const pad = () => " ".repeat(indent);
225
+ const tokens = html.replace(/>\s+</g, "><").replace(/(<\/?[^>]+>)/g, "\0$1\0").split("\0").filter(Boolean);
226
+ const lines = [];
227
+ let inline = "";
228
+ const flush = () => {
229
+ if (inline.trim()) {
230
+ lines.push(pad() + inline.trim());
231
+ inline = "";
232
+ }
233
+ };
234
+ for (const tok of tokens) {
235
+ const ot = tok.match(/^<([a-zA-Z][a-zA-Z0-9]*)[^>]*>$/);
236
+ const ct = tok.match(/^<\/([a-zA-Z][a-zA-Z0-9]*)>$/);
237
+ if (tok.match(/^<[^>]+\/>$/)) {
238
+ flush();
239
+ lines.push(pad() + tok);
240
+ continue;
241
+ }
242
+ if (ot) {
243
+ const tag = ot[1].toLowerCase();
244
+ if (INLINE.has(tag)) {
245
+ inline += tok;
246
+ continue;
247
+ }
248
+ flush();
249
+ lines.push(pad() + tok);
250
+ indent++;
251
+ continue;
252
+ }
253
+ if (ct) {
254
+ const tag = ct[1].toLowerCase();
255
+ if (INLINE.has(tag)) {
256
+ inline += tok;
257
+ continue;
258
+ }
259
+ flush();
260
+ indent = Math.max(0, indent - 1);
261
+ const prev = lines[lines.length - 1];
262
+ prev && prev.trim().startsWith("<") && !prev.includes("</") ? lines[lines.length - 1] = prev + tok : lines.push(pad() + tok);
263
+ continue;
264
+ }
265
+ inline += tok;
266
+ }
267
+ flush();
268
+ return lines.join("\n");
269
+ }
270
+ function getCurrentCell() {
271
+ var _a;
272
+ const node = (_a = window.getSelection()) == null ? void 0 : _a.anchorNode;
273
+ const el = (node == null ? void 0 : node.nodeType) === 1 ? node : node == null ? void 0 : node.parentElement;
274
+ return el == null ? void 0 : el.closest("td, th");
275
+ }
276
+ function getCurrentTable() {
277
+ var _a;
278
+ return (_a = getCurrentCell()) == null ? void 0 : _a.closest("table");
279
+ }
280
+ function getCurrentLink() {
281
+ var _a;
282
+ const node = (_a = window.getSelection()) == null ? void 0 : _a.anchorNode;
283
+ const el = (node == null ? void 0 : node.nodeType) === 1 ? node : node == null ? void 0 : node.parentElement;
284
+ return el == null ? void 0 : el.closest("a");
285
+ }
286
+ function getCellCoords(table, cell) {
287
+ for (let r = 0; r < table.rows.length; r++) {
288
+ const cells = Array.from(table.rows[r].cells);
289
+ for (let c = 0; c < cells.length; c++) {
290
+ if (cells[c] === cell) return [r, c];
291
+ }
292
+ }
293
+ return null;
294
+ }
295
+ function getCellsInRange(table, a, b) {
296
+ const ca = getCellCoords(table, a), cb = getCellCoords(table, b);
297
+ if (!ca || !cb) return [a];
298
+ const [r1, c1] = [Math.min(ca[0], cb[0]), Math.min(ca[1], cb[1])];
299
+ const [r2, c2] = [Math.max(ca[0], cb[0]), Math.max(ca[1], cb[1])];
300
+ const result = [];
301
+ Array.from(table.rows).forEach((row, ri) => {
302
+ if (ri >= r1 && ri <= r2)
303
+ Array.from(row.cells).forEach((cell, ci) => {
304
+ if (ci >= c1 && ci <= c2) result.push(cell);
305
+ });
306
+ });
307
+ return result;
308
+ }
309
+
310
+ // src/rte/Btn.tsx
311
+ var import_jsx_runtime = require("react/jsx-runtime");
196
312
  function Btn({ onClick, title, active, danger, children, style }) {
197
313
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
198
314
  "button",
@@ -211,6 +327,162 @@ function Btn({ onClick, title, active, danger, children, style }) {
211
327
  function Sep() {
212
328
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rte-sep" });
213
329
  }
330
+
331
+ // src/rte/Icons.tsx
332
+ var import_jsx_runtime2 = require("react/jsx-runtime");
333
+ function IcoUL() {
334
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: "15", height: "15", viewBox: "0 0 15 15", fill: "none", children: [
335
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "2", cy: "4", r: "1.3", fill: "currentColor" }),
336
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "2", cy: "8", r: "1.3", fill: "currentColor" }),
337
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "2", cy: "12", r: "1.3", fill: "currentColor" }),
338
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "5.5", y: "3.2", width: "8.5", height: "1.6", rx: ".8", fill: "currentColor" }),
339
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "5.5", y: "7.2", width: "8.5", height: "1.6", rx: ".8", fill: "currentColor" }),
340
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "5.5", y: "11.2", width: "8.5", height: "1.6", rx: ".8", fill: "currentColor" })
341
+ ] });
342
+ }
343
+ function IcoOL() {
344
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: "15", height: "15", viewBox: "0 0 15 15", fill: "none", children: [
345
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("text", { x: "0", y: "5", fontSize: "5.5", fill: "currentColor", fontFamily: "monospace", children: "1." }),
346
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("text", { x: "0", y: "9.5", fontSize: "5.5", fill: "currentColor", fontFamily: "monospace", children: "2." }),
347
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("text", { x: "0", y: "14", fontSize: "5.5", fill: "currentColor", fontFamily: "monospace", children: "3." }),
348
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "5.5", y: "3.2", width: "8.5", height: "1.6", rx: ".8", fill: "currentColor" }),
349
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "5.5", y: "7.2", width: "8.5", height: "1.6", rx: ".8", fill: "currentColor" }),
350
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "5.5", y: "11.2", width: "8.5", height: "1.6", rx: ".8", fill: "currentColor" })
351
+ ] });
352
+ }
353
+ function IcoIndent() {
354
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: "15", height: "15", viewBox: "0 0 15 15", fill: "none", children: [
355
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "1", y: "2", width: "13", height: "1.6", rx: ".8", fill: "currentColor" }),
356
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "4.5", y: "6", width: "9.5", height: "1.6", rx: ".8", fill: "currentColor" }),
357
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "4.5", y: "10", width: "9.5", height: "1.6", rx: ".8", fill: "currentColor" }),
358
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M1 6.5L3.5 8.25L1 10V6.5Z", fill: "currentColor" })
359
+ ] });
360
+ }
361
+ function IcoOutdent() {
362
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: "15", height: "15", viewBox: "0 0 15 15", fill: "none", children: [
363
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "1", y: "2", width: "13", height: "1.6", rx: ".8", fill: "currentColor" }),
364
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "4.5", y: "6", width: "9.5", height: "1.6", rx: ".8", fill: "currentColor" }),
365
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "4.5", y: "10", width: "9.5", height: "1.6", rx: ".8", fill: "currentColor" }),
366
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M3.5 6.5L1 8.25L3.5 10V6.5Z", fill: "currentColor" })
367
+ ] });
368
+ }
369
+ function IcoLink() {
370
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: "15", height: "15", viewBox: "0 0 15 15", fill: "none", children: [
371
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M6 9C6.4 9.6 7.1 10 7.8 10H9.8C10.6 10 11.4 9.6 11.9 9C12.4 8.4 12.6 7.6 12.6 6.8C12.6 6 12.4 5.3 11.9 4.7C11.4 4.1 10.6 3.8 9.8 3.8H8.6", stroke: "currentColor", strokeWidth: "1.3", strokeLinecap: "round" }),
372
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M9 6C8.6 5.4 7.9 5 7.2 5H5.2C4.4 5 3.6 5.4 3.1 6C2.6 6.6 2.4 7.4 2.4 8.2C2.4 9 2.6 9.7 3.1 10.3C3.6 10.9 4.4 11.2 5.2 11.2H6.4", stroke: "currentColor", strokeWidth: "1.3", strokeLinecap: "round" })
373
+ ] });
374
+ }
375
+ function IcoCode() {
376
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: "15", height: "15", viewBox: "0 0 15 15", fill: "none", children: [
377
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M5 4.5L1.5 7.5L5 10.5", stroke: "currentColor", strokeWidth: "1.4", strokeLinecap: "round", strokeLinejoin: "round" }),
378
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M10 4.5L13.5 7.5L10 10.5", stroke: "currentColor", strokeWidth: "1.4", strokeLinecap: "round", strokeLinejoin: "round" }),
379
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M8.5 2L6.5 13", stroke: "currentColor", strokeWidth: "1.4", strokeLinecap: "round" })
380
+ ] });
381
+ }
382
+ function IcoCopy() {
383
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", children: [
384
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "1", y: "3", width: "8.5", height: "10", rx: "1.5", stroke: "currentColor", strokeWidth: "1.2" }),
385
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M4 1H12.5C13.1 1 13.5 1.4 13.5 2V10", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round" })
386
+ ] });
387
+ }
388
+ function IcoTable() {
389
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: "15", height: "15", viewBox: "0 0 15 15", fill: "none", children: [
390
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "1", y: "1", width: "13", height: "13", rx: "1.5", stroke: "currentColor", strokeWidth: "1.2" }),
391
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "1", y1: "5.5", x2: "14", y2: "5.5", stroke: "currentColor", strokeWidth: "1.1" }),
392
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "1", y1: "10", x2: "14", y2: "10", stroke: "currentColor", strokeWidth: "1.1" }),
393
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "5.5", y1: "5.5", x2: "5.5", y2: "14", stroke: "currentColor", strokeWidth: "1.1" }),
394
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "10", y1: "5.5", x2: "10", y2: "14", stroke: "currentColor", strokeWidth: "1.1" })
395
+ ] });
396
+ }
397
+ function IcoImage() {
398
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: "15", height: "15", viewBox: "0 0 15 15", fill: "none", children: [
399
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "1", y: "2", width: "13", height: "11", rx: "1.5", stroke: "currentColor", strokeWidth: "1.2" }),
400
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "5", cy: "5.5", r: "1.2", fill: "currentColor" }),
401
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M1 10L4.5 7L7 9.5L9.5 7L14 11", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" })
402
+ ] });
403
+ }
404
+ function IcoRowAbove() {
405
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: [
406
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "1", y: "7", width: "14", height: "8", rx: "1", stroke: "currentColor", strokeWidth: "1.1" }),
407
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "8", y1: "7", x2: "8", y2: "15", stroke: "currentColor", strokeWidth: "1" }),
408
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M8 5V1M6 3L8 1L10 3", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" })
409
+ ] });
410
+ }
411
+ function IcoRowBelow() {
412
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: [
413
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "1", y: "1", width: "14", height: "8", rx: "1", stroke: "currentColor", strokeWidth: "1.1" }),
414
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "8", y1: "1", x2: "8", y2: "9", stroke: "currentColor", strokeWidth: "1" }),
415
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M8 11V15M6 13L8 15L10 13", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" })
416
+ ] });
417
+ }
418
+ function IcoDelRow() {
419
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: [
420
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "1", y: "4", width: "14", height: "8", rx: "1", stroke: "currentColor", strokeWidth: "1.1" }),
421
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "1", y1: "8", x2: "15", y2: "8", stroke: "currentColor", strokeWidth: "1" }),
422
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M5.5 6L10.5 10M10.5 6L5.5 10", stroke: "currentColor", strokeWidth: "1.3", strokeLinecap: "round" })
423
+ ] });
424
+ }
425
+ function IcoColLeft() {
426
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: [
427
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "7", y: "1", width: "8", height: "14", rx: "1", stroke: "currentColor", strokeWidth: "1.1" }),
428
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "7", y1: "8", x2: "15", y2: "8", stroke: "currentColor", strokeWidth: "1" }),
429
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M5 8H1M3 6L1 8L3 10", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" })
430
+ ] });
431
+ }
432
+ function IcoColRight() {
433
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: [
434
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "1", y: "1", width: "8", height: "14", rx: "1", stroke: "currentColor", strokeWidth: "1.1" }),
435
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "1", y1: "8", x2: "9", y2: "8", stroke: "currentColor", strokeWidth: "1" }),
436
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M11 8H15M13 6L15 8L13 10", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" })
437
+ ] });
438
+ }
439
+ function IcoDelCol() {
440
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: [
441
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "4", y: "1", width: "8", height: "14", rx: "1", stroke: "currentColor", strokeWidth: "1.1" }),
442
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "8", y1: "1", x2: "8", y2: "15", stroke: "currentColor", strokeWidth: "1" }),
443
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M6 5.5L10 10.5M10 5.5L6 10.5", stroke: "currentColor", strokeWidth: "1.3", strokeLinecap: "round" })
444
+ ] });
445
+ }
446
+ function IcoMerge() {
447
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: [
448
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "1", y: "1", width: "6", height: "14", rx: "1", stroke: "currentColor", strokeWidth: "1.1" }),
449
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "9", y: "1", width: "6", height: "14", rx: "1", stroke: "currentColor", strokeWidth: "1.1" }),
450
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M7 8H9M7.5 6.5L9 8L7.5 9.5M8.5 6.5L7 8L8.5 9.5", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" })
451
+ ] });
452
+ }
453
+ function IcoSplit() {
454
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: [
455
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "1", y: "1", width: "14", height: "14", rx: "1", stroke: "currentColor", strokeWidth: "1.1" }),
456
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "8", y1: "1", x2: "8", y2: "15", stroke: "currentColor", strokeWidth: "1.2" }),
457
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M5.5 8H3M12.5 8H10", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round" }),
458
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M4.5 6.5L3 8L4.5 9.5M11.5 6.5L13 8L11.5 9.5", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" })
459
+ ] });
460
+ }
461
+ function IcoDelTable() {
462
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: [
463
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "1", y: "1", width: "14", height: "14", rx: "1.5", stroke: "currentColor", strokeWidth: "1.1" }),
464
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M5 5L11 11M11 5L5 11", stroke: "currentColor", strokeWidth: "1.4", strokeLinecap: "round" })
465
+ ] });
466
+ }
467
+ function AlignIco({ t }) {
468
+ const w = { left: [13, 9, 11], center: [9, 7, 11], right: [13, 9, 11], justify: [13, 13, 13] };
469
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: "15", height: "15", viewBox: "0 0 15 15", fill: "none", children: [0, 1, 2].map((i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
470
+ "rect",
471
+ {
472
+ x: t === "right" ? 15 - w[t][i] - 1 : 1,
473
+ y: [2, 6.5, 11][i],
474
+ width: w[t][i],
475
+ height: "1.6",
476
+ rx: ".8",
477
+ fill: "currentColor"
478
+ },
479
+ i
480
+ )) });
481
+ }
482
+
483
+ // src/rte/ColorPicker.tsx
484
+ var import_react = require("react");
485
+ var import_jsx_runtime3 = require("react/jsx-runtime");
214
486
  function CustomColorPicker({ initialColor, onApply, onBack }) {
215
487
  const [hsv, setHsv] = (0, import_react.useState)(() => hex2hsv(initialColor || "#ff0000"));
216
488
  const [hexInput, setHexInput] = (0, import_react.useState)(initialColor || "#ff0000");
@@ -306,19 +578,19 @@ function CustomColorPicker({ initialColor, onApply, onBack }) {
306
578
  window.removeEventListener("mouseup", mu);
307
579
  };
308
580
  }, [updateSV, updateHue]);
309
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
310
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
581
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
582
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
311
583
  "button",
312
584
  {
313
585
  onMouseDown: onBack,
314
586
  style: { background: "none", border: "none", cursor: "pointer", color: "#666", fontSize: 12, display: "flex", alignItems: "center", gap: 4, padding: "2px 4px", borderRadius: 3, marginBottom: 8 },
315
587
  children: [
316
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M8 2L4 6L8 10", stroke: "currentColor", strokeWidth: "1.4", strokeLinecap: "round" }) }),
588
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M8 2L4 6L8 10", stroke: "currentColor", strokeWidth: "1.4", strokeLinecap: "round" }) }),
317
589
  "Back"
318
590
  ]
319
591
  }
320
592
  ),
321
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
593
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
322
594
  "canvas",
323
595
  {
324
596
  ref: svRef,
@@ -331,7 +603,7 @@ function CustomColorPicker({ initialColor, onApply, onBack }) {
331
603
  }
332
604
  }
333
605
  ),
334
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
606
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
335
607
  "canvas",
336
608
  {
337
609
  ref: hueRef,
@@ -344,9 +616,9 @@ function CustomColorPicker({ initialColor, onApply, onBack }) {
344
616
  }
345
617
  }
346
618
  ),
347
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 8, marginBottom: 10 }, children: [
348
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { width: 28, height: 28, borderRadius: 4, background: currentHex, border: "1px solid rgba(0,0,0,0.15)", flexShrink: 0 } }),
349
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
619
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 8, marginBottom: 10 }, children: [
620
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { width: 28, height: 28, borderRadius: 4, background: currentHex, border: "1px solid rgba(0,0,0,0.15)", flexShrink: 0 } }),
621
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
350
622
  "input",
351
623
  {
352
624
  value: hexInput,
@@ -360,7 +632,7 @@ function CustomColorPicker({ initialColor, onApply, onBack }) {
360
632
  }
361
633
  )
362
634
  ] }),
363
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
635
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
364
636
  "button",
365
637
  {
366
638
  onMouseDown: () => onApply(currentHex),
@@ -376,8 +648,8 @@ function ColorPicker({ color, onColor, onRemove, onClose }) {
376
648
  onColor(c);
377
649
  onClose();
378
650
  };
379
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rte-cpick", children: custom ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CustomColorPicker, { initialColor: color, onApply: pick, onBack: () => setCustom(false) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
380
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rte-cgrid", children: PALETTE.map((hex) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
651
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "rte-cpick", children: custom ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(CustomColorPicker, { initialColor: color, onApply: pick, onBack: () => setCustom(false) }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
652
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "rte-cgrid", children: PALETTE.map((hex) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
381
653
  "div",
382
654
  {
383
655
  className: `rte-ccell${color.toLowerCase() === hex.toLowerCase() ? " sel" : ""}`,
@@ -387,34 +659,38 @@ function ColorPicker({ color, onColor, onRemove, onClose }) {
387
659
  },
388
660
  hex
389
661
  )) }),
390
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rte-cactions", children: [
391
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rte-caction", title: "Black", onMouseDown: () => pick("#000000"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: [
392
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "2", y: "2", width: "12", height: "12", rx: "2", fill: "#000" }),
393
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M5 8L7 10L11 6", stroke: "#fff", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
662
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "rte-cactions", children: [
663
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "rte-caction", title: "Black", onMouseDown: () => pick("#000000"), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: [
664
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("rect", { x: "2", y: "2", width: "12", height: "12", rx: "2", fill: "#000" }),
665
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M5 8L7 10L11 6", stroke: "#fff", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
394
666
  ] }) }),
395
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rte-caction", title: "Remove color", onMouseDown: () => {
667
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "rte-caction", title: "Remove color", onMouseDown: () => {
396
668
  onRemove();
397
669
  onClose();
398
- }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: [
399
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "2", y: "7.5", width: "12", height: "1.2", rx: ".6", fill: "#e74c3c", transform: "rotate(-30 8 8)" }),
400
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "1", y: "11", width: "14", height: "2", rx: "1", fill: "#e74c3c" })
670
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: [
671
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("rect", { x: "2", y: "7.5", width: "12", height: "1.2", rx: ".6", fill: "#e74c3c", transform: "rotate(-30 8 8)" }),
672
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("rect", { x: "1", y: "11", width: "14", height: "2", rx: "1", fill: "#e74c3c" })
401
673
  ] }) }),
402
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rte-caction", title: "Custom color", onMouseDown: () => setCustom(true), children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: [
403
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "8", cy: "8", r: "6", stroke: "#888", strokeWidth: "1.2", fill: "none" }),
404
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "5.5", cy: "6", r: "1.5", fill: "#e74c3c" }),
405
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "10.5", cy: "6", r: "1.5", fill: "#3498db" }),
406
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "8", cy: "10.5", r: "1.5", fill: "#2ecc71" })
674
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "rte-caction", title: "Custom color", onMouseDown: () => setCustom(true), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: [
675
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: "8", cy: "8", r: "6", stroke: "#888", strokeWidth: "1.2", fill: "none" }),
676
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: "5.5", cy: "6", r: "1.5", fill: "#e74c3c" }),
677
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: "10.5", cy: "6", r: "1.5", fill: "#3498db" }),
678
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: "8", cy: "10.5", r: "1.5", fill: "#2ecc71" })
407
679
  ] }) })
408
680
  ] })
409
681
  ] }) });
410
682
  }
683
+
684
+ // src/rte/TablePicker.tsx
685
+ var import_react2 = require("react");
686
+ var import_jsx_runtime4 = require("react/jsx-runtime");
411
687
  function TablePicker({ onInsert, onClose }) {
412
- const [hover, setHover] = (0, import_react.useState)([0, 0]);
413
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rte-tpick", children: [
414
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rte-tplbl", children: hover[0] > 0 ? `${hover[0]} \xD7 ${hover[1]}` : "Select table size" }),
415
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rte-tpgrid", children: Array.from({ length: 64 }, (_, i) => {
688
+ const [hover, setHover] = (0, import_react2.useState)([0, 0]);
689
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "rte-tpick", children: [
690
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "rte-tplbl", children: hover[0] > 0 ? `${hover[0]} \xD7 ${hover[1]}` : "Select table size" }),
691
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "rte-tpgrid", children: Array.from({ length: 64 }, (_, i) => {
416
692
  const r = Math.floor(i / 8) + 1, c = i % 8 + 1;
417
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
693
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
418
694
  "div",
419
695
  {
420
696
  className: `rte-tpcell${r <= hover[0] && c <= hover[1] ? " on" : ""}`,
@@ -432,13 +708,17 @@ function TablePicker({ onInsert, onClose }) {
432
708
  }) })
433
709
  ] });
434
710
  }
711
+
712
+ // src/rte/ImagePicker.tsx
713
+ var import_react3 = require("react");
714
+ var import_jsx_runtime5 = require("react/jsx-runtime");
435
715
  function ImagePicker({ onInsert, onClose }) {
436
- const [tab, setTab] = (0, import_react.useState)("upload");
437
- const [url, setUrl] = (0, import_react.useState)("");
438
- const [preview, setPreview] = (0, import_react.useState)(null);
439
- const [dragging, setDragging] = (0, import_react.useState)(false);
440
- const [urlError, setUrlError] = (0, import_react.useState)(false);
441
- const fileRef = (0, import_react.useRef)(null);
716
+ const [tab, setTab] = (0, import_react3.useState)("upload");
717
+ const [url, setUrl] = (0, import_react3.useState)("");
718
+ const [preview, setPreview] = (0, import_react3.useState)(null);
719
+ const [dragging, setDragging] = (0, import_react3.useState)(false);
720
+ const [urlError, setUrlError] = (0, import_react3.useState)(false);
721
+ const fileRef = (0, import_react3.useRef)(null);
442
722
  const readFile = (file) => {
443
723
  if (!file.type.startsWith("image/")) return;
444
724
  const reader = new FileReader();
@@ -446,11 +726,11 @@ function ImagePicker({ onInsert, onClose }) {
446
726
  reader.readAsDataURL(file);
447
727
  };
448
728
  const canInsert = tab === "upload" ? !!preview : !!url.trim() && !urlError;
449
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rte-ipick", children: [
450
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rte-itabs", children: ["upload", "url"].map((t) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: `rte-itab${tab === t ? " active" : ""}`, onMouseDown: () => setTab(t), children: t === "upload" ? "Upload / Drop" : "Image URL" }, t)) }),
451
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rte-ipbody", children: [
452
- tab === "upload" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
453
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
729
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "rte-ipick", children: [
730
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "rte-itabs", children: ["upload", "url"].map((t) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { className: `rte-itab${tab === t ? " active" : ""}`, onMouseDown: () => setTab(t), children: t === "upload" ? "Upload / Drop" : "Image URL" }, t)) }),
731
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "rte-ipbody", children: [
732
+ tab === "upload" && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
733
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
454
734
  "div",
455
735
  {
456
736
  className: `rte-idrop${dragging ? " drag" : ""}`,
@@ -469,21 +749,21 @@ function ImagePicker({ onInsert, onClose }) {
469
749
  var _a;
470
750
  return (_a = fileRef.current) == null ? void 0 : _a.click();
471
751
  },
472
- children: preview ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: preview, alt: "preview", style: { maxWidth: "100%", maxHeight: 130, objectFit: "contain", borderRadius: 4, border: "1px solid #eee" } }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
473
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "28", height: "28", viewBox: "0 0 28 28", fill: "none", children: [
474
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "1", y: "4", width: "26", height: "20", rx: "3", stroke: "#aaa", strokeWidth: "1.5" }),
475
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "9", cy: "10", r: "2.5", stroke: "#aaa", strokeWidth: "1.5" }),
476
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M1 20L9 13L14 18L19 13.5L27 21", stroke: "#aaa", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
752
+ children: preview ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("img", { src: preview, alt: "preview", style: { maxWidth: "100%", maxHeight: 130, objectFit: "contain", borderRadius: 4, border: "1px solid #eee" } }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
753
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("svg", { width: "28", height: "28", viewBox: "0 0 28 28", fill: "none", children: [
754
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("rect", { x: "1", y: "4", width: "26", height: "20", rx: "3", stroke: "#aaa", strokeWidth: "1.5" }),
755
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { cx: "9", cy: "10", r: "2.5", stroke: "#aaa", strokeWidth: "1.5" }),
756
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M1 20L9 13L14 18L19 13.5L27 21", stroke: "#aaa", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
477
757
  ] }),
478
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { fontSize: 12, color: "#888" }, children: [
479
- "Drop image or ",
480
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: "#1a5fb4", textDecoration: "underline" }, children: "browse" })
758
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { style: { fontSize: 12, color: "#888" }, children: [
759
+ "Drop or ",
760
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { color: "#1a5fb4", textDecoration: "underline" }, children: "browse" })
481
761
  ] }),
482
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: 11, color: "#bbb" }, children: "PNG, JPG, GIF, WEBP" })
762
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { fontSize: 11, color: "#bbb" }, children: "PNG, JPG, GIF, WEBP" })
483
763
  ] })
484
764
  }
485
765
  ),
486
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
766
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
487
767
  "input",
488
768
  {
489
769
  ref: fileRef,
@@ -498,7 +778,7 @@ function ImagePicker({ onInsert, onClose }) {
498
778
  }
499
779
  }
500
780
  ),
501
- preview && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
781
+ preview && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
502
782
  "button",
503
783
  {
504
784
  onMouseDown: () => setPreview(null),
@@ -507,8 +787,8 @@ function ImagePicker({ onInsert, onClose }) {
507
787
  }
508
788
  )
509
789
  ] }),
510
- tab === "url" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
511
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
790
+ tab === "url" && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
791
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
512
792
  "input",
513
793
  {
514
794
  type: "text",
@@ -521,7 +801,7 @@ function ImagePicker({ onInsert, onClose }) {
521
801
  style: { width: "100%", height: 30, border: `1px solid ${urlError ? "#e74c3c" : "#ccc"}`, borderRadius: 4, padding: "0 8px", fontSize: 12, outline: "none", fontFamily: "var(--font-sans)" }
522
802
  }
523
803
  ),
524
- url && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
804
+ url && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
525
805
  "img",
526
806
  {
527
807
  src: url,
@@ -530,9 +810,9 @@ function ImagePicker({ onInsert, onClose }) {
530
810
  onError: () => setUrlError(true)
531
811
  }
532
812
  ),
533
- urlError && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: 11, color: "#e74c3c" }, children: "Could not load image from this URL." })
813
+ urlError && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { fontSize: 11, color: "#e74c3c" }, children: "Could not load image." })
534
814
  ] }),
535
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
815
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
536
816
  "button",
537
817
  {
538
818
  className: "rte-iinsert",
@@ -550,207 +830,308 @@ function ImagePicker({ onInsert, onClose }) {
550
830
  ] })
551
831
  ] });
552
832
  }
553
- function IcoUL() {
554
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "15", height: "15", viewBox: "0 0 15 15", fill: "none", children: [
555
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "2", cy: "4", r: "1.3", fill: "currentColor" }),
556
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "2", cy: "8", r: "1.3", fill: "currentColor" }),
557
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "2", cy: "12", r: "1.3", fill: "currentColor" }),
558
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "5.5", y: "3.2", width: "8.5", height: "1.6", rx: ".8", fill: "currentColor" }),
559
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "5.5", y: "7.2", width: "8.5", height: "1.6", rx: ".8", fill: "currentColor" }),
560
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "5.5", y: "11.2", width: "8.5", height: "1.6", rx: ".8", fill: "currentColor" })
561
- ] });
562
- }
563
- function IcoOL() {
564
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "15", height: "15", viewBox: "0 0 15 15", fill: "none", children: [
565
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("text", { x: "0", y: "5", fontSize: "5.5", fill: "currentColor", fontFamily: "monospace", children: "1." }),
566
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("text", { x: "0", y: "9.5", fontSize: "5.5", fill: "currentColor", fontFamily: "monospace", children: "2." }),
567
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("text", { x: "0", y: "14", fontSize: "5.5", fill: "currentColor", fontFamily: "monospace", children: "3." }),
568
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "5.5", y: "3.2", width: "8.5", height: "1.6", rx: ".8", fill: "currentColor" }),
569
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "5.5", y: "7.2", width: "8.5", height: "1.6", rx: ".8", fill: "currentColor" }),
570
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "5.5", y: "11.2", width: "8.5", height: "1.6", rx: ".8", fill: "currentColor" })
571
- ] });
572
- }
573
- function IcoIndent() {
574
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "15", height: "15", viewBox: "0 0 15 15", fill: "none", children: [
575
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "1", y: "2", width: "13", height: "1.6", rx: ".8", fill: "currentColor" }),
576
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "4.5", y: "6", width: "9.5", height: "1.6", rx: ".8", fill: "currentColor" }),
577
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "4.5", y: "10", width: "9.5", height: "1.6", rx: ".8", fill: "currentColor" }),
578
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M1 6.5L3.5 8.25L1 10V6.5Z", fill: "currentColor" })
579
- ] });
580
- }
581
- function IcoOutdent() {
582
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "15", height: "15", viewBox: "0 0 15 15", fill: "none", children: [
583
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "1", y: "2", width: "13", height: "1.6", rx: ".8", fill: "currentColor" }),
584
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "4.5", y: "6", width: "9.5", height: "1.6", rx: ".8", fill: "currentColor" }),
585
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "4.5", y: "10", width: "9.5", height: "1.6", rx: ".8", fill: "currentColor" }),
586
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3.5 6.5L1 8.25L3.5 10V6.5Z", fill: "currentColor" })
587
- ] });
588
- }
589
- function IcoLink() {
590
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "15", height: "15", viewBox: "0 0 15 15", fill: "none", children: [
591
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M6 9C6.4 9.6 7.1 10 7.8 10H9.8C10.6 10 11.4 9.6 11.9 9C12.4 8.4 12.6 7.6 12.6 6.8C12.6 6 12.4 5.3 11.9 4.7C11.4 4.1 10.6 3.8 9.8 3.8H8.6", stroke: "currentColor", strokeWidth: "1.3", strokeLinecap: "round" }),
592
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M9 6C8.6 5.4 7.9 5 7.2 5H5.2C4.4 5 3.6 5.4 3.1 6C2.6 6.6 2.4 7.4 2.4 8.2C2.4 9 2.6 9.7 3.1 10.3C3.6 10.9 4.4 11.2 5.2 11.2H6.4", stroke: "currentColor", strokeWidth: "1.3", strokeLinecap: "round" })
593
- ] });
594
- }
595
- function IcoCode() {
596
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "15", height: "15", viewBox: "0 0 15 15", fill: "none", children: [
597
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M5 4.5L1.5 7.5L5 10.5", stroke: "currentColor", strokeWidth: "1.4", strokeLinecap: "round", strokeLinejoin: "round" }),
598
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M10 4.5L13.5 7.5L10 10.5", stroke: "currentColor", strokeWidth: "1.4", strokeLinecap: "round", strokeLinejoin: "round" }),
599
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M8.5 2L6.5 13", stroke: "currentColor", strokeWidth: "1.4", strokeLinecap: "round" })
600
- ] });
601
- }
602
- function IcoCopy() {
603
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", children: [
604
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "1", y: "3", width: "8.5", height: "10", rx: "1.5", stroke: "currentColor", strokeWidth: "1.2" }),
605
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M4 1H12.5C13.1 1 13.5 1.4 13.5 2V10", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round" })
606
- ] });
607
- }
608
- function IcoTable() {
609
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "15", height: "15", viewBox: "0 0 15 15", fill: "none", children: [
610
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "1", y: "1", width: "13", height: "13", rx: "1.5", stroke: "currentColor", strokeWidth: "1.2" }),
611
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "1", y1: "5.5", x2: "14", y2: "5.5", stroke: "currentColor", strokeWidth: "1.1" }),
612
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "1", y1: "10", x2: "14", y2: "10", stroke: "currentColor", strokeWidth: "1.1" }),
613
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "5.5", y1: "5.5", x2: "5.5", y2: "14", stroke: "currentColor", strokeWidth: "1.1" }),
614
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "10", y1: "5.5", x2: "10", y2: "14", stroke: "currentColor", strokeWidth: "1.1" })
615
- ] });
616
- }
617
- function IcoImage() {
618
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "15", height: "15", viewBox: "0 0 15 15", fill: "none", children: [
619
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "1", y: "2", width: "13", height: "11", rx: "1.5", stroke: "currentColor", strokeWidth: "1.2" }),
620
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "5", cy: "5.5", r: "1.2", fill: "currentColor" }),
621
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M1 10L4.5 7L7 9.5L9.5 7L14 11", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" })
622
- ] });
623
- }
624
- function IcoRowAbove() {
625
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: [
626
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "1", y: "7", width: "14", height: "8", rx: "1", stroke: "currentColor", strokeWidth: "1.1" }),
627
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "8", y1: "7", x2: "8", y2: "15", stroke: "currentColor", strokeWidth: "1" }),
628
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M8 5V1M6 3L8 1L10 3", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" })
629
- ] });
630
- }
631
- function IcoRowBelow() {
632
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: [
633
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "1", y: "1", width: "14", height: "8", rx: "1", stroke: "currentColor", strokeWidth: "1.1" }),
634
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "8", y1: "1", x2: "8", y2: "9", stroke: "currentColor", strokeWidth: "1" }),
635
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M8 11V15M6 13L8 15L10 13", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" })
636
- ] });
637
- }
638
- function IcoDelRow() {
639
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: [
640
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "1", y: "4", width: "14", height: "8", rx: "1", stroke: "currentColor", strokeWidth: "1.1" }),
641
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "1", y1: "8", x2: "15", y2: "8", stroke: "currentColor", strokeWidth: "1" }),
642
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M5.5 6L10.5 10M10.5 6L5.5 10", stroke: "currentColor", strokeWidth: "1.3", strokeLinecap: "round" })
643
- ] });
644
- }
645
- function IcoColLeft() {
646
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: [
647
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "7", y: "1", width: "8", height: "14", rx: "1", stroke: "currentColor", strokeWidth: "1.1" }),
648
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "7", y1: "8", x2: "15", y2: "8", stroke: "currentColor", strokeWidth: "1" }),
649
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M5 8H1M3 6L1 8L3 10", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" })
650
- ] });
651
- }
652
- function IcoColRight() {
653
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: [
654
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "1", y: "1", width: "8", height: "14", rx: "1", stroke: "currentColor", strokeWidth: "1.1" }),
655
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "1", y1: "8", x2: "9", y2: "8", stroke: "currentColor", strokeWidth: "1" }),
656
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M11 8H15M13 6L15 8L13 10", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" })
657
- ] });
658
- }
659
- function IcoDelCol() {
660
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: [
661
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "4", y: "1", width: "8", height: "14", rx: "1", stroke: "currentColor", strokeWidth: "1.1" }),
662
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "8", y1: "1", x2: "8", y2: "15", stroke: "currentColor", strokeWidth: "1" }),
663
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M6 5.5L10 10.5M10 5.5L6 10.5", stroke: "currentColor", strokeWidth: "1.3", strokeLinecap: "round" })
664
- ] });
665
- }
666
- function IcoMerge() {
667
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: [
668
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "1", y: "1", width: "6", height: "14", rx: "1", stroke: "currentColor", strokeWidth: "1.1" }),
669
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "9", y: "1", width: "6", height: "14", rx: "1", stroke: "currentColor", strokeWidth: "1.1" }),
670
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M7 8H9M7.5 6.5L9 8L7.5 9.5M8.5 6.5L7 8L8.5 9.5", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" })
671
- ] });
672
- }
673
- function IcoSplit() {
674
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: [
675
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "1", y: "1", width: "14", height: "14", rx: "1", stroke: "currentColor", strokeWidth: "1.1" }),
676
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "8", y1: "1", x2: "8", y2: "15", stroke: "currentColor", strokeWidth: "1.2" }),
677
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M5.5 8H3M12.5 8H10", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round" }),
678
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M4.5 6.5L3 8L4.5 9.5M11.5 6.5L13 8L11.5 9.5", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" })
679
- ] });
680
- }
681
- function IcoDelTable() {
682
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: [
683
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: "1", y: "1", width: "14", height: "14", rx: "1.5", stroke: "currentColor", strokeWidth: "1.1" }),
684
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M5 5L11 11M11 5L5 11", stroke: "currentColor", strokeWidth: "1.4", strokeLinecap: "round" })
685
- ] });
686
- }
687
- function AlignIco({ t }) {
688
- const w = { left: [13, 9, 11], center: [9, 7, 11], right: [13, 9, 11], justify: [13, 13, 13] };
689
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "15", height: "15", viewBox: "0 0 15 15", fill: "none", children: [0, 1, 2].map((i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x: t === "right" ? 15 - w[t][i] - 1 : 1, y: [2, 6.5, 11][i], width: w[t][i], height: "1.6", rx: ".8", fill: "currentColor" }, i)) });
690
- }
691
- function getCurrentCell() {
692
- var _a;
693
- const node = (_a = window.getSelection()) == null ? void 0 : _a.anchorNode;
694
- const el = (node == null ? void 0 : node.nodeType) === 1 ? node : node == null ? void 0 : node.parentElement;
695
- return el == null ? void 0 : el.closest("td, th");
696
- }
697
- function getCurrentTable() {
698
- var _a;
699
- return (_a = getCurrentCell()) == null ? void 0 : _a.closest("table");
833
+
834
+ // src/rte/ImageEditor.tsx
835
+ var import_react4 = require("react");
836
+ var import_jsx_runtime6 = require("react/jsx-runtime");
837
+ var HANDLE_POS = {
838
+ nw: [0, 0],
839
+ n: [0, 50],
840
+ ne: [0, 100],
841
+ e: [50, 100],
842
+ se: [100, 100],
843
+ s: [100, 50],
844
+ sw: [100, 0],
845
+ w: [50, 0]
846
+ };
847
+ var HANDLE_CURSOR = {
848
+ nw: "nw-resize",
849
+ n: "n-resize",
850
+ ne: "ne-resize",
851
+ e: "e-resize",
852
+ se: "se-resize",
853
+ s: "s-resize",
854
+ sw: "sw-resize",
855
+ w: "w-resize"
856
+ };
857
+ function readAlign(img) {
858
+ if (img.style.float === "right") return "right";
859
+ if (img.style.float === "left") return "left";
860
+ const ml = img.style.marginLeft, mr = img.style.marginRight;
861
+ if (ml === "auto" && (mr === "0px" || mr === "0")) return "right";
862
+ if (ml === "auto" && mr === "auto") return "center";
863
+ return "left";
700
864
  }
701
- function getCurrentLink() {
865
+ function ImageEditor({ img, containerRef, onClose, onDelete, onChange }) {
702
866
  var _a;
703
- const node = (_a = window.getSelection()) == null ? void 0 : _a.anchorNode;
704
- const el = (node == null ? void 0 : node.nodeType) === 1 ? node : node == null ? void 0 : node.parentElement;
705
- return el == null ? void 0 : el.closest("a");
706
- }
707
- function getCellCoords(table, cell) {
708
- for (let r = 0; r < table.rows.length; r++) {
709
- const cells = Array.from(table.rows[r].cells);
710
- for (let c = 0; c < cells.length; c++) {
711
- if (cells[c] === cell) return [r, c];
712
- }
713
- }
714
- return null;
715
- }
716
- function getCellsInRange(table, a, b) {
717
- const ca = getCellCoords(table, a), cb = getCellCoords(table, b);
718
- if (!ca || !cb) return [a];
719
- const [r1, c1] = [Math.min(ca[0], cb[0]), Math.min(ca[1], cb[1])];
720
- const [r2, c2] = [Math.max(ca[0], cb[0]), Math.max(ca[1], cb[1])];
721
- const result = [];
722
- Array.from(table.rows).forEach((row, ri) => {
723
- if (ri >= r1 && ri <= r2)
724
- Array.from(row.cells).forEach((cell, ci) => {
725
- if (ci >= c1 && ci <= c2) result.push(cell);
726
- });
867
+ const [overlay, setOverlay] = (0, import_react4.useState)({ top: 0, left: 0, width: 0, height: 0 });
868
+ const [activeTab, setActiveTab] = (0, import_react4.useState)("style");
869
+ const [dispMode, setDispMode] = (0, import_react4.useState)(img.style.display === "inline" ? "inline" : "block");
870
+ const [align, setAlign] = (0, import_react4.useState)(() => readAlign(img));
871
+ const [widthVal, setWidthVal] = (0, import_react4.useState)(img.style.width || `${img.offsetWidth}px`);
872
+ const [altVal, setAltVal] = (0, import_react4.useState)(img.alt || "");
873
+ const [captionTxt, setCaptionTxt] = (0, import_react4.useState)(() => {
874
+ var _a2, _b;
875
+ return ((_b = (_a2 = img.closest("figure")) == null ? void 0 : _a2.querySelector("figcaption")) == null ? void 0 : _b.textContent) || "";
727
876
  });
728
- return result;
877
+ const [showCaption, setShowCaption] = (0, import_react4.useState)(() => !!img.closest("figure"));
878
+ const [linkVal, setLinkVal] = (0, import_react4.useState)(() => {
879
+ var _a2;
880
+ return ((_a2 = img.closest("a")) == null ? void 0 : _a2.href) || "";
881
+ });
882
+ const aspectRef = (0, import_react4.useRef)(img.naturalWidth && img.naturalHeight ? img.naturalWidth / img.naturalHeight : img.offsetWidth / Math.max(img.offsetHeight, 1));
883
+ const updateOverlay = (0, import_react4.useCallback)(() => {
884
+ if (!containerRef.current) return;
885
+ const r = img.getBoundingClientRect(), cr = containerRef.current.getBoundingClientRect();
886
+ setOverlay({ top: r.top - cr.top, left: r.left - cr.left, width: r.width, height: r.height });
887
+ }, [img, containerRef]);
888
+ (0, import_react4.useEffect)(() => {
889
+ updateOverlay();
890
+ window.addEventListener("resize", updateOverlay);
891
+ return () => window.removeEventListener("resize", updateOverlay);
892
+ }, [updateOverlay]);
893
+ const startResize = (0, import_react4.useCallback)((e, handle) => {
894
+ e.preventDefault();
895
+ e.stopPropagation();
896
+ const sx = e.clientX, sy = e.clientY, sw = img.offsetWidth, sh = img.offsetHeight;
897
+ const isCorner = handle.length === 2;
898
+ const onMove = (ev) => {
899
+ const dx = ev.clientX - sx, dy = ev.clientY - sy;
900
+ let nw = sw;
901
+ if (handle.includes("e")) nw = Math.max(50, sw + dx);
902
+ if (handle.includes("w")) nw = Math.max(50, sw - dx);
903
+ if (isCorner) {
904
+ img.style.width = `${Math.round(nw)}px`;
905
+ img.style.height = `${Math.round(nw / aspectRef.current)}px`;
906
+ } else {
907
+ if (handle.includes("e") || handle.includes("w")) {
908
+ img.style.width = `${Math.round(nw)}px`;
909
+ img.style.height = "auto";
910
+ } else {
911
+ const nh = handle === "s" ? Math.max(30, sh + dy) : Math.max(30, sh - dy);
912
+ img.style.height = `${Math.round(nh)}px`;
913
+ }
914
+ }
915
+ setWidthVal(`${Math.round(img.offsetWidth)}px`);
916
+ updateOverlay();
917
+ };
918
+ const onUp = () => {
919
+ window.removeEventListener("mousemove", onMove);
920
+ window.removeEventListener("mouseup", onUp);
921
+ onChange();
922
+ };
923
+ window.addEventListener("mousemove", onMove);
924
+ window.addEventListener("mouseup", onUp);
925
+ }, [img, onChange, updateOverlay]);
926
+ const applyWidth = (w) => {
927
+ img.style.width = w;
928
+ img.style.height = "auto";
929
+ setWidthVal(w);
930
+ updateOverlay();
931
+ onChange();
932
+ };
933
+ const applyAlign = (a) => {
934
+ setAlign(a);
935
+ if (dispMode === "block") {
936
+ img.style.float = "none";
937
+ img.style.marginLeft = a === "center" || a === "right" ? "auto" : "0";
938
+ img.style.marginRight = a === "center" || a === "left" ? "auto" : "0";
939
+ } else {
940
+ img.style.float = a === "left" ? "left" : a === "right" ? "right" : "none";
941
+ img.style.marginLeft = "0";
942
+ img.style.marginRight = "0";
943
+ }
944
+ onChange();
945
+ };
946
+ const applyDisplay = (m) => {
947
+ setDispMode(m);
948
+ img.style.display = m;
949
+ img.style.float = "none";
950
+ img.style.marginLeft = "0";
951
+ img.style.marginRight = "auto";
952
+ setAlign("left");
953
+ onChange();
954
+ };
955
+ const applyAlt = (v) => {
956
+ setAltVal(v);
957
+ img.alt = v;
958
+ onChange();
959
+ };
960
+ const toggleCaption = () => {
961
+ var _a2, _b;
962
+ const fig = img.closest("figure");
963
+ if (fig) {
964
+ (_a2 = fig.parentNode) == null ? void 0 : _a2.insertBefore(img, fig);
965
+ fig.remove();
966
+ setShowCaption(false);
967
+ setCaptionTxt("");
968
+ } else {
969
+ const figure = document.createElement("figure");
970
+ figure.style.cssText = "margin:0.8em 0;display:block;overflow:hidden;";
971
+ const figcap = document.createElement("figcaption");
972
+ figcap.contentEditable = "true";
973
+ figcap.style.cssText = "font-size:13px;color:#666;text-align:center;padding:4px 0;outline:none;clear:both;display:block;";
974
+ figcap.textContent = captionTxt || "Caption";
975
+ (_b = img.parentNode) == null ? void 0 : _b.insertBefore(figure, img);
976
+ figure.appendChild(img);
977
+ figure.appendChild(figcap);
978
+ setShowCaption(true);
979
+ }
980
+ updateOverlay();
981
+ onChange();
982
+ };
983
+ const updateCaption = (v) => {
984
+ var _a2;
985
+ setCaptionTxt(v);
986
+ const fc = (_a2 = img.closest("figure")) == null ? void 0 : _a2.querySelector("figcaption");
987
+ if (fc) {
988
+ fc.textContent = v;
989
+ onChange();
990
+ }
991
+ };
992
+ const applyLink = (href) => {
993
+ var _a2, _b;
994
+ const existing = img.closest("a");
995
+ if (!href.trim()) {
996
+ if (existing) {
997
+ (_a2 = existing.parentNode) == null ? void 0 : _a2.insertBefore(img, existing);
998
+ existing.remove();
999
+ }
1000
+ } else if (existing) {
1001
+ existing.href = href;
1002
+ } else {
1003
+ const a = document.createElement("a");
1004
+ a.href = href;
1005
+ a.target = "_blank";
1006
+ a.rel = "noopener";
1007
+ (_b = img.parentNode) == null ? void 0 : _b.insertBefore(a, img);
1008
+ a.appendChild(img);
1009
+ }
1010
+ onChange();
1011
+ };
1012
+ const PANEL_W = 218;
1013
+ const panelRight = overlay.left + overlay.width + 8;
1014
+ const containerW = ((_a = containerRef.current) == null ? void 0 : _a.clientWidth) || 600;
1015
+ const panelLeft = panelRight + PANEL_W < containerW ? panelRight : Math.max(4, overlay.left + overlay.width - PANEL_W);
1016
+ const panelTop = panelRight + PANEL_W < containerW ? overlay.top : overlay.top + overlay.height + 10;
1017
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
1018
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { position: "absolute", top: overlay.top, left: overlay.left, width: overlay.width, height: overlay.height, pointerEvents: "none", zIndex: 51 }, children: [
1019
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { position: "absolute", inset: 0, border: "2px solid #1a5fb4", borderRadius: 2, boxSizing: "border-box" } }),
1020
+ Object.keys(HANDLE_POS).map((h) => {
1021
+ const [tp, lp] = HANDLE_POS[h];
1022
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1023
+ "div",
1024
+ {
1025
+ className: "rte-handle",
1026
+ style: { top: `calc(${tp}% - 5px)`, left: `calc(${lp}% - 5px)`, cursor: HANDLE_CURSOR[h] },
1027
+ onMouseDown: (e) => startResize(e, h)
1028
+ },
1029
+ h
1030
+ );
1031
+ })
1032
+ ] }),
1033
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "rte-ie-panel", style: { top: panelTop, left: panelLeft }, children: [
1034
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1035
+ "button",
1036
+ {
1037
+ onMouseDown: onClose,
1038
+ style: { position: "absolute", top: 4, right: 6, background: "none", border: "none", cursor: "pointer", color: "#999", fontSize: 13, lineHeight: 1 },
1039
+ children: "\u2715"
1040
+ }
1041
+ ),
1042
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "rte-ie-tabs", children: ["style", "caption", "link"].map((t) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { className: `rte-ie-tab${activeTab === t ? " active" : ""}`, onMouseDown: () => setActiveTab(t), children: t === "style" ? "Style" : t === "caption" ? "Caption" : "Link" }, t)) }),
1043
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "rte-ie-body", children: [
1044
+ activeTab === "style" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
1045
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { children: [
1046
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "rte-ie-label", children: "Display" }),
1047
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "rte-ie-row", children: ["block", "inline"].map((m) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { className: `rte-ie-seg-btn${dispMode === m ? " active" : ""}`, onMouseDown: () => applyDisplay(m), children: m === "block" ? "\u2B1B Block" : "\u25AC Inline" }, m)) })
1048
+ ] }),
1049
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { children: [
1050
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "rte-ie-label", children: "Alignment" }),
1051
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "rte-ie-row", children: ["left", "center", "right"].map((a) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { className: `rte-ie-seg-btn${align === a ? " active" : ""}`, onMouseDown: () => applyAlign(a), children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(AlignIco, { t: a }) }, a)) })
1052
+ ] }),
1053
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { children: [
1054
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "rte-ie-label", children: "Width" }),
1055
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "rte-ie-row", style: { marginBottom: 4 }, children: [
1056
+ [25, 50, 75, 100].map((p) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("button", { className: "rte-ie-preset", onMouseDown: () => applyWidth(`${p}%`), children: [
1057
+ p,
1058
+ "%"
1059
+ ] }, p)),
1060
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { className: "rte-ie-preset", title: "Natural size", onMouseDown: () => applyWidth(`${img.naturalWidth || img.offsetWidth}px`), children: "Orig" })
1061
+ ] }),
1062
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1063
+ "input",
1064
+ {
1065
+ className: "rte-ie-input",
1066
+ value: widthVal,
1067
+ onChange: (e) => setWidthVal(e.target.value),
1068
+ onBlur: (e) => applyWidth(e.target.value),
1069
+ onKeyDown: (e) => e.key === "Enter" && applyWidth(widthVal),
1070
+ placeholder: "e.g. 300px or 50%"
1071
+ }
1072
+ )
1073
+ ] }),
1074
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { children: [
1075
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "rte-ie-label", children: "Alt text" }),
1076
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("input", { className: "rte-ie-input", value: altVal, onChange: (e) => applyAlt(e.target.value), placeholder: "Describe the image" })
1077
+ ] }),
1078
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { className: "rte-ie-delete", onMouseDown: onDelete, children: "Delete image" })
1079
+ ] }),
1080
+ activeTab === "caption" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
1081
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { style: { fontSize: 11, color: "#777", margin: 0, lineHeight: 1.5, fontFamily: "var(--font-sans)" }, children: [
1082
+ "Wraps image in ",
1083
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("code", { children: "<figure>" }),
1084
+ " with ",
1085
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("code", { children: "<figcaption>" }),
1086
+ "."
1087
+ ] }),
1088
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { style: { display: "flex", alignItems: "center", gap: 8, fontSize: 12, cursor: "pointer", fontFamily: "var(--font-sans)" }, children: [
1089
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("input", { type: "checkbox", checked: showCaption, onChange: toggleCaption }),
1090
+ " Show caption"
1091
+ ] }),
1092
+ showCaption && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("input", { className: "rte-ie-input", value: captionTxt, onChange: (e) => updateCaption(e.target.value), placeholder: "Caption text" })
1093
+ ] }),
1094
+ activeTab === "link" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
1095
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "rte-ie-label", children: "Wrap image in a hyperlink" }),
1096
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("input", { className: "rte-ie-input", value: linkVal, onChange: (e) => setLinkVal(e.target.value), placeholder: "https://example.com" }),
1097
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "rte-ie-row", children: [
1098
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { className: "rte-ie-apply", onMouseDown: () => applyLink(linkVal), children: "Apply" }),
1099
+ img.closest("a") && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { className: "rte-ie-remove", onMouseDown: () => {
1100
+ setLinkVal("");
1101
+ applyLink("");
1102
+ }, children: "Remove" })
1103
+ ] })
1104
+ ] })
1105
+ ] })
1106
+ ] })
1107
+ ] });
729
1108
  }
730
- function RichTextEditor({ value, onChange }) {
1109
+
1110
+ // src/RichTextEditor.tsx
1111
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1112
+ function RichTextEditor({ value, onChange, toolbar }) {
731
1113
  var _a;
732
- const editorRef = (0, import_react.useRef)(null);
733
- const editorAreaRef = (0, import_react.useRef)(null);
734
- const savedRangeRef = (0, import_react.useRef)(null);
735
- const dragStartCell = (0, import_react.useRef)(null);
736
- const isDragging = (0, import_react.useRef)(false);
737
- const [isCode, setIsCode] = (0, import_react.useState)(false);
738
- const [codeVal, setCodeVal] = (0, import_react.useState)("");
739
- const [fmt, setFmt] = (0, import_react.useState)({ block: "p" });
740
- const [color, setColor] = (0, import_react.useState)("#000000");
741
- const [words, setWords] = (0, import_react.useState)(0);
742
- const [linkBar, setLinkBar] = (0, import_react.useState)(false);
743
- const [linkUrl, setLinkUrl] = (0, import_react.useState)("https://");
744
- const [showTable, setShowTable] = (0, import_react.useState)(false);
745
- const [showColor, setShowColor] = (0, import_react.useState)(false);
746
- const [showImagePicker, setShowImagePicker] = (0, import_react.useState)(false);
747
- const [selCells, setSelCells] = (0, import_react.useState)([]);
748
- const [tableFP, setTableFP] = (0, import_react.useState)(null);
749
- const [linkFP, setLinkFP] = (0, import_react.useState)(null);
750
- const [linkInfoFP, setLinkInfoFP] = (0, import_react.useState)(null);
751
- const [selectedImg, setSelectedImg] = (0, import_react.useState)(null);
752
- const [imgFP, setImgFP] = (0, import_react.useState)(null);
753
- const calcFloat = (0, import_react.useCallback)((el, w) => {
1114
+ const editorRef = (0, import_react5.useRef)(null);
1115
+ const editorAreaRef = (0, import_react5.useRef)(null);
1116
+ const savedRangeRef = (0, import_react5.useRef)(null);
1117
+ const dragStartCell = (0, import_react5.useRef)(null);
1118
+ const isDragging = (0, import_react5.useRef)(false);
1119
+ const [isCode, setIsCode] = (0, import_react5.useState)(false);
1120
+ const [codeVal, setCodeVal] = (0, import_react5.useState)("");
1121
+ const [fmt, setFmt] = (0, import_react5.useState)({ block: "p" });
1122
+ const [color, setColor] = (0, import_react5.useState)("#000000");
1123
+ const [words, setWords] = (0, import_react5.useState)(0);
1124
+ const [linkBar, setLinkBar] = (0, import_react5.useState)(false);
1125
+ const [linkUrl, setLinkUrl] = (0, import_react5.useState)("https://");
1126
+ const [showTable, setShowTable] = (0, import_react5.useState)(false);
1127
+ const [showColor, setShowColor] = (0, import_react5.useState)(false);
1128
+ const [showImagePicker, setShowImagePicker] = (0, import_react5.useState)(false);
1129
+ const [selCells, setSelCells] = (0, import_react5.useState)([]);
1130
+ const [tableFP, setTableFP] = (0, import_react5.useState)(null);
1131
+ const [linkFP, setLinkFP] = (0, import_react5.useState)(null);
1132
+ const [linkInfoFP, setLinkInfoFP] = (0, import_react5.useState)(null);
1133
+ const [selectedImg, setSelectedImg] = (0, import_react5.useState)(null);
1134
+ const calcFloat = (0, import_react5.useCallback)((el, w) => {
754
1135
  const area = editorAreaRef.current;
755
1136
  const er = el.getBoundingClientRect(), ar = area.getBoundingClientRect();
756
1137
  const ac = er.left + er.width / 2 - ar.left;
@@ -758,32 +1139,20 @@ function RichTextEditor({ value, onChange }) {
758
1139
  const left = Math.max(4, Math.min(rawL, ar.width - w - 4));
759
1140
  return { top: er.bottom - ar.top + 10, left, arrowLeft: Math.max(8, Math.min(ac - left - 7, w - 22)) };
760
1141
  }, []);
761
- const applySelection = (0, import_react.useCallback)((cells) => {
1142
+ const applySelection = (0, import_react5.useCallback)((cells) => {
762
1143
  var _a2;
763
1144
  (_a2 = editorRef.current) == null ? void 0 : _a2.querySelectorAll(".rte-sel").forEach((c) => c.classList.remove("rte-sel"));
764
1145
  cells.forEach((c) => c.classList.add("rte-sel"));
765
1146
  setSelCells(cells);
766
1147
  }, []);
767
- const clearSelection = (0, import_react.useCallback)(() => {
1148
+ const clearSelection = (0, import_react5.useCallback)(() => {
768
1149
  var _a2;
769
1150
  (_a2 = editorRef.current) == null ? void 0 : _a2.querySelectorAll(".rte-sel").forEach((c) => c.classList.remove("rte-sel"));
770
1151
  setSelCells([]);
771
1152
  dragStartCell.current = null;
772
1153
  }, []);
773
- const selectImage = (0, import_react.useCallback)((img) => {
774
- var _a2;
775
- (_a2 = editorRef.current) == null ? void 0 : _a2.querySelectorAll("img.rte-img-sel").forEach((i) => i.classList.remove("rte-img-sel"));
776
- img.classList.add("rte-img-sel");
777
- setSelectedImg(img);
778
- if (editorAreaRef.current) setImgFP(calcFloat(img, 260));
779
- }, [calcFloat]);
780
- const clearImageSelection = (0, import_react.useCallback)(() => {
781
- var _a2;
782
- (_a2 = editorRef.current) == null ? void 0 : _a2.querySelectorAll("img.rte-img-sel").forEach((i) => i.classList.remove("rte-img-sel"));
783
- setSelectedImg(null);
784
- setImgFP(null);
785
- }, []);
786
- const fixFontTags = (0, import_react.useCallback)(() => {
1154
+ const clearImageSel = (0, import_react5.useCallback)(() => setSelectedImg(null), []);
1155
+ const fixFontTags = (0, import_react5.useCallback)(() => {
787
1156
  var _a2;
788
1157
  (_a2 = editorRef.current) == null ? void 0 : _a2.querySelectorAll("font[color]").forEach((font) => {
789
1158
  var _a3;
@@ -793,21 +1162,23 @@ function RichTextEditor({ value, onChange }) {
793
1162
  font.replaceWith(span);
794
1163
  });
795
1164
  }, []);
796
- const fixListNesting = (0, import_react.useCallback)(() => {
1165
+ const fixListNesting = (0, import_react5.useCallback)(() => {
797
1166
  var _a2;
798
1167
  (_a2 = editorRef.current) == null ? void 0 : _a2.querySelectorAll("ol > ol, ol > ul, ul > ol, ul > ul").forEach((orphan) => {
799
1168
  const prev = orphan.previousElementSibling;
800
1169
  if ((prev == null ? void 0 : prev.tagName) === "LI") prev.appendChild(orphan);
801
1170
  });
802
1171
  }, []);
803
- const refresh = (0, import_react.useCallback)(() => {
1172
+ const refresh = (0, import_react5.useCallback)(() => {
804
1173
  var _a2, _b, _c, _d;
805
1174
  const raw = document.queryCommandValue("formatBlock").toLowerCase().replace(/[<>]/g, "");
806
1175
  const block = ["h1", "h2", "h3"].includes(raw) ? raw : "p";
807
1176
  setColor(getColorAtCursor(editorRef.current));
808
- const cell = getCurrentCell(), inTable = !!cell;
1177
+ const cell = getCurrentCell();
1178
+ const inTable = !!cell;
809
1179
  const cellMerged = cell ? cell.colSpan > 1 || cell.rowSpan > 1 : false;
810
- const anchor = getCurrentLink(), inLink = !!anchor;
1180
+ const anchor = getCurrentLink();
1181
+ const inLink = !!anchor;
811
1182
  setFmt({
812
1183
  bold: document.queryCommandState("bold"),
813
1184
  italic: document.queryCommandState("italic"),
@@ -832,7 +1203,7 @@ function RichTextEditor({ value, onChange }) {
832
1203
  setWords(txt.trim() ? txt.trim().split(/\s+/).length : 0);
833
1204
  onChange == null ? void 0 : onChange((_d = (_c = editorRef.current) == null ? void 0 : _c.innerHTML) != null ? _d : "");
834
1205
  }, [onChange, calcFloat, linkBar]);
835
- const exec = (0, import_react.useCallback)((cmd, val = null) => {
1206
+ const exec = (0, import_react5.useCallback)((cmd, val = null) => {
836
1207
  var _a2;
837
1208
  (_a2 = editorRef.current) == null ? void 0 : _a2.focus();
838
1209
  document.execCommand(cmd, false, val != null ? val : void 0);
@@ -840,19 +1211,19 @@ function RichTextEditor({ value, onChange }) {
840
1211
  fixListNesting();
841
1212
  refresh();
842
1213
  }, [fixFontTags, fixListNesting, refresh]);
843
- const insertImage = (0, import_react.useCallback)((src) => {
1214
+ const insertImage = (0, import_react5.useCallback)((src) => {
844
1215
  var _a2;
845
1216
  (_a2 = editorRef.current) == null ? void 0 : _a2.focus();
846
- document.execCommand("insertHTML", false, `<img src="${src}" alt="" style="max-width:100%;height:auto;" />`);
1217
+ document.execCommand("insertHTML", false, `<img src="${src}" alt="" style="max-width:100%;height:auto;display:block;" />`);
847
1218
  refresh();
848
1219
  }, [refresh]);
849
- const handleEditorMouseDown = (0, import_react.useCallback)((e) => {
1220
+ const handleEditorMouseDown = (0, import_react5.useCallback)((e) => {
850
1221
  if (e.target.tagName === "IMG") {
851
1222
  e.preventDefault();
852
- selectImage(e.target);
1223
+ setSelectedImg(e.target);
853
1224
  return;
854
1225
  }
855
- clearImageSelection();
1226
+ clearImageSel();
856
1227
  const target = e.target.closest("td, th");
857
1228
  if (!target) {
858
1229
  clearSelection();
@@ -869,8 +1240,8 @@ function RichTextEditor({ value, onChange }) {
869
1240
  dragStartCell.current = target;
870
1241
  isDragging.current = true;
871
1242
  applySelection([target]);
872
- }, [applySelection, clearSelection, selectImage, clearImageSelection]);
873
- const handleEditorMouseMove = (0, import_react.useCallback)((e) => {
1243
+ }, [applySelection, clearSelection, clearImageSel]);
1244
+ const handleEditorMouseMove = (0, import_react5.useCallback)((e) => {
874
1245
  if (!isDragging.current || !dragStartCell.current) return;
875
1246
  const target = e.target.closest("td, th");
876
1247
  if (!target || target === dragStartCell.current) return;
@@ -882,10 +1253,10 @@ function RichTextEditor({ value, onChange }) {
882
1253
  applySelection(cells);
883
1254
  }
884
1255
  }, [applySelection]);
885
- const handleKeyDown = (0, import_react.useCallback)((e) => {
1256
+ const handleKeyDown = (0, import_react5.useCallback)((e) => {
886
1257
  var _a2, _b;
887
1258
  clearSelection();
888
- clearImageSelection();
1259
+ clearImageSel();
889
1260
  if (e.key === "Tab") {
890
1261
  e.preventDefault();
891
1262
  const cell = getCurrentCell();
@@ -917,7 +1288,7 @@ function RichTextEditor({ value, onChange }) {
917
1288
  exec("underline");
918
1289
  }
919
1290
  }
920
- }, [exec, clearSelection, clearImageSelection]);
1291
+ }, [exec, clearSelection, clearImageSel]);
921
1292
  const insertTable = (rows, cols) => {
922
1293
  var _a2;
923
1294
  (_a2 = editorRef.current) == null ? void 0 : _a2.focus();
@@ -931,7 +1302,7 @@ function RichTextEditor({ value, onChange }) {
931
1302
  document.execCommand("insertHTML", false, html);
932
1303
  refresh();
933
1304
  };
934
- const tableOp = (0, import_react.useCallback)((op) => {
1305
+ const tableOp = (0, import_react5.useCallback)((op) => {
935
1306
  const cell = getCurrentCell(), table = getCurrentTable();
936
1307
  if (!cell || !table) return;
937
1308
  const row = cell.closest("tr");
@@ -969,7 +1340,7 @@ function RichTextEditor({ value, onChange }) {
969
1340
  }
970
1341
  refresh();
971
1342
  }, [clearSelection, refresh]);
972
- const doMerge = (0, import_react.useCallback)((cells) => {
1343
+ const doMerge = (0, import_react5.useCallback)((cells) => {
973
1344
  var _a2;
974
1345
  if (cells.length < 2) return;
975
1346
  const table = cells[0].closest("table");
@@ -987,12 +1358,13 @@ function RichTextEditor({ value, onChange }) {
987
1358
  clearSelection();
988
1359
  refresh();
989
1360
  }, [clearSelection, refresh]);
990
- const doSplit = (0, import_react.useCallback)(() => {
1361
+ const doSplit = (0, import_react5.useCallback)(() => {
991
1362
  const cell = getCurrentCell();
992
1363
  if (!cell || cell.colSpan === 1 && cell.rowSpan === 1) return;
993
1364
  const cs = cell.colSpan, rs = cell.rowSpan;
994
1365
  const table = cell.closest("table");
995
- const rows = Array.from(table.rows), row = cell.closest("tr");
1366
+ const rows = Array.from(table.rows);
1367
+ const row = cell.closest("tr");
996
1368
  const ri = rows.indexOf(row), ci = Array.from(row.cells).indexOf(cell);
997
1369
  cell.colSpan = 1;
998
1370
  cell.rowSpan = 1;
@@ -1019,7 +1391,9 @@ function RichTextEditor({ value, onChange }) {
1019
1391
  savedRangeRef.current = (sel == null ? void 0 : sel.rangeCount) ? sel.getRangeAt(0).cloneRange() : null;
1020
1392
  if ((sel == null ? void 0 : sel.rangeCount) && editorAreaRef.current) {
1021
1393
  const rect = sel.getRangeAt(0).getBoundingClientRect();
1022
- setLinkFP(rect.width > 0 || rect.height > 0 ? calcFloat({ getBoundingClientRect: () => rect }, 360) : { top: 60, left: 20, arrowLeft: 20 });
1394
+ setLinkFP(
1395
+ rect.width > 0 || rect.height > 0 ? calcFloat({ getBoundingClientRect: () => rect }, 360) : { top: 60, left: 20, arrowLeft: 20 }
1396
+ );
1023
1397
  }
1024
1398
  setLinkUrl("https://");
1025
1399
  setLinkBar(true);
@@ -1033,8 +1407,9 @@ function RichTextEditor({ value, onChange }) {
1033
1407
  sel.removeAllRanges();
1034
1408
  sel.addRange(savedRangeRef.current);
1035
1409
  }
1036
- if ((_b = savedRangeRef.current) == null ? void 0 : _b.toString()) document.execCommand("createLink", false, linkUrl);
1037
- else if (savedRangeRef.current) {
1410
+ if ((_b = savedRangeRef.current) == null ? void 0 : _b.toString()) {
1411
+ document.execCommand("createLink", false, linkUrl);
1412
+ } else if (savedRangeRef.current) {
1038
1413
  const a = document.createElement("a");
1039
1414
  a.href = linkUrl;
1040
1415
  a.textContent = linkUrl;
@@ -1045,70 +1420,11 @@ function RichTextEditor({ value, onChange }) {
1045
1420
  setLinkFP(null);
1046
1421
  refresh();
1047
1422
  };
1048
- const prettifyHtml = (html) => {
1049
- const INLINE = /* @__PURE__ */ new Set(["a", "b", "i", "u", "em", "strong", "span", "code", "br", "small", "sub", "sup"]);
1050
- let indent = 0;
1051
- const pad = () => " ".repeat(indent);
1052
- const tokens = html.replace(/>\s+</g, "><").replace(/(<\/?[^>]+>)/g, "\0$1\0").split("\0").filter(Boolean);
1053
- const lines = [];
1054
- let inline = "";
1055
- const flush = () => {
1056
- if (inline.trim()) {
1057
- lines.push(pad() + inline.trim());
1058
- inline = "";
1059
- }
1060
- };
1061
- for (const tok of tokens) {
1062
- const ot = tok.match(/^<([a-zA-Z][a-zA-Z0-9]*)[^>]*>$/), ct = tok.match(/^<\/([a-zA-Z][a-zA-Z0-9]*)>$/);
1063
- if (tok.match(/^<[^>]+\/>$/)) {
1064
- flush();
1065
- lines.push(pad() + tok);
1066
- continue;
1067
- }
1068
- if (ot) {
1069
- const tag = ot[1].toLowerCase();
1070
- if (INLINE.has(tag)) {
1071
- inline += tok;
1072
- continue;
1073
- }
1074
- flush();
1075
- lines.push(pad() + tok);
1076
- indent++;
1077
- continue;
1078
- }
1079
- if (ct) {
1080
- const tag = ct[1].toLowerCase();
1081
- if (INLINE.has(tag)) {
1082
- inline += tok;
1083
- continue;
1084
- }
1085
- flush();
1086
- indent = Math.max(0, indent - 1);
1087
- const prev = lines[lines.length - 1];
1088
- prev && prev.trim().startsWith("<") && !prev.includes("</") ? lines[lines.length - 1] = prev + tok : lines.push(pad() + tok);
1089
- continue;
1090
- }
1091
- inline += tok;
1092
- }
1093
- flush();
1094
- return lines.join("\n");
1095
- };
1096
- const toCode = () => {
1097
- var _a2, _b;
1098
- setCodeVal(prettifyHtml((_b = (_a2 = editorRef.current) == null ? void 0 : _a2.innerHTML) != null ? _b : ""));
1099
- setIsCode(true);
1100
- };
1101
- const toVisual = () => {
1102
- if (editorRef.current) editorRef.current.innerHTML = codeVal;
1103
- setIsCode(false);
1104
- refresh();
1105
- };
1106
1423
  const insertCodeBlock = () => {
1107
1424
  const sel = window.getSelection();
1108
1425
  if (!(sel == null ? void 0 : sel.rangeCount)) return;
1109
1426
  const range = sel.getRangeAt(0);
1110
- const pre = document.createElement("pre");
1111
- const code = document.createElement("code");
1427
+ const pre = document.createElement("pre"), code = document.createElement("code");
1112
1428
  code.textContent = range.toString() || "// code here";
1113
1429
  pre.appendChild(code);
1114
1430
  range.deleteContents();
@@ -1121,34 +1437,55 @@ function RichTextEditor({ value, onChange }) {
1121
1437
  sel.addRange(range);
1122
1438
  refresh();
1123
1439
  };
1440
+ const toCode = () => {
1441
+ var _a2, _b;
1442
+ setCodeVal(prettifyHtml((_b = (_a2 = editorRef.current) == null ? void 0 : _a2.innerHTML) != null ? _b : ""));
1443
+ setIsCode(true);
1444
+ };
1445
+ const toVisual = () => {
1446
+ if (editorRef.current) editorRef.current.innerHTML = codeVal;
1447
+ setIsCode(false);
1448
+ refresh();
1449
+ };
1124
1450
  const copyHtml = () => {
1125
1451
  var _a2, _b;
1126
1452
  return navigator.clipboard.writeText(isCode ? codeVal : (_b = (_a2 = editorRef.current) == null ? void 0 : _a2.innerHTML) != null ? _b : "").catch(() => {
1127
1453
  });
1128
1454
  };
1129
- (0, import_react.useEffect)(() => {
1455
+ (0, import_react5.useEffect)(() => {
1130
1456
  if (editorRef.current) {
1131
1457
  editorRef.current.innerHTML = value != null ? value : "<p>Start writing here...</p>";
1132
1458
  refresh();
1133
1459
  }
1134
1460
  }, []);
1135
- const canMerge = selCells.length >= 2, canSplit = fmt.cellMerged;
1461
+ const canMerge = selCells.length >= 2;
1462
+ const canSplit = fmt.cellMerged;
1136
1463
  const backdrop = { position: "fixed", inset: 0, zIndex: 199 };
1137
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { padding: "1rem 0" }, children: [
1138
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: CSS }),
1139
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { border: "1px solid #d8d8d8", borderRadius: 4, boxShadow: "0 1px 3px rgba(0,0,0,0.06)" }, children: [
1140
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rte-toolbar", children: [
1141
- !isCode && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1142
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Btn, { onClick: () => exec("bold"), title: "Bold (Ctrl+B)", active: fmt.bold, style: { fontWeight: 800, fontFamily: "Georgia,serif" }, children: "B" }),
1143
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Btn, { onClick: () => exec("italic"), title: "Italic (Ctrl+I)", active: fmt.italic, style: { fontStyle: "italic", fontFamily: "Georgia,serif" }, children: "I" }),
1144
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Btn, { onClick: () => exec("underline"), title: "Underline (Ctrl+U)", active: fmt.underline, style: { textDecoration: "underline" }, children: "U" }),
1145
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { position: "relative", display: "inline-flex" }, children: [
1146
- showColor && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: backdrop, onMouseDown: () => setShowColor(false) }),
1147
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Btn, { onClick: () => setShowColor((v) => !v), title: "Text color", active: showColor, style: { flexDirection: "column", gap: 1, padding: "3px 6px" }, children: [
1148
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: 13, fontWeight: 800, fontFamily: "Georgia,serif", lineHeight: 1, color: "#222" }, children: "A" }),
1149
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rte-swatch", style: { background: color } })
1150
- ] }),
1151
- showColor && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { position: "absolute", top: 34, left: -4, zIndex: 200 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1464
+ const show = (key) => !toolbar || toolbar.includes(key);
1465
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { padding: "1rem 0" }, children: [
1466
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("style", { children: CSS }),
1467
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { border: "1px solid #d8d8d8", borderRadius: 4, boxShadow: "0 1px 3px rgba(0,0,0,0.06)" }, children: [
1468
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "rte-toolbar", children: [
1469
+ !isCode && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
1470
+ 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" }),
1471
+ show("italic") && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { onClick: () => exec("italic"), title: "Italic (Ctrl+I)", active: fmt.italic, style: { fontStyle: "italic", fontFamily: "Georgia,serif" }, children: "I" }),
1472
+ show("underline") && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { onClick: () => exec("underline"), title: "Underline (Ctrl+U)", active: fmt.underline, style: { textDecoration: "underline" }, children: "U" }),
1473
+ show("color") && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { position: "relative", display: "inline-flex" }, children: [
1474
+ showColor && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: backdrop, onMouseDown: () => setShowColor(false) }),
1475
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1476
+ Btn,
1477
+ {
1478
+ onClick: () => setShowColor((v) => !v),
1479
+ title: "Text color",
1480
+ active: showColor,
1481
+ style: { flexDirection: "column", gap: 1, padding: "3px 6px" },
1482
+ children: [
1483
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { fontSize: 13, fontWeight: 800, fontFamily: "Georgia,serif", lineHeight: 1, color: "#222" }, children: "A" }),
1484
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "rte-swatch", style: { background: color } })
1485
+ ]
1486
+ }
1487
+ ),
1488
+ showColor && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { position: "absolute", top: 34, left: -4, zIndex: 200 }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1152
1489
  ColorPicker,
1153
1490
  {
1154
1491
  color,
@@ -1165,8 +1502,8 @@ function RichTextEditor({ value, onChange }) {
1165
1502
  }
1166
1503
  ) })
1167
1504
  ] }),
1168
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Sep, {}),
1169
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1505
+ (show("bold") || show("italic") || show("underline") || show("color")) && (show("blockFormat") || show("alignLeft") || show("alignCenter") || show("alignRight") || show("alignJustify")) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Sep, {}),
1506
+ show("blockFormat") && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1170
1507
  "select",
1171
1508
  {
1172
1509
  className: "rte-select",
@@ -1182,64 +1519,67 @@ function RichTextEditor({ value, onChange }) {
1182
1519
  refresh();
1183
1520
  },
1184
1521
  children: [
1185
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "p", children: "Paragraph" }),
1186
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "h1", children: "Heading 1" }),
1187
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "h2", children: "Heading 2" }),
1188
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "h3", children: "Heading 3" })
1522
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: "p", children: "Paragraph" }),
1523
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: "h1", children: "Heading 1" }),
1524
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: "h2", children: "Heading 2" }),
1525
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: "h3", children: "Heading 3" })
1189
1526
  ]
1190
1527
  }
1191
1528
  ),
1192
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Sep, {}),
1193
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Btn, { onClick: () => exec("justifyLeft"), title: "Align left", active: fmt.aL, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlignIco, { t: "left" }) }),
1194
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Btn, { onClick: () => exec("justifyCenter"), title: "Align center", active: fmt.aC, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlignIco, { t: "center" }) }),
1195
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Btn, { onClick: () => exec("justifyRight"), title: "Align right", active: fmt.aR, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlignIco, { t: "right" }) }),
1196
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Btn, { onClick: () => exec("justifyFull"), title: "Justify", active: fmt.aJ, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlignIco, { t: "justify" }) }),
1197
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Sep, {}),
1198
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Btn, { onClick: () => exec("insertUnorderedList"), title: "Bullet list", active: fmt.ul, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IcoUL, {}) }),
1199
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Btn, { onClick: () => exec("insertOrderedList"), title: "Numbered list", active: fmt.ol, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IcoOL, {}) }),
1200
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Btn, { onClick: () => exec("indent"), title: "Indent (Tab)", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IcoIndent, {}) }),
1201
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Btn, { onClick: () => exec("outdent"), title: "Outdent (Shift+Tab)", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IcoOutdent, {}) }),
1202
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Sep, {}),
1203
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Btn, { onClick: openLinkBar, title: "Insert link", active: linkBar, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IcoLink, {}) }),
1204
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Btn, { onClick: insertCodeBlock, title: "Code block", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IcoCode, {}) }),
1205
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { position: "relative", display: "inline-flex" }, children: [
1206
- showImagePicker && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: backdrop, onMouseDown: () => setShowImagePicker(false) }),
1207
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Btn, { onClick: () => setShowImagePicker((v) => !v), title: "Insert image", active: showImagePicker, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IcoImage, {}) }),
1208
- showImagePicker && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { position: "absolute", top: 34, left: 0, zIndex: 200 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ImagePicker, { onInsert: (src) => {
1209
- insertImage(src);
1210
- setShowImagePicker(false);
1211
- }, onClose: () => setShowImagePicker(false) }) })
1529
+ show("blockFormat") && (show("alignLeft") || show("alignCenter") || show("alignRight") || show("alignJustify")) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Sep, {}),
1530
+ show("alignLeft") && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { onClick: () => exec("justifyLeft"), title: "Align left", active: fmt.aL, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AlignIco, { t: "left" }) }),
1531
+ show("alignCenter") && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { onClick: () => exec("justifyCenter"), title: "Align center", active: fmt.aC, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AlignIco, { t: "center" }) }),
1532
+ show("alignRight") && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { onClick: () => exec("justifyRight"), title: "Align right", active: fmt.aR, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AlignIco, { t: "right" }) }),
1533
+ show("alignJustify") && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { onClick: () => exec("justifyFull"), title: "Justify", active: fmt.aJ, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AlignIco, { t: "justify" }) }),
1534
+ (show("alignLeft") || show("alignCenter") || show("alignRight") || show("alignJustify")) && (show("bulletList") || show("numberedList") || show("indent") || show("outdent")) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Sep, {}),
1535
+ show("bulletList") && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { onClick: () => exec("insertUnorderedList"), title: "Bullet list", active: fmt.ul, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IcoUL, {}) }),
1536
+ show("numberedList") && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { onClick: () => exec("insertOrderedList"), title: "Numbered list", active: fmt.ol, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IcoOL, {}) }),
1537
+ show("indent") && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { onClick: () => exec("indent"), title: "Indent (Tab)", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IcoIndent, {}) }),
1538
+ show("outdent") && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { onClick: () => exec("outdent"), title: "Outdent (Shift+Tab)", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IcoOutdent, {}) }),
1539
+ (show("bulletList") || show("numberedList") || show("indent") || show("outdent")) && (show("link") || show("codeBlock") || show("image") || show("table")) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Sep, {}),
1540
+ show("link") && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { onClick: openLinkBar, title: "Insert link", active: linkBar, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IcoLink, {}) }),
1541
+ show("codeBlock") && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { onClick: insertCodeBlock, title: "Code block", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IcoCode, {}) }),
1542
+ show("image") && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { position: "relative", display: "inline-flex" }, children: [
1543
+ showImagePicker && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: backdrop, onMouseDown: () => setShowImagePicker(false) }),
1544
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { onClick: () => setShowImagePicker((v) => !v), title: "Insert image", active: showImagePicker, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IcoImage, {}) }),
1545
+ showImagePicker && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { position: "absolute", top: 34, left: 0, zIndex: 200 }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1546
+ ImagePicker,
1547
+ {
1548
+ onInsert: (src) => {
1549
+ insertImage(src);
1550
+ setShowImagePicker(false);
1551
+ },
1552
+ onClose: () => setShowImagePicker(false)
1553
+ }
1554
+ ) })
1212
1555
  ] }),
1213
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { position: "relative", display: "inline-flex" }, children: [
1214
- showTable && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: backdrop, onMouseDown: () => setShowTable(false) }),
1215
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Btn, { onClick: () => setShowTable((v) => !v), title: "Insert table", active: showTable || !!fmt.inTable, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IcoTable, {}) }),
1216
- showTable && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { position: "absolute", top: 34, left: 0, zIndex: 200 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TablePicker, { onInsert: (r, c) => {
1217
- insertTable(r, c);
1218
- setShowTable(false);
1219
- }, onClose: () => setShowTable(false) }) })
1556
+ show("table") && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { position: "relative", display: "inline-flex" }, children: [
1557
+ showTable && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: backdrop, onMouseDown: () => setShowTable(false) }),
1558
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { onClick: () => setShowTable((v) => !v), title: "Insert table", active: showTable || !!fmt.inTable, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IcoTable, {}) }),
1559
+ showTable && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { position: "absolute", top: 34, left: 0, zIndex: 200 }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1560
+ TablePicker,
1561
+ {
1562
+ onInsert: (r, c) => {
1563
+ insertTable(r, c);
1564
+ setShowTable(false);
1565
+ },
1566
+ onClose: () => setShowTable(false)
1567
+ }
1568
+ ) })
1220
1569
  ] }),
1221
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Sep, {})
1570
+ (show("link") || show("codeBlock") || show("image") || show("table")) && (show("html") || show("copyHtml")) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Sep, {})
1222
1571
  ] }),
1223
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1224
- Btn,
1225
- {
1226
- onClick: isCode ? toVisual : toCode,
1227
- title: "Toggle HTML",
1228
- active: isCode,
1229
- style: { fontSize: 12, fontWeight: 600, letterSpacing: "0.03em", padding: "0 8px" },
1230
- children: isCode ? "Visual" : "HTML"
1231
- }
1232
- ),
1233
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Btn, { onClick: copyHtml, title: "Copy HTML", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IcoCopy, {}) }),
1234
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { flex: 1 } }),
1235
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { fontSize: 12, color: "#aaa" }, children: [
1572
+ show("html") && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { onClick: isCode ? toVisual : toCode, title: "Toggle HTML", active: isCode, style: { fontSize: 12, fontWeight: 600, letterSpacing: "0.03em", padding: "0 8px" }, children: isCode ? "Visual" : "HTML" }),
1573
+ show("copyHtml") && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { onClick: copyHtml, title: "Copy HTML", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IcoCopy, {}) }),
1574
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { flex: 1 } }),
1575
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { style: { fontSize: 12, color: "#aaa" }, children: [
1236
1576
  words,
1237
1577
  " ",
1238
1578
  words === 1 ? "word" : "words"
1239
1579
  ] })
1240
1580
  ] }),
1241
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rte-area", ref: editorAreaRef, children: [
1242
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1581
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "rte-area", ref: editorAreaRef, children: [
1582
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1243
1583
  "textarea",
1244
1584
  {
1245
1585
  className: "rte-code",
@@ -1249,7 +1589,7 @@ function RichTextEditor({ value, onChange }) {
1249
1589
  style: { display: isCode ? "block" : "none" }
1250
1590
  }
1251
1591
  ),
1252
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1592
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1253
1593
  "div",
1254
1594
  {
1255
1595
  ref: editorRef,
@@ -1280,68 +1620,48 @@ function RichTextEditor({ value, onChange }) {
1280
1620
  style: { display: isCode ? "none" : "block" }
1281
1621
  }
1282
1622
  ),
1283
- !isCode && selectedImg && imgFP && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rte-float", style: { top: imgFP.top, left: imgFP.left, gap: 2 }, children: [
1284
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rte-float-arrow", style: { left: imgFP.arrowLeft } }),
1285
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Btn, { title: "Align left", onClick: () => {
1286
- selectedImg.style.marginLeft = "0";
1287
- selectedImg.style.marginRight = "auto";
1288
- selectImage(selectedImg);
1289
- }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlignIco, { t: "left" }) }),
1290
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Btn, { title: "Align center", onClick: () => {
1291
- selectedImg.style.marginLeft = "auto";
1292
- selectedImg.style.marginRight = "auto";
1293
- selectImage(selectedImg);
1294
- }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlignIco, { t: "center" }) }),
1295
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Btn, { title: "Align right", onClick: () => {
1296
- selectedImg.style.marginLeft = "auto";
1297
- selectedImg.style.marginRight = "0";
1298
- selectImage(selectedImg);
1299
- }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlignIco, { t: "right" }) }),
1300
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Sep, {}),
1301
- [25, 50, 75, 100].map((pct) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1302
- Btn,
1303
- {
1304
- title: `Width ${pct}%`,
1305
- onClick: () => {
1306
- selectedImg.style.width = `${pct}%`;
1307
- selectImage(selectedImg);
1308
- },
1309
- style: { fontSize: 10, minWidth: 28, padding: "0 4px" },
1310
- children: [
1311
- pct,
1312
- "%"
1313
- ]
1623
+ !isCode && selectedImg && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1624
+ ImageEditor,
1625
+ {
1626
+ img: selectedImg,
1627
+ containerRef: editorAreaRef,
1628
+ onClose: clearImageSel,
1629
+ onDelete: () => {
1630
+ selectedImg.remove();
1631
+ clearImageSel();
1632
+ refresh();
1314
1633
  },
1315
- pct
1316
- )),
1317
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Sep, {}),
1318
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Btn, { title: "Delete image", danger: true, onClick: () => {
1319
- selectedImg.remove();
1320
- clearImageSelection();
1321
- refresh();
1322
- }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "13", height: "13", viewBox: "0 0 13 13", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M2 2L11 11M11 2L2 11", stroke: "currentColor", strokeWidth: "1.4", strokeLinecap: "round" }) }) })
1323
- ] }),
1324
- !isCode && fmt.inTable && tableFP && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rte-float", style: { top: tableFP.top, left: tableFP.left }, children: [
1325
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rte-float-arrow", style: { left: tableFP.arrowLeft } }),
1326
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Btn, { onClick: () => tableOp("addRowAbove"), title: "Add row above", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IcoRowAbove, {}) }),
1327
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Btn, { onClick: () => tableOp("addRowBelow"), title: "Add row below", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IcoRowBelow, {}) }),
1328
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Btn, { onClick: () => tableOp("deleteRow"), title: "Delete row", danger: true, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IcoDelRow, {}) }),
1329
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Sep, {}),
1330
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Btn, { onClick: () => tableOp("addColLeft"), title: "Add col left", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IcoColLeft, {}) }),
1331
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Btn, { onClick: () => tableOp("addColRight"), title: "Add col right", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IcoColRight, {}) }),
1332
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Btn, { onClick: () => tableOp("deleteCol"), title: "Delete col", danger: true, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IcoDelCol, {}) }),
1333
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Sep, {}),
1334
- canMerge && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Btn, { onClick: () => doMerge(selCells), title: `Merge ${selCells.length} cells`, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IcoMerge, {}) }),
1335
- canSplit && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Btn, { onClick: doSplit, title: "Split merged cell", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IcoSplit, {}) }),
1336
- (canMerge || canSplit) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Sep, {}),
1337
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Btn, { onClick: () => tableOp("deleteTable"), title: "Delete table", danger: true, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IcoDelTable, {}) })
1634
+ onChange: refresh
1635
+ }
1636
+ ),
1637
+ !isCode && fmt.inTable && tableFP && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "rte-float", style: { top: tableFP.top, left: tableFP.left }, children: [
1638
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "rte-float-arrow", style: { left: tableFP.arrowLeft } }),
1639
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { onClick: () => tableOp("addRowAbove"), title: "Add row above", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IcoRowAbove, {}) }),
1640
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { onClick: () => tableOp("addRowBelow"), title: "Add row below", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IcoRowBelow, {}) }),
1641
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { onClick: () => tableOp("deleteRow"), title: "Delete row", danger: true, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IcoDelRow, {}) }),
1642
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Sep, {}),
1643
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { onClick: () => tableOp("addColLeft"), title: "Add col left", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IcoColLeft, {}) }),
1644
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { onClick: () => tableOp("addColRight"), title: "Add col right", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IcoColRight, {}) }),
1645
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { onClick: () => tableOp("deleteCol"), title: "Delete col", danger: true, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IcoDelCol, {}) }),
1646
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Sep, {}),
1647
+ canMerge && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { onClick: () => doMerge(selCells), title: `Merge ${selCells.length} cells`, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IcoMerge, {}) }),
1648
+ canSplit && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { onClick: doSplit, title: "Split merged cell", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IcoSplit, {}) }),
1649
+ (canMerge || canSplit) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Sep, {}),
1650
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { onClick: () => tableOp("deleteTable"), title: "Delete table", danger: true, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IcoDelTable, {}) })
1338
1651
  ] }),
1339
- !isCode && fmt.inLink && linkInfoFP && !linkBar && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rte-float", style: { top: linkInfoFP.top, left: linkInfoFP.left, gap: 4 }, children: [
1340
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rte-float-arrow", style: { left: linkInfoFP.arrowLeft } }),
1341
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IcoLink, {}),
1342
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: 12, color: "#1a6fc4", maxWidth: 160, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, title: fmt.linkHref, children: fmt.linkHref }),
1343
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Sep, {}),
1344
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Btn, { title: "Edit link", onClick: () => {
1652
+ !isCode && fmt.inLink && linkInfoFP && !linkBar && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "rte-float", style: { top: linkInfoFP.top, left: linkInfoFP.left, gap: 4 }, children: [
1653
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "rte-float-arrow", style: { left: linkInfoFP.arrowLeft } }),
1654
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IcoLink, {}),
1655
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1656
+ "span",
1657
+ {
1658
+ style: { fontSize: 12, color: "#1a6fc4", maxWidth: 160, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" },
1659
+ title: fmt.linkHref,
1660
+ children: fmt.linkHref
1661
+ }
1662
+ ),
1663
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Sep, {}),
1664
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { title: "Edit link", onClick: () => {
1345
1665
  var _a2;
1346
1666
  const anchor = getCurrentLink();
1347
1667
  if (!anchor) return;
@@ -1355,8 +1675,8 @@ function RichTextEditor({ value, onChange }) {
1355
1675
  setLinkUrl((_a2 = anchor.getAttribute("href")) != null ? _a2 : "https://");
1356
1676
  setLinkBar(true);
1357
1677
  setLinkInfoFP(null);
1358
- }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "13", height: "13", viewBox: "0 0 13 13", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M9 2L11 4L4.5 10.5H2.5V8.5L9 2Z", stroke: "currentColor", strokeWidth: "1.2", strokeLinejoin: "round" }) }) }),
1359
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Btn, { title: "Remove link", danger: true, onClick: () => {
1678
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { width: "13", height: "13", viewBox: "0 0 13 13", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M9 2L11 4L4.5 10.5H2.5V8.5L9 2Z", stroke: "currentColor", strokeWidth: "1.2", strokeLinejoin: "round" }) }) }),
1679
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Btn, { title: "Remove link", danger: true, onClick: () => {
1360
1680
  const anchor = getCurrentLink();
1361
1681
  if (!anchor) return;
1362
1682
  const sel = window.getSelection();
@@ -1366,16 +1686,16 @@ function RichTextEditor({ value, onChange }) {
1366
1686
  sel == null ? void 0 : sel.addRange(range);
1367
1687
  document.execCommand("unlink", false);
1368
1688
  refresh();
1369
- }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "13", height: "13", viewBox: "0 0 13 13", fill: "none", children: [
1370
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M4.5 7C4.9 7.6 5.5 8 6.1 8H7.9C8.6 8 9.2 7.7 9.6 7.2", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round" }),
1371
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M8.5 6C8.1 5.4 7.5 5 6.9 5H5.1C4.4 5 3.8 5.3 3.4 5.8", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round" }),
1372
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M2 2L11 11", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round" })
1689
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { width: "13", height: "13", viewBox: "0 0 13 13", fill: "none", children: [
1690
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M4.5 7C4.9 7.6 5.5 8 6.1 8H7.9C8.6 8 9.2 7.7 9.6 7.2", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round" }),
1691
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M8.5 6C8.1 5.4 7.5 5 6.9 5H5.1C4.4 5 3.8 5.3 3.4 5.8", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round" }),
1692
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M2 2L11 11", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round" })
1373
1693
  ] }) })
1374
1694
  ] }),
1375
- !isCode && linkBar && linkFP && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rte-float rte-linkbar", style: { top: linkFP.top, left: linkFP.left }, children: [
1376
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rte-float-arrow", style: { left: linkFP.arrowLeft } }),
1377
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IcoLink, {}),
1378
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1695
+ !isCode && linkBar && linkFP && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "rte-float rte-linkbar", style: { top: linkFP.top, left: linkFP.left }, children: [
1696
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "rte-float-arrow", style: { left: linkFP.arrowLeft } }),
1697
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IcoLink, {}),
1698
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1379
1699
  "input",
1380
1700
  {
1381
1701
  autoFocus: true,
@@ -1392,26 +1712,36 @@ function RichTextEditor({ value, onChange }) {
1392
1712
  placeholder: "https://example.com"
1393
1713
  }
1394
1714
  ),
1395
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: applyLink, style: { height: 26, padding: "0 10px", background: "#1a6fc4", color: "#fff", border: "none", borderRadius: 3, fontSize: 12, fontWeight: 600, cursor: "pointer" }, children: "Apply" }),
1396
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => {
1397
- setLinkBar(false);
1398
- setLinkFP(null);
1399
- }, style: { height: 26, padding: "0 8px", background: "transparent", color: "#666", border: "1px solid #ccc", borderRadius: 3, fontSize: 12, cursor: "pointer" }, children: "\u2715" })
1715
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1716
+ "button",
1717
+ {
1718
+ onClick: applyLink,
1719
+ style: { height: 26, padding: "0 10px", background: "#1a6fc4", color: "#fff", border: "none", borderRadius: 3, fontSize: 12, fontWeight: 600, cursor: "pointer" },
1720
+ children: "Apply"
1721
+ }
1722
+ ),
1723
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1724
+ "button",
1725
+ {
1726
+ onClick: () => {
1727
+ setLinkBar(false);
1728
+ setLinkFP(null);
1729
+ },
1730
+ style: { height: 26, padding: "0 8px", background: "transparent", color: "#666", border: "1px solid #ccc", borderRadius: 3, fontSize: 12, cursor: "pointer" },
1731
+ children: "\u2715"
1732
+ }
1733
+ )
1400
1734
  ] })
1401
1735
  ] }),
1402
- !isCode && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rte-footer", children: [
1403
- "Table: ",
1404
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: "drag" }),
1736
+ !isCode && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "rte-footer", children: [
1737
+ "Click image to edit \xA0\xB7\xA0 Drag handles to resize \xA0\xB7\xA0 Drop image file to insert \xA0\xB7\xA0 Table: ",
1738
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("strong", { children: "drag" }),
1405
1739
  " or ",
1406
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: "Shift+click" }),
1407
- " to select cells \xA0\xB7\xA0 ",
1408
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: "Tab" }),
1409
- " moves between cells \xA0\xB7\xA0 Drop an image file to insert"
1740
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("strong", { children: "Shift+click" }),
1741
+ " to select cells \xA0\xB7\xA0",
1742
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("strong", { children: "Tab" }),
1743
+ " moves between cells"
1410
1744
  ] })
1411
1745
  ] })
1412
1746
  ] });
1413
1747
  }
1414
- // Annotate the CommonJS export names for ESM import in node:
1415
- 0 && (module.exports = {
1416
- RichTextEditor
1417
- });