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