@refactico/pages 0.1.0 → 0.2.1

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.cjs CHANGED
@@ -113,154 +113,914 @@ const moveArrayItem = (arr, fromIndex, toIndex) => {
113
113
  return newArr;
114
114
  };
115
115
 
116
- const PlusIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs("svg", { className, width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
117
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "12", y1: "5", x2: "12", y2: "19" }),
118
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
119
- ] });
120
- const TextIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs("svg", { className, width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
121
- /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "4 7 4 4 20 4 20 7" }),
122
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "9", y1: "20", x2: "15", y2: "20" }),
123
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "12", y1: "4", x2: "12", y2: "20" })
124
- ] });
125
- const HeadingIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs("svg", { className, width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
126
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 4v16" }),
127
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 4v16" }),
128
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 12h12" })
129
- ] });
130
- const ImageIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs("svg", { className, width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
131
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }),
132
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "8.5", cy: "8.5", r: "1.5" }),
133
- /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "21 15 16 10 5 21" })
134
- ] });
135
- const CodeIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs("svg", { className, width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
136
- /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "16 18 22 12 16 6" }),
137
- /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "8 6 2 12 8 18" })
138
- ] });
139
- const TableIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs("svg", { className, width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
140
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }),
141
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "3", y1: "9", x2: "21", y2: "9" }),
142
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "3", y1: "15", x2: "21", y2: "15" }),
143
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "9", y1: "3", x2: "9", y2: "21" }),
144
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "15", y1: "3", x2: "15", y2: "21" })
145
- ] });
146
- const DividerIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsx("svg", { className, width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "3", y1: "12", x2: "21", y2: "12" }) });
147
- const QuoteIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs("svg", { className, width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
148
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 21c3 0 7-1 7-8V5c0-1.25-.756-2.017-2-2H4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2 1 0 1 0 1 1v1c0 1-1 2-2 2s-1 .008-1 1.031V21c0 1 0 1 1 1z" }),
149
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2h-4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2h.75c0 2.25.25 4-2.75 4v3c0 1 0 1 1 1z" })
150
- ] });
151
- const ListIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs("svg", { className, width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
152
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "8", y1: "6", x2: "21", y2: "6" }),
153
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "8", y1: "12", x2: "21", y2: "12" }),
154
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "8", y1: "18", x2: "21", y2: "18" }),
155
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "3", y1: "6", x2: "3.01", y2: "6" }),
156
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "3", y1: "12", x2: "3.01", y2: "12" }),
157
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "3", y1: "18", x2: "3.01", y2: "18" })
158
- ] });
159
- const CalloutIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs("svg", { className, width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
160
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10" }),
161
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "12", y1: "16", x2: "12", y2: "12" }),
162
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "12", y1: "8", x2: "12.01", y2: "8" })
163
- ] });
164
- const TrashIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs("svg", { className, width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
165
- /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "3 6 5 6 21 6" }),
166
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })
167
- ] });
168
- const DragIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs("svg", { className, width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
169
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "9", cy: "5", r: "1" }),
170
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "9", cy: "12", r: "1" }),
171
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "9", cy: "19", r: "1" }),
172
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "15", cy: "5", r: "1" }),
173
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "15", cy: "12", r: "1" }),
174
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "15", cy: "19", r: "1" })
175
- ] });
176
- const CopyIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs("svg", { className, width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
177
- /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", ry: "2" }),
178
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
179
- ] });
180
- const ChevronUpIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsx("svg", { className, width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "18 15 12 9 6 15" }) });
181
- const ChevronDownIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsx("svg", { className, width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "6 9 12 15 18 9" }) });
182
- const BoldIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs("svg", { className, width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
183
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z" }),
184
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z" })
185
- ] });
186
- const ItalicIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs("svg", { className, width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
187
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "19", y1: "4", x2: "10", y2: "4" }),
188
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "14", y1: "20", x2: "5", y2: "20" }),
189
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "15", y1: "4", x2: "9", y2: "20" })
190
- ] });
191
- const UnderlineIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs("svg", { className, width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
192
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 3v7a6 6 0 0 0 6 6 6 6 0 0 0 6-6V3" }),
193
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "4", y1: "21", x2: "20", y2: "21" })
194
- ] });
195
- const AlignLeftIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs("svg", { className, width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
196
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "17", y1: "10", x2: "3", y2: "10" }),
197
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "21", y1: "6", x2: "3", y2: "6" }),
198
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "21", y1: "14", x2: "3", y2: "14" }),
199
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "17", y1: "18", x2: "3", y2: "18" })
200
- ] });
201
- const AlignCenterIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs("svg", { className, width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
202
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "18", y1: "10", x2: "6", y2: "10" }),
203
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "21", y1: "6", x2: "3", y2: "6" }),
204
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "21", y1: "14", x2: "3", y2: "14" }),
205
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "18", y1: "18", x2: "6", y2: "18" })
206
- ] });
207
- const AlignRightIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs("svg", { className, width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
208
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "21", y1: "10", x2: "7", y2: "10" }),
209
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "21", y1: "6", x2: "3", y2: "6" }),
210
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "21", y1: "14", x2: "3", y2: "14" }),
211
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "21", y1: "18", x2: "7", y2: "18" })
212
- ] });
213
- const CheckIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsx("svg", { className, width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "20 6 9 17 4 12" }) });
214
- const UploadIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs("svg", { className, width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
215
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
216
- /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "17 8 12 3 7 8" }),
217
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "12", y1: "3", x2: "12", y2: "15" })
218
- ] });
116
+ const PlusIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs(
117
+ "svg",
118
+ {
119
+ className,
120
+ width: size,
121
+ height: size,
122
+ viewBox: "0 0 24 24",
123
+ fill: "none",
124
+ stroke: "currentColor",
125
+ strokeWidth: "2",
126
+ strokeLinecap: "round",
127
+ strokeLinejoin: "round",
128
+ children: [
129
+ /* @__PURE__ */ jsxRuntime.jsx(
130
+ "line",
131
+ {
132
+ x1: "12",
133
+ y1: "5",
134
+ x2: "12",
135
+ y2: "19"
136
+ }
137
+ ),
138
+ /* @__PURE__ */ jsxRuntime.jsx(
139
+ "line",
140
+ {
141
+ x1: "5",
142
+ y1: "12",
143
+ x2: "19",
144
+ y2: "12"
145
+ }
146
+ )
147
+ ]
148
+ }
149
+ );
150
+ const TextIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs(
151
+ "svg",
152
+ {
153
+ className,
154
+ width: size,
155
+ height: size,
156
+ viewBox: "0 0 24 24",
157
+ fill: "none",
158
+ stroke: "currentColor",
159
+ strokeWidth: "2",
160
+ strokeLinecap: "round",
161
+ strokeLinejoin: "round",
162
+ children: [
163
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "4 7 4 4 20 4 20 7" }),
164
+ /* @__PURE__ */ jsxRuntime.jsx(
165
+ "line",
166
+ {
167
+ x1: "9",
168
+ y1: "20",
169
+ x2: "15",
170
+ y2: "20"
171
+ }
172
+ ),
173
+ /* @__PURE__ */ jsxRuntime.jsx(
174
+ "line",
175
+ {
176
+ x1: "12",
177
+ y1: "4",
178
+ x2: "12",
179
+ y2: "20"
180
+ }
181
+ )
182
+ ]
183
+ }
184
+ );
185
+ const HeadingIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs(
186
+ "svg",
187
+ {
188
+ className,
189
+ width: size,
190
+ height: size,
191
+ viewBox: "0 0 24 24",
192
+ fill: "none",
193
+ stroke: "currentColor",
194
+ strokeWidth: "2",
195
+ strokeLinecap: "round",
196
+ strokeLinejoin: "round",
197
+ children: [
198
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 4v16" }),
199
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 4v16" }),
200
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 12h12" })
201
+ ]
202
+ }
203
+ );
204
+ const ImageIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs(
205
+ "svg",
206
+ {
207
+ className,
208
+ width: size,
209
+ height: size,
210
+ viewBox: "0 0 24 24",
211
+ fill: "none",
212
+ stroke: "currentColor",
213
+ strokeWidth: "2",
214
+ strokeLinecap: "round",
215
+ strokeLinejoin: "round",
216
+ children: [
217
+ /* @__PURE__ */ jsxRuntime.jsx(
218
+ "rect",
219
+ {
220
+ x: "3",
221
+ y: "3",
222
+ width: "18",
223
+ height: "18",
224
+ rx: "2",
225
+ ry: "2"
226
+ }
227
+ ),
228
+ /* @__PURE__ */ jsxRuntime.jsx(
229
+ "circle",
230
+ {
231
+ cx: "8.5",
232
+ cy: "8.5",
233
+ r: "1.5"
234
+ }
235
+ ),
236
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "21 15 16 10 5 21" })
237
+ ]
238
+ }
239
+ );
240
+ const CodeIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs(
241
+ "svg",
242
+ {
243
+ className,
244
+ width: size,
245
+ height: size,
246
+ viewBox: "0 0 24 24",
247
+ fill: "none",
248
+ stroke: "currentColor",
249
+ strokeWidth: "2",
250
+ strokeLinecap: "round",
251
+ strokeLinejoin: "round",
252
+ children: [
253
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "16 18 22 12 16 6" }),
254
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "8 6 2 12 8 18" })
255
+ ]
256
+ }
257
+ );
258
+ const TableIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs(
259
+ "svg",
260
+ {
261
+ className,
262
+ width: size,
263
+ height: size,
264
+ viewBox: "0 0 24 24",
265
+ fill: "none",
266
+ stroke: "currentColor",
267
+ strokeWidth: "2",
268
+ strokeLinecap: "round",
269
+ strokeLinejoin: "round",
270
+ children: [
271
+ /* @__PURE__ */ jsxRuntime.jsx(
272
+ "rect",
273
+ {
274
+ x: "3",
275
+ y: "3",
276
+ width: "18",
277
+ height: "18",
278
+ rx: "2",
279
+ ry: "2"
280
+ }
281
+ ),
282
+ /* @__PURE__ */ jsxRuntime.jsx(
283
+ "line",
284
+ {
285
+ x1: "3",
286
+ y1: "9",
287
+ x2: "21",
288
+ y2: "9"
289
+ }
290
+ ),
291
+ /* @__PURE__ */ jsxRuntime.jsx(
292
+ "line",
293
+ {
294
+ x1: "3",
295
+ y1: "15",
296
+ x2: "21",
297
+ y2: "15"
298
+ }
299
+ ),
300
+ /* @__PURE__ */ jsxRuntime.jsx(
301
+ "line",
302
+ {
303
+ x1: "9",
304
+ y1: "3",
305
+ x2: "9",
306
+ y2: "21"
307
+ }
308
+ ),
309
+ /* @__PURE__ */ jsxRuntime.jsx(
310
+ "line",
311
+ {
312
+ x1: "15",
313
+ y1: "3",
314
+ x2: "15",
315
+ y2: "21"
316
+ }
317
+ )
318
+ ]
319
+ }
320
+ );
321
+ const DividerIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsx(
322
+ "svg",
323
+ {
324
+ className,
325
+ width: size,
326
+ height: size,
327
+ viewBox: "0 0 24 24",
328
+ fill: "none",
329
+ stroke: "currentColor",
330
+ strokeWidth: "2",
331
+ strokeLinecap: "round",
332
+ strokeLinejoin: "round",
333
+ children: /* @__PURE__ */ jsxRuntime.jsx(
334
+ "line",
335
+ {
336
+ x1: "3",
337
+ y1: "12",
338
+ x2: "21",
339
+ y2: "12"
340
+ }
341
+ )
342
+ }
343
+ );
344
+ const QuoteIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs(
345
+ "svg",
346
+ {
347
+ className,
348
+ width: size,
349
+ height: size,
350
+ viewBox: "0 0 24 24",
351
+ fill: "none",
352
+ stroke: "currentColor",
353
+ strokeWidth: "2",
354
+ strokeLinecap: "round",
355
+ strokeLinejoin: "round",
356
+ children: [
357
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 21c3 0 7-1 7-8V5c0-1.25-.756-2.017-2-2H4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2 1 0 1 0 1 1v1c0 1-1 2-2 2s-1 .008-1 1.031V21c0 1 0 1 1 1z" }),
358
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2h-4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2h.75c0 2.25.25 4-2.75 4v3c0 1 0 1 1 1z" })
359
+ ]
360
+ }
361
+ );
362
+ const ListIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs(
363
+ "svg",
364
+ {
365
+ className,
366
+ width: size,
367
+ height: size,
368
+ viewBox: "0 0 24 24",
369
+ fill: "none",
370
+ stroke: "currentColor",
371
+ strokeWidth: "2",
372
+ strokeLinecap: "round",
373
+ strokeLinejoin: "round",
374
+ children: [
375
+ /* @__PURE__ */ jsxRuntime.jsx(
376
+ "line",
377
+ {
378
+ x1: "8",
379
+ y1: "6",
380
+ x2: "21",
381
+ y2: "6"
382
+ }
383
+ ),
384
+ /* @__PURE__ */ jsxRuntime.jsx(
385
+ "line",
386
+ {
387
+ x1: "8",
388
+ y1: "12",
389
+ x2: "21",
390
+ y2: "12"
391
+ }
392
+ ),
393
+ /* @__PURE__ */ jsxRuntime.jsx(
394
+ "line",
395
+ {
396
+ x1: "8",
397
+ y1: "18",
398
+ x2: "21",
399
+ y2: "18"
400
+ }
401
+ ),
402
+ /* @__PURE__ */ jsxRuntime.jsx(
403
+ "line",
404
+ {
405
+ x1: "3",
406
+ y1: "6",
407
+ x2: "3.01",
408
+ y2: "6"
409
+ }
410
+ ),
411
+ /* @__PURE__ */ jsxRuntime.jsx(
412
+ "line",
413
+ {
414
+ x1: "3",
415
+ y1: "12",
416
+ x2: "3.01",
417
+ y2: "12"
418
+ }
419
+ ),
420
+ /* @__PURE__ */ jsxRuntime.jsx(
421
+ "line",
422
+ {
423
+ x1: "3",
424
+ y1: "18",
425
+ x2: "3.01",
426
+ y2: "18"
427
+ }
428
+ )
429
+ ]
430
+ }
431
+ );
432
+ const CalloutIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs(
433
+ "svg",
434
+ {
435
+ className,
436
+ width: size,
437
+ height: size,
438
+ viewBox: "0 0 24 24",
439
+ fill: "none",
440
+ stroke: "currentColor",
441
+ strokeWidth: "2",
442
+ strokeLinecap: "round",
443
+ strokeLinejoin: "round",
444
+ children: [
445
+ /* @__PURE__ */ jsxRuntime.jsx(
446
+ "circle",
447
+ {
448
+ cx: "12",
449
+ cy: "12",
450
+ r: "10"
451
+ }
452
+ ),
453
+ /* @__PURE__ */ jsxRuntime.jsx(
454
+ "line",
455
+ {
456
+ x1: "12",
457
+ y1: "16",
458
+ x2: "12",
459
+ y2: "12"
460
+ }
461
+ ),
462
+ /* @__PURE__ */ jsxRuntime.jsx(
463
+ "line",
464
+ {
465
+ x1: "12",
466
+ y1: "8",
467
+ x2: "12.01",
468
+ y2: "8"
469
+ }
470
+ )
471
+ ]
472
+ }
473
+ );
474
+ const TrashIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs(
475
+ "svg",
476
+ {
477
+ className,
478
+ width: size,
479
+ height: size,
480
+ viewBox: "0 0 24 24",
481
+ fill: "none",
482
+ stroke: "currentColor",
483
+ strokeWidth: "2",
484
+ strokeLinecap: "round",
485
+ strokeLinejoin: "round",
486
+ children: [
487
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "3 6 5 6 21 6" }),
488
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })
489
+ ]
490
+ }
491
+ );
492
+ const DragIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs(
493
+ "svg",
494
+ {
495
+ className,
496
+ width: size,
497
+ height: size,
498
+ viewBox: "0 0 24 24",
499
+ fill: "none",
500
+ stroke: "currentColor",
501
+ strokeWidth: "2",
502
+ strokeLinecap: "round",
503
+ strokeLinejoin: "round",
504
+ children: [
505
+ /* @__PURE__ */ jsxRuntime.jsx(
506
+ "circle",
507
+ {
508
+ cx: "9",
509
+ cy: "5",
510
+ r: "1"
511
+ }
512
+ ),
513
+ /* @__PURE__ */ jsxRuntime.jsx(
514
+ "circle",
515
+ {
516
+ cx: "9",
517
+ cy: "12",
518
+ r: "1"
519
+ }
520
+ ),
521
+ /* @__PURE__ */ jsxRuntime.jsx(
522
+ "circle",
523
+ {
524
+ cx: "9",
525
+ cy: "19",
526
+ r: "1"
527
+ }
528
+ ),
529
+ /* @__PURE__ */ jsxRuntime.jsx(
530
+ "circle",
531
+ {
532
+ cx: "15",
533
+ cy: "5",
534
+ r: "1"
535
+ }
536
+ ),
537
+ /* @__PURE__ */ jsxRuntime.jsx(
538
+ "circle",
539
+ {
540
+ cx: "15",
541
+ cy: "12",
542
+ r: "1"
543
+ }
544
+ ),
545
+ /* @__PURE__ */ jsxRuntime.jsx(
546
+ "circle",
547
+ {
548
+ cx: "15",
549
+ cy: "19",
550
+ r: "1"
551
+ }
552
+ )
553
+ ]
554
+ }
555
+ );
556
+ const CopyIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs(
557
+ "svg",
558
+ {
559
+ className,
560
+ width: size,
561
+ height: size,
562
+ viewBox: "0 0 24 24",
563
+ fill: "none",
564
+ stroke: "currentColor",
565
+ strokeWidth: "2",
566
+ strokeLinecap: "round",
567
+ strokeLinejoin: "round",
568
+ children: [
569
+ /* @__PURE__ */ jsxRuntime.jsx(
570
+ "rect",
571
+ {
572
+ x: "9",
573
+ y: "9",
574
+ width: "13",
575
+ height: "13",
576
+ rx: "2",
577
+ ry: "2"
578
+ }
579
+ ),
580
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
581
+ ]
582
+ }
583
+ );
584
+ const ChevronUpIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsx(
585
+ "svg",
586
+ {
587
+ className,
588
+ width: size,
589
+ height: size,
590
+ viewBox: "0 0 24 24",
591
+ fill: "none",
592
+ stroke: "currentColor",
593
+ strokeWidth: "2",
594
+ strokeLinecap: "round",
595
+ strokeLinejoin: "round",
596
+ children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "18 15 12 9 6 15" })
597
+ }
598
+ );
599
+ const ChevronDownIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsx(
600
+ "svg",
601
+ {
602
+ className,
603
+ width: size,
604
+ height: size,
605
+ viewBox: "0 0 24 24",
606
+ fill: "none",
607
+ stroke: "currentColor",
608
+ strokeWidth: "2",
609
+ strokeLinecap: "round",
610
+ strokeLinejoin: "round",
611
+ children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "6 9 12 15 18 9" })
612
+ }
613
+ );
614
+ const ChevronLeftIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsx(
615
+ "svg",
616
+ {
617
+ className,
618
+ width: size,
619
+ height: size,
620
+ viewBox: "0 0 24 24",
621
+ fill: "none",
622
+ stroke: "currentColor",
623
+ strokeWidth: "2",
624
+ strokeLinecap: "round",
625
+ strokeLinejoin: "round",
626
+ children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "15 18 9 12 15 6" })
627
+ }
628
+ );
629
+ const ChevronRightIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsx(
630
+ "svg",
631
+ {
632
+ className,
633
+ width: size,
634
+ height: size,
635
+ viewBox: "0 0 24 24",
636
+ fill: "none",
637
+ stroke: "currentColor",
638
+ strokeWidth: "2",
639
+ strokeLinecap: "round",
640
+ strokeLinejoin: "round",
641
+ children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "9 18 15 12 9 6" })
642
+ }
643
+ );
644
+ const BoldIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs(
645
+ "svg",
646
+ {
647
+ className,
648
+ width: size,
649
+ height: size,
650
+ viewBox: "0 0 24 24",
651
+ fill: "none",
652
+ stroke: "currentColor",
653
+ strokeWidth: "2",
654
+ strokeLinecap: "round",
655
+ strokeLinejoin: "round",
656
+ children: [
657
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z" }),
658
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z" })
659
+ ]
660
+ }
661
+ );
662
+ const ItalicIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs(
663
+ "svg",
664
+ {
665
+ className,
666
+ width: size,
667
+ height: size,
668
+ viewBox: "0 0 24 24",
669
+ fill: "none",
670
+ stroke: "currentColor",
671
+ strokeWidth: "2",
672
+ strokeLinecap: "round",
673
+ strokeLinejoin: "round",
674
+ children: [
675
+ /* @__PURE__ */ jsxRuntime.jsx(
676
+ "line",
677
+ {
678
+ x1: "19",
679
+ y1: "4",
680
+ x2: "10",
681
+ y2: "4"
682
+ }
683
+ ),
684
+ /* @__PURE__ */ jsxRuntime.jsx(
685
+ "line",
686
+ {
687
+ x1: "14",
688
+ y1: "20",
689
+ x2: "5",
690
+ y2: "20"
691
+ }
692
+ ),
693
+ /* @__PURE__ */ jsxRuntime.jsx(
694
+ "line",
695
+ {
696
+ x1: "15",
697
+ y1: "4",
698
+ x2: "9",
699
+ y2: "20"
700
+ }
701
+ )
702
+ ]
703
+ }
704
+ );
705
+ const UnderlineIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs(
706
+ "svg",
707
+ {
708
+ className,
709
+ width: size,
710
+ height: size,
711
+ viewBox: "0 0 24 24",
712
+ fill: "none",
713
+ stroke: "currentColor",
714
+ strokeWidth: "2",
715
+ strokeLinecap: "round",
716
+ strokeLinejoin: "round",
717
+ children: [
718
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 3v7a6 6 0 0 0 6 6 6 6 0 0 0 6-6V3" }),
719
+ /* @__PURE__ */ jsxRuntime.jsx(
720
+ "line",
721
+ {
722
+ x1: "4",
723
+ y1: "21",
724
+ x2: "20",
725
+ y2: "21"
726
+ }
727
+ )
728
+ ]
729
+ }
730
+ );
731
+ const AlignLeftIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs(
732
+ "svg",
733
+ {
734
+ className,
735
+ width: size,
736
+ height: size,
737
+ viewBox: "0 0 24 24",
738
+ fill: "none",
739
+ stroke: "currentColor",
740
+ strokeWidth: "2",
741
+ strokeLinecap: "round",
742
+ strokeLinejoin: "round",
743
+ children: [
744
+ /* @__PURE__ */ jsxRuntime.jsx(
745
+ "line",
746
+ {
747
+ x1: "17",
748
+ y1: "10",
749
+ x2: "3",
750
+ y2: "10"
751
+ }
752
+ ),
753
+ /* @__PURE__ */ jsxRuntime.jsx(
754
+ "line",
755
+ {
756
+ x1: "21",
757
+ y1: "6",
758
+ x2: "3",
759
+ y2: "6"
760
+ }
761
+ ),
762
+ /* @__PURE__ */ jsxRuntime.jsx(
763
+ "line",
764
+ {
765
+ x1: "21",
766
+ y1: "14",
767
+ x2: "3",
768
+ y2: "14"
769
+ }
770
+ ),
771
+ /* @__PURE__ */ jsxRuntime.jsx(
772
+ "line",
773
+ {
774
+ x1: "17",
775
+ y1: "18",
776
+ x2: "3",
777
+ y2: "18"
778
+ }
779
+ )
780
+ ]
781
+ }
782
+ );
783
+ const AlignCenterIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs(
784
+ "svg",
785
+ {
786
+ className,
787
+ width: size,
788
+ height: size,
789
+ viewBox: "0 0 24 24",
790
+ fill: "none",
791
+ stroke: "currentColor",
792
+ strokeWidth: "2",
793
+ strokeLinecap: "round",
794
+ strokeLinejoin: "round",
795
+ children: [
796
+ /* @__PURE__ */ jsxRuntime.jsx(
797
+ "line",
798
+ {
799
+ x1: "18",
800
+ y1: "10",
801
+ x2: "6",
802
+ y2: "10"
803
+ }
804
+ ),
805
+ /* @__PURE__ */ jsxRuntime.jsx(
806
+ "line",
807
+ {
808
+ x1: "21",
809
+ y1: "6",
810
+ x2: "3",
811
+ y2: "6"
812
+ }
813
+ ),
814
+ /* @__PURE__ */ jsxRuntime.jsx(
815
+ "line",
816
+ {
817
+ x1: "21",
818
+ y1: "14",
819
+ x2: "3",
820
+ y2: "14"
821
+ }
822
+ ),
823
+ /* @__PURE__ */ jsxRuntime.jsx(
824
+ "line",
825
+ {
826
+ x1: "18",
827
+ y1: "18",
828
+ x2: "6",
829
+ y2: "18"
830
+ }
831
+ )
832
+ ]
833
+ }
834
+ );
835
+ const AlignRightIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs(
836
+ "svg",
837
+ {
838
+ className,
839
+ width: size,
840
+ height: size,
841
+ viewBox: "0 0 24 24",
842
+ fill: "none",
843
+ stroke: "currentColor",
844
+ strokeWidth: "2",
845
+ strokeLinecap: "round",
846
+ strokeLinejoin: "round",
847
+ children: [
848
+ /* @__PURE__ */ jsxRuntime.jsx(
849
+ "line",
850
+ {
851
+ x1: "21",
852
+ y1: "10",
853
+ x2: "7",
854
+ y2: "10"
855
+ }
856
+ ),
857
+ /* @__PURE__ */ jsxRuntime.jsx(
858
+ "line",
859
+ {
860
+ x1: "21",
861
+ y1: "6",
862
+ x2: "3",
863
+ y2: "6"
864
+ }
865
+ ),
866
+ /* @__PURE__ */ jsxRuntime.jsx(
867
+ "line",
868
+ {
869
+ x1: "21",
870
+ y1: "14",
871
+ x2: "3",
872
+ y2: "14"
873
+ }
874
+ ),
875
+ /* @__PURE__ */ jsxRuntime.jsx(
876
+ "line",
877
+ {
878
+ x1: "21",
879
+ y1: "18",
880
+ x2: "7",
881
+ y2: "18"
882
+ }
883
+ )
884
+ ]
885
+ }
886
+ );
887
+ const CheckIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsx(
888
+ "svg",
889
+ {
890
+ className,
891
+ width: size,
892
+ height: size,
893
+ viewBox: "0 0 24 24",
894
+ fill: "none",
895
+ stroke: "currentColor",
896
+ strokeWidth: "2",
897
+ strokeLinecap: "round",
898
+ strokeLinejoin: "round",
899
+ children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "20 6 9 17 4 12" })
900
+ }
901
+ );
902
+ const UploadIcon = ({ className = "", size = 20 }) => /* @__PURE__ */ jsxRuntime.jsxs(
903
+ "svg",
904
+ {
905
+ className,
906
+ width: size,
907
+ height: size,
908
+ viewBox: "0 0 24 24",
909
+ fill: "none",
910
+ stroke: "currentColor",
911
+ strokeWidth: "2",
912
+ strokeLinecap: "round",
913
+ strokeLinejoin: "round",
914
+ children: [
915
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
916
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "17 8 12 3 7 8" }),
917
+ /* @__PURE__ */ jsxRuntime.jsx(
918
+ "line",
919
+ {
920
+ x1: "12",
921
+ y1: "3",
922
+ x2: "12",
923
+ y2: "15"
924
+ }
925
+ )
926
+ ]
927
+ }
928
+ );
219
929
 
220
930
  const blockOptions = [
221
931
  { type: "text", label: "Text", description: "Plain text paragraph", icon: TextIcon },
222
932
  { type: "heading", label: "Heading", description: "Section heading", icon: HeadingIcon },
223
933
  { type: "image", label: "Image", description: "Upload or embed image", icon: ImageIcon },
224
- { type: "code", label: "Code", description: "Code block with syntax highlighting", icon: CodeIcon },
934
+ {
935
+ type: "code",
936
+ label: "Code",
937
+ description: "Code block with syntax highlighting",
938
+ icon: CodeIcon
939
+ },
225
940
  { type: "table", label: "Table", description: "Insert a table", icon: TableIcon },
226
941
  { type: "list", label: "List", description: "Bullet, numbered, or checklist", icon: ListIcon },
227
942
  { type: "quote", label: "Quote", description: "Blockquote", icon: QuoteIcon },
228
- { type: "callout", label: "Callout", description: "Info, warning, or tip box", icon: CalloutIcon },
229
- { type: "divider", label: "Divider", description: "Horizontal line separator", icon: DividerIcon }
943
+ {
944
+ type: "callout",
945
+ label: "Callout",
946
+ description: "Info, warning, or tip box",
947
+ icon: CalloutIcon
948
+ },
949
+ {
950
+ type: "divider",
951
+ label: "Divider",
952
+ description: "Horizontal line separator",
953
+ icon: DividerIcon
954
+ }
230
955
  ];
231
956
  const AddBlockMenu = ({ onAdd, onClose, theme = "light" }) => {
232
957
  const menuRef = react.useRef(null);
233
958
  const [focusedIndex, setFocusedIndex] = react.useState(0);
959
+ const [alignment, setAlignment] = react.useState("left");
234
960
  const isDark = theme === "dark";
235
- const handleKeyDown = react.useCallback((e) => {
236
- switch (e.key) {
237
- case "ArrowDown":
238
- e.preventDefault();
239
- setFocusedIndex((prev) => (prev + 1) % blockOptions.length);
240
- break;
241
- case "ArrowUp":
242
- e.preventDefault();
243
- setFocusedIndex((prev) => (prev - 1 + blockOptions.length) % blockOptions.length);
244
- break;
245
- case "Enter":
246
- case " ": {
247
- e.preventDefault();
248
- const option = blockOptions[focusedIndex];
249
- if (option) {
250
- onAdd(option.type);
251
- onClose();
961
+ react.useEffect(() => {
962
+ const adjustPosition = () => {
963
+ if (!menuRef.current) return;
964
+ const menu = menuRef.current;
965
+ const rect = menu.getBoundingClientRect();
966
+ const viewportWidth = window.innerWidth;
967
+ const menuWidth = rect.width;
968
+ const padding = 8;
969
+ const parentRect = menu.parentElement?.getBoundingClientRect();
970
+ if (!parentRect) return;
971
+ const leftAlignedRight = parentRect.left + menuWidth;
972
+ const overflowsRight = leftAlignedRight > viewportWidth - padding;
973
+ const rightAlignedLeft = parentRect.right - menuWidth;
974
+ const overflowsLeft = rightAlignedLeft < padding;
975
+ if (overflowsRight && overflowsLeft) {
976
+ setAlignment("center");
977
+ } else if (overflowsRight) {
978
+ setAlignment("right");
979
+ } else {
980
+ setAlignment("left");
981
+ }
982
+ };
983
+ const timer = setTimeout(() => {
984
+ adjustPosition();
985
+ }, 0);
986
+ window.addEventListener("resize", adjustPosition);
987
+ return () => {
988
+ clearTimeout(timer);
989
+ window.removeEventListener("resize", adjustPosition);
990
+ };
991
+ }, []);
992
+ const handleKeyDown = react.useCallback(
993
+ (e) => {
994
+ switch (e.key) {
995
+ case "ArrowDown":
996
+ e.preventDefault();
997
+ setFocusedIndex((prev) => (prev + 1) % blockOptions.length);
998
+ break;
999
+ case "ArrowUp":
1000
+ e.preventDefault();
1001
+ setFocusedIndex((prev) => (prev - 1 + blockOptions.length) % blockOptions.length);
1002
+ break;
1003
+ case "Enter":
1004
+ case " ": {
1005
+ e.preventDefault();
1006
+ const option = blockOptions[focusedIndex];
1007
+ if (option) {
1008
+ onAdd(option.type);
1009
+ onClose();
1010
+ }
1011
+ break;
252
1012
  }
253
- break;
1013
+ case "Escape":
1014
+ e.preventDefault();
1015
+ onClose();
1016
+ break;
1017
+ case "Tab":
1018
+ onClose();
1019
+ break;
254
1020
  }
255
- case "Escape":
256
- e.preventDefault();
257
- onClose();
258
- break;
259
- case "Tab":
260
- onClose();
261
- break;
262
- }
263
- }, [focusedIndex, onAdd, onClose]);
1021
+ },
1022
+ [focusedIndex, onAdd, onClose]
1023
+ );
264
1024
  react.useEffect(() => {
265
1025
  const handleClickOutside = (event) => {
266
1026
  if (menuRef.current && !menuRef.current.contains(event.target)) {
@@ -288,7 +1048,7 @@ const AddBlockMenu = ({ onAdd, onClose, theme = "light" }) => {
288
1048
  "aria-label": "Add block menu",
289
1049
  tabIndex: 0,
290
1050
  onKeyDown: handleKeyDown,
291
- className: `absolute z-50 mt-2 w-72 max-h-80 overflow-y-auto rounded-xl shadow-xl border animate-in fade-in slide-in-from-top-2 duration-200 focus:outline-none ${isDark ? "bg-slate-800 border-slate-700" : "bg-white border-slate-200"}`,
1051
+ className: `absolute z-50 top-full mt-2 w-72 max-w-[calc(100vw-16px)] max-h-80 overflow-y-auto rounded-xl shadow-xl border animate-in fade-in slide-in-from-top-2 duration-200 focus:outline-none ${alignment === "center" ? "left-1/2 -translate-x-1/2" : alignment === "right" ? "right-0" : "left-0"} ${isDark ? "bg-slate-800 border-slate-700" : "bg-white border-slate-200"}`,
292
1052
  children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-2", children: [
293
1053
  /* @__PURE__ */ jsxRuntime.jsx(
294
1054
  "p",
@@ -298,78 +1058,164 @@ const AddBlockMenu = ({ onAdd, onClose, theme = "light" }) => {
298
1058
  children: "Add Block"
299
1059
  }
300
1060
  ),
301
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1", role: "group", "aria-labelledby": "add-block-menu-label", children: blockOptions.map((option, index) => {
302
- const Icon = option.icon;
303
- const isFocused = index === focusedIndex;
304
- return /* @__PURE__ */ jsxRuntime.jsxs(
305
- "button",
306
- {
307
- role: "menuitem",
308
- type: "button",
309
- tabIndex: -1,
310
- onClick: () => {
311
- onAdd(option.type);
312
- onClose();
313
- },
314
- onMouseEnter: () => setFocusedIndex(index),
315
- "aria-label": `Add ${option.label} block: ${option.description}`,
316
- className: `w-full flex items-center gap-3 px-3 py-2.5 rounded-lg transition-colors text-left group ${isFocused ? isDark ? "bg-slate-700" : "bg-slate-100" : isDark ? "hover:bg-slate-700" : "hover:bg-slate-50"}`,
317
- children: [
318
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex-shrink-0 w-10 h-10 flex items-center justify-center rounded-lg transition-colors ${isDark ? "bg-slate-700 group-hover:bg-slate-600" : "bg-slate-100 group-hover:bg-slate-200"}`, children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: isDark ? "text-slate-300" : "text-slate-600", size: 20, "aria-hidden": "true" }) }),
319
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
320
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-sm font-medium ${isDark ? "text-white" : "text-slate-900"}`, children: option.label }),
321
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-xs truncate ${isDark ? "text-slate-400" : "text-slate-500"}`, children: option.description })
322
- ] })
323
- ]
324
- },
325
- option.type
326
- );
327
- }) })
1061
+ /* @__PURE__ */ jsxRuntime.jsx(
1062
+ "div",
1063
+ {
1064
+ className: "space-y-1",
1065
+ role: "group",
1066
+ "aria-labelledby": "add-block-menu-label",
1067
+ children: blockOptions.map((option, index) => {
1068
+ const Icon = option.icon;
1069
+ const isFocused = index === focusedIndex;
1070
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1071
+ "button",
1072
+ {
1073
+ role: "menuitem",
1074
+ type: "button",
1075
+ tabIndex: -1,
1076
+ onClick: () => {
1077
+ onAdd(option.type);
1078
+ onClose();
1079
+ },
1080
+ onMouseEnter: () => setFocusedIndex(index),
1081
+ "aria-label": `Add ${option.label} block: ${option.description}`,
1082
+ className: `w-full flex items-center gap-3 px-3 py-2.5 rounded-lg transition-colors text-left group ${isFocused ? isDark ? "bg-slate-700" : "bg-slate-100" : isDark ? "hover:bg-slate-700" : "hover:bg-slate-50"}`,
1083
+ children: [
1084
+ /* @__PURE__ */ jsxRuntime.jsx(
1085
+ "div",
1086
+ {
1087
+ className: `flex-shrink-0 w-10 h-10 flex items-center justify-center rounded-lg transition-colors ${isDark ? "bg-slate-700 group-hover:bg-slate-600" : "bg-slate-100 group-hover:bg-slate-200"}`,
1088
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1089
+ Icon,
1090
+ {
1091
+ className: isDark ? "text-slate-300" : "text-slate-600",
1092
+ size: 20,
1093
+ "aria-hidden": "true"
1094
+ }
1095
+ )
1096
+ }
1097
+ ),
1098
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
1099
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-sm font-medium ${isDark ? "text-white" : "text-slate-900"}`, children: option.label }),
1100
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-xs truncate ${isDark ? "text-slate-400" : "text-slate-500"}`, children: option.description })
1101
+ ] })
1102
+ ]
1103
+ },
1104
+ option.type
1105
+ );
1106
+ })
1107
+ }
1108
+ )
328
1109
  ] })
329
1110
  }
330
1111
  );
331
1112
  };
332
1113
 
1114
+ function useToolbarPosition({
1115
+ containerRef,
1116
+ isVisible,
1117
+ minSpaceAbove = 60,
1118
+ topOffset = 0
1119
+ }) {
1120
+ const [showBelow, setShowBelow] = react.useState(false);
1121
+ const recalculate = react.useCallback(() => {
1122
+ if (!containerRef.current || !isVisible) {
1123
+ return;
1124
+ }
1125
+ const rect = containerRef.current.getBoundingClientRect();
1126
+ const spaceAbove = rect.top - topOffset;
1127
+ setShowBelow(spaceAbove < minSpaceAbove);
1128
+ }, [containerRef, isVisible, minSpaceAbove, topOffset]);
1129
+ react.useEffect(() => {
1130
+ if (!isVisible) {
1131
+ return;
1132
+ }
1133
+ recalculate();
1134
+ const handleScroll = () => recalculate();
1135
+ const handleResize = () => recalculate();
1136
+ window.addEventListener("scroll", handleScroll, { passive: true });
1137
+ window.addEventListener("resize", handleResize, { passive: true });
1138
+ const scrollParents = [];
1139
+ let scrollParent = containerRef.current?.parentElement;
1140
+ while (scrollParent) {
1141
+ scrollParent.addEventListener("scroll", handleScroll, { passive: true });
1142
+ scrollParents.push(scrollParent);
1143
+ scrollParent = scrollParent.parentElement;
1144
+ }
1145
+ return () => {
1146
+ window.removeEventListener("scroll", handleScroll);
1147
+ window.removeEventListener("resize", handleResize);
1148
+ scrollParents.forEach((parent) => {
1149
+ parent.removeEventListener("scroll", handleScroll);
1150
+ });
1151
+ };
1152
+ }, [isVisible, recalculate, containerRef]);
1153
+ return { showBelow, recalculate };
1154
+ }
1155
+
333
1156
  const fontSizeMap = {
334
1157
  sm: "text-sm leading-relaxed",
335
1158
  base: "text-base leading-relaxed",
336
1159
  lg: "text-lg leading-relaxed",
337
1160
  xl: "text-xl leading-relaxed"
338
1161
  };
339
- const alignmentMap$2 = {
1162
+ const alignmentMap$1 = {
340
1163
  left: "text-left",
341
1164
  center: "text-center",
342
1165
  right: "text-right",
343
1166
  justify: "text-justify"
344
1167
  };
345
- const TextBlockComponent = ({ block, onUpdate, readOnly, theme = "light" }) => {
1168
+ const TextBlockComponent = ({
1169
+ block,
1170
+ onUpdate,
1171
+ readOnly,
1172
+ theme = "light"
1173
+ }) => {
346
1174
  const [showToolbar, setShowToolbar] = react.useState(false);
347
1175
  const textareaRef = react.useRef(null);
1176
+ const containerRef = react.useRef(null);
348
1177
  const isDark = theme === "dark";
1178
+ const { showBelow } = useToolbarPosition({
1179
+ containerRef,
1180
+ isVisible: showToolbar && !readOnly,
1181
+ minSpaceAbove: 60
1182
+ });
349
1183
  react.useEffect(() => {
350
1184
  if (textareaRef.current) {
351
1185
  textareaRef.current.style.height = "auto";
352
1186
  textareaRef.current.style.height = textareaRef.current.scrollHeight + "px";
353
1187
  }
354
1188
  }, [block.content]);
355
- const handleChange = react.useCallback((e) => {
356
- onUpdate({ ...block, content: e.target.value });
357
- }, [block, onUpdate]);
358
- const toggleStyle = react.useCallback((style) => {
359
- onUpdate({
360
- ...block,
361
- style: {
362
- ...block.style,
363
- [style]: !block.style?.[style]
364
- }
365
- });
366
- }, [block, onUpdate]);
367
- const setAlignment = react.useCallback((alignment) => {
368
- onUpdate({ ...block, alignment });
369
- }, [block, onUpdate]);
370
- const setFontSize = react.useCallback((fontSize) => {
371
- onUpdate({ ...block, fontSize });
372
- }, [block, onUpdate]);
1189
+ const handleChange = react.useCallback(
1190
+ (e) => {
1191
+ onUpdate({ ...block, content: e.target.value });
1192
+ },
1193
+ [block, onUpdate]
1194
+ );
1195
+ const toggleStyle = react.useCallback(
1196
+ (style) => {
1197
+ onUpdate({
1198
+ ...block,
1199
+ style: {
1200
+ ...block.style,
1201
+ [style]: !block.style?.[style]
1202
+ }
1203
+ });
1204
+ },
1205
+ [block, onUpdate]
1206
+ );
1207
+ const setAlignment = react.useCallback(
1208
+ (alignment) => {
1209
+ onUpdate({ ...block, alignment });
1210
+ },
1211
+ [block, onUpdate]
1212
+ );
1213
+ const setFontSize = react.useCallback(
1214
+ (fontSize) => {
1215
+ onUpdate({ ...block, fontSize });
1216
+ },
1217
+ [block, onUpdate]
1218
+ );
373
1219
  const handleFocus = react.useCallback(() => setShowToolbar(true), []);
374
1220
  const handleBlur = react.useCallback((e) => {
375
1221
  if (!e.currentTarget.contains(e.relatedTarget)) {
@@ -387,87 +1233,94 @@ const TextBlockComponent = ({ block, onUpdate, readOnly, theme = "light" }) => {
387
1233
  return /* @__PURE__ */ jsxRuntime.jsxs(
388
1234
  "div",
389
1235
  {
1236
+ ref: containerRef,
390
1237
  className: "group relative",
391
1238
  onFocus: handleFocus,
392
1239
  onBlur: handleBlur,
393
1240
  children: [
394
- showToolbar && !readOnly && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `absolute -top-12 left-0 flex items-center gap-1 p-1.5 rounded-xl shadow-lg border z-10 ${isDark ? "bg-slate-800 border-slate-600" : "bg-white border-slate-200"}`, children: [
395
- /* @__PURE__ */ jsxRuntime.jsx(
396
- "button",
397
- {
398
- onClick: () => toggleStyle("bold"),
399
- className: toolbarBtnClass(block.style?.bold),
400
- title: "Bold",
401
- children: /* @__PURE__ */ jsxRuntime.jsx(BoldIcon, { size: 16 })
402
- }
403
- ),
404
- /* @__PURE__ */ jsxRuntime.jsx(
405
- "button",
406
- {
407
- onClick: () => toggleStyle("italic"),
408
- className: toolbarBtnClass(block.style?.italic),
409
- title: "Italic",
410
- children: /* @__PURE__ */ jsxRuntime.jsx(ItalicIcon, { size: 16 })
411
- }
412
- ),
413
- /* @__PURE__ */ jsxRuntime.jsx(
414
- "button",
415
- {
416
- onClick: () => toggleStyle("underline"),
417
- className: toolbarBtnClass(block.style?.underline),
418
- title: "Underline",
419
- children: /* @__PURE__ */ jsxRuntime.jsx(UnderlineIcon, { size: 16 })
420
- }
421
- ),
422
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-px h-6 mx-1 ${isDark ? "bg-slate-600" : "bg-slate-200"}` }),
423
- /* @__PURE__ */ jsxRuntime.jsx(
424
- "button",
425
- {
426
- onClick: () => setAlignment("left"),
427
- className: toolbarBtnClass(block.alignment === "left"),
428
- title: "Align Left",
429
- children: /* @__PURE__ */ jsxRuntime.jsx(AlignLeftIcon, { size: 16 })
430
- }
431
- ),
432
- /* @__PURE__ */ jsxRuntime.jsx(
433
- "button",
434
- {
435
- onClick: () => setAlignment("center"),
436
- className: toolbarBtnClass(block.alignment === "center"),
437
- title: "Align Center",
438
- children: /* @__PURE__ */ jsxRuntime.jsx(AlignCenterIcon, { size: 16 })
439
- }
440
- ),
441
- /* @__PURE__ */ jsxRuntime.jsx(
442
- "button",
443
- {
444
- onClick: () => setAlignment("right"),
445
- className: toolbarBtnClass(block.alignment === "right"),
446
- title: "Align Right",
447
- children: /* @__PURE__ */ jsxRuntime.jsx(AlignRightIcon, { size: 16 })
448
- }
449
- ),
450
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-px h-6 mx-1 ${isDark ? "bg-slate-600" : "bg-slate-200"}` }),
451
- /* @__PURE__ */ jsxRuntime.jsxs(
452
- "select",
453
- {
454
- value: block.fontSize || "base",
455
- onChange: (e) => setFontSize(e.target.value),
456
- className: `px-2 py-1.5 text-sm rounded-lg border ${isDark ? "bg-slate-700 border-slate-600 text-slate-200" : "bg-white border-slate-200 text-slate-700"}`,
457
- children: [
458
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "sm", children: "Small" }),
459
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "base", children: "Normal" }),
460
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "lg", children: "Large" }),
461
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "xl", children: "X-Large" })
462
- ]
463
- }
464
- )
465
- ] }),
1241
+ showToolbar && !readOnly && /* @__PURE__ */ jsxRuntime.jsxs(
1242
+ "div",
1243
+ {
1244
+ className: `absolute left-0 flex items-center gap-1 p-1.5 rounded-xl shadow-lg border z-10 ${showBelow ? "top-full mt-2" : "-top-12"} ${isDark ? "bg-slate-800 border-slate-600" : "bg-white border-slate-200"}`,
1245
+ children: [
1246
+ /* @__PURE__ */ jsxRuntime.jsx(
1247
+ "button",
1248
+ {
1249
+ onClick: () => toggleStyle("bold"),
1250
+ className: toolbarBtnClass(block.style?.bold),
1251
+ title: "Bold",
1252
+ children: /* @__PURE__ */ jsxRuntime.jsx(BoldIcon, { size: 16 })
1253
+ }
1254
+ ),
1255
+ /* @__PURE__ */ jsxRuntime.jsx(
1256
+ "button",
1257
+ {
1258
+ onClick: () => toggleStyle("italic"),
1259
+ className: toolbarBtnClass(block.style?.italic),
1260
+ title: "Italic",
1261
+ children: /* @__PURE__ */ jsxRuntime.jsx(ItalicIcon, { size: 16 })
1262
+ }
1263
+ ),
1264
+ /* @__PURE__ */ jsxRuntime.jsx(
1265
+ "button",
1266
+ {
1267
+ onClick: () => toggleStyle("underline"),
1268
+ className: toolbarBtnClass(block.style?.underline),
1269
+ title: "Underline",
1270
+ children: /* @__PURE__ */ jsxRuntime.jsx(UnderlineIcon, { size: 16 })
1271
+ }
1272
+ ),
1273
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-px h-6 mx-1 ${isDark ? "bg-slate-600" : "bg-slate-200"}` }),
1274
+ /* @__PURE__ */ jsxRuntime.jsx(
1275
+ "button",
1276
+ {
1277
+ onClick: () => setAlignment("left"),
1278
+ className: toolbarBtnClass(block.alignment === "left"),
1279
+ title: "Align Left",
1280
+ children: /* @__PURE__ */ jsxRuntime.jsx(AlignLeftIcon, { size: 16 })
1281
+ }
1282
+ ),
1283
+ /* @__PURE__ */ jsxRuntime.jsx(
1284
+ "button",
1285
+ {
1286
+ onClick: () => setAlignment("center"),
1287
+ className: toolbarBtnClass(block.alignment === "center"),
1288
+ title: "Align Center",
1289
+ children: /* @__PURE__ */ jsxRuntime.jsx(AlignCenterIcon, { size: 16 })
1290
+ }
1291
+ ),
1292
+ /* @__PURE__ */ jsxRuntime.jsx(
1293
+ "button",
1294
+ {
1295
+ onClick: () => setAlignment("right"),
1296
+ className: toolbarBtnClass(block.alignment === "right"),
1297
+ title: "Align Right",
1298
+ children: /* @__PURE__ */ jsxRuntime.jsx(AlignRightIcon, { size: 16 })
1299
+ }
1300
+ ),
1301
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-px h-6 mx-1 ${isDark ? "bg-slate-600" : "bg-slate-200"}` }),
1302
+ /* @__PURE__ */ jsxRuntime.jsxs(
1303
+ "select",
1304
+ {
1305
+ value: block.fontSize || "base",
1306
+ onChange: (e) => setFontSize(e.target.value),
1307
+ className: `px-2 py-1.5 text-sm rounded-lg border ${isDark ? "bg-slate-700 border-slate-600 text-slate-200" : "bg-white border-slate-200 text-slate-700"}`,
1308
+ children: [
1309
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "sm", children: "Small" }),
1310
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "base", children: "Normal" }),
1311
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "lg", children: "Large" }),
1312
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "xl", children: "X-Large" })
1313
+ ]
1314
+ }
1315
+ )
1316
+ ]
1317
+ }
1318
+ ),
466
1319
  readOnly ? /* @__PURE__ */ jsxRuntime.jsx(
467
1320
  "div",
468
1321
  {
469
1322
  style: textStyle,
470
- className: `w-full whitespace-pre-wrap break-words ${fontSizeMap[block.fontSize || "base"]} ${alignmentMap$2[block.alignment || "left"]} ${isDark ? "text-slate-200" : "text-slate-800"}`,
1323
+ className: `w-full whitespace-pre-wrap break-words ${fontSizeMap[block.fontSize || "base"]} ${alignmentMap$1[block.alignment || "left"]} ${isDark ? "text-slate-200" : "text-slate-800"}`,
471
1324
  children: block.content || /* @__PURE__ */ jsxRuntime.jsx("span", { className: isDark ? "text-slate-500" : "text-slate-400", children: "Empty text block" })
472
1325
  }
473
1326
  ) : /* @__PURE__ */ jsxRuntime.jsx(
@@ -478,7 +1331,7 @@ const TextBlockComponent = ({ block, onUpdate, readOnly, theme = "light" }) => {
478
1331
  onChange: handleChange,
479
1332
  placeholder: "Start typing...",
480
1333
  style: textStyle,
481
- className: `w-full min-h-[2.5rem] p-2 resize-none outline-none bg-transparent ${fontSizeMap[block.fontSize || "base"]} ${alignmentMap$2[block.alignment || "left"]} ${isDark ? "text-slate-200 placeholder:text-slate-500" : "text-slate-800 placeholder:text-slate-400"}`,
1334
+ className: `w-full min-h-[2.5rem] p-2 resize-none outline-none bg-transparent ${fontSizeMap[block.fontSize || "base"]} ${alignmentMap$1[block.alignment || "left"]} ${isDark ? "text-slate-200 placeholder:text-slate-500" : "text-slate-800 placeholder:text-slate-400"}`,
482
1335
  rows: 1
483
1336
  }
484
1337
  )
@@ -496,15 +1349,26 @@ const headingSizeMap = {
496
1349
  5: "text-lg font-medium",
497
1350
  6: "text-base font-medium"
498
1351
  };
499
- const alignmentMap$1 = {
1352
+ const alignmentMap = {
500
1353
  left: "text-left",
501
1354
  center: "text-center",
502
1355
  right: "text-right"
503
1356
  };
504
- const HeadingBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
1357
+ const HeadingBlock = ({
1358
+ block,
1359
+ onUpdate,
1360
+ readOnly,
1361
+ theme = "light"
1362
+ }) => {
505
1363
  const [showToolbar, setShowToolbar] = react.useState(false);
506
1364
  const inputRef = react.useRef(null);
1365
+ const containerRef = react.useRef(null);
507
1366
  const isDark = theme === "dark";
1367
+ const { showBelow } = useToolbarPosition({
1368
+ containerRef,
1369
+ isVisible: showToolbar && !readOnly,
1370
+ minSpaceAbove: 60
1371
+ });
508
1372
  const handleChange = (e) => {
509
1373
  onUpdate({ ...block, content: e.target.value });
510
1374
  };
@@ -518,6 +1382,7 @@ const HeadingBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
518
1382
  return /* @__PURE__ */ jsxRuntime.jsxs(
519
1383
  "div",
520
1384
  {
1385
+ ref: containerRef,
521
1386
  className: "group relative",
522
1387
  onFocus: () => setShowToolbar(true),
523
1388
  onBlur: (e) => {
@@ -526,56 +1391,62 @@ const HeadingBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
526
1391
  }
527
1392
  },
528
1393
  children: [
529
- showToolbar && !readOnly && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `absolute -top-12 left-0 flex items-center gap-1 p-1.5 rounded-xl shadow-lg border z-10 ${isDark ? "bg-slate-800 border-slate-600" : "bg-white border-slate-200"}`, children: [
530
- /* @__PURE__ */ jsxRuntime.jsxs(
531
- "select",
532
- {
533
- value: block.level,
534
- onChange: (e) => setLevel(parseInt(e.target.value)),
535
- className: `px-2 py-1.5 text-sm rounded-lg border ${isDark ? "bg-slate-700 border-slate-600 text-slate-200" : "bg-white border-slate-200 text-slate-700"}`,
536
- children: [
537
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: 1, children: "Heading 1" }),
538
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: 2, children: "Heading 2" }),
539
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: 3, children: "Heading 3" }),
540
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: 4, children: "Heading 4" }),
541
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: 5, children: "Heading 5" }),
542
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: 6, children: "Heading 6" })
543
- ]
544
- }
545
- ),
546
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-px h-6 mx-1 ${isDark ? "bg-slate-600" : "bg-slate-200"}` }),
547
- /* @__PURE__ */ jsxRuntime.jsx(
548
- "button",
549
- {
550
- onClick: () => setAlignment("left"),
551
- className: toolbarBtnClass(block.alignment === "left"),
552
- title: "Align Left",
553
- children: /* @__PURE__ */ jsxRuntime.jsx(AlignLeftIcon, { size: 16 })
554
- }
555
- ),
556
- /* @__PURE__ */ jsxRuntime.jsx(
557
- "button",
558
- {
559
- onClick: () => setAlignment("center"),
560
- className: toolbarBtnClass(block.alignment === "center"),
561
- title: "Align Center",
562
- children: /* @__PURE__ */ jsxRuntime.jsx(AlignCenterIcon, { size: 16 })
563
- }
564
- ),
565
- /* @__PURE__ */ jsxRuntime.jsx(
566
- "button",
567
- {
568
- onClick: () => setAlignment("right"),
569
- className: toolbarBtnClass(block.alignment === "right"),
570
- title: "Align Right",
571
- children: /* @__PURE__ */ jsxRuntime.jsx(AlignRightIcon, { size: 16 })
572
- }
573
- )
574
- ] }),
1394
+ showToolbar && !readOnly && /* @__PURE__ */ jsxRuntime.jsxs(
1395
+ "div",
1396
+ {
1397
+ className: `absolute left-0 flex items-center gap-1 p-1.5 rounded-xl shadow-lg border z-10 ${showBelow ? "top-full mt-2" : "-top-12"} ${isDark ? "bg-slate-800 border-slate-600" : "bg-white border-slate-200"}`,
1398
+ children: [
1399
+ /* @__PURE__ */ jsxRuntime.jsxs(
1400
+ "select",
1401
+ {
1402
+ value: block.level,
1403
+ onChange: (e) => setLevel(parseInt(e.target.value)),
1404
+ className: `px-2 py-1.5 text-sm rounded-lg border ${isDark ? "bg-slate-700 border-slate-600 text-slate-200" : "bg-white border-slate-200 text-slate-700"}`,
1405
+ children: [
1406
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: 1, children: "Heading 1" }),
1407
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: 2, children: "Heading 2" }),
1408
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: 3, children: "Heading 3" }),
1409
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: 4, children: "Heading 4" }),
1410
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: 5, children: "Heading 5" }),
1411
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: 6, children: "Heading 6" })
1412
+ ]
1413
+ }
1414
+ ),
1415
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-px h-6 mx-1 ${isDark ? "bg-slate-600" : "bg-slate-200"}` }),
1416
+ /* @__PURE__ */ jsxRuntime.jsx(
1417
+ "button",
1418
+ {
1419
+ onClick: () => setAlignment("left"),
1420
+ className: toolbarBtnClass(block.alignment === "left"),
1421
+ title: "Align Left",
1422
+ children: /* @__PURE__ */ jsxRuntime.jsx(AlignLeftIcon, { size: 16 })
1423
+ }
1424
+ ),
1425
+ /* @__PURE__ */ jsxRuntime.jsx(
1426
+ "button",
1427
+ {
1428
+ onClick: () => setAlignment("center"),
1429
+ className: toolbarBtnClass(block.alignment === "center"),
1430
+ title: "Align Center",
1431
+ children: /* @__PURE__ */ jsxRuntime.jsx(AlignCenterIcon, { size: 16 })
1432
+ }
1433
+ ),
1434
+ /* @__PURE__ */ jsxRuntime.jsx(
1435
+ "button",
1436
+ {
1437
+ onClick: () => setAlignment("right"),
1438
+ className: toolbarBtnClass(block.alignment === "right"),
1439
+ title: "Align Right",
1440
+ children: /* @__PURE__ */ jsxRuntime.jsx(AlignRightIcon, { size: 16 })
1441
+ }
1442
+ )
1443
+ ]
1444
+ }
1445
+ ),
575
1446
  readOnly ? /* @__PURE__ */ jsxRuntime.jsx(
576
1447
  "div",
577
1448
  {
578
- className: `w-full p-2 ${headingSizeMap[block.level]} ${alignmentMap$1[block.alignment || "left"]} ${isDark ? "text-white" : "text-slate-900"}`,
1449
+ className: `w-full p-2 ${headingSizeMap[block.level]} ${alignmentMap[block.alignment || "left"]} ${isDark ? "text-white" : "text-slate-900"}`,
579
1450
  children: block.content || /* @__PURE__ */ jsxRuntime.jsx("span", { className: isDark ? "text-slate-500" : "text-slate-400", children: "Empty heading" })
580
1451
  }
581
1452
  ) : /* @__PURE__ */ jsxRuntime.jsx(
@@ -586,7 +1457,7 @@ const HeadingBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
586
1457
  value: block.content,
587
1458
  onChange: handleChange,
588
1459
  placeholder: `Heading ${block.level}`,
589
- className: `w-full p-2 outline-none bg-transparent ${headingSizeMap[block.level]} ${alignmentMap$1[block.alignment || "left"]} ${isDark ? "text-white placeholder:text-slate-500" : "text-slate-900 placeholder:text-slate-400"}`
1460
+ className: `w-full p-2 outline-none bg-transparent ${headingSizeMap[block.level]} ${alignmentMap[block.alignment || "left"]} ${isDark ? "text-white placeholder:text-slate-500" : "text-slate-900 placeholder:text-slate-400"}`
590
1461
  }
591
1462
  )
592
1463
  ]
@@ -594,16 +1465,22 @@ const HeadingBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
594
1465
  );
595
1466
  };
596
1467
 
597
- const alignmentMap = {
598
- left: "mr-auto",
599
- center: "mx-auto",
600
- right: "ml-auto"
601
- };
602
- const ImageBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
1468
+ const ImageBlock = ({
1469
+ block,
1470
+ onUpdate,
1471
+ readOnly,
1472
+ theme = "light"
1473
+ }) => {
603
1474
  const [showToolbar, setShowToolbar] = react.useState(false);
604
1475
  const [isDragging, setIsDragging] = react.useState(false);
605
1476
  const fileInputRef = react.useRef(null);
1477
+ const containerRef = react.useRef(null);
606
1478
  const isDark = theme === "dark";
1479
+ const { showBelow } = useToolbarPosition({
1480
+ containerRef,
1481
+ isVisible: showToolbar && !readOnly && !!block.src,
1482
+ minSpaceAbove: 60
1483
+ });
607
1484
  const handleFileChange = async (file) => {
608
1485
  if (file && file.type.startsWith("image/")) {
609
1486
  try {
@@ -672,7 +1549,12 @@ const ImageBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
672
1549
  }
673
1550
  ),
674
1551
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center text-center", children: [
675
- /* @__PURE__ */ jsxRuntime.jsx(UploadIcon, { className: `w-12 h-12 mb-4 ${isDark ? "text-slate-500" : "text-slate-400"}` }),
1552
+ /* @__PURE__ */ jsxRuntime.jsx(
1553
+ UploadIcon,
1554
+ {
1555
+ className: `w-12 h-12 mb-4 ${isDark ? "text-slate-500" : "text-slate-400"}`
1556
+ }
1557
+ ),
676
1558
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: `mb-2 ${isDark ? "text-slate-400" : "text-slate-600"}`, children: "Drag and drop an image here, or" }),
677
1559
  /* @__PURE__ */ jsxRuntime.jsx(
678
1560
  "button",
@@ -692,96 +1574,117 @@ const ImageBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
692
1574
  return /* @__PURE__ */ jsxRuntime.jsxs(
693
1575
  "div",
694
1576
  {
1577
+ ref: containerRef,
695
1578
  className: "group relative",
696
1579
  onFocus: () => setShowToolbar(true),
697
1580
  onBlur: (e) => {
698
- if (!e.currentTarget.contains(e.relatedTarget)) {
699
- setShowToolbar(false);
700
- }
701
- },
702
- children: [
703
- showToolbar && !readOnly && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `absolute -top-12 left-1/2 -translate-x-1/2 flex items-center gap-1 p-1.5 rounded-xl shadow-lg border z-10 ${isDark ? "bg-slate-800 border-slate-600" : "bg-white border-slate-200"}`, children: [
704
- /* @__PURE__ */ jsxRuntime.jsx(
705
- "button",
706
- {
707
- onClick: () => setAlignment("left"),
708
- className: toolbarBtnClass(block.alignment === "left"),
709
- title: "Align Left",
710
- children: /* @__PURE__ */ jsxRuntime.jsx(AlignLeftIcon, { size: 16 })
711
- }
712
- ),
713
- /* @__PURE__ */ jsxRuntime.jsx(
714
- "button",
715
- {
716
- onClick: () => setAlignment("center"),
717
- className: toolbarBtnClass(block.alignment === "center"),
718
- title: "Align Center",
719
- children: /* @__PURE__ */ jsxRuntime.jsx(AlignCenterIcon, { size: 16 })
720
- }
721
- ),
722
- /* @__PURE__ */ jsxRuntime.jsx(
723
- "button",
724
- {
725
- onClick: () => setAlignment("right"),
726
- className: toolbarBtnClass(block.alignment === "right"),
727
- title: "Align Right",
728
- children: /* @__PURE__ */ jsxRuntime.jsx(AlignRightIcon, { size: 16 })
729
- }
730
- ),
731
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-px h-6 mx-1 ${isDark ? "bg-slate-600" : "bg-slate-200"}` }),
732
- /* @__PURE__ */ jsxRuntime.jsx(
733
- "input",
734
- {
735
- type: "number",
736
- value: block.width || "",
737
- onChange: handleWidthChange,
738
- placeholder: "Width",
739
- className: `w-20 px-2 py-1.5 text-sm rounded-lg border ${isDark ? "bg-slate-700 border-slate-600 text-slate-200" : "bg-white border-slate-200 text-slate-700"}`
740
- }
741
- ),
742
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-px h-6 mx-1 ${isDark ? "bg-slate-600" : "bg-slate-200"}` }),
743
- /* @__PURE__ */ jsxRuntime.jsx(
744
- "button",
745
- {
746
- onClick: clearImage,
747
- className: `p-2 rounded-lg hover:text-red-500 ${isDark ? "hover:bg-red-950/30 text-slate-400" : "hover:bg-red-50 text-slate-400"}`,
748
- title: "Remove Image",
749
- children: /* @__PURE__ */ jsxRuntime.jsx(TrashIcon, { size: 16 })
750
- }
751
- )
752
- ] }),
753
- /* @__PURE__ */ jsxRuntime.jsxs("figure", { className: `${alignmentMap[block.alignment || "center"]}`, style: { maxWidth: block.width ? `${block.width}px` : "100%" }, children: [
754
- /* @__PURE__ */ jsxRuntime.jsx(
755
- "img",
756
- {
757
- src: block.src,
758
- alt: block.alt || "",
759
- className: "max-w-full h-auto rounded-xl shadow-sm"
760
- }
761
- ),
762
- !readOnly ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 space-y-2", children: [
763
- /* @__PURE__ */ jsxRuntime.jsx(
764
- "input",
765
- {
766
- type: "text",
767
- value: block.caption || "",
768
- onChange: handleCaptionChange,
769
- placeholder: "Add a caption...",
770
- className: `w-full text-center text-sm bg-transparent outline-none ${isDark ? "text-slate-400 placeholder:text-slate-500" : "text-slate-600 placeholder:text-slate-400"}`
771
- }
772
- ),
773
- /* @__PURE__ */ jsxRuntime.jsx(
774
- "input",
775
- {
776
- type: "text",
777
- value: block.alt || "",
778
- onChange: handleAltChange,
779
- placeholder: "Alt text for accessibility...",
780
- className: `w-full text-center text-xs bg-transparent outline-none ${isDark ? "text-slate-500 placeholder:text-slate-600" : "text-slate-500 placeholder:text-slate-400"}`
781
- }
782
- )
783
- ] }) : block.caption ? /* @__PURE__ */ jsxRuntime.jsx("figcaption", { className: `mt-3 text-center text-sm ${isDark ? "text-slate-400" : "text-slate-600"}`, children: block.caption }) : null
784
- ] })
1581
+ if (!e.currentTarget.contains(e.relatedTarget)) {
1582
+ setShowToolbar(false);
1583
+ }
1584
+ },
1585
+ children: [
1586
+ showToolbar && !readOnly && /* @__PURE__ */ jsxRuntime.jsxs(
1587
+ "div",
1588
+ {
1589
+ className: `absolute left-1/2 -translate-x-1/2 flex items-center gap-1 p-1.5 rounded-xl shadow-lg border z-10 ${showBelow ? "top-full mt-2" : "-top-12"} ${isDark ? "bg-slate-800 border-slate-600" : "bg-white border-slate-200"}`,
1590
+ children: [
1591
+ /* @__PURE__ */ jsxRuntime.jsx(
1592
+ "button",
1593
+ {
1594
+ onClick: () => setAlignment("left"),
1595
+ className: toolbarBtnClass(block.alignment === "left"),
1596
+ title: "Align Left",
1597
+ children: /* @__PURE__ */ jsxRuntime.jsx(AlignLeftIcon, { size: 16 })
1598
+ }
1599
+ ),
1600
+ /* @__PURE__ */ jsxRuntime.jsx(
1601
+ "button",
1602
+ {
1603
+ onClick: () => setAlignment("center"),
1604
+ className: toolbarBtnClass(block.alignment === "center"),
1605
+ title: "Align Center",
1606
+ children: /* @__PURE__ */ jsxRuntime.jsx(AlignCenterIcon, { size: 16 })
1607
+ }
1608
+ ),
1609
+ /* @__PURE__ */ jsxRuntime.jsx(
1610
+ "button",
1611
+ {
1612
+ onClick: () => setAlignment("right"),
1613
+ className: toolbarBtnClass(block.alignment === "right"),
1614
+ title: "Align Right",
1615
+ children: /* @__PURE__ */ jsxRuntime.jsx(AlignRightIcon, { size: 16 })
1616
+ }
1617
+ ),
1618
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-px h-6 mx-1 ${isDark ? "bg-slate-600" : "bg-slate-200"}` }),
1619
+ /* @__PURE__ */ jsxRuntime.jsx(
1620
+ "input",
1621
+ {
1622
+ type: "number",
1623
+ value: block.width || "",
1624
+ onChange: handleWidthChange,
1625
+ placeholder: "Width",
1626
+ className: `w-20 px-2 py-1.5 text-sm rounded-lg border ${isDark ? "bg-slate-700 border-slate-600 text-slate-200" : "bg-white border-slate-200 text-slate-700"}`
1627
+ }
1628
+ ),
1629
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-px h-6 mx-1 ${isDark ? "bg-slate-600" : "bg-slate-200"}` }),
1630
+ /* @__PURE__ */ jsxRuntime.jsx(
1631
+ "button",
1632
+ {
1633
+ onClick: clearImage,
1634
+ className: `p-2 rounded-lg hover:text-red-500 ${isDark ? "hover:bg-red-950/30 text-slate-400" : "hover:bg-red-50 text-slate-400"}`,
1635
+ title: "Remove Image",
1636
+ children: /* @__PURE__ */ jsxRuntime.jsx(TrashIcon, { size: 16 })
1637
+ }
1638
+ )
1639
+ ]
1640
+ }
1641
+ ),
1642
+ /* @__PURE__ */ jsxRuntime.jsxs(
1643
+ "figure",
1644
+ {
1645
+ className: "flex flex-col items-center w-full",
1646
+ style: { maxWidth: "100%" },
1647
+ children: [
1648
+ /* @__PURE__ */ jsxRuntime.jsx(
1649
+ "img",
1650
+ {
1651
+ src: block.src,
1652
+ alt: block.alt || "",
1653
+ className: "max-w-full h-auto rounded-xl shadow-sm",
1654
+ style: { maxWidth: block.width ? `${block.width}px` : "100%" }
1655
+ }
1656
+ ),
1657
+ !readOnly ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 space-y-2", children: [
1658
+ /* @__PURE__ */ jsxRuntime.jsx(
1659
+ "input",
1660
+ {
1661
+ type: "text",
1662
+ value: block.caption || "",
1663
+ onChange: handleCaptionChange,
1664
+ placeholder: "Add a caption...",
1665
+ className: `w-full text-center text-sm bg-transparent outline-none ${isDark ? "text-slate-400 placeholder:text-slate-500" : "text-slate-600 placeholder:text-slate-400"}`
1666
+ }
1667
+ ),
1668
+ /* @__PURE__ */ jsxRuntime.jsx(
1669
+ "input",
1670
+ {
1671
+ type: "text",
1672
+ value: block.alt || "",
1673
+ onChange: handleAltChange,
1674
+ placeholder: "Alt text for accessibility...",
1675
+ className: `w-full text-center text-xs bg-transparent outline-none ${isDark ? "text-slate-500 placeholder:text-slate-600" : "text-slate-500 placeholder:text-slate-400"}`
1676
+ }
1677
+ )
1678
+ ] }) : block.caption ? /* @__PURE__ */ jsxRuntime.jsx(
1679
+ "figcaption",
1680
+ {
1681
+ className: `mt-3 text-center text-sm ${isDark ? "text-slate-400" : "text-slate-600"}`,
1682
+ children: block.caption
1683
+ }
1684
+ ) : null
1685
+ ]
1686
+ }
1687
+ )
785
1688
  ]
786
1689
  }
787
1690
  );
@@ -817,17 +1720,29 @@ const SUPPORTED_LANGUAGES = [
817
1720
  "plaintext"
818
1721
  ];
819
1722
 
820
- const CodeBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
1723
+ const CodeBlock = ({
1724
+ block,
1725
+ onUpdate,
1726
+ readOnly,
1727
+ theme = "light"
1728
+ }) => {
821
1729
  const [copied, setCopied] = react.useState(false);
822
1730
  const textareaRef = react.useRef(null);
823
1731
  const isDark = theme === "dark";
824
- const handleCodeChange = (e) => {
825
- onUpdate({ ...block, code: e.target.value });
1732
+ const resizeTextarea = () => {
826
1733
  if (textareaRef.current) {
827
1734
  textareaRef.current.style.height = "auto";
828
1735
  textareaRef.current.style.height = textareaRef.current.scrollHeight + "px";
829
1736
  }
830
1737
  };
1738
+ react.useEffect(() => {
1739
+ if (!readOnly) {
1740
+ resizeTextarea();
1741
+ }
1742
+ }, [block.code, readOnly]);
1743
+ const handleCodeChange = (e) => {
1744
+ onUpdate({ ...block, code: e.target.value });
1745
+ };
831
1746
  const handleLanguageChange = (e) => {
832
1747
  onUpdate({ ...block, language: e.target.value });
833
1748
  };
@@ -853,58 +1768,78 @@ const CodeBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
853
1768
  {
854
1769
  className: `group relative rounded-xl overflow-hidden ${isDark ? "bg-slate-950" : "bg-slate-900"}`,
855
1770
  children: [
856
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex items-center justify-between px-4 py-2.5 border-b ${isDark ? "bg-slate-900 border-slate-800" : "bg-slate-800 border-slate-700"}`, children: [
857
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
858
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-1.5", children: [
859
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-3 h-3 rounded-full bg-red-500/80" }),
860
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-3 h-3 rounded-full bg-yellow-500/80" }),
861
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-3 h-3 rounded-full bg-green-500/80" })
862
- ] }),
863
- !readOnly ? /* @__PURE__ */ jsxRuntime.jsx(
864
- "input",
865
- {
866
- type: "text",
867
- value: block.filename || "",
868
- onChange: handleFilenameChange,
869
- placeholder: "filename.js",
870
- className: "text-sm text-slate-400 bg-transparent outline-none placeholder:text-slate-600 w-32"
871
- }
872
- ) : block.filename ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-slate-400", children: block.filename }) : null
873
- ] }),
874
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
875
- !readOnly && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
876
- /* @__PURE__ */ jsxRuntime.jsx(
877
- "select",
878
- {
879
- value: block.language,
880
- onChange: handleLanguageChange,
881
- className: "text-xs px-2 py-1.5 bg-slate-700 text-slate-300 rounded-lg border border-slate-600 outline-none",
882
- children: SUPPORTED_LANGUAGES.map((lang) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: lang, children: lang }, lang))
883
- }
884
- ),
885
- /* @__PURE__ */ jsxRuntime.jsx(
886
- "button",
887
- {
888
- onClick: toggleLineNumbers,
889
- className: `text-xs px-2 py-1.5 rounded-lg transition-colors ${block.showLineNumbers ? "bg-indigo-600 text-white" : "bg-slate-700 text-slate-300 hover:bg-slate-600"}`,
890
- children: "#"
891
- }
892
- )
893
- ] }),
894
- /* @__PURE__ */ jsxRuntime.jsx(
895
- "button",
896
- {
897
- onClick: copyToClipboard,
898
- className: "p-1.5 rounded-lg hover:bg-slate-700 text-slate-400 hover:text-white transition-colors",
899
- title: "Copy code",
900
- children: copied ? /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, { size: 16 }) : /* @__PURE__ */ jsxRuntime.jsx(CopyIcon, { size: 16 })
901
- }
902
- )
903
- ] })
904
- ] }),
905
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex overflow-x-auto", children: [
906
- block.showLineNumbers && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0 py-4 pl-4 pr-3 text-right select-none border-r border-slate-800", children: lineNumbers.map((num) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-slate-600 leading-6 font-mono", children: num }, num)) }),
907
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 p-4 overflow-x-auto", children: readOnly ? /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "text-sm text-slate-100 font-mono leading-6 whitespace-pre", children: /* @__PURE__ */ jsxRuntime.jsx("code", { children: block.code }) }) : /* @__PURE__ */ jsxRuntime.jsx(
1771
+ /* @__PURE__ */ jsxRuntime.jsxs(
1772
+ "div",
1773
+ {
1774
+ className: `flex items-center justify-between px-4 py-2.5 border-b ${isDark ? "bg-slate-900 border-slate-800" : "bg-slate-800 border-slate-700"}`,
1775
+ children: [
1776
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
1777
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-1.5", children: [
1778
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-3 h-3 rounded-full bg-red-500/80" }),
1779
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-3 h-3 rounded-full bg-yellow-500/80" }),
1780
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-3 h-3 rounded-full bg-green-500/80" })
1781
+ ] }),
1782
+ !readOnly ? /* @__PURE__ */ jsxRuntime.jsx(
1783
+ "input",
1784
+ {
1785
+ type: "text",
1786
+ value: block.filename || "",
1787
+ onChange: handleFilenameChange,
1788
+ placeholder: "filename.js",
1789
+ className: "text-sm text-slate-400 bg-transparent outline-none placeholder:text-slate-600 w-32"
1790
+ }
1791
+ ) : block.filename ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-slate-400", children: block.filename }) : null
1792
+ ] }),
1793
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1794
+ !readOnly && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1795
+ /* @__PURE__ */ jsxRuntime.jsx(
1796
+ "select",
1797
+ {
1798
+ value: block.language,
1799
+ onChange: handleLanguageChange,
1800
+ className: "text-xs px-2 py-1.5 bg-slate-700 text-slate-300 rounded-lg border border-slate-600 outline-none",
1801
+ children: SUPPORTED_LANGUAGES.map((lang) => /* @__PURE__ */ jsxRuntime.jsx(
1802
+ "option",
1803
+ {
1804
+ value: lang,
1805
+ children: lang
1806
+ },
1807
+ lang
1808
+ ))
1809
+ }
1810
+ ),
1811
+ /* @__PURE__ */ jsxRuntime.jsx(
1812
+ "button",
1813
+ {
1814
+ onClick: toggleLineNumbers,
1815
+ className: `text-xs px-2 py-1.5 rounded-lg transition-colors ${block.showLineNumbers ? "bg-indigo-600 text-white" : "bg-slate-700 text-slate-300 hover:bg-slate-600"}`,
1816
+ children: "#"
1817
+ }
1818
+ )
1819
+ ] }),
1820
+ /* @__PURE__ */ jsxRuntime.jsx(
1821
+ "button",
1822
+ {
1823
+ onClick: copyToClipboard,
1824
+ className: "p-1.5 rounded-lg hover:bg-slate-700 text-slate-400 hover:text-white transition-colors",
1825
+ title: "Copy code",
1826
+ children: copied ? /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, { size: 16 }) : /* @__PURE__ */ jsxRuntime.jsx(CopyIcon, { size: 16 })
1827
+ }
1828
+ )
1829
+ ] })
1830
+ ]
1831
+ }
1832
+ ),
1833
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex", children: [
1834
+ block.showLineNumbers && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0 py-4 pl-4 pr-3 text-right select-none border-r border-slate-800", children: lineNumbers.map((num) => /* @__PURE__ */ jsxRuntime.jsx(
1835
+ "div",
1836
+ {
1837
+ className: "text-xs text-slate-600 leading-6 font-mono",
1838
+ children: num
1839
+ },
1840
+ num
1841
+ )) }),
1842
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 p-4", children: readOnly ? /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "text-sm text-slate-100 font-mono leading-6 whitespace-pre overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsx("code", { children: block.code }) }) : /* @__PURE__ */ jsxRuntime.jsx(
908
1843
  "textarea",
909
1844
  {
910
1845
  ref: textareaRef,
@@ -912,8 +1847,8 @@ const CodeBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
912
1847
  onChange: handleCodeChange,
913
1848
  placeholder: "// Write your code here...",
914
1849
  spellCheck: false,
915
- className: "w-full min-h-[100px] text-sm text-slate-100 font-mono leading-6 bg-transparent outline-none resize-none placeholder:text-slate-600",
916
- style: { tabSize: 2 },
1850
+ className: "w-full min-h-[100px] text-sm text-slate-100 font-mono leading-6 bg-transparent outline-none resize-none placeholder:text-slate-600 overflow-hidden",
1851
+ style: { tabSize: 2, height: "auto" },
917
1852
  onKeyDown: (e) => {
918
1853
  if (e.key === "Tab") {
919
1854
  e.preventDefault();
@@ -937,10 +1872,45 @@ const CodeBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
937
1872
  );
938
1873
  };
939
1874
 
940
- const TableBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
1875
+ const TableBlock = ({
1876
+ block,
1877
+ onUpdate,
1878
+ readOnly,
1879
+ theme = "light"
1880
+ }) => {
941
1881
  const [showToolbar, setShowToolbar] = react.useState(false);
942
- const [selectedCell, setSelectedCell] = react.useState(null);
1882
+ const [activeCell, setActiveCell] = react.useState(null);
1883
+ const [toolbarPosition, setToolbarPosition] = react.useState(null);
1884
+ const containerRef = react.useRef(null);
1885
+ const toolbarRef = react.useRef(null);
1886
+ const cellRefs = react.useRef(/* @__PURE__ */ new Map());
943
1887
  const isDark = theme === "dark";
1888
+ const updateToolbarPosition = (row, col) => {
1889
+ const cellKey = `${row}-${col}`;
1890
+ const cellEl = cellRefs.current.get(cellKey);
1891
+ const containerEl = containerRef.current;
1892
+ if (cellEl && containerEl) {
1893
+ const cellRect = cellEl.getBoundingClientRect();
1894
+ const containerRect = containerEl.getBoundingClientRect();
1895
+ const containerWidth = containerRect.width;
1896
+ let left = cellRect.left - containerRect.left;
1897
+ const toolbarWidth = 520;
1898
+ const availableRight = containerWidth - left;
1899
+ if (availableRight < toolbarWidth) {
1900
+ left = Math.max(0, containerWidth - toolbarWidth);
1901
+ }
1902
+ setToolbarPosition({
1903
+ top: cellRect.top - containerRect.top - 44,
1904
+ // 44px above cell
1905
+ left: Math.max(0, left)
1906
+ });
1907
+ }
1908
+ };
1909
+ const handleCellFocus = (row, col) => {
1910
+ setActiveCell({ row, col });
1911
+ setShowToolbar(true);
1912
+ setTimeout(() => updateToolbarPosition(row, col), 0);
1913
+ };
944
1914
  const updateCell = (rowIndex, colIndex, content) => {
945
1915
  const currentRow = block.rows[rowIndex];
946
1916
  if (!currentRow) return;
@@ -973,6 +1943,44 @@ const TableBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
973
1943
  const newRows = block.rows.map((row) => row.filter((_, i) => i !== colIndex));
974
1944
  onUpdate({ ...block, rows: newRows });
975
1945
  };
1946
+ const moveRowUp = (rowIndex) => {
1947
+ if (rowIndex === 0) return;
1948
+ const newRows = [...block.rows];
1949
+ const temp = newRows[rowIndex - 1];
1950
+ newRows[rowIndex - 1] = newRows[rowIndex];
1951
+ newRows[rowIndex] = temp;
1952
+ onUpdate({ ...block, rows: newRows });
1953
+ };
1954
+ const moveRowDown = (rowIndex) => {
1955
+ if (rowIndex >= block.rows.length - 1) return;
1956
+ const newRows = [...block.rows];
1957
+ const temp = newRows[rowIndex];
1958
+ newRows[rowIndex] = newRows[rowIndex + 1];
1959
+ newRows[rowIndex + 1] = temp;
1960
+ onUpdate({ ...block, rows: newRows });
1961
+ };
1962
+ const moveColumnLeft = (colIndex) => {
1963
+ if (colIndex === 0) return;
1964
+ const newRows = block.rows.map((row) => {
1965
+ const newRow = [...row];
1966
+ const temp = newRow[colIndex - 1];
1967
+ newRow[colIndex - 1] = newRow[colIndex];
1968
+ newRow[colIndex] = temp;
1969
+ return newRow;
1970
+ });
1971
+ onUpdate({ ...block, rows: newRows });
1972
+ };
1973
+ const moveColumnRight = (colIndex) => {
1974
+ if (colIndex >= (block.rows[0]?.length ?? 0) - 1) return;
1975
+ const newRows = block.rows.map((row) => {
1976
+ const newRow = [...row];
1977
+ const temp = newRow[colIndex];
1978
+ newRow[colIndex] = newRow[colIndex + 1];
1979
+ newRow[colIndex + 1] = temp;
1980
+ return newRow;
1981
+ });
1982
+ onUpdate({ ...block, rows: newRows });
1983
+ };
976
1984
  const toggleHeader = () => {
977
1985
  const newRows = block.rows.map(
978
1986
  (row, rowIndex) => row.map((cell) => ({
@@ -982,26 +1990,14 @@ const TableBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
982
1990
  );
983
1991
  onUpdate({ ...block, rows: newRows, hasHeader: !block.hasHeader });
984
1992
  };
985
- const setCellAlignment = (alignment) => {
986
- if (!selectedCell) return;
987
- const currentRow = block.rows[selectedCell.row];
988
- if (!currentRow) return;
989
- const currentCell = currentRow[selectedCell.col];
990
- if (!currentCell) return;
991
- const newRows = [...block.rows];
992
- const newRow = [...currentRow];
993
- newRow[selectedCell.col] = {
994
- ...currentCell,
995
- alignment
996
- };
997
- newRows[selectedCell.row] = newRow;
998
- onUpdate({ ...block, rows: newRows });
999
- };
1000
1993
  const toolbarBtnClass = (isActive) => `px-2 py-1 text-sm rounded-lg transition-colors ${isActive ? isDark ? "bg-indigo-900/50 text-indigo-400" : "bg-indigo-100 text-indigo-600" : isDark ? "hover:bg-slate-700 text-slate-300" : "hover:bg-slate-100 text-slate-700"}`;
1001
1994
  return /* @__PURE__ */ jsxRuntime.jsxs(
1002
1995
  "div",
1003
1996
  {
1997
+ ref: containerRef,
1004
1998
  className: "group relative",
1999
+ tabIndex: 0,
2000
+ onClick: () => setShowToolbar(true),
1005
2001
  onFocus: () => setShowToolbar(true),
1006
2002
  onBlur: (e) => {
1007
2003
  if (!e.currentTarget.contains(e.relatedTarget)) {
@@ -1009,114 +2005,194 @@ const TableBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
1009
2005
  }
1010
2006
  },
1011
2007
  children: [
1012
- showToolbar && !readOnly && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `absolute -top-12 left-0 flex items-center gap-1 p-1.5 rounded-xl shadow-lg border z-10 ${isDark ? "bg-slate-800 border-slate-600" : "bg-white border-slate-200"}`, children: [
1013
- /* @__PURE__ */ jsxRuntime.jsxs(
1014
- "button",
1015
- {
1016
- onClick: addRow,
1017
- className: `flex items-center gap-1 ${toolbarBtnClass()}`,
1018
- title: "Add Row",
1019
- children: [
1020
- /* @__PURE__ */ jsxRuntime.jsx(PlusIcon, { size: 14 }),
1021
- " Row"
1022
- ]
1023
- }
1024
- ),
1025
- /* @__PURE__ */ jsxRuntime.jsxs(
1026
- "button",
1027
- {
1028
- onClick: addColumn,
1029
- className: `flex items-center gap-1 ${toolbarBtnClass()}`,
1030
- title: "Add Column",
1031
- children: [
1032
- /* @__PURE__ */ jsxRuntime.jsx(PlusIcon, { size: 14 }),
1033
- " Col"
1034
- ]
1035
- }
1036
- ),
1037
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-px h-6 mx-1 ${isDark ? "bg-slate-600" : "bg-slate-200"}` }),
1038
- /* @__PURE__ */ jsxRuntime.jsx(
1039
- "button",
1040
- {
1041
- onClick: toggleHeader,
1042
- className: toolbarBtnClass(block.hasHeader),
1043
- children: "Header"
1044
- }
1045
- ),
1046
- selectedCell && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1047
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-px h-6 mx-1 ${isDark ? "bg-slate-600" : "bg-slate-200"}` }),
1048
- /* @__PURE__ */ jsxRuntime.jsx(
1049
- "button",
1050
- {
1051
- onClick: () => setCellAlignment("left"),
1052
- className: toolbarBtnClass(),
1053
- children: "Left"
1054
- }
1055
- ),
1056
- /* @__PURE__ */ jsxRuntime.jsx(
1057
- "button",
1058
- {
1059
- onClick: () => setCellAlignment("center"),
1060
- className: toolbarBtnClass(),
1061
- children: "Center"
1062
- }
1063
- ),
1064
- /* @__PURE__ */ jsxRuntime.jsx(
1065
- "button",
1066
- {
1067
- onClick: () => setCellAlignment("right"),
1068
- className: toolbarBtnClass(),
1069
- children: "Right"
1070
- }
1071
- )
1072
- ] })
1073
- ] }),
1074
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto rounded-xl", children: /* @__PURE__ */ jsxRuntime.jsx("table", { className: `w-full border-collapse border ${isDark ? "border-slate-600" : "border-slate-300"}`, children: /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: block.rows.map((row, rowIndex) => /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "group/row", children: [
1075
- row.map((cell, colIndex) => {
1076
- const isHeader = block.hasHeader && rowIndex === 0;
1077
- const CellTag = isHeader ? "th" : "td";
1078
- const alignClass = cell.alignment === "center" ? "text-center" : cell.alignment === "right" ? "text-right" : "text-left";
1079
- return /* @__PURE__ */ jsxRuntime.jsxs(
1080
- CellTag,
2008
+ showToolbar && !readOnly && activeCell && toolbarPosition && /* @__PURE__ */ jsxRuntime.jsxs(
2009
+ "div",
2010
+ {
2011
+ ref: toolbarRef,
2012
+ style: { top: toolbarPosition.top, left: toolbarPosition.left },
2013
+ className: `absolute flex items-center gap-1 p-1.5 rounded-xl shadow-lg border z-50 whitespace-nowrap ${isDark ? "bg-slate-800 border-slate-600" : "bg-white border-slate-200"}`,
2014
+ children: [
2015
+ /* @__PURE__ */ jsxRuntime.jsxs(
2016
+ "button",
2017
+ {
2018
+ onMouseDown: (e) => {
2019
+ e.preventDefault();
2020
+ addRow();
2021
+ },
2022
+ className: `flex items-center gap-1 ${toolbarBtnClass()}`,
2023
+ title: "Add Row",
2024
+ children: [
2025
+ /* @__PURE__ */ jsxRuntime.jsx(PlusIcon, { size: 14 }),
2026
+ " Row"
2027
+ ]
2028
+ }
2029
+ ),
2030
+ /* @__PURE__ */ jsxRuntime.jsxs(
2031
+ "button",
2032
+ {
2033
+ onMouseDown: (e) => {
2034
+ e.preventDefault();
2035
+ addColumn();
2036
+ },
2037
+ className: `flex items-center gap-1 ${toolbarBtnClass()}`,
2038
+ title: "Add Column",
2039
+ children: [
2040
+ /* @__PURE__ */ jsxRuntime.jsx(PlusIcon, { size: 14 }),
2041
+ " Col"
2042
+ ]
2043
+ }
2044
+ ),
2045
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-px h-6 mx-1 ${isDark ? "bg-slate-600" : "bg-slate-200"}` }),
2046
+ /* @__PURE__ */ jsxRuntime.jsx(
2047
+ "button",
2048
+ {
2049
+ onMouseDown: (e) => {
2050
+ e.preventDefault();
2051
+ toggleHeader();
2052
+ },
2053
+ className: toolbarBtnClass(block.hasHeader),
2054
+ children: "Header"
2055
+ }
2056
+ ),
2057
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-px h-6 mx-1 ${isDark ? "bg-slate-600" : "bg-slate-200"}` }),
2058
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `text-xs ${isDark ? "text-slate-500" : "text-slate-400"}`, children: "Row:" }),
2059
+ /* @__PURE__ */ jsxRuntime.jsx(
2060
+ "button",
2061
+ {
2062
+ onMouseDown: (e) => {
2063
+ e.preventDefault();
2064
+ moveRowUp(activeCell.row);
2065
+ updateToolbarPosition(activeCell.row - 1, activeCell.col);
2066
+ },
2067
+ disabled: activeCell.row === 0,
2068
+ className: `p-1 rounded ${activeCell.row === 0 ? "opacity-30 cursor-not-allowed" : ""} ${toolbarBtnClass()}`,
2069
+ title: "Move Row Up",
2070
+ children: /* @__PURE__ */ jsxRuntime.jsx(ChevronUpIcon, { size: 14 })
2071
+ }
2072
+ ),
2073
+ /* @__PURE__ */ jsxRuntime.jsx(
2074
+ "button",
2075
+ {
2076
+ onMouseDown: (e) => {
2077
+ e.preventDefault();
2078
+ moveRowDown(activeCell.row);
2079
+ updateToolbarPosition(activeCell.row + 1, activeCell.col);
2080
+ },
2081
+ disabled: activeCell.row >= block.rows.length - 1,
2082
+ className: `p-1 rounded ${activeCell.row >= block.rows.length - 1 ? "opacity-30 cursor-not-allowed" : ""} ${toolbarBtnClass()}`,
2083
+ title: "Move Row Down",
2084
+ children: /* @__PURE__ */ jsxRuntime.jsx(ChevronDownIcon, { size: 14 })
2085
+ }
2086
+ ),
2087
+ /* @__PURE__ */ jsxRuntime.jsx(
2088
+ "button",
2089
+ {
2090
+ onMouseDown: (e) => {
2091
+ e.preventDefault();
2092
+ deleteRow(activeCell.row);
2093
+ setActiveCell(null);
2094
+ setShowToolbar(false);
2095
+ },
2096
+ disabled: block.rows.length <= 1,
2097
+ className: `p-1 rounded text-red-500 hover:bg-red-100 ${block.rows.length <= 1 ? "opacity-30 cursor-not-allowed" : ""}`,
2098
+ title: "Delete Row",
2099
+ children: /* @__PURE__ */ jsxRuntime.jsx(TrashIcon, { size: 14 })
2100
+ }
2101
+ ),
2102
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-px h-6 mx-1 ${isDark ? "bg-slate-600" : "bg-slate-200"}` }),
2103
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `text-xs ${isDark ? "text-slate-500" : "text-slate-400"}`, children: "Col:" }),
2104
+ /* @__PURE__ */ jsxRuntime.jsx(
2105
+ "button",
2106
+ {
2107
+ onMouseDown: (e) => {
2108
+ e.preventDefault();
2109
+ moveColumnLeft(activeCell.col);
2110
+ updateToolbarPosition(activeCell.row, activeCell.col - 1);
2111
+ },
2112
+ disabled: activeCell.col === 0,
2113
+ className: `p-1 rounded ${activeCell.col === 0 ? "opacity-30 cursor-not-allowed" : ""} ${toolbarBtnClass()}`,
2114
+ title: "Move Column Left",
2115
+ children: /* @__PURE__ */ jsxRuntime.jsx(ChevronLeftIcon, { size: 14 })
2116
+ }
2117
+ ),
2118
+ /* @__PURE__ */ jsxRuntime.jsx(
2119
+ "button",
2120
+ {
2121
+ onMouseDown: (e) => {
2122
+ e.preventDefault();
2123
+ moveColumnRight(activeCell.col);
2124
+ updateToolbarPosition(activeCell.row, activeCell.col + 1);
2125
+ },
2126
+ disabled: activeCell.col >= (block.rows[0]?.length ?? 0) - 1,
2127
+ className: `p-1 rounded ${activeCell.col >= (block.rows[0]?.length ?? 0) - 1 ? "opacity-30 cursor-not-allowed" : ""} ${toolbarBtnClass()}`,
2128
+ title: "Move Column Right",
2129
+ children: /* @__PURE__ */ jsxRuntime.jsx(ChevronRightIcon, { size: 14 })
2130
+ }
2131
+ ),
2132
+ /* @__PURE__ */ jsxRuntime.jsx(
2133
+ "button",
2134
+ {
2135
+ onMouseDown: (e) => {
2136
+ e.preventDefault();
2137
+ deleteColumn(activeCell.col);
2138
+ setActiveCell(null);
2139
+ setShowToolbar(false);
2140
+ },
2141
+ disabled: (block.rows[0]?.length ?? 0) <= 1,
2142
+ className: `p-1 rounded text-red-500 hover:bg-red-100 ${(block.rows[0]?.length ?? 0) <= 1 ? "opacity-30 cursor-not-allowed" : ""}`,
2143
+ title: "Delete Column",
2144
+ children: /* @__PURE__ */ jsxRuntime.jsx(TrashIcon, { size: 14 })
2145
+ }
2146
+ )
2147
+ ]
2148
+ }
2149
+ ),
2150
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto rounded-xl", children: /* @__PURE__ */ jsxRuntime.jsx(
2151
+ "table",
2152
+ {
2153
+ className: `w-full border-collapse border ${isDark ? "border-slate-600" : "border-slate-300"}`,
2154
+ children: /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: block.rows.map((row, rowIndex) => /* @__PURE__ */ jsxRuntime.jsx(
2155
+ "tr",
1081
2156
  {
1082
- className: `relative border p-0 ${isDark ? "border-slate-600" : "border-slate-300"} ${isHeader ? isDark ? "bg-slate-800 font-semibold" : "bg-slate-100 font-semibold" : isDark ? "bg-slate-900" : "bg-white"} ${alignClass}`,
1083
- children: [
1084
- readOnly ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: `px-3 py-2 min-h-[40px] ${isDark ? "text-slate-200" : "text-slate-700"}`, children: cell.content }) : /* @__PURE__ */ jsxRuntime.jsx(
1085
- "input",
1086
- {
1087
- type: "text",
1088
- value: cell.content,
1089
- onChange: (e) => updateCell(rowIndex, colIndex, e.target.value),
1090
- onFocus: () => setSelectedCell({ row: rowIndex, col: colIndex }),
1091
- onBlur: () => setSelectedCell(null),
1092
- className: `w-full px-3 py-2 min-h-[40px] outline-none bg-transparent ${alignClass} ${isHeader ? "font-semibold" : ""} ${isDark ? "text-slate-200 placeholder:text-slate-500" : "text-slate-700 placeholder:text-slate-400"} focus:ring-2 focus:ring-indigo-500 focus:ring-inset`,
1093
- placeholder: isHeader ? "Header" : ""
1094
- }
1095
- ),
1096
- !readOnly && rowIndex === 0 && showToolbar && /* @__PURE__ */ jsxRuntime.jsx(
1097
- "button",
2157
+ className: "group/row",
2158
+ children: row.map((cell, colIndex) => {
2159
+ const isHeader = block.hasHeader && rowIndex === 0;
2160
+ const CellTag = isHeader ? "th" : "td";
2161
+ const isActive = activeCell?.row === rowIndex && activeCell?.col === colIndex;
2162
+ const alignClass = cell.alignment === "center" ? "text-center" : cell.alignment === "right" ? "text-right" : "text-left";
2163
+ return /* @__PURE__ */ jsxRuntime.jsx(
2164
+ CellTag,
1098
2165
  {
1099
- onClick: () => deleteColumn(colIndex),
1100
- className: "absolute -top-6 left-1/2 -translate-x-1/2 p-1 rounded-lg bg-red-500 text-white opacity-0 group-hover:opacity-100 transition-opacity",
1101
- title: "Delete Column",
1102
- children: /* @__PURE__ */ jsxRuntime.jsx(TrashIcon, { size: 12 })
1103
- }
1104
- )
1105
- ]
2166
+ ref: (el) => {
2167
+ if (el) cellRefs.current.set(`${rowIndex}-${colIndex}`, el);
2168
+ },
2169
+ className: `relative border p-0 ${isDark ? "border-slate-600" : "border-slate-300"} ${isHeader ? isDark ? "bg-slate-800 font-semibold" : "bg-slate-100 font-semibold" : isDark ? "bg-slate-900" : "bg-white"} ${alignClass} ${isActive ? "ring-2 ring-indigo-500 ring-inset" : ""}`,
2170
+ children: readOnly ? /* @__PURE__ */ jsxRuntime.jsx(
2171
+ "div",
2172
+ {
2173
+ className: `px-3 py-2 min-h-[40px] ${isDark ? "text-slate-200" : "text-slate-700"}`,
2174
+ children: cell.content
2175
+ }
2176
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
2177
+ "input",
2178
+ {
2179
+ type: "text",
2180
+ value: cell.content,
2181
+ onChange: (e) => updateCell(rowIndex, colIndex, e.target.value),
2182
+ onFocus: () => handleCellFocus(rowIndex, colIndex),
2183
+ className: `w-full px-3 py-2 min-h-[40px] outline-none bg-transparent ${alignClass} ${isHeader ? "font-semibold" : ""} ${isDark ? "text-slate-200 placeholder:text-slate-500" : "text-slate-700 placeholder:text-slate-400"}`,
2184
+ placeholder: isHeader ? "Header" : ""
2185
+ }
2186
+ )
2187
+ },
2188
+ colIndex
2189
+ );
2190
+ })
1106
2191
  },
1107
- colIndex
1108
- );
1109
- }),
1110
- !readOnly && showToolbar && /* @__PURE__ */ jsxRuntime.jsx("td", { className: "w-8 border-none bg-transparent p-0", children: /* @__PURE__ */ jsxRuntime.jsx(
1111
- "button",
1112
- {
1113
- onClick: () => deleteRow(rowIndex),
1114
- className: "p-1 rounded-lg bg-red-500 text-white opacity-0 group-hover/row:opacity-100 transition-opacity",
1115
- title: "Delete Row",
1116
- children: /* @__PURE__ */ jsxRuntime.jsx(TrashIcon, { size: 12 })
1117
- }
1118
- ) })
1119
- ] }, rowIndex)) }) }) })
2192
+ rowIndex
2193
+ )) })
2194
+ }
2195
+ ) })
1120
2196
  ]
1121
2197
  }
1122
2198
  );
@@ -1127,7 +2203,12 @@ const styleMap = {
1127
2203
  dashed: "border-dashed",
1128
2204
  dotted: "border-dotted"
1129
2205
  };
1130
- const DividerBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
2206
+ const DividerBlock = ({
2207
+ block,
2208
+ onUpdate,
2209
+ readOnly,
2210
+ theme = "light"
2211
+ }) => {
1131
2212
  const isDark = theme === "dark";
1132
2213
  const cycleStyle = () => {
1133
2214
  if (readOnly) return;
@@ -1143,19 +2224,36 @@ const DividerBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
1143
2224
  onClick: cycleStyle,
1144
2225
  className: `border-t-2 ${styleMap[block.style || "solid"]} ${isDark ? "border-slate-700" + (!readOnly ? " hover:border-slate-500" : "") : "border-slate-200" + (!readOnly ? " hover:border-slate-400" : "")} ${!readOnly ? "cursor-pointer" : ""}`
1145
2226
  }
1146
- ),
1147
- !readOnly && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: `text-xs text-center mt-1 opacity-0 group-hover:opacity-100 transition-opacity ${isDark ? "text-slate-500" : "text-slate-400"}`, children: [
1148
- "Click to change style (",
1149
- block.style || "solid",
1150
- ")"
1151
- ] })
2227
+ ),
2228
+ !readOnly && /* @__PURE__ */ jsxRuntime.jsxs(
2229
+ "p",
2230
+ {
2231
+ className: `text-xs text-center mt-1 opacity-0 group-hover:opacity-100 transition-opacity ${isDark ? "text-slate-500" : "text-slate-400"}`,
2232
+ children: [
2233
+ "Click to change style (",
2234
+ block.style || "solid",
2235
+ ")"
2236
+ ]
2237
+ }
2238
+ )
1152
2239
  ] });
1153
2240
  };
1154
2241
 
1155
- const QuoteBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
2242
+ const QuoteBlock = ({
2243
+ block,
2244
+ onUpdate,
2245
+ readOnly,
2246
+ theme = "light"
2247
+ }) => {
1156
2248
  const [showToolbar, setShowToolbar] = react.useState(false);
1157
2249
  const textareaRef = react.useRef(null);
2250
+ const containerRef = react.useRef(null);
1158
2251
  const isDark = theme === "dark";
2252
+ const { showBelow } = useToolbarPosition({
2253
+ containerRef,
2254
+ isVisible: showToolbar && !readOnly,
2255
+ minSpaceAbove: 60
2256
+ });
1159
2257
  const styleClasses = {
1160
2258
  default: `border-l-4 pl-4 italic ${isDark ? "border-slate-600" : "border-slate-300"}`,
1161
2259
  bordered: `border-l-4 pl-4 py-3 rounded-r ${isDark ? "border-indigo-500 bg-indigo-950/30" : "border-indigo-500 bg-indigo-50"}`,
@@ -1180,6 +2278,7 @@ const QuoteBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
1180
2278
  return /* @__PURE__ */ jsxRuntime.jsxs(
1181
2279
  "div",
1182
2280
  {
2281
+ ref: containerRef,
1183
2282
  className: "group relative",
1184
2283
  onFocus: () => setShowToolbar(true),
1185
2284
  onBlur: (e) => {
@@ -1188,69 +2287,98 @@ const QuoteBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
1188
2287
  }
1189
2288
  },
1190
2289
  children: [
1191
- showToolbar && !readOnly && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `absolute -top-12 left-0 flex items-center gap-1 p-1.5 rounded-xl shadow-lg border z-10 ${isDark ? "bg-slate-800 border-slate-600" : "bg-white border-slate-200"}`, children: [
1192
- /* @__PURE__ */ jsxRuntime.jsx(
1193
- "button",
1194
- {
1195
- onClick: () => setStyle("default"),
1196
- className: toolbarBtnClass(block.style === "default" || !block.style),
1197
- children: "Simple"
1198
- }
1199
- ),
1200
- /* @__PURE__ */ jsxRuntime.jsx(
1201
- "button",
1202
- {
1203
- onClick: () => setStyle("bordered"),
1204
- className: toolbarBtnClass(block.style === "bordered"),
1205
- children: "Bordered"
1206
- }
1207
- ),
1208
- /* @__PURE__ */ jsxRuntime.jsx(
1209
- "button",
1210
- {
1211
- onClick: () => setStyle("modern"),
1212
- className: toolbarBtnClass(block.style === "modern"),
1213
- children: "Modern"
1214
- }
1215
- )
1216
- ] }),
1217
- /* @__PURE__ */ jsxRuntime.jsx("blockquote", { className: `${styleClasses[block.style || "default"]} ${isDark ? "text-slate-300" : "text-slate-700"}`, children: readOnly ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1218
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-lg leading-relaxed whitespace-pre-wrap", children: block.content }),
1219
- block.author && /* @__PURE__ */ jsxRuntime.jsxs("cite", { className: `block mt-3 text-sm not-italic ${isDark ? "text-slate-400" : "text-slate-500"}`, children: [
1220
- "— ",
1221
- block.author
1222
- ] })
1223
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1224
- /* @__PURE__ */ jsxRuntime.jsx(
1225
- "textarea",
1226
- {
1227
- ref: textareaRef,
1228
- value: block.content,
1229
- onChange: handleContentChange,
1230
- placeholder: "Enter quote...",
1231
- className: `w-full text-lg leading-relaxed bg-transparent outline-none resize-none ${isDark ? "placeholder:text-slate-500" : "placeholder:text-slate-400"}`,
1232
- rows: 1
1233
- }
1234
- ),
1235
- /* @__PURE__ */ jsxRuntime.jsx(
1236
- "input",
1237
- {
1238
- type: "text",
1239
- value: block.author || "",
1240
- onChange: handleAuthorChange,
1241
- placeholder: "— Author name",
1242
- className: `w-full mt-2 text-sm bg-transparent outline-none ${isDark ? "text-slate-400 placeholder:text-slate-500" : "text-slate-500 placeholder:text-slate-400"}`
1243
- }
1244
- )
1245
- ] }) })
2290
+ showToolbar && !readOnly && /* @__PURE__ */ jsxRuntime.jsxs(
2291
+ "div",
2292
+ {
2293
+ className: `absolute left-0 flex items-center gap-1 p-1.5 rounded-xl shadow-lg border z-10 ${showBelow ? "top-full mt-2" : "-top-12"} ${isDark ? "bg-slate-800 border-slate-600" : "bg-white border-slate-200"}`,
2294
+ children: [
2295
+ /* @__PURE__ */ jsxRuntime.jsx(
2296
+ "button",
2297
+ {
2298
+ onClick: () => setStyle("default"),
2299
+ className: toolbarBtnClass(block.style === "default" || !block.style),
2300
+ children: "Simple"
2301
+ }
2302
+ ),
2303
+ /* @__PURE__ */ jsxRuntime.jsx(
2304
+ "button",
2305
+ {
2306
+ onClick: () => setStyle("bordered"),
2307
+ className: toolbarBtnClass(block.style === "bordered"),
2308
+ children: "Bordered"
2309
+ }
2310
+ ),
2311
+ /* @__PURE__ */ jsxRuntime.jsx(
2312
+ "button",
2313
+ {
2314
+ onClick: () => setStyle("modern"),
2315
+ className: toolbarBtnClass(block.style === "modern"),
2316
+ children: "Modern"
2317
+ }
2318
+ )
2319
+ ]
2320
+ }
2321
+ ),
2322
+ /* @__PURE__ */ jsxRuntime.jsx(
2323
+ "blockquote",
2324
+ {
2325
+ className: `${styleClasses[block.style || "default"]} ${isDark ? "text-slate-300" : "text-slate-700"}`,
2326
+ children: readOnly ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2327
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-lg leading-relaxed whitespace-pre-wrap", children: block.content }),
2328
+ block.author && /* @__PURE__ */ jsxRuntime.jsxs(
2329
+ "cite",
2330
+ {
2331
+ className: `block mt-3 text-sm not-italic ${isDark ? "text-slate-400" : "text-slate-500"}`,
2332
+ children: [
2333
+ "— ",
2334
+ block.author
2335
+ ]
2336
+ }
2337
+ )
2338
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2339
+ /* @__PURE__ */ jsxRuntime.jsx(
2340
+ "textarea",
2341
+ {
2342
+ ref: textareaRef,
2343
+ value: block.content,
2344
+ onChange: handleContentChange,
2345
+ placeholder: "Enter quote...",
2346
+ className: `w-full text-lg leading-relaxed bg-transparent outline-none resize-none ${isDark ? "placeholder:text-slate-500" : "placeholder:text-slate-400"}`,
2347
+ rows: 1
2348
+ }
2349
+ ),
2350
+ /* @__PURE__ */ jsxRuntime.jsx(
2351
+ "input",
2352
+ {
2353
+ type: "text",
2354
+ value: block.author || "",
2355
+ onChange: handleAuthorChange,
2356
+ placeholder: "— Author name",
2357
+ className: `w-full mt-2 text-sm bg-transparent outline-none ${isDark ? "text-slate-400 placeholder:text-slate-500" : "text-slate-500 placeholder:text-slate-400"}`
2358
+ }
2359
+ )
2360
+ ] })
2361
+ }
2362
+ )
1246
2363
  ]
1247
2364
  }
1248
2365
  );
1249
2366
  };
1250
2367
 
1251
- const ListBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
2368
+ const ListBlock = ({
2369
+ block,
2370
+ onUpdate,
2371
+ readOnly,
2372
+ theme = "light"
2373
+ }) => {
1252
2374
  const [showToolbar, setShowToolbar] = react.useState(false);
2375
+ const containerRef = react.useRef(null);
1253
2376
  const isDark = theme === "dark";
2377
+ const { showBelow } = useToolbarPosition({
2378
+ containerRef,
2379
+ isVisible: showToolbar && !readOnly,
2380
+ minSpaceAbove: 60
2381
+ });
1254
2382
  const updateItem = (index, value) => {
1255
2383
  const newItems = [...block.items];
1256
2384
  newItems[index] = value;
@@ -1308,6 +2436,7 @@ const ListBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
1308
2436
  return /* @__PURE__ */ jsxRuntime.jsxs(
1309
2437
  "div",
1310
2438
  {
2439
+ ref: containerRef,
1311
2440
  className: "group relative",
1312
2441
  onFocus: () => setShowToolbar(true),
1313
2442
  onBlur: (e) => {
@@ -1316,65 +2445,90 @@ const ListBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
1316
2445
  }
1317
2446
  },
1318
2447
  children: [
1319
- showToolbar && !readOnly && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `absolute -top-12 left-0 flex items-center gap-1 p-1.5 rounded-xl shadow-lg border z-10 ${isDark ? "bg-slate-800 border-slate-600" : "bg-white border-slate-200"}`, children: [
1320
- /* @__PURE__ */ jsxRuntime.jsx(
1321
- "button",
1322
- {
1323
- onClick: () => setListType("bullet"),
1324
- className: toolbarBtnClass(block.listType === "bullet"),
1325
- children: "• Bullet"
1326
- }
1327
- ),
1328
- /* @__PURE__ */ jsxRuntime.jsx(
1329
- "button",
1330
- {
1331
- onClick: () => setListType("numbered"),
1332
- className: toolbarBtnClass(block.listType === "numbered"),
1333
- children: "1. Numbered"
1334
- }
1335
- ),
1336
- /* @__PURE__ */ jsxRuntime.jsx(
1337
- "button",
1338
- {
1339
- onClick: () => setListType("checklist"),
1340
- className: toolbarBtnClass(block.listType === "checklist"),
1341
- children: "☑ Checklist"
1342
- }
1343
- )
1344
- ] }),
1345
- /* @__PURE__ */ jsxRuntime.jsx(ListWrapper, { className: `space-y-1 ${block.listType === "numbered" ? "list-decimal" : block.listType === "bullet" ? "list-disc" : "list-none"} ${block.listType !== "checklist" ? "pl-6" : ""} ${isDark ? "text-slate-200" : "text-slate-700"}`, children: block.items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "group/item flex items-center gap-2", children: [
1346
- block.listType === "checklist" && /* @__PURE__ */ jsxRuntime.jsx(
1347
- "button",
1348
- {
1349
- onClick: () => toggleChecked(index),
1350
- disabled: readOnly,
1351
- className: `flex-shrink-0 w-5 h-5 rounded border-2 flex items-center justify-center transition-colors ${block.checkedItems?.[index] ? "bg-indigo-500 border-indigo-500 text-white" : isDark ? "border-slate-500 hover:border-indigo-400" : "border-slate-300 hover:border-indigo-400"}`,
1352
- children: block.checkedItems?.[index] && /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, { size: 12 })
1353
- }
1354
- ),
1355
- readOnly ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: block.checkedItems?.[index] ? isDark ? "line-through text-slate-500" : "line-through text-slate-400" : "", children: item }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1356
- /* @__PURE__ */ jsxRuntime.jsx(
1357
- "input",
1358
- {
1359
- type: "text",
1360
- "data-list-input": block.id,
1361
- value: item,
1362
- onChange: (e) => updateItem(index, e.target.value),
1363
- onKeyDown: (e) => handleKeyDown(e, index),
1364
- placeholder: "List item...",
1365
- className: `flex-1 outline-none bg-transparent ${block.checkedItems?.[index] ? isDark ? "line-through text-slate-500" : "line-through text-slate-400" : ""} ${isDark ? "placeholder:text-slate-500" : "placeholder:text-slate-400"}`
1366
- }
1367
- ),
1368
- /* @__PURE__ */ jsxRuntime.jsx(
1369
- "button",
2448
+ showToolbar && !readOnly && /* @__PURE__ */ jsxRuntime.jsxs(
2449
+ "div",
2450
+ {
2451
+ className: `absolute left-0 flex items-center gap-1 p-1.5 rounded-xl shadow-lg border z-10 ${showBelow ? "top-full mt-2" : "-top-12"} ${isDark ? "bg-slate-800 border-slate-600" : "bg-white border-slate-200"}`,
2452
+ children: [
2453
+ /* @__PURE__ */ jsxRuntime.jsx(
2454
+ "button",
2455
+ {
2456
+ onClick: () => setListType("bullet"),
2457
+ className: toolbarBtnClass(block.listType === "bullet"),
2458
+ children: "• Bullet"
2459
+ }
2460
+ ),
2461
+ /* @__PURE__ */ jsxRuntime.jsx(
2462
+ "button",
2463
+ {
2464
+ onClick: () => setListType("numbered"),
2465
+ className: toolbarBtnClass(block.listType === "numbered"),
2466
+ children: "1. Numbered"
2467
+ }
2468
+ ),
2469
+ /* @__PURE__ */ jsxRuntime.jsx(
2470
+ "button",
2471
+ {
2472
+ onClick: () => setListType("checklist"),
2473
+ className: toolbarBtnClass(block.listType === "checklist"),
2474
+ children: " Checklist"
2475
+ }
2476
+ )
2477
+ ]
2478
+ }
2479
+ ),
2480
+ /* @__PURE__ */ jsxRuntime.jsx(
2481
+ ListWrapper,
2482
+ {
2483
+ className: `space-y-1 ${block.listType === "numbered" ? "list-decimal" : block.listType === "bullet" ? "list-disc" : "list-none"} ${block.listType !== "checklist" ? "pl-6" : ""} ${isDark ? "text-slate-200" : "text-slate-700"}`,
2484
+ children: block.items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs(
2485
+ "li",
1370
2486
  {
1371
- onClick: () => removeItem(index),
1372
- className: `opacity-0 group-hover/item:opacity-100 p-1 transition-all ${isDark ? "text-slate-500 hover:text-red-400" : "text-slate-400 hover:text-red-500"}`,
1373
- children: /* @__PURE__ */ jsxRuntime.jsx(TrashIcon, { size: 14 })
1374
- }
1375
- )
1376
- ] })
1377
- ] }, index)) }),
2487
+ className: "group/item flex items-center gap-2",
2488
+ children: [
2489
+ block.listType === "checklist" && /* @__PURE__ */ jsxRuntime.jsx(
2490
+ "button",
2491
+ {
2492
+ onClick: () => toggleChecked(index),
2493
+ disabled: readOnly,
2494
+ className: `flex-shrink-0 w-5 h-5 rounded border-2 flex items-center justify-center transition-colors ${block.checkedItems?.[index] ? "bg-indigo-500 border-indigo-500 text-white" : isDark ? "border-slate-500 hover:border-indigo-400" : "border-slate-300 hover:border-indigo-400"}`,
2495
+ children: block.checkedItems?.[index] && /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, { size: 12 })
2496
+ }
2497
+ ),
2498
+ readOnly ? /* @__PURE__ */ jsxRuntime.jsx(
2499
+ "span",
2500
+ {
2501
+ className: block.checkedItems?.[index] ? isDark ? "line-through text-slate-500" : "line-through text-slate-400" : "",
2502
+ children: item
2503
+ }
2504
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2505
+ /* @__PURE__ */ jsxRuntime.jsx(
2506
+ "input",
2507
+ {
2508
+ type: "text",
2509
+ "data-list-input": block.id,
2510
+ value: item,
2511
+ onChange: (e) => updateItem(index, e.target.value),
2512
+ onKeyDown: (e) => handleKeyDown(e, index),
2513
+ placeholder: "List item...",
2514
+ className: `flex-1 outline-none bg-transparent ${block.checkedItems?.[index] ? isDark ? "line-through text-slate-500" : "line-through text-slate-400" : ""} ${isDark ? "placeholder:text-slate-500" : "placeholder:text-slate-400"}`
2515
+ }
2516
+ ),
2517
+ /* @__PURE__ */ jsxRuntime.jsx(
2518
+ "button",
2519
+ {
2520
+ onClick: () => removeItem(index),
2521
+ className: `opacity-0 group-hover/item:opacity-100 p-1 transition-all ${isDark ? "text-slate-500 hover:text-red-400" : "text-slate-400 hover:text-red-500"}`,
2522
+ children: /* @__PURE__ */ jsxRuntime.jsx(TrashIcon, { size: 14 })
2523
+ }
2524
+ )
2525
+ ] })
2526
+ ]
2527
+ },
2528
+ index
2529
+ ))
2530
+ }
2531
+ ),
1378
2532
  !readOnly && /* @__PURE__ */ jsxRuntime.jsxs(
1379
2533
  "button",
1380
2534
  {
@@ -1442,10 +2596,21 @@ const variantLabels = {
1442
2596
  error: "Error",
1443
2597
  tip: "Tip"
1444
2598
  };
1445
- const CalloutBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
2599
+ const CalloutBlock = ({
2600
+ block,
2601
+ onUpdate,
2602
+ readOnly,
2603
+ theme = "light"
2604
+ }) => {
1446
2605
  const [showToolbar, setShowToolbar] = react.useState(false);
1447
2606
  const textareaRef = react.useRef(null);
2607
+ const containerRef = react.useRef(null);
1448
2608
  const isDark = theme === "dark";
2609
+ const { showBelow } = useToolbarPosition({
2610
+ containerRef,
2611
+ isVisible: showToolbar && !readOnly,
2612
+ minSpaceAbove: 60
2613
+ });
1449
2614
  const handleContentChange = (e) => {
1450
2615
  onUpdate({ ...block, content: e.target.value });
1451
2616
  if (textareaRef.current) {
@@ -1465,6 +2630,7 @@ const CalloutBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
1465
2630
  return /* @__PURE__ */ jsxRuntime.jsxs(
1466
2631
  "div",
1467
2632
  {
2633
+ ref: containerRef,
1468
2634
  className: "group relative",
1469
2635
  onFocus: () => setShowToolbar(true),
1470
2636
  onBlur: (e) => {
@@ -1473,19 +2639,25 @@ const CalloutBlock = ({ block, onUpdate, readOnly, theme = "light" }) => {
1473
2639
  }
1474
2640
  },
1475
2641
  children: [
1476
- showToolbar && !readOnly && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `absolute -top-12 left-0 flex items-center gap-1 p-1.5 rounded-xl shadow-lg border z-10 ${isDark ? "bg-slate-800 border-slate-600" : "bg-white border-slate-200"}`, children: Object.keys(variantStyles).map((variant) => /* @__PURE__ */ jsxRuntime.jsxs(
1477
- "button",
2642
+ showToolbar && !readOnly && /* @__PURE__ */ jsxRuntime.jsx(
2643
+ "div",
1478
2644
  {
1479
- onClick: () => setVariant(variant),
1480
- className: toolbarBtnClass(block.variant === variant),
1481
- children: [
1482
- variantIcons[variant],
1483
- " ",
1484
- variantLabels[variant]
1485
- ]
1486
- },
1487
- variant
1488
- )) }),
2645
+ className: `absolute left-0 flex items-center gap-1 p-1.5 rounded-xl shadow-lg border z-10 ${showBelow ? "top-full mt-2" : "-top-12"} ${isDark ? "bg-slate-800 border-slate-600" : "bg-white border-slate-200"}`,
2646
+ children: Object.keys(variantStyles).map((variant) => /* @__PURE__ */ jsxRuntime.jsxs(
2647
+ "button",
2648
+ {
2649
+ onClick: () => setVariant(variant),
2650
+ className: toolbarBtnClass(block.variant === variant),
2651
+ children: [
2652
+ variantIcons[variant],
2653
+ " ",
2654
+ variantLabels[variant]
2655
+ ]
2656
+ },
2657
+ variant
2658
+ ))
2659
+ }
2660
+ ),
1489
2661
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: `rounded-xl border ${styles.bg} ${styles.border} p-4`, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3", children: [
1490
2662
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: `text-xl flex-shrink-0 ${styles.icon}`, children: variantIcons[block.variant] }),
1491
2663
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: readOnly ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
@@ -1559,37 +2731,103 @@ const BlockWrapper = ({
1559
2731
  }
1560
2732
  return () => document.removeEventListener("mousedown", handleClickOutside);
1561
2733
  }, [isSelected]);
1562
- const handleBlockClick = react.useCallback((e) => {
1563
- const target = e.target;
1564
- const interactiveElements = ["INPUT", "TEXTAREA", "BUTTON", "SELECT"];
1565
- if (interactiveElements.includes(target.tagName)) {
1566
- return;
1567
- }
1568
- if (!readOnly) {
1569
- setIsSelected(true);
1570
- }
1571
- }, [readOnly]);
2734
+ const handleBlockClick = react.useCallback(
2735
+ (e) => {
2736
+ const target = e.target;
2737
+ const interactiveElements = ["INPUT", "TEXTAREA", "BUTTON", "SELECT"];
2738
+ if (interactiveElements.includes(target.tagName)) {
2739
+ return;
2740
+ }
2741
+ if (!readOnly) {
2742
+ setIsSelected(true);
2743
+ }
2744
+ },
2745
+ [readOnly]
2746
+ );
1572
2747
  const renderBlock = react.useCallback(() => {
1573
2748
  const commonProps = { readOnly, theme };
1574
2749
  switch (block.type) {
1575
2750
  case "text":
1576
- return /* @__PURE__ */ jsxRuntime.jsx(TextBlock, { block, onUpdate: (b) => onUpdate(b), ...commonProps });
2751
+ return /* @__PURE__ */ jsxRuntime.jsx(
2752
+ TextBlock,
2753
+ {
2754
+ block,
2755
+ onUpdate: (b) => onUpdate(b),
2756
+ ...commonProps
2757
+ }
2758
+ );
1577
2759
  case "heading":
1578
- return /* @__PURE__ */ jsxRuntime.jsx(HeadingBlock, { block, onUpdate: (b) => onUpdate(b), ...commonProps });
2760
+ return /* @__PURE__ */ jsxRuntime.jsx(
2761
+ HeadingBlock,
2762
+ {
2763
+ block,
2764
+ onUpdate: (b) => onUpdate(b),
2765
+ ...commonProps
2766
+ }
2767
+ );
1579
2768
  case "image":
1580
- return /* @__PURE__ */ jsxRuntime.jsx(ImageBlock, { block, onUpdate: (b) => onUpdate(b), ...commonProps });
2769
+ return /* @__PURE__ */ jsxRuntime.jsx(
2770
+ ImageBlock,
2771
+ {
2772
+ block,
2773
+ onUpdate: (b) => onUpdate(b),
2774
+ ...commonProps
2775
+ }
2776
+ );
1581
2777
  case "code":
1582
- return /* @__PURE__ */ jsxRuntime.jsx(CodeBlock, { block, onUpdate: (b) => onUpdate(b), ...commonProps });
2778
+ return /* @__PURE__ */ jsxRuntime.jsx(
2779
+ CodeBlock,
2780
+ {
2781
+ block,
2782
+ onUpdate: (b) => onUpdate(b),
2783
+ ...commonProps
2784
+ }
2785
+ );
1583
2786
  case "table":
1584
- return /* @__PURE__ */ jsxRuntime.jsx(TableBlock, { block, onUpdate: (b) => onUpdate(b), ...commonProps });
2787
+ return /* @__PURE__ */ jsxRuntime.jsx(
2788
+ TableBlock,
2789
+ {
2790
+ block,
2791
+ onUpdate: (b) => onUpdate(b),
2792
+ ...commonProps
2793
+ }
2794
+ );
1585
2795
  case "divider":
1586
- return /* @__PURE__ */ jsxRuntime.jsx(DividerBlock, { block, onUpdate: (b) => onUpdate(b), ...commonProps });
2796
+ return /* @__PURE__ */ jsxRuntime.jsx(
2797
+ DividerBlock,
2798
+ {
2799
+ block,
2800
+ onUpdate: (b) => onUpdate(b),
2801
+ ...commonProps
2802
+ }
2803
+ );
1587
2804
  case "quote":
1588
- return /* @__PURE__ */ jsxRuntime.jsx(QuoteBlock, { block, onUpdate: (b) => onUpdate(b), ...commonProps });
2805
+ return /* @__PURE__ */ jsxRuntime.jsx(
2806
+ QuoteBlock,
2807
+ {
2808
+ block,
2809
+ onUpdate: (b) => onUpdate(b),
2810
+ ...commonProps
2811
+ }
2812
+ );
1589
2813
  case "list":
1590
- return /* @__PURE__ */ jsxRuntime.jsx(ListBlock, { block, onUpdate: (b) => onUpdate(b), ...commonProps });
2814
+ return /* @__PURE__ */ jsxRuntime.jsx(
2815
+ ListBlock,
2816
+ {
2817
+ block,
2818
+ onUpdate: (b) => onUpdate(b),
2819
+ ...commonProps
2820
+ }
2821
+ );
1591
2822
  case "callout":
1592
- return /* @__PURE__ */ jsxRuntime.jsx(CalloutBlock, { block, onUpdate: (b) => onUpdate(b), ...commonProps });
2823
+ return /* @__PURE__ */ jsxRuntime.jsx(
2824
+ CalloutBlock,
2825
+ {
2826
+ block,
2827
+ onUpdate: (b) => onUpdate(b),
2828
+ ...commonProps
2829
+ }
2830
+ );
1593
2831
  default: {
1594
2832
  const _exhaustiveCheck = block;
1595
2833
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
@@ -1600,43 +2838,53 @@ const BlockWrapper = ({
1600
2838
  }
1601
2839
  }, [block, onUpdate, readOnly, theme]);
1602
2840
  const buttonBaseClass = `p-1.5 rounded-lg transition-all ${isDark ? "text-slate-400 hover:text-slate-200 hover:bg-slate-700" : "text-slate-500 hover:text-slate-700 hover:bg-slate-100"}`;
1603
- const showControls = !readOnly && isSelected;
1604
- const handleKeyDown = react.useCallback((e) => {
1605
- if (readOnly || !isSelected) return;
1606
- switch (e.key) {
1607
- case "Escape":
1608
- setIsSelected(false);
1609
- setShowAddMenu(false);
1610
- break;
1611
- case "Delete":
1612
- case "Backspace":
1613
- if (!e.target.matches("input, textarea, [contenteditable]")) {
1614
- e.preventDefault();
1615
- onDelete();
1616
- }
1617
- break;
1618
- case "ArrowUp":
1619
- if (e.altKey) {
1620
- e.preventDefault();
1621
- onMoveUp();
1622
- }
1623
- break;
1624
- case "ArrowDown":
1625
- if (e.altKey) {
1626
- e.preventDefault();
1627
- onMoveDown();
1628
- }
1629
- break;
1630
- case "d":
1631
- if (e.ctrlKey || e.metaKey) {
1632
- e.preventDefault();
1633
- onDuplicate();
1634
- }
1635
- break;
1636
- }
1637
- }, [readOnly, isSelected, onDelete, onMoveUp, onMoveDown, onDuplicate]);
2841
+ const handleKeyDown = react.useCallback(
2842
+ (e) => {
2843
+ if (readOnly || !isSelected) return;
2844
+ switch (e.key) {
2845
+ case "Escape":
2846
+ setIsSelected(false);
2847
+ setShowAddMenu(false);
2848
+ break;
2849
+ case "Delete":
2850
+ case "Backspace":
2851
+ if (!e.target.matches("input, textarea, [contenteditable]")) {
2852
+ e.preventDefault();
2853
+ onDelete();
2854
+ }
2855
+ break;
2856
+ case "ArrowUp":
2857
+ if (e.altKey) {
2858
+ e.preventDefault();
2859
+ onMoveUp();
2860
+ }
2861
+ break;
2862
+ case "ArrowDown":
2863
+ if (e.altKey) {
2864
+ e.preventDefault();
2865
+ onMoveDown();
2866
+ }
2867
+ break;
2868
+ case "d":
2869
+ if (e.ctrlKey || e.metaKey) {
2870
+ e.preventDefault();
2871
+ onDuplicate();
2872
+ }
2873
+ break;
2874
+ }
2875
+ },
2876
+ [readOnly, isSelected, onDelete, onMoveUp, onMoveDown, onDuplicate]
2877
+ );
1638
2878
  const editModeBorderClass = !readOnly ? isSelected ? isDark ? "ring-2 ring-indigo-500 rounded-lg bg-slate-800/30" : "ring-2 ring-indigo-500 rounded-lg bg-indigo-50/30" : isDark ? "border border-slate-700 rounded-lg hover:border-slate-500" : "border border-slate-200 rounded-lg hover:border-slate-400" : "";
1639
2879
  const blockTypeLabel = block.type.charAt(0).toUpperCase() + block.type.slice(1);
2880
+ const showControls = !readOnly;
2881
+ const handleAddBlock = react.useCallback(
2882
+ (type) => {
2883
+ onAddBlock(type, index);
2884
+ setShowAddMenu(false);
2885
+ },
2886
+ [onAddBlock, index]
2887
+ );
1640
2888
  return /* @__PURE__ */ jsxRuntime.jsxs(
1641
2889
  "div",
1642
2890
  {
@@ -1661,109 +2909,126 @@ const BlockWrapper = ({
1661
2909
  {
1662
2910
  role: "toolbar",
1663
2911
  "aria-label": "Block controls",
1664
- className: `flex items-center justify-between gap-1 px-2 py-1.5 mb-1 rounded-t-lg border-b ${isDark ? "bg-slate-800 border-slate-700" : "bg-slate-50 border-slate-200"}`,
2912
+ className: `relative flex items-center justify-between gap-1 px-2 py-1.5 mb-1 rounded-t-lg border-b ${isDark ? "bg-slate-800 border-slate-700" : "bg-slate-50 border-slate-200"}`,
1665
2913
  children: [
1666
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", role: "group", "aria-label": "Reorder controls", children: [
1667
- /* @__PURE__ */ jsxRuntime.jsx(
1668
- "button",
1669
- {
1670
- type: "button",
1671
- className: `${buttonBaseClass} cursor-grab active:cursor-grabbing`,
1672
- title: "Drag to reorder",
1673
- "aria-label": "Drag to reorder block",
1674
- children: /* @__PURE__ */ jsxRuntime.jsx(DragIcon, { size: 16 })
1675
- }
1676
- ),
1677
- /* @__PURE__ */ jsxRuntime.jsx(
1678
- "button",
1679
- {
1680
- type: "button",
1681
- onClick: (e) => {
1682
- e.stopPropagation();
1683
- onMoveUp();
1684
- },
1685
- disabled: index === 0,
1686
- className: `${buttonBaseClass} disabled:opacity-30 disabled:cursor-not-allowed`,
1687
- title: "Move up (Alt+↑)",
1688
- "aria-label": "Move block up",
1689
- "aria-disabled": index === 0,
1690
- children: /* @__PURE__ */ jsxRuntime.jsx(ChevronUpIcon, { size: 16 })
1691
- }
1692
- ),
1693
- /* @__PURE__ */ jsxRuntime.jsx(
1694
- "button",
1695
- {
1696
- type: "button",
1697
- onClick: (e) => {
1698
- e.stopPropagation();
1699
- onMoveDown();
1700
- },
1701
- disabled: index === totalBlocks - 1,
1702
- className: `${buttonBaseClass} disabled:opacity-30 disabled:cursor-not-allowed`,
1703
- title: "Move down (Alt+↓)",
1704
- "aria-label": "Move block down",
1705
- "aria-disabled": index === totalBlocks - 1,
1706
- children: /* @__PURE__ */ jsxRuntime.jsx(ChevronDownIcon, { size: 16 })
1707
- }
1708
- )
1709
- ] }),
1710
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", role: "group", "aria-label": "Block actions", children: [
1711
- /* @__PURE__ */ jsxRuntime.jsx(
1712
- "button",
1713
- {
1714
- type: "button",
1715
- onClick: (e) => {
1716
- e.stopPropagation();
1717
- setShowAddMenu(!showAddMenu);
1718
- },
1719
- className: `${buttonBaseClass} hover:!text-indigo-500`,
1720
- title: "Add block below",
1721
- "aria-label": "Add new block below",
1722
- "aria-expanded": showAddMenu,
1723
- "aria-haspopup": "menu",
1724
- children: /* @__PURE__ */ jsxRuntime.jsx(PlusIcon, { size: 16 })
1725
- }
1726
- ),
1727
- /* @__PURE__ */ jsxRuntime.jsx(
1728
- "button",
1729
- {
1730
- type: "button",
1731
- onClick: (e) => {
1732
- e.stopPropagation();
1733
- onDuplicate();
1734
- },
1735
- className: `${buttonBaseClass} hover:!text-indigo-500`,
1736
- title: "Duplicate (Ctrl+D)",
1737
- "aria-label": "Duplicate block",
1738
- children: /* @__PURE__ */ jsxRuntime.jsx(CopyIcon, { size: 16 })
1739
- }
1740
- ),
1741
- /* @__PURE__ */ jsxRuntime.jsx(
1742
- "button",
1743
- {
1744
- type: "button",
1745
- onClick: (e) => {
1746
- e.stopPropagation();
1747
- onDelete();
1748
- },
1749
- className: `${buttonBaseClass} hover:!text-red-500`,
1750
- title: "Delete",
1751
- "aria-label": "Delete block",
1752
- children: /* @__PURE__ */ jsxRuntime.jsx(TrashIcon, { size: 16 })
1753
- }
1754
- )
1755
- ] }),
1756
- showAddMenu && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute left-1/2 -translate-x-1/2 top-full mt-1 z-50", children: /* @__PURE__ */ jsxRuntime.jsx(
2914
+ /* @__PURE__ */ jsxRuntime.jsxs(
2915
+ "div",
2916
+ {
2917
+ className: "flex items-center gap-1",
2918
+ role: "group",
2919
+ "aria-label": "Reorder controls",
2920
+ children: [
2921
+ /* @__PURE__ */ jsxRuntime.jsx(
2922
+ "button",
2923
+ {
2924
+ type: "button",
2925
+ className: `${buttonBaseClass} cursor-grab active:cursor-grabbing`,
2926
+ title: "Drag to reorder",
2927
+ "aria-label": "Drag to reorder block",
2928
+ onClick: (e) => {
2929
+ e.stopPropagation();
2930
+ setIsSelected(true);
2931
+ },
2932
+ children: /* @__PURE__ */ jsxRuntime.jsx(DragIcon, { size: 16 })
2933
+ }
2934
+ ),
2935
+ /* @__PURE__ */ jsxRuntime.jsx(
2936
+ "button",
2937
+ {
2938
+ type: "button",
2939
+ onClick: (e) => {
2940
+ e.stopPropagation();
2941
+ onMoveUp();
2942
+ },
2943
+ disabled: index === 0,
2944
+ className: `${buttonBaseClass} disabled:opacity-30 disabled:cursor-not-allowed`,
2945
+ title: "Move up (Alt+↑)",
2946
+ "aria-label": "Move block up",
2947
+ "aria-disabled": index === 0,
2948
+ children: /* @__PURE__ */ jsxRuntime.jsx(ChevronUpIcon, { size: 16 })
2949
+ }
2950
+ ),
2951
+ /* @__PURE__ */ jsxRuntime.jsx(
2952
+ "button",
2953
+ {
2954
+ type: "button",
2955
+ onClick: (e) => {
2956
+ e.stopPropagation();
2957
+ onMoveDown();
2958
+ },
2959
+ disabled: index === totalBlocks - 1,
2960
+ className: `${buttonBaseClass} disabled:opacity-30 disabled:cursor-not-allowed`,
2961
+ title: "Move down (Alt+↓)",
2962
+ "aria-label": "Move block down",
2963
+ "aria-disabled": index === totalBlocks - 1,
2964
+ children: /* @__PURE__ */ jsxRuntime.jsx(ChevronDownIcon, { size: 16 })
2965
+ }
2966
+ )
2967
+ ]
2968
+ }
2969
+ ),
2970
+ /* @__PURE__ */ jsxRuntime.jsxs(
2971
+ "div",
2972
+ {
2973
+ className: "flex items-center gap-1",
2974
+ role: "group",
2975
+ "aria-label": "Block actions",
2976
+ children: [
2977
+ /* @__PURE__ */ jsxRuntime.jsx(
2978
+ "button",
2979
+ {
2980
+ type: "button",
2981
+ onClick: (e) => {
2982
+ e.stopPropagation();
2983
+ setShowAddMenu(!showAddMenu);
2984
+ },
2985
+ className: `${buttonBaseClass} hover:!text-indigo-500`,
2986
+ title: "Add block below",
2987
+ "aria-label": "Add new block below",
2988
+ "aria-expanded": showAddMenu,
2989
+ "aria-haspopup": "menu",
2990
+ children: /* @__PURE__ */ jsxRuntime.jsx(PlusIcon, { size: 16 })
2991
+ }
2992
+ ),
2993
+ /* @__PURE__ */ jsxRuntime.jsx(
2994
+ "button",
2995
+ {
2996
+ type: "button",
2997
+ onClick: (e) => {
2998
+ e.stopPropagation();
2999
+ onDuplicate();
3000
+ },
3001
+ className: `${buttonBaseClass} hover:!text-indigo-500`,
3002
+ title: "Duplicate (Ctrl+D)",
3003
+ "aria-label": "Duplicate block",
3004
+ children: /* @__PURE__ */ jsxRuntime.jsx(CopyIcon, { size: 16 })
3005
+ }
3006
+ ),
3007
+ /* @__PURE__ */ jsxRuntime.jsx(
3008
+ "button",
3009
+ {
3010
+ type: "button",
3011
+ onClick: (e) => {
3012
+ e.stopPropagation();
3013
+ onDelete();
3014
+ },
3015
+ className: `${buttonBaseClass} hover:!text-red-500`,
3016
+ title: "Delete",
3017
+ "aria-label": "Delete block",
3018
+ children: /* @__PURE__ */ jsxRuntime.jsx(TrashIcon, { size: 16 })
3019
+ }
3020
+ )
3021
+ ]
3022
+ }
3023
+ ),
3024
+ showAddMenu && /* @__PURE__ */ jsxRuntime.jsx(
1757
3025
  AddBlockMenu,
1758
3026
  {
1759
- onAdd: (type) => {
1760
- onAddBlock(type, index);
1761
- setShowAddMenu(false);
1762
- },
3027
+ onAdd: handleAddBlock,
1763
3028
  onClose: () => setShowAddMenu(false),
1764
3029
  theme
1765
3030
  }
1766
- ) })
3031
+ )
1767
3032
  ]
1768
3033
  }
1769
3034
  ),
@@ -1946,14 +3211,14 @@ const PagesEditor = ({
1946
3211
  ]
1947
3212
  }
1948
3213
  ),
1949
- showInitialAddMenu && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute left-1/2 -translate-x-1/2 top-full mt-2 z-50", children: /* @__PURE__ */ jsxRuntime.jsx(
3214
+ showInitialAddMenu && /* @__PURE__ */ jsxRuntime.jsx(
1950
3215
  AddBlockMenu,
1951
3216
  {
1952
3217
  onAdd: (type) => addBlock(type),
1953
3218
  onClose: () => setShowInitialAddMenu(false),
1954
3219
  theme
1955
3220
  }
1956
- ) })
3221
+ )
1957
3222
  ] })
1958
3223
  ] })
1959
3224
  ) : (
@@ -1999,19 +3264,21 @@ const PagesEditor = ({
1999
3264
  ]
2000
3265
  }
2001
3266
  ),
2002
- showInitialAddMenu && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute left-1/2 -translate-x-1/2 bottom-full mb-2 z-50", children: /* @__PURE__ */ jsxRuntime.jsx(
3267
+ showInitialAddMenu && /* @__PURE__ */ jsxRuntime.jsx(
2003
3268
  AddBlockMenu,
2004
3269
  {
2005
3270
  onAdd: (type) => addBlock(type),
2006
3271
  onClose: () => setShowInitialAddMenu(false),
2007
3272
  theme
2008
3273
  }
2009
- ) })
3274
+ )
2010
3275
  ] }) }) })
2011
3276
  ] }) }) });
2012
3277
  };
2013
3278
 
2014
- function useBlockToolbar({ readOnly = false } = {}) {
3279
+ function useBlockToolbar({
3280
+ readOnly = false
3281
+ } = {}) {
2015
3282
  const [showToolbar, setShowToolbar] = react.useState(false);
2016
3283
  const handleFocus = react.useCallback(() => {
2017
3284
  if (!readOnly) {